Merge "resourceloader: Omit empty parameters from mw.loader.implement calls"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Mon, 6 Apr 2015 06:22:45 +0000 (06:22 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Mon, 6 Apr 2015 06:22:45 +0000 (06:22 +0000)
1  2 
includes/resourceloader/ResourceLoader.php
tests/phpunit/includes/OutputPageTest.php

@@@ -72,11 -72,6 +72,11 @@@ class ResourceLoader 
         */
        protected $errors = array();
  
 +      /**
 +       * @var MessageBlobStore
 +       */
 +      protected $blobStore;
 +
        /**
         * Load information stored in the database about modules.
         *
                        $this->registerTestModules();
                }
  
 +              $this->setMessageBlobStore( new MessageBlobStore() );
        }
  
        /**
                return $this->config;
        }
  
 +      /**
 +       * @param MessageBlobStore $blobStore
 +       * @since 1.25
 +       */
 +      public function setMessageBlobStore( MessageBlobStore $blobStore ) {
 +              $this->blobStore = $blobStore;
 +      }
 +
        /**
         * Register a module with the ResourceLoader system.
         *
@@@ -899,7 -885,7 +899,7 @@@ MESSAGE
                // Pre-fetch blobs
                if ( $context->shouldIncludeMessages() ) {
                        try {
 -                              $blobs = MessageBlobStore::getInstance()->get( $this, $modules, $context->getLanguage() );
 +                              $blobs = $this->blobStore->get( $this, $modules, $context->getLanguage() );
                        } catch ( Exception $e ) {
                                MWExceptionHandler::logException( $e );
                                wfDebugLog(
                } elseif ( !is_array( $scripts ) ) {
                        throw new MWException( 'Invalid scripts error. Array of URLs or string of code expected.' );
                }
-               return Xml::encodeJsCall(
-                       'mw.loader.implement',
-                       array(
-                               $name,
-                               $scripts,
-                               // Force objects. mw.loader.implement requires them to be javascript objects.
-                               // Although these variables are associative arrays, which become javascript
-                               // objects through json_encode. In many cases they will be empty arrays, and
-                               // PHP/json_encode() consider empty arrays to be numerical arrays and
-                               // output javascript "[]" instead of "{}". This fixes that.
-                               (object)$styles,
-                               (object)$messages,
-                               (object)$templates,
-                       ),
-                       ResourceLoader::inDebugMode()
+               // 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.
+               $module = array(
+                       $name,
+                       $scripts,
+                       (object) $styles,
+                       (object) $messages,
+                       (object) $templates,
                );
+               self::trimArray( $module );
+               return Xml::encodeJsCall( 'mw.loader.implement', $module, ResourceLoader::inDebugMode() );
        }
  
        /**
                );
        }
  
+       private static function isEmptyObject( stdClass $obj ) {
+               foreach ( $obj as $key => &$value ) {
+                       return false;
+               }
+               return true;
+       }
        /**
         * Remove empty values from the end of an array.
         *
         * Values considered empty:
         *
         * - null
-        * - empty array
+        * - array()
+        * - new XmlJsCode( '{}' )
+        * - new stdClass() // (object) array()
         *
         * @param Array $array
         */
        private static function trimArray( Array &$array ) {
                $i = count( $array );
                while ( $i-- ) {
-                       if ( $array[$i] === null || $array[$i] === array() ) {
+                       if ( $array[$i] === null
+                               || $array[$i] === array()
+                               || ( $array[$i] instanceof XmlJsCode && $array[$i]->value === '{}' )
+                               || ( $array[$i] instanceof stdClass && self::isEmptyObject( $array[$i] ) )
+                       ) {
                                unset( $array[$i] );
                        } else {
                                break;
@@@ -172,7 -172,7 +172,7 @@@ mw.test.baz({token:123});mw.loader.stat
                        array(
                                array( 'test.quux', ResourceLoaderModule::TYPE_COMBINED ),
                                '<script>if(window.mw){
- mw.loader.implement("test.quux",function($,jQuery){mw.test.baz({token:123});},{"css":[".mw-icon{transition:none}\n"]},{},{});
+ mw.loader.implement("test.quux",function($,jQuery){mw.test.baz({token:123});},{"css":[".mw-icon{transition:none}\n"]});
  
  }</script>
  '
@@@ -239,7 -239,6 +239,7 @@@ document.write("\u003Cscript src=\"http
                $ctx->setLanguage( 'en' );
                $out = new OutputPage( $ctx );
                $rl = $out->getResourceLoader();
 +              $rl->setMessageBlobStore( new NullMessageBlobStore() );
                $rl->register( array(
                        'test.foo' => new ResourceLoaderTestModule( array(
                                'script' => 'mw.test.foo( { a: true } );',
                $this->assertEquals( $expectedHtml, $actualHtml );
        }
  }
 +
 +/**
 + * MessageBlobStore that doesn't do anything
 + */
 +class NullMessageBlobStore extends MessageBlobStore {
 +      public function get ( ResourceLoader $resourceLoader, $modules, $lang ) {
 +              return array();
 +      }
 +
 +      public function insertMessageBlob ( $name, ResourceLoaderModule $module, $lang ) {
 +              return false;
 +      }
 +
 +      public function updateModule ( $name, ResourceLoaderModule $module, $lang ) {
 +              return;
 +      }
 +
 +      public function updateMessage ( $key ) {
 +      }
 +      public function clear() {
 +      }
 +}
 +