}
$script .= '});';
- $wgOut->addScript( Html::inlineScript( ResourceLoader::makeLoaderConditionalScript( $script ) ) );
+ $wgOut->addScript( ResourceLoader::makeInlineScript( $script ) );
$toolbar = '<div id="toolbar"></div>';
$ret .= $item . "\n";
}
+ $ret .= $this->getInlineHeadScript();
+
// No newline after buildCssLinks since makeResourceLoaderLink did that already
$ret .= $this->buildCssLinks();
- $ret .= $this->getHeadScripts() . "\n";
+ $ret .= $this->getHeadScripts();
foreach ( $this->mHeadItems as $item ) {
$ret .= $item . "\n";
$resourceLoader->makeModuleResponse( $context, $grpModules )
);
} else {
- $links['html'] .= Html::inlineScript(
- ResourceLoader::makeLoaderConditionalScript(
- $resourceLoader->makeModuleResponse( $context, $grpModules )
- )
+ $links['html'] .= ResourceLoader::makeInlineScript(
+ $resourceLoader->makeModuleResponse( $context, $grpModules )
);
}
$links['html'] .= "\n";
if ( $only === ResourceLoaderModule::TYPE_STYLES ) {
$link = Html::linkedStyle( $url );
} elseif ( $loadCall ) {
- $link = Html::inlineScript(
- ResourceLoader::makeLoaderConditionalScript(
- Xml::encodeJsCall( 'mw.loader.load', array( $url, 'text/javascript', true ) )
- )
+ $link = ResourceLoader::makeInlineScript(
+ Xml::encodeJsCall( 'mw.loader.load', array( $url, 'text/javascript', true ) )
);
} else {
$link = Html::linkedScript( $url );
// browsers not supported by the startup module would unconditionally
// execute this module. Otherwise users will get "ReferenceError: mw is
// undefined" or "jQuery is undefined" from e.g. a "site" module.
- $link = Html::inlineScript(
- ResourceLoader::makeLoaderConditionalScript(
- Xml::encodeJsCall( 'document.write', array( $link ) )
- )
+ $link = ResourceLoader::makeInlineScript(
+ Xml::encodeJsCall( 'document.write', array( $link ) )
);
}
}
if ( count( $states ) ) {
- $html = Html::inlineScript(
- ResourceLoader::makeLoaderConditionalScript(
- ResourceLoader::makeLoaderStateScript( $states )
- )
+ $html = ResourceLoader::makeInlineScript(
+ ResourceLoader::makeLoaderStateScript( $states )
) . "\n" . $html;
}
return $html;
}
+ /**
+ * Get <script> tags for <head> whose source is inline.
+ *
+ * @since 1.25
+ * @return string HTML fragment
+ */
+ public function getInlineHeadScript() {
+ // Load config before anything else.
+ $html = ResourceLoader::makeInlineScript(
+ ResourceLoader::makeConfigSetScript( $this->getJSVars() )
+ );
+
+ // Load embeddable private modules before any loader links.
+ $inlineModulesLink = $this->makeResourceLoaderLink(
+ array( 'user.options', 'user.tokens' ), ResourceLoaderModule::TYPE_COMBINED
+ );
+ $html .= "\n" . self::getHtmlFromLoaderLinks( array( $inlineModulesLink ) );
+
+ // Construct mw.loader.load() call for top-loaded modules.
+ // Client-side code will request these modules and their dependencies.
+ $topModules = $this->getModules( true, 'top' );
+ if ( $topModules ) {
+ $html .= ResourceLoader::makeInlineScript(
+ Xml::encodeJsCall( 'mw.loader.load', array( $topModules ) )
+ ) . "\n";
+ }
+
+ return $html;
+ }
+
/**
* JS stuff to put in the "<head>". This is the startup module, config
* vars and modules marked with position 'top'
$links = array();
$links[] = $this->makeResourceLoaderLink( 'startup', ResourceLoaderModule::TYPE_SCRIPTS, true );
- // Load config before anything else
- $links[] = Html::inlineScript(
- ResourceLoader::makeLoaderConditionalScript(
- ResourceLoader::makeConfigSetScript( $this->getJSVars() )
- )
- );
-
- // Load embeddable private modules before any loader links
- // This needs to be TYPE_COMBINED so these modules are properly wrapped
- // in mw.loader.implement() calls and deferred until mw.user is available
- $embedScripts = array( 'user.options', 'user.tokens' );
- $links[] = $this->makeResourceLoaderLink( $embedScripts, ResourceLoaderModule::TYPE_COMBINED );
-
// Scripts and messages "only" requests marked for top inclusion
// Messages should go first
$links[] = $this->makeResourceLoaderLink(
ResourceLoaderModule::TYPE_SCRIPTS
);
- // Modules requests - let the client calculate dependencies and batch requests as it likes
- // Only load modules that have marked themselves for loading at the top
- $modules = $this->getModules( true, 'top' );
- if ( $modules ) {
- $links[] = Html::inlineScript(
- ResourceLoader::makeLoaderConditionalScript(
- Xml::encodeJsCall( 'mw.loader.load', array( $modules ) )
- )
- );
- }
-
if ( $this->getConfig()->get( 'ResourceLoaderExperimentalAsyncLoading' ) ) {
$links[] = $this->getScriptsForBottomQueue( true );
}
// Only load modules that have marked themselves for loading at the bottom
$modules = $this->getModules( true, 'bottom' );
if ( $modules ) {
- $links[] = Html::inlineScript(
- ResourceLoader::makeLoaderConditionalScript(
- Xml::encodeJsCall( 'mw.loader.load', array( $modules, null, true ) )
- )
+ $links[] = ResourceLoader::makeInlineScript(
+ Xml::encodeJsCall( 'mw.loader.load', array( $modules, null, true ) )
);
}
// Cannot use OutputPage::addJsConfigVars because those are already outputted
// by the time this method is called.
- $html = Html::inlineScript(
- ResourceLoader::makeLoaderConditionalScript(
- ResourceLoader::makeConfigSetScript( array( 'debugInfo' => $debugInfo ) )
- )
+ $html = ResourceLoader::makeInlineScript(
+ ResourceLoader::makeConfigSetScript( array( 'debugInfo' => $debugInfo ) )
);
}
* Returns JS code which runs given JS code if the client-side framework is
* present.
*
+ * @deprecated since 1.25; use makeInlineScript instead
* @param string $script JavaScript code
* @return string
*/
return "if(window.mw){\n" . trim( $script ) . "\n}";
}
+ /**
+ * Construct an inline script tag with given JS code.
+ *
+ * The code will be wrapped in a closure, and it will be executed by ResourceLoader
+ * only if the client has adequate support for MediaWiki JavaScript code.
+ *
+ * @param string $script JavaScript code
+ * @return string HTML
+ */
+ public static function makeInlineScript( $script ) {
+ $js = 'var _mwq = _mwq || []; _mwq.push( function ( mw ) { ' . $script . ' } );';
+ return Html::inlineScript( $js );
+ }
+
/**
* Returns JS code which will set the MediaWiki configuration array to
* the given value.
ResourceLoader::inDebugMode()
);
+ // Process the deferred inline script queue, and ensure that any
+ // functions enqueued after this point are executed immediately.
+ $mwqJs = (
+ 'window._mwq = window._mwq || [];' .
+ 'while ( _mwq.length ) _mwq.shift()( mw );' .
+ '_mwq.push = function ( f ) { f( mw ); };'
+ );
+
$out .= "var startUp = function () {\n" .
"\tmw.config = new " .
$mwMapJsCall . "\n" .
"\t$registrations\n" .
- "\t" . $mwConfigSetJsCall .
+ "\t" . $mwConfigSetJsCall . "\n" .
+ "\t" . $mwqJs . "\n" .
"};\n";
// Conditional script injection
*/
static function makeVariablesScript( $data ) {
if ( $data ) {
- return Html::inlineScript(
- ResourceLoader::makeLoaderConditionalScript( ResourceLoader::makeConfigSetScript( $data ) )
+ return ResourceLoader::makeInlineScript(
+ ResourceLoader::makeConfigSetScript( $data )
);
} else {
return '';
// The testrunner configures QUnit and essentially depends on it. However, test suites
// are reusable in environments that preload QUnit (or a compatibility interface to
// another framework). Therefore we have to load it ourselves.
- $out->addHtml( Html::inlineScript(
- ResourceLoader::makeLoaderConditionalScript(
- Xml::encodeJsCall( 'mw.loader.using', array(
- array( 'jquery.qunit', 'jquery.qunit.completenessTest' ),
- new XmlJsCode(
- 'function () {' . Xml::encodeJsCall( 'mw.loader.load', array( $modules ) ) . '}'
- )
- ) )
- )
+ $out->addHtml( ResourceLoader::makeInlineScript(
+ Xml::encodeJsCall( 'mw.loader.using', array(
+ array( 'jquery.qunit', 'jquery.qunit.completenessTest' ),
+ new XmlJsCode(
+ 'function () {' . Xml::encodeJsCall( 'mw.loader.load', array( $modules ) ) . '}'
+ )
+ ) )
) );
}
// Load module script only
array(
array( 'test.foo', ResourceLoaderModule::TYPE_SCRIPTS ),
- '<script>if(window.mw){
-document.write("\u003Cscript src=\"http://127.0.0.1:8080/w/load.php?debug=false\u0026amp;lang=en\u0026amp;modules=test.foo\u0026amp;only=scripts\u0026amp;skin=fallback\u0026amp;*\"\u003E\u003C/script\u003E");
-}</script>
+ '<script>var _mwq = _mwq || []; _mwq.push( function ( mw ) {' .
+ ' document.write("\u003Cscript src=\"http://127.0.0.1:8080/w/load.php?debug=' .
+ 'false\u0026amp;lang=en\u0026amp;modules=test.foo\u0026amp;only=scripts\u0026' .
+ 'amp;skin=fallback\u0026amp;*\"\u003E\u003C/script\u003E"); } );</script>
'
),
array(
// Don't condition wrap raw modules (like the startup module)
array( 'test.raw', ResourceLoaderModule::TYPE_SCRIPTS ),
- '<script src="http://127.0.0.1:8080/w/load.php?debug=false&lang=en&modules=test.raw&only=scripts&skin=fallback&*"></script>
+ '<script src="http://127.0.0.1:8080/w/load.php?debug=false&lang=en&' .
+ 'modules=test.raw&only=scripts&skin=fallback&*"></script>
'
),
// Load module styles only
// This also tests the order the modules are put into the url
array(
array( array( 'test.baz', 'test.foo', 'test.bar' ), ResourceLoaderModule::TYPE_STYLES ),
- '<link rel=stylesheet href="http://127.0.0.1:8080/w/load.php?debug=false&lang=en&modules=test.bar%2Cbaz%2Cfoo&only=styles&skin=fallback&*">
+ '<link rel=stylesheet href="http://127.0.0.1:8080/w/load.php?debug=false&' .
+ 'lang=en&modules=test.bar%2Cbaz%2Cfoo&only=styles&skin=fallback&*">
'
),
// Load private module (only=scripts)
array(
array( 'test.quux', ResourceLoaderModule::TYPE_SCRIPTS ),
- '<script>if(window.mw){
-mw.test.baz({token:123});mw.loader.state({"test.quux":"ready"});
-
-}</script>
+ '<script>var _mwq = _mwq || []; _mwq.push( function ( mw ) {' .
+ ' mw.test.baz({token:123});mw.loader.state({"test.quux":"ready"});
+' . ' } );</script>
'
),
// Load private module (combined)
array(
array( 'test.quux', ResourceLoaderModule::TYPE_COMBINED ),
- '<script>if(window.mw){
-mw.loader.implement("test.quux",function($,jQuery){mw.test.baz({token:123});},{"css":[".mw-icon{transition:none}\n"]},{},{});
-
-}</script>
+ '<script>var _mwq = _mwq || []; _mwq.push( function ( mw ) {' .
+ ' mw.loader.implement("test.quux",function($,jQuery){mw.test.baz({token:123});}' .
+ ',{"css":[".mw-icon{transition:none}\n"]},{},{});
+' . ' } );</script>
'
),
// Load module script with ESI
array(
array( 'test.foo', ResourceLoaderModule::TYPE_SCRIPTS, true ),
- '<script><esi:include src="http://127.0.0.1:8080/w/load.php?debug=false&lang=en&modules=test.foo&only=scripts&skin=fallback&*" /></script>
+ '<script><esi:include src="http://127.0.0.1:8080/w/load.php?debug=false&' .
+ 'lang=en&modules=test.foo&only=scripts&skin=fallback&*" /></script>
'
),
// Load module styles with ESI
array(
array( 'test.foo', ResourceLoaderModule::TYPE_STYLES, true ),
- '<style><esi:include src="http://127.0.0.1:8080/w/load.php?debug=false&lang=en&modules=test.foo&only=styles&skin=fallback&*" /></style>
+ '<style><esi:include src="http://127.0.0.1:8080/w/load.php?debug=false&' .
+ 'lang=en&modules=test.foo&only=styles&skin=fallback&*" /></style>
',
),
// Load no modules
// noscript group
array(
array( 'test.noscript', ResourceLoaderModule::TYPE_STYLES ),
- '<noscript><link rel=stylesheet href="http://127.0.0.1:8080/w/load.php?debug=false&lang=en&modules=test.noscript&only=styles&skin=fallback&*"></noscript>
+ '<noscript><link rel=stylesheet href="http://127.0.0.1:8080/w/load.php?debug=' .
+ 'false&lang=en&modules=test.noscript&only=styles&skin=fallback' .
+ '&*"></noscript>
'
),
// Load two modules in separate groups
array(
array( array( 'test.group.foo', 'test.group.bar' ), ResourceLoaderModule::TYPE_COMBINED ),
- '<script>if(window.mw){
-document.write("\u003Cscript src=\"http://127.0.0.1:8080/w/load.php?debug=false\u0026amp;lang=en\u0026amp;modules=test.group.bar\u0026amp;skin=fallback\u0026amp;*\"\u003E\u003C/script\u003E");
-}</script>
-<script>if(window.mw){
-document.write("\u003Cscript src=\"http://127.0.0.1:8080/w/load.php?debug=false\u0026amp;lang=en\u0026amp;modules=test.group.foo\u0026amp;skin=fallback\u0026amp;*\"\u003E\u003C/script\u003E");
-}</script>
+ '<script>var _mwq = _mwq || []; _mwq.push( function ( mw ) { ' .
+ 'document.write("\u003Cscript src=\"http://127.0.0.1:8080/w/load.php?debug=false' .
+ '\u0026amp;lang=en\u0026amp;modules=test.group.bar\u0026amp;skin=fallback\u0026' .
+ 'amp;*\"\u003E\u003C/script\u003E"); } );</script>
+<script>var _mwq = _mwq || []; _mwq.push( function ( mw ) { document.write(' .
+ '"\u003Cscript src=\"http://127.0.0.1:8080/w/load.php?debug=false\u0026amp;' .
+ 'lang=en\u0026amp;modules=test.group.foo\u0026amp;skin=fallback\u0026amp;*\\' .
+ '"\u003E\u003C/script\u003E"); } );</script>
'
),
);