Skip to content

Commit

Permalink
fix(dia.Paper): don't leak animation frame request (#2561)
Browse files Browse the repository at this point in the history
When `resetViews()` calls `_resetUpdates()` it's possible that there's an animation frame request, but `resetUpdates()` was not checking for this and cancelling any such request, potentially causing `updateViewsAsync()` to be called when it shouldn't be.

This can cause unexpected behavior if the paper was frozen, or cause an error to be thrown if the paper was destroyed.
  • Loading branch information
bendemboski committed Mar 1, 2024
1 parent 7bd39e2 commit d300545
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 0 deletions.
2 changes: 2 additions & 0 deletions packages/joint-core/src/dia/Paper.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,8 @@ export const Paper = View.extend({
},

_resetUpdates: function() {
if (this._updates && this._updates.id) cancelFrame(this._updates.id);

return this._updates = {
id: null,
priorities: [{}, {}, {}],
Expand Down
20 changes: 20 additions & 0 deletions packages/joint-core/test/jointjs/dia/Paper.js
Original file line number Diff line number Diff line change
Expand Up @@ -1886,6 +1886,26 @@ QUnit.module('joint.dia.Paper', function(hooks) {
});
});

QUnit.module('resetViews()', function() {
QUnit.test('does not leak animation frames', function(assert) {
var done = assert.async();
assert.expect(1);

graph.resetCells([
new joint.shapes.standard.Rectangle(),
]);
paper.freeze();

var spy = sinon.spy(paper, 'updateViewsAsync');
requestAnimationFrame(function() {
requestAnimationFrame(function() {
assert.equal(spy.callCount, 0);
done();
});
});
});
});

QUnit.test('hasScheduledUpdates()', function(assert) {
var done = assert.async();
assert.expect(4);
Expand Down

0 comments on commit d300545

Please sign in to comment.