Skip to content

Commit

Permalink
Fix race condition when unregister an event inside handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
luin committed Aug 31, 2024
1 parent 583fccf commit cc9e564
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 7 deletions.
12 changes: 6 additions & 6 deletions src/Node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2379,18 +2379,18 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {

const topListeners = this._getProtoListeners(eventType);
if (topListeners) {
for (var i = 0; i < topListeners.length; i++) {
topListeners[i].handler.call(this, evt);
}
topListeners.slice(0).forEach((listener) => {
listener.handler.call(this, evt);
});
}

// it is important to iterate over self listeners without cache
// because events can be added/removed while firing
const selfListeners = this.eventListeners[eventType];
if (selfListeners) {
for (var i = 0; i < selfListeners.length; i++) {
selfListeners[i].handler.call(this, evt);
}
selfListeners.slice(0).forEach((listener) => {
listener.handler.call(this, evt);
});
}
}
/**
Expand Down
43 changes: 42 additions & 1 deletion test/unit/Node-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2004,7 +2004,7 @@ describe('Node', function () {
});

// ======================================================
it('remove event with with callback', function () {
it('remove event with callback', function () {
var stage = addStage();
var layer = new Konva.Layer();
var circle = new Konva.Circle({
Expand Down Expand Up @@ -2045,6 +2045,47 @@ describe('Node', function () {
assert.equal(event2, 2, 'event2 triggered twice');
});

// ======================================================
it('remove and add event inside callback handler', function () {
var stage = addStage();
var layer = new Konva.Layer();
var circle = new Konva.Circle();
stage.add(layer);
layer.add(circle);
layer.draw();

var event1 = 0;
var event2 = 0;
var event3 = 0;

var callback1 = function () {
event1 += 1;
circle.off('event', callback1);
circle.on('event', callback3);
};
var callback2 = function () {
event2 += 1;
};
var callback3 = function () {
event3 += 1;
};

circle.on('event', callback1);
circle.on('event', callback2);

circle.fire('event');

assert.equal(event1, 1, 'event1 triggered once');
assert.equal(event2, 1, 'event2 triggered once');
assert.equal(event3, 0, 'event2 not triggered');

circle.fire('event');

assert.equal(event1, 1, 'event1 still triggered once');
assert.equal(event2, 2, 'event2 triggered twice');
assert.equal(event3, 1, 'event3 triggered once');
});

// ======================================================
it('simulate event bubble', function () {
var stage = addStage();
Expand Down

0 comments on commit cc9e564

Please sign in to comment.