X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2Fresourceloader%2FResourceLoaderStartUpModule.php;h=acc2503d902ad396afb348af9b7a1801dc1e1245;hb=39a72e0804285f596c63f32a02a0a84861f8a277;hp=2457fe8c720432456ce062f0fb83629cfb7c9d49;hpb=bc6457b28d70641d366a554d8a82385b53a46fc9;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/resourceloader/ResourceLoaderStartUpModule.php b/includes/resourceloader/ResourceLoaderStartUpModule.php index 2457fe8c72..acc2503d90 100644 --- a/includes/resourceloader/ResourceLoaderStartUpModule.php +++ b/includes/resourceloader/ResourceLoaderStartUpModule.php @@ -40,21 +40,13 @@ use MediaWiki\MediaWikiServices; * See also: OutputPage::disallowUserJs() */ class ResourceLoaderStartUpModule extends ResourceLoaderModule { - - // Cache for getConfigSettings() as it's called by multiple methods - protected $configVars = []; protected $targets = [ 'desktop', 'mobile' ]; /** * @param ResourceLoaderContext $context * @return array */ - protected function getConfigSettings( $context ) { - $hash = $context->getHash(); - if ( isset( $this->configVars[$hash] ) ) { - return $this->configVars[$hash]; - } - + private function getConfigSettings( $context ) { $conf = $this->getConfig(); // We can't use Title::newMainPage() if 'mainpage' is in @@ -83,13 +75,13 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule { } $illegalFileChars = $conf->get( 'IllegalFileChars' ); - $oldCommentSchema = $conf->get( 'CommentTableSchemaMigrationStage' ) === MIGRATION_OLD; // Build list of variables + $skin = $context->getSkin(); $vars = [ 'wgLoadScript' => wfScript( 'load' ), 'debug' => $context->getDebug(), - 'skin' => $context->getSkin(), + 'skin' => $skin, 'stylepath' => $conf->get( 'StylePath' ), 'wgUrlProtocols' => wfUrlProtocols(), 'wgArticlePath' => $conf->get( 'ArticlePath' ), @@ -115,14 +107,12 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule { 'wgSiteName' => $conf->get( 'Sitename' ), 'wgDBname' => $conf->get( 'DBname' ), 'wgExtraSignatureNamespaces' => $conf->get( 'ExtraSignatureNamespaces' ), - 'wgAvailableSkins' => Skin::getSkinNames(), 'wgExtensionAssetsPath' => $conf->get( 'ExtensionAssetsPath' ), // MediaWiki sets cookies to have this prefix by default 'wgCookiePrefix' => $conf->get( 'CookiePrefix' ), 'wgCookieDomain' => $conf->get( 'CookieDomain' ), 'wgCookiePath' => $conf->get( 'CookiePath' ), 'wgCookieExpiration' => $conf->get( 'CookieExpiration' ), - 'wgResourceLoaderMaxQueryLength' => $conf->get( 'ResourceLoaderMaxQueryLength' ), 'wgCaseSensitiveNamespaces' => $caseSensitiveNamespaces, 'wgLegalTitleChars' => Title::convertByteClassToUnicodeClass( Title::legalChars() ), 'wgIllegalFileChars' => Title::convertByteClassToUnicodeClass( $illegalFileChars ), @@ -130,14 +120,13 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule { 'wgResourceLoaderStorageEnabled' => $conf->get( 'ResourceLoaderStorageEnabled' ), 'wgForeignUploadTargets' => $conf->get( 'ForeignUploadTargets' ), 'wgEnableUploads' => $conf->get( 'EnableUploads' ), - 'wgCommentByteLimit' => $oldCommentSchema ? 255 : null, - 'wgCommentCodePointLimit' => $oldCommentSchema ? null : CommentStore::COMMENT_CHARACTER_LIMIT, + 'wgCommentByteLimit' => null, + 'wgCommentCodePointLimit' => CommentStore::COMMENT_CHARACTER_LIMIT, ]; - Hooks::run( 'ResourceLoaderGetConfigVars', [ &$vars ] ); + Hooks::run( 'ResourceLoaderGetConfigVars', [ &$vars, $skin ] ); - $this->configVars[$hash] = $vars; - return $this->configVars[$hash]; + return $vars; } /** @@ -222,9 +211,23 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule { $out = ''; $states = []; $registryData = []; + $moduleNames = $resourceLoader->getModuleNames(); + + // Preload with a batch so that the below calls to getVersionHash() for each module + // don't require on-demand loading of more information. + try { + $resourceLoader->preloadModuleInfo( $moduleNames, $context ); + } catch ( Exception $e ) { + // Don't fail the request (T152266) + // Also print the error in the main output + $resourceLoader->outputErrorAndLog( $e, + 'Preloading module info from startup failed: {exception}', + [ 'exception' => $e ] + ); + } // Get registry data - foreach ( $resourceLoader->getModuleNames() as $name ) { + foreach ( $moduleNames as $name ) { $module = $resourceLoader->getModule( $name ); $moduleTargets = $module->getTargets(); if ( @@ -235,18 +238,25 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule { } if ( $module->isRaw() ) { - // Don't register "raw" modules (like 'jquery' and 'mediawiki') client-side because - // depending on them is illegal anyway and would only lead to them being reloaded - // causing any state to be lost (like jQuery plugins, mw.config etc.) + // Don't register "raw" modules (like 'startup') client-side because depending on them + // is illegal anyway and would only lead to them being loaded a second time, + // causing any state to be lost. + + // ATTENTION: Because of the line below, this is not going to cause infinite recursion. + // Think carefully before making changes to this code! + // The below code is going to call ResourceLoaderModule::getVersionHash() for every module. + // For StartUpModule (this module) the hash is computed based on the manifest content, + // which is the very thing we are computing right here. As such, this must skip iterating + // over 'startup' itself. continue; } try { $versionHash = $module->getVersionHash( $context ); } catch ( Exception $e ) { - // See also T152266 and ResourceLoader::getCombinedVersion() - MWExceptionHandler::logException( $e ); - $context->getLogger()->warning( + // Don't fail the request (T152266) + // Also print the error in the main output + $resourceLoader->outputErrorAndLog( $e, 'Calculating version for "{module}" failed: {exception}', [ 'module' => $name, @@ -375,6 +385,8 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule { */ public function getScript( ResourceLoaderContext $context ) { global $IP; + $conf = $this->getConfig(); + if ( $context->getOnly() !== 'scripts' ) { return '/* Requires only=script */'; } @@ -388,31 +400,44 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule { if ( $context->getDebug() ) { $mwLoaderCode .= file_get_contents( "$IP/resources/src/startup/mediawiki.log.js" ); } - - $mapToJson = function ( $value ) { - $value = FormatJson::encode( $value, ResourceLoader::inDebugMode(), FormatJson::ALL_OK ); - // Fix indentation - $value = str_replace( "\n", "\n\t", $value ); - return $value; - }; + if ( $conf->get( 'ResourceLoaderEnableJSProfiler' ) ) { + $mwLoaderCode .= file_get_contents( "$IP/resources/src/startup/profiler.js" ); + } // Perform replacements for mediawiki.js - $mwLoaderCode = strtr( $mwLoaderCode, [ - '$VARS.baseModules' => $mapToJson( $this->getBaseModules() ), - ] ); - - // Perform replacements for startup.js - $pairs = array_map( $mapToJson, [ - '$VARS.wgLegacyJavaScriptGlobals' => $this->getConfig()->get( 'LegacyJavaScriptGlobals' ), - '$VARS.configuration' => $this->getConfigSettings( $context ), - ] ); - // Raw JavaScript code (not for JSON) - $pairs['$CODE.registrations();'] = str_replace( - "\n", - "\n\t", - trim( $this->getModuleRegistrations( $context ) ) - ); - $pairs['$CODE.defineLoader();'] = $mwLoaderCode; + $mwLoaderPairs = [ + '$VARS.baseModules' => ResourceLoader::encodeJsonForScript( $this->getBaseModules() ), + '$VARS.maxQueryLength' => ResourceLoader::encodeJsonForScript( + $conf->get( 'ResourceLoaderMaxQueryLength' ) + ), + ]; + $profilerStubs = [ + '$CODE.profileExecuteStart();' => 'mw.loader.profiler.onExecuteStart( module );', + '$CODE.profileExecuteEnd();' => 'mw.loader.profiler.onExecuteEnd( module );', + '$CODE.profileScriptStart();' => 'mw.loader.profiler.onScriptStart( module );', + '$CODE.profileScriptEnd();' => 'mw.loader.profiler.onScriptEnd( module );', + ]; + if ( $conf->get( 'ResourceLoaderEnableJSProfiler' ) ) { + // When profiling is enabled, insert the calls. + $mwLoaderPairs += $profilerStubs; + } else { + // When disabled (by default), insert nothing. + $mwLoaderPairs += array_fill_keys( array_keys( $profilerStubs ), '' ); + } + $mwLoaderCode = strtr( $mwLoaderCode, $mwLoaderPairs ); + + // Perform string replacements for startup.js + $pairs = [ + '$VARS.wgLegacyJavaScriptGlobals' => ResourceLoader::encodeJsonForScript( + $conf->get( 'LegacyJavaScriptGlobals' ) + ), + '$VARS.configuration' => ResourceLoader::encodeJsonForScript( + $this->getConfigSettings( $context ) + ), + // Raw JavaScript code (not JSON) + '$CODE.registrations();' => trim( $this->getModuleRegistrations( $context ) ), + '$CODE.defineLoader();' => $mwLoaderCode, + ]; $startupCode = strtr( $startupCode, $pairs ); return $startupCode; @@ -426,50 +451,12 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule { } /** - * Get the definition summary for this module. - * - * @param ResourceLoaderContext $context - * @return array - */ - public function getDefinitionSummary( ResourceLoaderContext $context ) { - global $IP; - $summary = parent::getDefinitionSummary( $context ); - $summary[] = [ - // Detect changes to variables exposed in mw.config (T30899). - 'vars' => $this->getConfigSettings( $context ), - // Changes how getScript() creates mw.Map for mw.config - 'wgLegacyJavaScriptGlobals' => $this->getConfig()->get( 'LegacyJavaScriptGlobals' ), - // Detect changes to the module registrations - 'moduleHashes' => $this->getAllModuleHashes( $context ), - - 'fileHashes' => [ - $this->safeFileHash( "$IP/resources/src/startup/startup.js" ), - $this->safeFileHash( "$IP/resources/src/startup/mediawiki.js" ), - $this->safeFileHash( "$IP/resources/src/startup/mediawiki.requestIdleCallback.js" ), - ], - ]; - return $summary; - } - - /** - * Helper method for getDefinitionSummary(). - * - * @param ResourceLoaderContext $context - * @return string SHA-1 + * @return bool */ - protected function getAllModuleHashes( ResourceLoaderContext $context ) { - $rl = $context->getResourceLoader(); - // Preload for getCombinedVersion() - $rl->preloadModuleInfo( $rl->getModuleNames(), $context ); - - // ATTENTION: Because of the line below, this is not going to cause infinite recursion. - // Think carefully before making changes to this code! - // Pre-populate versionHash with something because the loop over all modules below includes - // the startup module (this module). - // See ResourceLoaderModule::getVersionHash() for usage of this cache. - $this->versionHash[$context->getHash()] = null; - - return $rl->getCombinedVersion( $context, $rl->getModuleNames() ); + public function enableModuleContentVersion() { + // Enabling this means that ResourceLoader::getVersionHash will simply call getScript() + // and hash it to determine the version (as used by E-Tag HTTP response header). + return true; } /**