$.globalEval( script );
markModuleReady();
}
+ } else {
+ // Module without script
+ markModuleReady();
}
} );
} catch ( e ) {
throw new Error( 'module already implemented: ' + module );
}
// Attach components
- registry[ module ].script = script || [];
- registry[ module ].style = style || {};
- registry[ module ].messages = messages || {};
- registry[ module ].templates = templates || {};
+ registry[ module ].script = script || null;
+ registry[ module ].style = style || null;
+ registry[ module ].messages = messages || null;
+ registry[ module ].templates = templates || null;
// The module may already have been marked as erroneous
if ( $.inArray( registry[ module ].state, [ 'error', 'missing' ] ) === -1 ) {
registry[ module ].state = 'loaded';
}
}
- // subscribe to error streams
+ // Subscribe to error streams
mw.trackSubscribe( 'resourceloader.exception', log );
mw.trackSubscribe( 'resourceloader.assert', log );
+ /**
+ * Fired when all modules associated with the page have finished loading.
+ *
+ * @event resourceloader_loadEnd
+ * @member mw.hook
+ */
+ $( function () {
+ var loading = $.grep( mw.loader.getModuleNames(), function ( module ) {
+ return mw.loader.getState( module ) === 'loading';
+ } );
+ // In order to use jQuery.when (which stops early if one of the promises got rejected)
+ // cast any loading failures into successes. We only need a callback, not the module.
+ loading = $.map( loading, function ( module ) {
+ return mw.loader.using( module ).then( null, function () {
+ return $.Deferred().resolve();
+ } );
+ } );
+ $.when.apply( $, loading ).then( function () {
+ performance.mark( 'mwLoadEnd' );
+ mw.hook( 'resourceloader.loadEnd' ).fire();
+ } );
+ } );
+
// Attach to window and globally alias
window.mw = window.mediaWiki = mw;
}( jQuery ) );