Ver código fonte

Changed the plugin initialization procedure to guarantee that asynchronous dependencies execute first.

fredck 10 anos atrás
pai
commit
0366d486e6

+ 14 - 7
packages/ckeditor5-engine/src/editor.js

@@ -80,17 +80,24 @@ CKEDITOR.define( [ 'mvc/model', 'editorconfig', 'plugincollection' ], function(
 			}
 
 			function initPlugins() {
-				var rets = [];
+				// Start with a resolved promise.
+				var promise = Promise.resolve();
 
-				// Call init() on every plugin, saving the return value in the rets array.
+				// Chain it with promises that resolve with the init() call of every plugin.
 				for ( var i = 0; i < that.plugins.length; i++ ) {
-					rets.push( that.plugins.get( i ).init() );
+					promise = promise.then( getInitResolveFn( i ) );
 				}
 
-				// Returns a promise that resolves when all initialization values are resolved. If they are promises,
-				// we will wait for them to resolve. If they are something else, they resolve immediately (as per
-				// Promise.all specs).
-				return Promise.all( rets );
+				// Return the promise chain.
+				return promise;
+
+				function getInitResolveFn( index ) {
+					return function() {
+						// Resolve with the return value of init(). If it is a Promise, it'll inherit its state. For
+						// everything else it resolves immediately.
+						return Promise.resolve( that.plugins.get( index ).init() );
+					};
+				}
 			}
 		},
 

+ 40 - 1
packages/ckeditor5-engine/tests/editor/editor.js

@@ -3,7 +3,7 @@
  * For licensing, see LICENSE.md.
  */
 
-/* globals describe, it, expect, beforeEach, sinon, document */
+/* globals describe, it, expect, beforeEach, sinon, document, setTimeout */
 
 'use strict';
 
@@ -51,6 +51,28 @@ CKEDITOR.define( 'plugin!E', [ 'plugin' ], function( Plugin ) {
 	return Plugin.extend( {} );
 } );
 
+// Synchronous plugin that depends on an asynchronous one.
+CKEDITOR.define( 'plugin!F', [ 'plugin', 'plugin!async' ], function( Plugin ) {
+	return Plugin.extend( {
+		init: sinon.spy().named( 'F' )
+	} );
+} );
+
+var asyncSpy = sinon.spy().named( 'async-call-spy' );
+
+CKEDITOR.define( 'plugin!async', [ 'plugin' ], function( Plugin ) {
+	return Plugin.extend( {
+		init: sinon.spy( function() {
+			return new Promise( function( resolve ) {
+				setTimeout( function() {
+					asyncSpy();
+					resolve();
+				}, 0 );
+			} );
+		} )
+	} );
+} );
+
 ///////////////////
 
 describe( 'constructor', function() {
@@ -119,6 +141,23 @@ describe( 'init', function() {
 		} );
 	} );
 
+	it( 'should initialize plugins in the right order, waiting for asynchronous ones', function() {
+		var Editor = modules.editor;
+
+		editor = new Editor( element, {
+			plugins: 'A,F'
+		} );
+
+		return editor.init().then( function() {
+			sinon.assert.callOrder(
+				editor.plugins.get( 'A' ).init,
+				editor.plugins.get( 'async' ).init,
+				asyncSpy,	// This one is called with delay by the async init
+				editor.plugins.get( 'F' ).init
+			);
+		} );
+	} );
+
 	it( 'should not fail if loading a plugin that doesn\'t define init()', function() {
 		var Editor = modules.editor;