Merge "resourceloader: Support TestModules registration via extension.json"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Wed, 6 Feb 2019 00:17:03 +0000 (00:17 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Wed, 6 Feb 2019 00:17:03 +0000 (00:17 +0000)
1  2 
RELEASE-NOTES-1.33
includes/resourceloader/ResourceLoader.php

diff --combined RELEASE-NOTES-1.33
@@@ -42,8 -42,6 +42,8 @@@ production
    additional information about the authentication event.
  * TextContent::getText() was introduced as a replacement for
    Content::getNativeData() for text-based content models.
 +* (T210814) SVGs are now by default displayed in wiki language on image
 +  pages.
  
  === External library changes in 1.33 ===
  
@@@ -224,6 -222,9 +224,9 @@@ because of Phabricator reports
  * Password::equals() is deprecated, use verify().
  * BaseTemplate::msgWiki() and QuickTemplate::msgWiki() will be removed. Use
    other means to fetch a properly escaped message string or Message object.
+ * (T126091) The 'ResourceLoaderTestModules' hook, which lets you declare QUnit
+   testing code for your JavaScript modules, is deprecated. Instead, you can now
+   use the new extension registration key 'QUnitTestModule'.
  
  === Other changes in 1.33 ===
  * (T208871) The hard-coded Google search form on the database error page was
@@@ -408,24 -408,24 +408,24 @@@ class ResourceLoader implements LoggerA
                                . 'Edit your <code>LocalSettings.php</code> to enable it.' );
                }
  
-               // Get core test suites
-               $testModules = [];
-               $testModules['qunit'] = [];
-               // Get other test suites (e.g. from extensions)
+               $testModules = [
+                       'qunit' => [],
+               ];
+               // Get test suites from extensions
                // Avoid PHP 7.1 warning from passing $this by reference
                $rl = $this;
                Hooks::run( 'ResourceLoaderTestModules', [ &$testModules, &$rl ] );
+               $extRegistry = ExtensionRegistry::getInstance();
+               // In case of conflict, the deprecated hook has precedence.
+               $testModules['qunit'] += $extRegistry->getAttribute( 'QUnitTestModules' );
  
-               // Add the testrunner (which configures QUnit) to the dependencies.
-               // Since it must be ready before any of the test suites are executed.
+               // Add the QUnit testrunner as implicit dependency to extension test suites.
                foreach ( $testModules['qunit'] as &$module ) {
-                       // Make sure all test modules are top-loading so that when QUnit starts
-                       // on document-ready, it will run once and finish. If some tests arrive
-                       // later (possibly after QUnit has already finished) they will be ignored.
-                       $module['position'] = 'top';
                        $module['dependencies'][] = 'test.mediawiki.qunit.testrunner';
                }
  
+               // Get core test suites
                $testModules['qunit'] =
                        ( include "$IP/tests/qunit/QUnitTestResources.php" ) + $testModules['qunit'];
  
@@@ -1081,7 -1081,7 +1081,7 @@@ MESSAGE
                                                        // Load scripts raw...
                                                        $strContent = $scripts;
                                                } elseif ( is_array( $scripts ) ) {
 -                                                      // ...except when $scripts is an array of URLs
 +                                                      // ...except when $scripts is an array of URLs or an associative array
                                                        $strContent = self::makeLoaderImplementScript( $implementKey, $scripts, [], [], [] );
                                                }
                                                break;
         *
         * @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, or a string of JavaScript for `$.globalEval`.
 +       *  list of URLs to JavaScript files, string of JavaScript for `$.globalEval`, or array with
 +       *  'files' and 'main' properties (see ResourceLoaderModule::getScript())
         * @param mixed $styles Array of CSS strings keyed by media type, or an array of lists of URLs
         *   to CSS files keyed by media type
         * @param mixed $messages List of messages associated with this module. May either be an
                        } else {
                                $scripts = new XmlJsCode( 'function($,jQuery,require,module){' . $scripts->value . '}' );
                        }
 +              } elseif ( is_array( $scripts ) && isset( $scripts['files'] ) ) {
 +                      $files = $scripts['files'];
 +                      foreach ( $files as $path => &$file ) {
 +                              // $file is changed (by reference) from a descriptor array to the content of the file
 +                              // 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() ) {
 +                                              $file = new XmlJsCode( "function ( require, module ) {\n{$file['content']}\n}" );
 +                                      } else {
 +                                              $file = new XmlJsCode( 'function(require,module){' . $file['content'] . '}' );
 +                                      }
 +                              } else {
 +                                      $file = $file['content'];
 +                              }
 +                      }
 +                      $scripts = XmlJsCode::encodeObject( [
 +                              'main' => $scripts['main'],
 +                              'files' => XmlJsCode::encodeObject( $files, self::inDebugMode() )
 +                      ], self::inDebugMode() );
                } elseif ( !is_string( $scripts ) && !is_array( $scripts ) ) {
                        throw new MWException( 'Invalid scripts error. Array of URLs or string of code expected.' );
                }
 +
                // mw.loader.implement requires 'styles', 'messages' and 'templates' to be objects (not
                // arrays). json_encode considers empty arrays to be numerical and outputs "[]" instead
                // of "{}". Force them to objects.
                        $scripts,
                        (object)$styles,
                        (object)$messages,
 -                      (object)$templates,
 +                      (object)$templates
                ];
                self::trimArray( $module );