From: Fomafix Date: Mon, 9 Sep 2019 15:50:13 +0000 (+0200) Subject: resourceloader: Add $context to static functions in ResourceLoader X-Git-Tag: 1.34.0-rc.0~67^2 X-Git-Url: http://git.cyclocoop.org/?a=commitdiff_plain;h=2fc229116d6b040667b6f8592c48a8527abf2673;p=lhc%2Fweb%2Fwiklou.git resourceloader: Add $context to static functions in ResourceLoader This change allows to use the context in the functions. The following internal static functions from ResourceLoader get now a reference to the ResourceLoaderContext object: * makeLoaderImplementScript * makeLoaderStateScript * makeLoaderRegisterScript * makeLoaderSourcesScript ResouceLoader::encodeJsonForScript is duplicated to ResourceLoaderContext::encodeJson loading the debug mode from context. ResourceLoader::encodeJsonForScript is kept for other usages without context. The debug mode is loaded from $context->getDebug() instead of from ResourceLoader::inDebugMode(). This does not support to enable the debug mode by setting the cookie 'resourceLoaderDebug' or the configuration variable wgResourceLoaderDebug. Only the URL parameter debug=true enables the debug mode. This should be sufficient for the subsequent ResourceLoader requests. The tests don't need the global variable wgResourceLoaderDebug anymore. The initial ResourceLoader context in OutputPage still uses ResourceLoader::inDebugMode() with cookie and global configuration variable. This change adds the parameter $context with a ResourceLoaderContext object to ResourceLoaderModule::getDeprecationInformation and deprecates omitting the parameter. Ifa1a3bb56b731b83864022a358916c6aca5d7c10 updates this in extension ExtJSBase. Bug: T229311 Change-Id: I5341f18625209446a6d006f60244990f65530319 --- diff --git a/includes/resourceloader/ResourceLoader.php b/includes/resourceloader/ResourceLoader.php index 6121bbf304..563b95e94f 100644 --- a/includes/resourceloader/ResourceLoader.php +++ b/includes/resourceloader/ResourceLoader.php @@ -813,7 +813,7 @@ class ResourceLoader implements LoggerAwareInterface { $errorResponse = self::makeComment( $errorText ); if ( $context->shouldIncludeScripts() ) { $errorResponse .= 'if (window.console && console.error) { console.error(' - . self::encodeJsonForScript( $errorText ) + . $context->encodeJson( $errorText ) . "); }\n"; } @@ -1087,7 +1087,14 @@ MESSAGE; $strContent = $scripts; } elseif ( is_array( $scripts ) ) { // ...except when $scripts is an array of URLs or an associative array - $strContent = self::makeLoaderImplementScript( $implementKey, $scripts, [], [], [] ); + $strContent = self::makeLoaderImplementScript( + $context, + $implementKey, + $scripts, + [], + [], + [] + ); } break; case 'styles': @@ -1113,6 +1120,7 @@ MESSAGE; } } $strContent = self::makeLoaderImplementScript( + $context, $implementKey, $scripts, $content['styles'] ?? [], @@ -1158,7 +1166,7 @@ MESSAGE; // Set the state of modules we didn't respond to with mw.loader.implement if ( $states ) { - $stateScript = self::makeLoaderStateScript( $states ); + $stateScript = self::makeLoaderStateScript( $context, $states ); if ( !$context->getDebug() ) { $stateScript = self::filter( 'minify-js', $stateScript ); } @@ -1167,7 +1175,7 @@ MESSAGE; } } elseif ( $states ) { $this->errors[] = 'Problematic modules: ' - . self::encodeJsonForScript( $states ); + . $context->encodeJson( $states ); } return $out; @@ -1206,6 +1214,7 @@ MESSAGE; /** * Return JS code that calls mw.loader.implement with given module properties. * + * @param ResourceLoaderContext $context * @param string $name Module name or implement key (format "`[name]@[version]`") * @param XmlJsCode|array|string $scripts Code as XmlJsCode (to be wrapped in a closure), * list of URLs to JavaScript files, string of JavaScript for `$.globalEval`, or array with @@ -1220,13 +1229,13 @@ MESSAGE; * @throws MWException * @return string JavaScript code */ - protected static function makeLoaderImplementScript( - $name, $scripts, $styles, $messages, $templates + private static function makeLoaderImplementScript( + ResourceLoaderContext $context, $name, $scripts, $styles, $messages, $templates ) { if ( $scripts instanceof XmlJsCode ) { if ( $scripts->value === '' ) { $scripts = null; - } elseif ( self::inDebugMode() ) { + } elseif ( $context->getDebug() ) { $scripts = new XmlJsCode( "function ( $, jQuery, require, module ) {\n{$scripts->value}\n}" ); } else { $scripts = new XmlJsCode( 'function($,jQuery,require,module){' . $scripts->value . '}' ); @@ -1238,7 +1247,7 @@ MESSAGE; // All of these essentially do $file = $file['content'];, some just have wrapping around it if ( $file['type'] === 'script' ) { // Multi-file modules only get two parameters ($ and jQuery are being phased out) - if ( self::inDebugMode() ) { + if ( $context->getDebug() ) { $file = new XmlJsCode( "function ( require, module ) {\n{$file['content']}\n}" ); } else { $file = new XmlJsCode( 'function(require,module){' . $file['content'] . '}' ); @@ -1249,8 +1258,8 @@ MESSAGE; } $scripts = XmlJsCode::encodeObject( [ 'main' => $scripts['main'], - 'files' => XmlJsCode::encodeObject( $files, self::inDebugMode() ) - ], self::inDebugMode() ); + 'files' => XmlJsCode::encodeObject( $files, $context->getDebug() ) + ], $context->getDebug() ); } elseif ( !is_string( $scripts ) && !is_array( $scripts ) ) { throw new MWException( 'Invalid scripts error. Array of URLs or string of code expected.' ); } @@ -1267,7 +1276,7 @@ MESSAGE; ]; self::trimArray( $module ); - return Xml::encodeJsCall( 'mw.loader.implement', $module, self::inDebugMode() ); + return Xml::encodeJsCall( 'mw.loader.implement', $module, $context->getDebug() ); } /** @@ -1349,22 +1358,26 @@ MESSAGE; * Returns a JS call to mw.loader.state, which sets the state of one * ore more modules to a given value. Has two calling conventions: * - * - ResourceLoader::makeLoaderStateScript( $name, $state ): + * - ResourceLoader::makeLoaderStateScript( $context, $name, $state ): * Set the state of a single module called $name to $state * - * - ResourceLoader::makeLoaderStateScript( [ $name => $state, ... ] ): + * - ResourceLoader::makeLoaderStateScript( $context, [ $name => $state, ... ] ): * Set the state of modules with the given names to the given states * + * @internal + * @param ResourceLoaderContext $context * @param array|string $states * @param string|null $state * @return string JavaScript code */ - public static function makeLoaderStateScript( $states, $state = null ) { + public static function makeLoaderStateScript( + ResourceLoaderContext $context, $states, $state = null + ) { if ( !is_array( $states ) ) { $states = [ $states => $state ]; } return 'mw.loader.state(' - . self::encodeJsonForScript( $states ) + . $context->encodeJson( $states ) . ');'; } @@ -1409,15 +1422,15 @@ MESSAGE; * @par Example * @code * - * ResourceLoader::makeLoaderRegisterScript( [ + * ResourceLoader::makeLoaderRegisterScript( $context, [ * [ $name1, $version1, $dependencies1, $group1, $source1, $skip1 ], * [ $name2, $version2, $dependencies1, $group2, $source2, $skip2 ], * ... * ] ): * @endcode * - * @internal - * @since 1.32 + * @internal For use by ResourceLoaderStartUpModule only + * @param ResourceLoaderContext $context * @param array $modules Array of module registration arrays, each containing * - string: module name * - string: module version @@ -1427,7 +1440,9 @@ MESSAGE; * - string|null: Script body of a skip function (optional) * @return string JavaScript code */ - public static function makeLoaderRegisterScript( array $modules ) { + public static function makeLoaderRegisterScript( + ResourceLoaderContext $context, array $modules + ) { // Optimisation: Transform dependency names into indexes when possible // to produce smaller output. They are expanded by mw.loader.register on // the other end using resolveIndexedDependencies(). @@ -1450,7 +1465,7 @@ MESSAGE; array_walk( $modules, [ self::class, 'trimArray' ] ); return 'mw.loader.register(' - . self::encodeJsonForScript( $modules ) + . $context->encodeJson( $modules ) . ');'; } @@ -1458,22 +1473,28 @@ MESSAGE; * Returns JS code which calls mw.loader.addSource() with the given * parameters. Has two calling conventions: * - * - ResourceLoader::makeLoaderSourcesScript( $id, $properties ): + * - ResourceLoader::makeLoaderSourcesScript( $context, $id, $properties ): * Register a single source * - * - ResourceLoader::makeLoaderSourcesScript( [ $id1 => $loadUrl, $id2 => $loadUrl, ... ] ); + * - ResourceLoader::makeLoaderSourcesScript( $context, + * [ $id1 => $loadUrl, $id2 => $loadUrl, ... ] + * ); * Register sources with the given IDs and properties. * + * @internal For use by ResourceLoaderStartUpModule only + * @param ResourceLoaderContext $context * @param string|array $sources Source ID * @param string|null $loadUrl load.php url * @return string JavaScript code */ - public static function makeLoaderSourcesScript( $sources, $loadUrl = null ) { + public static function makeLoaderSourcesScript( + ResourceLoaderContext $context, $sources, $loadUrl = null + ) { if ( !is_array( $sources ) ) { $sources = [ $sources => $loadUrl ]; } return 'mw.loader.addSource(' - . self::encodeJsonForScript( $sources ) + . $context->encodeJson( $sources ) . ');'; } diff --git a/includes/resourceloader/ResourceLoaderClientHtml.php b/includes/resourceloader/ResourceLoaderClientHtml.php index ea35de6bea..b38d722d0b 100644 --- a/includes/resourceloader/ResourceLoaderClientHtml.php +++ b/includes/resourceloader/ResourceLoaderClientHtml.php @@ -212,7 +212,7 @@ class ResourceLoaderClientHtml { // Load from load.php?only=styles via $data['styles'][] = $name; } - $deprecation = $module->getDeprecationInformation(); + $deprecation = $module->getDeprecationInformation( $context ); if ( $deprecation ) { $data['styleDeprecations'][] = $deprecation; } @@ -253,14 +253,14 @@ class ResourceLoaderClientHtml { // See also startup/startup.js. $nojsClass = $nojsClass ?? $this->getDocumentAttributes()['class']; $jsClass = preg_replace( '/(^|\s)client-nojs(\s|$)/', '$1client-js$2', $nojsClass ); - $jsClassJson = ResourceLoader::encodeJsonForScript( $jsClass ); + $jsClassJson = $this->context->encodeJson( $jsClass ); $script = <<config ) { - $confJson = ResourceLoader::encodeJsonForScript( $this->config ); + $confJson = $this->context->encodeJson( $this->config ); $script .= <<exemptStates, $data['states'] ); if ( $states ) { - $stateJson = ResourceLoader::encodeJsonForScript( $states ); + $stateJson = $this->context->encodeJson( $states ); $script .= <<context->encodeJson( $data['general'] ); $script .= <<encodeJson( $url ) . ');', $nonce ); } diff --git a/includes/resourceloader/ResourceLoaderContext.php b/includes/resourceloader/ResourceLoaderContext.php index 95b8ff0073..b9a76598bd 100644 --- a/includes/resourceloader/ResourceLoaderContext.php +++ b/includes/resourceloader/ResourceLoaderContext.php @@ -405,7 +405,7 @@ class ResourceLoaderContext implements MessageLocalizer { /** * Get the request base parameters, omitting any defaults. * - * @internal For internal use by ResourceLoaderStartUpModule only + * @internal For use by ResourceLoaderStartUpModule only * @return array */ public function getReqBase() { @@ -421,4 +421,32 @@ class ResourceLoaderContext implements MessageLocalizer { } return $reqBase; } + + /** + * Wrapper around json_encode that avoids needless escapes, + * and pretty-prints in debug mode. + * + * @internal + * @param mixed $data + * @return string|false JSON string, false on error + */ + public function encodeJson( $data ) { + // Keep output as small as possible by disabling needless escape modes + // that PHP uses by default. + // However, while most module scripts are only served on HTTP responses + // for JavaScript, some modules can also be embedded in the HTML as inline + // scripts. This, and the fact that we sometimes need to export strings + // containing user-generated content and labels that may genuinely contain + // a sequences like "", we need to encode either '/' or '<'. + // By default PHP escapes '/'. Let's escape '<' instead which is less common + // and allows URLs to mostly remain readable. + $jsonFlags = JSON_UNESCAPED_SLASHES | + JSON_UNESCAPED_UNICODE | + JSON_HEX_TAG | + JSON_HEX_AMP; + if ( $this->getDebug() ) { + $jsonFlags |= JSON_PRETTY_PRINT; + } + return json_encode( $data, $jsonFlags ); + } } diff --git a/includes/resourceloader/ResourceLoaderFileModule.php b/includes/resourceloader/ResourceLoaderFileModule.php index f2d0856c24..6c21e4b50b 100644 --- a/includes/resourceloader/ResourceLoaderFileModule.php +++ b/includes/resourceloader/ResourceLoaderFileModule.php @@ -383,7 +383,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule { * @return string|array JavaScript code for $context, or package files data structure */ public function getScript( ResourceLoaderContext $context ) { - $deprecationScript = $this->getDeprecationInformation(); + $deprecationScript = $this->getDeprecationInformation( $context ); if ( $this->packageFiles !== null ) { $packageFiles = $this->getPackageFiles( $context ); if ( $deprecationScript ) { diff --git a/includes/resourceloader/ResourceLoaderLanguageDataModule.php b/includes/resourceloader/ResourceLoaderLanguageDataModule.php index c0a0921e11..637d6d2524 100644 --- a/includes/resourceloader/ResourceLoaderLanguageDataModule.php +++ b/includes/resourceloader/ResourceLoaderLanguageDataModule.php @@ -54,8 +54,8 @@ class ResourceLoaderLanguageDataModule extends ResourceLoaderFileModule { public function getScript( ResourceLoaderContext $context ) { return parent::getScript( $context ) . 'mw.language.setData(' - . ResourceLoader::encodeJsonForScript( $context->getLanguage() ) . ',' - . ResourceLoader::encodeJsonForScript( $this->getData( $context ) ) + . $context->encodeJson( $context->getLanguage() ) . ',' + . $context->encodeJson( $this->getData( $context ) ) . ');'; } diff --git a/includes/resourceloader/ResourceLoaderModule.php b/includes/resourceloader/ResourceLoaderModule.php index ed2d09c8dc..38084bf43f 100644 --- a/includes/resourceloader/ResourceLoaderModule.php +++ b/includes/resourceloader/ResourceLoaderModule.php @@ -135,9 +135,13 @@ abstract class ResourceLoaderModule implements LoggerAwareInterface { /** * Get JS representing deprecation information for the current module if available * + * @param ResourceLoaderContext|null $context Missing $context is deprecated in 1.34 * @return string JavaScript code */ - public function getDeprecationInformation() { + public function getDeprecationInformation( ResourceLoaderContext $context = null ) { + if ( $context === null ) { + wfDeprecated( __METHOD__ . ' without a ResourceLoader context', '1.34' ); + } $deprecationInfo = $this->deprecated; if ( $deprecationInfo ) { $name = $this->getName(); @@ -145,7 +149,10 @@ abstract class ResourceLoaderModule implements LoggerAwareInterface { if ( is_string( $deprecationInfo ) ) { $warning .= "\n" . $deprecationInfo; } - return 'mw.log.warn(' . ResourceLoader::encodeJsonForScript( $warning ) . ');'; + if ( $context === null ) { + return 'mw.log.warn(' . ResourceLoader::encodeJsonForScript( $warning ) . ');'; + } + return 'mw.log.warn(' . $context->encodeJson( $warning ) . ');'; } else { return ''; } diff --git a/includes/resourceloader/ResourceLoaderStartUpModule.php b/includes/resourceloader/ResourceLoaderStartUpModule.php index 9f583a5933..3191057305 100644 --- a/includes/resourceloader/ResourceLoaderStartUpModule.php +++ b/includes/resourceloader/ResourceLoaderStartUpModule.php @@ -307,7 +307,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule { } $skipFunction = $module->getSkipFunction(); - if ( $skipFunction !== null && !ResourceLoader::inDebugMode() ) { + if ( $skipFunction !== null && !$context->getDebug() ) { $skipFunction = ResourceLoader::filter( 'minify-js', $skipFunction ); } @@ -323,7 +323,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule { self::compileUnresolvedDependencies( $registryData ); // Register sources - $out .= ResourceLoader::makeLoaderSourcesScript( $resourceLoader->getSources() ); + $out .= ResourceLoader::makeLoaderSourcesScript( $context, $resourceLoader->getSources() ); // Figure out the different call signatures for mw.loader.register $registrations = []; @@ -341,10 +341,10 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule { } // Register modules - $out .= "\n" . ResourceLoader::makeLoaderRegisterScript( $registrations ); + $out .= "\n" . ResourceLoader::makeLoaderRegisterScript( $context, $registrations ); if ( $states ) { - $out .= "\n" . ResourceLoader::makeLoaderStateScript( $states ); + $out .= "\n" . ResourceLoader::makeLoaderStateScript( $context, $states ); } return $out; @@ -423,23 +423,23 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule { // Perform replacements for mediawiki.js $mwLoaderPairs = [ - '$VARS.reqBase' => ResourceLoader::encodeJsonForScript( $context->getReqBase() ), - '$VARS.baseModules' => ResourceLoader::encodeJsonForScript( $this->getBaseModules() ), - '$VARS.maxQueryLength' => ResourceLoader::encodeJsonForScript( + '$VARS.reqBase' => $context->encodeJson( $context->getReqBase() ), + '$VARS.baseModules' => $context->encodeJson( $this->getBaseModules() ), + '$VARS.maxQueryLength' => $context->encodeJson( $conf->get( 'ResourceLoaderMaxQueryLength' ) ), // The client-side module cache can be disabled by site configuration. // It is also always disabled in debug mode. - '$VARS.storeEnabled' => ResourceLoader::encodeJsonForScript( + '$VARS.storeEnabled' => $context->encodeJson( $conf->get( 'ResourceLoaderStorageEnabled' ) && !$context->getDebug() ), - '$VARS.wgLegacyJavaScriptGlobals' => ResourceLoader::encodeJsonForScript( + '$VARS.wgLegacyJavaScriptGlobals' => $context->encodeJson( $conf->get( 'LegacyJavaScriptGlobals' ) ), - '$VARS.storeKey' => ResourceLoader::encodeJsonForScript( $this->getStoreKey() ), - '$VARS.storeVary' => ResourceLoader::encodeJsonForScript( $this->getStoreVary( $context ) ), - '$VARS.groupUser' => ResourceLoader::encodeJsonForScript( $this->getGroupId( 'user' ) ), - '$VARS.groupPrivate' => ResourceLoader::encodeJsonForScript( $this->getGroupId( 'private' ) ), + '$VARS.storeKey' => $context->encodeJson( $this->getStoreKey() ), + '$VARS.storeVary' => $context->encodeJson( $this->getStoreVary( $context ) ), + '$VARS.groupUser' => $context->encodeJson( $this->getGroupId( 'user' ) ), + '$VARS.groupPrivate' => $context->encodeJson( $this->getGroupId( 'private' ) ), ]; $profilerStubs = [ '$CODE.profileExecuteStart();' => 'mw.loader.profiler.onExecuteStart( module );', @@ -458,7 +458,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule { // Perform string replacements for startup.js $pairs = [ - '$VARS.configuration' => ResourceLoader::encodeJsonForScript( + '$VARS.configuration' => $context->encodeJson( $this->getConfigSettings( $context ) ), // Raw JavaScript code (not JSON) diff --git a/includes/resourceloader/ResourceLoaderUserDefaultsModule.php b/includes/resourceloader/ResourceLoaderUserDefaultsModule.php index 61cff822c9..de82502e0f 100644 --- a/includes/resourceloader/ResourceLoaderUserDefaultsModule.php +++ b/includes/resourceloader/ResourceLoaderUserDefaultsModule.php @@ -41,7 +41,7 @@ class ResourceLoaderUserDefaultsModule extends ResourceLoaderModule { */ public function getScript( ResourceLoaderContext $context ) { return 'mw.user.options.set(' - . ResourceLoader::encodeJsonForScript( User::getDefaultOptions() ) + . $context->encodeJson( User::getDefaultOptions() ) . ');'; } } diff --git a/includes/resourceloader/ResourceLoaderUserOptionsModule.php b/includes/resourceloader/ResourceLoaderUserOptionsModule.php index ecbb50193c..059a9b9db6 100644 --- a/includes/resourceloader/ResourceLoaderUserOptionsModule.php +++ b/includes/resourceloader/ResourceLoaderUserOptionsModule.php @@ -54,7 +54,7 @@ class ResourceLoaderUserOptionsModule extends ResourceLoaderModule { // Use FILTER_NOMIN annotation to prevent needless minification and caching (T84960). return ResourceLoader::FILTER_NOMIN . 'mw.user.options.set(' - . ResourceLoader::encodeJsonForScript( + . $context->encodeJson( $context->getUserObj()->getOptions( User::GETOPTIONS_EXCLUDE_DEFAULTS ) ) . ');'; diff --git a/includes/resourceloader/ResourceLoaderUserTokensModule.php b/includes/resourceloader/ResourceLoaderUserTokensModule.php index 85c14cb992..86012a0341 100644 --- a/includes/resourceloader/ResourceLoaderUserTokensModule.php +++ b/includes/resourceloader/ResourceLoaderUserTokensModule.php @@ -55,7 +55,7 @@ class ResourceLoaderUserTokensModule extends ResourceLoaderModule { // Use FILTER_NOMIN annotation to prevent needless minification and caching (T84960). return ResourceLoader::FILTER_NOMIN . 'mw.user.tokens.set(' - . ResourceLoader::encodeJsonForScript( $this->contextUserTokens( $context ) ) + . $context->encodeJson( $this->contextUserTokens( $context ) ) . ');'; } diff --git a/tests/phpunit/includes/resourceloader/ResourceLoaderStartUpModuleTest.php b/tests/phpunit/includes/resourceloader/ResourceLoaderStartUpModuleTest.php index 9bbf14d801..0c3512ada6 100644 --- a/tests/phpunit/includes/resourceloader/ResourceLoaderStartUpModuleTest.php +++ b/tests/phpunit/includes/resourceloader/ResourceLoaderStartUpModuleTest.php @@ -718,9 +718,9 @@ mw.loader.register([ * @dataProvider provideRegistrations */ public function testRegistrationsMinified( $modules ) { - $this->setMwGlobals( 'wgResourceLoaderDebug', false ); - - $context = $this->getResourceLoaderContext(); + $context = $this->getResourceLoaderContext( [ + 'debug' => 'false', + ] ); $rl = $context->getResourceLoader(); $rl->register( $modules ); $module = new ResourceLoaderStartUpModule(); @@ -743,7 +743,9 @@ mw.loader.register([ * @dataProvider provideRegistrations */ public function testRegistrationsUnminified( $modules ) { - $context = $this->getResourceLoaderContext(); + $context = $this->getResourceLoaderContext( [ + 'debug' => 'true', + ] ); $rl = $context->getResourceLoader(); $rl->register( $modules ); $module = new ResourceLoaderStartUpModule(); diff --git a/tests/phpunit/includes/resourceloader/ResourceLoaderTest.php b/tests/phpunit/includes/resourceloader/ResourceLoaderTest.php index 94e346139a..e728ad5788 100644 --- a/tests/phpunit/includes/resourceloader/ResourceLoaderTest.php +++ b/tests/phpunit/includes/resourceloader/ResourceLoaderTest.php @@ -518,13 +518,14 @@ END 'wrap' => true, 'styles' => [], 'templates' => [], 'messages' => new XmlJsCode( '{}' ), 'packageFiles' => [], ]; - ResourceLoader::clearCache(); - $this->setMwGlobals( 'wgResourceLoaderDebug', true ); - $rl = TestingAccessWrapper::newFromClass( ResourceLoader::class ); + $context = new ResourceLoaderContext( new EmptyResourceLoader(), new FauxRequest( [ + 'debug' => 'true', + ] ) ); $this->assertEquals( $case['expected'], $rl->makeLoaderImplementScript( + $context, $case['name'], ( $case['wrap'] && is_string( $case['scripts'] ) ) ? new XmlJsCode( $case['scripts'] ) @@ -543,7 +544,9 @@ END public function testMakeLoaderImplementScriptInvalid() { $this->setExpectedException( MWException::class, 'Invalid scripts error' ); $rl = TestingAccessWrapper::newFromClass( ResourceLoader::class ); + $context = new ResourceLoaderContext( new EmptyResourceLoader(), new FauxRequest() ); $rl->makeLoaderImplementScript( + $context, 'test', // name 123, // scripts null, // styles @@ -557,6 +560,9 @@ END * @covers ResourceLoader::makeLoaderRegisterScript */ public function testMakeLoaderRegisterScript() { + $context = new ResourceLoaderContext( new EmptyResourceLoader(), new FauxRequest( [ + 'debug' => 'true', + ] ) ); $this->assertEquals( 'mw.loader.register([ [ @@ -564,7 +570,7 @@ END "1234567" ] ]);', - ResourceLoader::makeLoaderRegisterScript( [ + ResourceLoader::makeLoaderRegisterScript( $context, [ [ 'test.name', '1234567' ], ] ), 'Nested array parameter' @@ -600,7 +606,7 @@ END "return true;" ] ]);', - ResourceLoader::makeLoaderRegisterScript( [ + ResourceLoader::makeLoaderRegisterScript( $context, [ [ 'test.foo', '100' , [], null, null ], [ 'test.bar', '200', [ 'test.unknown' ], null ], [ 'test.baz', '300', [ 'test.quux', 'test.foo' ], null ], @@ -614,31 +620,34 @@ END * @covers ResourceLoader::makeLoaderSourcesScript */ public function testMakeLoaderSourcesScript() { + $context = new ResourceLoaderContext( new EmptyResourceLoader(), new FauxRequest( [ + 'debug' => 'true', + ] ) ); $this->assertEquals( 'mw.loader.addSource({ "local": "/w/load.php" });', - ResourceLoader::makeLoaderSourcesScript( 'local', '/w/load.php' ) + ResourceLoader::makeLoaderSourcesScript( $context, 'local', '/w/load.php' ) ); $this->assertEquals( 'mw.loader.addSource({ "local": "/w/load.php" });', - ResourceLoader::makeLoaderSourcesScript( [ 'local' => '/w/load.php' ] ) + ResourceLoader::makeLoaderSourcesScript( $context, [ 'local' => '/w/load.php' ] ) ); $this->assertEquals( 'mw.loader.addSource({ "local": "/w/load.php", "example": "https://example.org/w/load.php" });', - ResourceLoader::makeLoaderSourcesScript( [ + ResourceLoader::makeLoaderSourcesScript( $context, [ 'local' => '/w/load.php', 'example' => 'https://example.org/w/load.php' ] ) ); $this->assertEquals( 'mw.loader.addSource([]);', - ResourceLoader::makeLoaderSourcesScript( [] ) + ResourceLoader::makeLoaderSourcesScript( $context, [] ) ); }