// List of modules to be loaded
queue = [],
- // List of callback functions waiting for modules to be ready to be called
+ /**
+ * List of callback jobs waiting for modules to be ready.
+ *
+ * Jobs are created by #request() and run by #handlePending().
+ *
+ * Typically when a job is created for a module, the job's dependencies contain
+ * both the module being requested and all its recursive dependencies.
+ *
+ * Format:
+ *
+ * {
+ * 'dependencies': [ module names ],
+ * 'ready': Function callback
+ * 'error': Function callback
+ * }
+ *
+ * @property {Object[]} jobs
+ * @private
+ */
jobs = [],
// Selector cache for the marker element. Use getMarker() to get/use the marker!
// Verify that the element before the marker actually is a
// <style> tag and one that came from ResourceLoader
// (not some other style tag or even a `<meta>` or `<script>`).
- if ( $style.data( 'ResourceLoaderDynamicStyleTag' ) === true ) {
+ if ( $style.data( 'ResourceLoaderDynamicStyleTag' ) ) {
// There's already a dynamic <style> tag present and
// we are able to append more to it.
styleEl = $style.get( 0 );
// Support: IE6-10
if ( styleEl.styleSheet ) {
try {
- styleEl.styleSheet.cssText += cssText;
+ // Support: IE9
+ // We can't do styleSheet.cssText += cssText, since IE9 mangles this property on
+ // write, dropping @media queries from the CSS text. If we read it and used its
+ // value, we would accidentally apply @media-specific styles to all media. (T108727)
+ if ( document.documentMode === 9 ) {
+ styleEl.styleSheet.cssText = $style.data( 'ResourceLoaderDynamicStyleTag' ) + cssText;
+ } else {
+ styleEl.styleSheet.cssText += cssText;
+ }
} catch ( e ) {
mw.track( 'resourceloader.exception', { exception: e, source: 'stylesheet' } );
}
}
}
- $( newStyleTag( cssText, getMarker() ) ).data( 'ResourceLoaderDynamicStyleTag', true );
+ $style = $( newStyleTag( cssText, getMarker() ) );
+
+ if ( document.documentMode === 9 ) {
+ // Support: IE9
+ // Preserve original CSS text because IE9 mangles it on write
+ $style.data( 'ResourceLoaderDynamicStyleTag', cssText );
+ } else {
+ $style.data( 'ResourceLoaderDynamicStyleTag', true );
+ }
fireCallbacks();
}
// Add ready and error callbacks if they were given
if ( ready !== undefined || error !== undefined ) {
- jobs[ jobs.length ] = {
+ jobs.push( {
+ // Narrow down the list to modules that are worth waiting for
dependencies: $.grep( dependencies, function ( module ) {
var state = mw.loader.getState( module );
- return state === 'registered' || state === 'loaded' || state === 'loading';
+ return state === 'registered' || state === 'loaded' || state === 'loading' || state === 'executing';
} ),
ready: ready,
error: error
- };
+ } );
}
$.each( dependencies, function ( idx, module ) {
if ( typeof modules !== 'object' && typeof modules !== 'string' ) {
throw new Error( 'modules must be a string or an array, not a ' + typeof modules );
}
- // Allow calling with an external url or single dependency as a string
+ // Allow calling with a url or single dependency as a string
if ( typeof modules === 'string' ) {
- if ( /^(https?:)?\/\//.test( modules ) ) {
+ // "https://example.org/x.js", "http://example.org/x.js", "//example.org/x.js", "/x.js"
+ if ( /^(https?:)?\/?\//.test( modules ) ) {
if ( type === 'text/css' ) {
// Support: IE 7-8
// Use properties instead of attributes as IE throws security
tokens: new Map()
},
+ // OOUI widgets specific to MediaWiki
+ widgets: {},
+
/**
* Registry and firing of events.
*
} );
} );
$.when.apply( $, loading ).then( function () {
- performance.mark( 'mwLoadEnd' );
+ mwPerformance.mark( 'mwLoadEnd' );
mw.hook( 'resourceloader.loadEnd' ).fire();
} );
} );