8
0
فهرست منبع

EmitterMixin fixed calling callbacks for event listeners that were created while firing that event.

Szymon Cofalik 10 سال پیش
والد
کامیت
ca1cde572c
2فایلهای تغییر یافته به همراه30 افزوده شده و 1 حذف شده
  1. 18 1
      packages/ckeditor5-engine/src/emittermixin.js
  2. 12 0
      packages/ckeditor5-engine/tests/emittermixin/emittermixin.js

+ 18 - 1
packages/ckeditor5-engine/src/emittermixin.js

@@ -14,6 +14,13 @@
 
 CKEDITOR.define( [ 'eventinfo', 'utils' ], ( EventInfo, utils ) => {
 	const EmitterMixin = {
+		/**
+		 * Saves how many callbacks has been already added. Does not decrement when callback is removed.
+		 * Used internally as a unique id for a callback.
+		 * @private
+		 */
+		_counter: 0,
+
 		/**
 		 * Registers a callback function to be executed when an event is fired.
 		 *
@@ -35,7 +42,9 @@ CKEDITOR.define( [ 'eventinfo', 'utils' ], ( EventInfo, utils ) => {
 			callback = {
 				callback: callback,
 				ctx: ctx || this,
-				priority: priority
+				priority: priority,
+				// Save counter value as unique id.
+				counter: ++this._counter
 			};
 
 			// Add the callback to the list in the right priority position.
@@ -226,7 +235,15 @@ CKEDITOR.define( [ 'eventinfo', 'utils' ], ( EventInfo, utils ) => {
 			args = Array.prototype.slice.call( arguments, 1 );
 			args.unshift( eventInfo );
 
+			// Save how many callbacks were added at the moment when the event has been fired.
+			const counter = this._counter;
+
 			for ( let i = 0; i < callbacks.length; i++ ) {
+				// Filter out callbacks that have been added after event has been fired.
+				if ( callbacks[ i ].counter > counter ) {
+					continue;
+				}
+
 				callbacks[ i ].callback.apply( callbacks[ i ].ctx, args );
 
 				// Remove the callback from future requests if off() has been called.

+ 12 - 0
packages/ckeditor5-engine/tests/emittermixin/emittermixin.js

@@ -118,6 +118,18 @@ describe( 'fire', () => {
 
 		sinon.assert.calledThrice( spy );
 	} );
+
+	it( 'should not fire callbacks for an event that were added while firing that event', () => {
+		let spy = sinon.spy();
+
+		emitter.on( 'test', () => {
+			emitter.on( 'test', spy );
+		} );
+
+		emitter.fire( 'test' );
+
+		sinon.assert.notCalled( spy );
+	} );
 } );
 
 describe( 'on', () => {