Merge "Add helper trait for deprecating properties"
[lhc/web/wiklou.git] / includes / resourceloader / ResourceLoaderStartUpModule.php
index 2e3c6fc..a4fd712 100644 (file)
  * the ability to vary based extra query parameters, in addition to those
  * from ResourceLoaderContext:
  *
- * - target: Only register modules in the client allowed within this target.
+ * - target: Only register modules in the client intended for this target.
  *   Default: "desktop".
  *   See also: OutputPage::setTarget(), ResourceLoaderModule::getTargets().
+ *
+ * - safemode: Only register modules that have ORIGIN_CORE as their origin.
+ *   This effectively disables ORIGIN_USER modules. (T185303)
+ *   See also: OutputPage::disallowUserJs()
  */
 class ResourceLoaderStartUpModule extends ResourceLoaderModule {
 
@@ -171,10 +175,10 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
         * Optimize the dependency tree in $this->modules.
         *
         * The optimization basically works like this:
-        *      Given we have module A with the dependencies B and C
-        *              and module B with the dependency C.
-        *      Now we don't have to tell the client to explicitly fetch module
-        *              C as that's already included in module B.
+        *      Given we have module A with the dependencies B and C
+        *              and module B with the dependency C.
+        *      Now we don't have to tell the client to explicitly fetch module
+        *              C as that's already included in module B.
         *
         * This way we can reasonably reduce the amount of module registration
         * data send to the client.
@@ -208,6 +212,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                // Future developers: Use WebRequest::getRawVal() instead getVal().
                // The getVal() method performs slow Language+UTF logic. (f303bb9360)
                $target = $context->getRequest()->getRawVal( 'target', 'desktop' );
+               $safemode = $context->getRequest()->getRawVal( 'safemode' ) === '1';
                // 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';
@@ -220,7 +225,10 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                foreach ( $resourceLoader->getModuleNames() as $name ) {
                        $module = $resourceLoader->getModule( $name );
                        $moduleTargets = $module->getTargets();
-                       if ( !$byPassTargetFilter && !in_array( $target, $moduleTargets ) ) {
+                       if (
+                               ( !$byPassTargetFilter && !in_array( $target, $moduleTargets ) )
+                               || ( $safemode && $module->getOrigin() > ResourceLoaderModule::ORIGIN_CORE_INDIVIDUAL )
+                       ) {
                                continue;
                        }
 
@@ -316,48 +324,64 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
         * @return array
         */
        public function getPreloadLinks( ResourceLoaderContext $context ) {
-               $url = self::getStartupModulesUrl( $context );
+               $url = $this->getBaseModulesUrl( $context );
                return [
                        $url => [ 'as' => 'script' ]
                ];
        }
 
        /**
-        * Base modules required for the base environment of ResourceLoader
+        * Internal modules used by ResourceLoader that cannot be depended on.
+        *
+        * These module(s) should have isRaw() return true, and are not
+        * legal dependencies (enforced by structure/ResourcesTest).
         *
+        * @deprecated since 1.32 No longer used.
         * @return array
         */
        public static function getStartupModules() {
-               return [ 'jquery', 'mediawiki' ];
+               wfDeprecated( __METHOD__, '1.32' );
+               return [];
        }
 
+       /**
+        * @deprecated since 1.32 No longer used.
+        * @return array
+        */
        public static function getLegacyModules() {
+               wfDeprecated( __METHOD__, '1.32' );
+               return [];
+       }
+
+       /**
+        * Base modules implicitly available to all modules.
+        *
+        * @since 1.32
+        * @return array
+        */
+       private function getBaseModules() {
                global $wgIncludeLegacyJavaScript;
 
-               $legacyModules = [];
+               $baseModules = [ 'jquery', 'mediawiki.base' ];
                if ( $wgIncludeLegacyJavaScript ) {
-                       $legacyModules[] = 'mediawiki.legacy.wikibits';
+                       $baseModules[] = 'mediawiki.legacy.wikibits';
                }
 
-               return $legacyModules;
+               return $baseModules;
        }
 
        /**
         * Get the load URL of the startup modules.
         *
-        * This is a helper for getScript(), but can also be called standalone, such
-        * as when generating an AppCache manifest.
+        * This is a helper for getScript().
         *
         * @param ResourceLoaderContext $context
         * @return string
         */
-       public static function getStartupModulesUrl( ResourceLoaderContext $context ) {
+       private function getBaseModulesUrl( ResourceLoaderContext $context ) {
                $rl = $context->getResourceLoader();
                $derivative = new DerivativeResourceLoaderContext( $context );
-               $derivative->setModules( array_merge(
-                       self::getStartupModules(),
-                       self::getLegacyModules()
-               ) );
+               $derivative->setModules( $this->getBaseModules() );
                $derivative->setOnly( 'scripts' );
                // Must setModules() before makeVersionQuery()
                $derivative->setVersion( $rl->makeVersionQuery( $derivative ) );
@@ -375,7 +399,15 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                        return '/* Requires only=script */';
                }
 
-               $out = file_get_contents( "$IP/resources/src/startup.js" );
+               $out = file_get_contents( "$IP/resources/src/startup/startup.js" );
+
+               // Keep in sync with maintenance/jsduck/eg-iframe.html and,
+               // keep in sync with 'fileHashes' in StartUpModule::getDefinitionSummary().
+               $mwLoaderCode = file_get_contents( "$IP/resources/src/startup/mediawiki.js" ) .
+                       file_get_contents( "$IP/resources/src/startup/mediawiki.requestIdleCallback.js" );
+               if ( $context->getDebug() ) {
+                       $mwLoaderCode .= file_get_contents( "$IP/resources/src/startup/mediawiki.log.js" );
+               }
 
                $pairs = array_map( function ( $value ) {
                        $value = FormatJson::encode( $value, ResourceLoader::inDebugMode(), FormatJson::ALL_OK );
@@ -386,13 +418,14 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                        '$VARS.wgLegacyJavaScriptGlobals' => $this->getConfig()->get( 'LegacyJavaScriptGlobals' ),
                        '$VARS.configuration' => $this->getConfigSettings( $context ),
                        // This url may be preloaded. See getPreloadLinks().
-                       '$VARS.baseModulesUri' => self::getStartupModulesUrl( $context ),
+                       '$VARS.baseModulesUri' => $this->getBaseModulesUrl( $context ),
                ] );
-               $pairs['$CODE.registrations()'] = str_replace(
+               $pairs['$CODE.registrations();'] = str_replace(
                        "\n",
                        "\n\t",
                        trim( $this->getModuleRegistrations( $context ) )
                );
+               $pairs['$CODE.defineLoader();'] = $mwLoaderCode;
 
                return strtr( $out, $pairs );
        }
@@ -421,8 +454,10 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                        // Detect changes to the module registrations
                        'moduleHashes' => $this->getAllModuleHashes( $context ),
 
-                       'fileMtimes' => [
-                               filemtime( "$IP/resources/src/startup.js" ),
+                       '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;