mediawiki.inspect: Fix intermittent test failure
authorTimo Tijhof <krinklemail@gmail.com>
Mon, 6 Mar 2017 21:11:48 +0000 (13:11 -0800)
committerTimo Tijhof <krinklemail@gmail.com>
Mon, 6 Mar 2017 21:11:48 +0000 (13:11 -0800)
Follows-up 15c0382121.

Bug: T159751
Change-Id: Ib60521c03e72b1fac694b643c570242d8ee8fab1

resources/src/mediawiki/mediawiki.inspect.js
tests/qunit/suites/resources/mediawiki/mediawiki.inspect.test.js

index 3ca9537..5c2f83f 100644 (file)
@@ -73,9 +73,9 @@
                 */
                getModuleSize: function ( moduleName ) {
                        var module = mw.loader.moduleRegistry[ moduleName ],
-                               args, i;
+                               args, i, size;
 
-                       if ( mw.loader.getState( moduleName ) !== 'ready' ) {
+                       if ( module.state !== 'ready' ) {
                                return null;
                        }
 
                                return 0;
                        }
 
-                       // Reverse-engineer the load.php response for this module.
-                       // For example: `mw.loader.implement("example", function(){}, );`
+                       function getFunctionBody( func ) {
+                               return String( func )
+                                       // To ensure a deterministic result, replace the start of the function
+                                       // declaration with a fixed string. For example, in Chrome 55, it seems
+                                       // V8 seemingly-at-random decides to sometimes put a line break between
+                                       // the opening brace and first statement of the function body. T159751.
+                                       .replace( /^\s*function\s*\([^)]*\)\s*{\s*/, 'function(){' )
+                                       .replace( /\s*}\s*$/, '}' );
+                       }
+
+                       // Based on the load.php response for this module.
+                       // For example: `mw.loader.implement("example", function(){}, {"css":[".x{color:red}"]});`
                        // @see mw.loader.store.set().
                        args = [
-                               JSON.stringify( moduleName ),
-                               // function, array of urls, or eval string
-                               typeof module.script === 'function' ?
-                                               String( module.script ) :
-                                               JSON.stringify( module.script ),
-                               JSON.stringify( module.style ),
-                               JSON.stringify( module.messages ),
-                               JSON.stringify( module.templates )
+                               moduleName,
+                               module.script,
+                               module.style,
+                               module.messages,
+                               module.templates
                        ];
                        // Trim trailing null or empty object, as load.php would have done.
                        // @see ResourceLoader::makeLoaderImplementScript and ResourceLoader::trimArray.
                        i = args.length;
                        while ( i-- ) {
-                               if ( args[ i ] === '{}' || args[ i ] === 'null' ) {
+                               if ( args[ i ] === null || ( $.isPlainObject( args[ i ] ) && $.isEmptyObject( args[ i ] ) ) ) {
                                        args.splice( i, 1 );
                                } else {
                                        break;
                                }
                        }
 
-                       return $.byteLength( args.join( ',' ) );
+                       size = 0;
+                       for ( i = 0; i < args.length; i++ ) {
+                               if ( typeof args[ i ] === 'function' ) {
+                                       size += $.byteLength( getFunctionBody( args[ i ] ) );
+                               } else {
+                                       size += $.byteLength( JSON.stringify( args[ i ] ) );
+                               }
+                       }
+
+                       return size;
                },
 
                /**
index 3bd15c4..1f7a5ec 100644 (file)
@@ -1,7 +1,4 @@
 ( function ( mw ) {
-       // Whitespace and serialisation of function bodies
-       // different in browsers.
-       var functionSize = String( function () {} ).length;
 
        QUnit.module( 'mediawiki.inspect' );
 
@@ -13,9 +10,9 @@
 
                return mw.loader.using( 'test.inspect.script' ).then( function () {
                        assert.equal(
-                               mw.inspect.getModuleSize( 'test.inspect.script' ) - functionSize,
+                               mw.inspect.getModuleSize( 'test.inspect.script' ),
                                // name, script function
-                               32,
+                               43,
                                'test.inspect.script'
                        );
                } );
@@ -30,9 +27,9 @@
 
                return mw.loader.using( 'test.inspect.both' ).then( function () {
                        assert.equal(
-                               mw.inspect.getModuleSize( 'test.inspect.both' ) - functionSize,
+                               mw.inspect.getModuleSize( 'test.inspect.both' ),
                                // name, script function, styles object
-                               54,
+                               64,
                                'test.inspect.both'
                        );
                } );
@@ -48,9 +45,9 @@
 
                return mw.loader.using( 'test.inspect.scriptmsg' ).then( function () {
                        assert.equal(
-                               mw.inspect.getModuleSize( 'test.inspect.scriptmsg' ) - functionSize,
+                               mw.inspect.getModuleSize( 'test.inspect.scriptmsg' ),
                                // name, script function, empty styles object, messages object
-                               65,
+                               74,
                                'test.inspect.scriptmsg'
                        );
                } );
@@ -67,9 +64,9 @@
 
                return mw.loader.using( 'test.inspect.all' ).then( function () {
                        assert.equal(
-                               mw.inspect.getModuleSize( 'test.inspect.all' ) - functionSize,
+                               mw.inspect.getModuleSize( 'test.inspect.all' ),
                                // name, script function, styles object, messages object, templates object
-                               118,
+                               126,
                                'test.inspect.all'
                        );
                } );