diff --git a/src/Node.ts b/src/Node.ts index 98a2f1eeb..2002a7e43 100644 --- a/src/Node.ts +++ b/src/Node.ts @@ -2379,18 +2379,18 @@ export abstract class Node { 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); + }); } } /** diff --git a/test/unit/Node-test.ts b/test/unit/Node-test.ts index 599254b65..27192711e 100644 --- a/test/unit/Node-test.ts +++ b/test/unit/Node-test.ts @@ -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({ @@ -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();