diff --git a/includes/resourceloader/ResourceLoaderModule.php b/includes/resourceloader/ResourceLoaderModule.php index 0db870ead52..e3b0ce189e6 100644 --- a/includes/resourceloader/ResourceLoaderModule.php +++ b/includes/resourceloader/ResourceLoaderModule.php @@ -56,6 +56,8 @@ abstract class ResourceLoaderModule implements LoggerAwareInterface { protected $name = null; /** @var string[] What client platforms the module targets (e.g. desktop, mobile) */ protected $targets = [ 'desktop' ]; + /** @var string[]|null Skin names */ + protected $skins = null; /** @var array Map of (variant => indirect file dependencies) */ protected $fileDeps = []; @@ -459,6 +461,22 @@ abstract class ResourceLoaderModule implements LoggerAwareInterface { return $this->targets; } + /** + * Get list of skins for which this module must be available to load. + * + * By default, modules are available to all skins. + * + * This information may be used by the startup module to optimise registrations + * based on the current skin. + * + * @stable to override + * @since 1.39 + * @return string[]|null + */ + public function getSkins(): ?array { + return $this->skins; + } + /** * Get the module's load type. * diff --git a/includes/resourceloader/ResourceLoaderStartUpModule.php b/includes/resourceloader/ResourceLoaderStartUpModule.php index ae48cfaa94b..a5c064446e1 100644 --- a/includes/resourceloader/ResourceLoaderStartUpModule.php +++ b/includes/resourceloader/ResourceLoaderStartUpModule.php @@ -157,6 +157,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule { // The getVal() method performs slow Language+UTF logic. (f303bb9360) $target = $context->getRequest()->getRawVal( 'target', 'desktop' ); $safemode = $context->getRequest()->getRawVal( 'safemode' ) === '1'; + $skin = $context->getSkin(); // Bypass target filter if this request is Special:JavaScriptTest. // To prevent misuse in production, this is only allowed if testing is enabled server-side. $byPassTargetFilter = $this->getConfig()->get( 'EnableJavaScriptTest' ) && $target === 'test'; @@ -185,9 +186,11 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule { foreach ( $moduleNames as $name ) { $module = $resourceLoader->getModule( $name ); $moduleTargets = $module->getTargets(); + $moduleSkins = $module->getSkins(); if ( ( !$byPassTargetFilter && !in_array( $target, $moduleTargets ) ) || ( $safemode && $module->getOrigin() > ResourceLoaderModule::ORIGIN_CORE_INDIVIDUAL ) + || ( $moduleSkins !== null && !in_array( $skin, $moduleSkins ) ) ) { continue; } diff --git a/tests/phpunit/includes/resourceloader/ResourceLoaderStartUpModuleTest.php b/tests/phpunit/includes/resourceloader/ResourceLoaderStartUpModuleTest.php index c36fbae3ccb..bf9ce370d9a 100644 --- a/tests/phpunit/includes/resourceloader/ResourceLoaderStartUpModuleTest.php +++ b/tests/phpunit/includes/resourceloader/ResourceLoaderStartUpModuleTest.php @@ -280,6 +280,34 @@ mw.loader.register([ "test.blank", "" ] +]);' + ] ], + [ [ + 'msg' => 'Different skin (irrelevant skin modules should not be registered)', + 'modules' => [ + 'test.blank' => [ 'class' => ResourceLoaderTestModule::class ], + 'test.skin.fallback' => [ + 'class' => ResourceLoaderTestModule::class, + 'skins' => [ 'fallback' ], + ], + 'test.skin.foo' => [ + 'class' => ResourceLoaderTestModule::class, + 'skins' => [ 'foo' ], + ], + ], + 'out' => ' +mw.loader.addSource({ + "local": "/w/load.php" +}); +mw.loader.register([ + [ + "test.blank", + "" + ], + [ + "test.skin.fallback", + "" + ] ]);' ] ], [ [