mediawiki.inspect: Simplify getModuleSize() by using module descriptor
authorTimo Tijhof <krinklemail@gmail.com>
Fri, 3 Mar 2017 22:01:59 +0000 (14:01 -0800)
committerTimo Tijhof <krinklemail@gmail.com>
Fri, 3 Mar 2017 22:01:59 +0000 (14:01 -0800)
Follows-up ce2652c9ec. Also add unit tests.

Change-Id: I26caaf982f0d317028b5b00374dded6995564ece

resources/src/mediawiki/mediawiki.inspect.js
tests/qunit/QUnitTestResources.php
tests/qunit/suites/resources/mediawiki/mediawiki.inspect.test.js [new file with mode: 0644]

index 6b3971e..3ca9537 100644 (file)
                 */
                getModuleSize: function ( moduleName ) {
                        var module = mw.loader.moduleRegistry[ moduleName ],
-                               payload = 0;
+                               args, i;
 
                        if ( mw.loader.getState( moduleName ) !== 'ready' ) {
                                return null;
                        }
 
                        if ( !module.style && !module.script ) {
-                               return null;
-                       }
-
-                       // Tally CSS
-                       if ( module.style && $.isArray( module.style.css ) ) {
-                               $.each( module.style.css, function ( i, stylesheet ) {
-                                       payload += $.byteLength( stylesheet );
-                               } );
+                               return 0;
                        }
 
-                       // Tally JavaScript
-                       if ( $.isFunction( module.script ) ) {
-                               payload += $.byteLength( module.script.toString() );
-                       }
-
-                       // Tally templates and messages. Calculate their JSON size so that keys
-                       // are included in the module size - in the case of messages, keys can be
-                       // longer than values - and so that empty objects are also included.
-                       $.each( [ module.templates, module.messages ], function ( i, object ) {
-                               if ( object ) {
-                                       payload += $.byteLength( JSON.stringify( object ) );
+                       // Reverse-engineer the load.php response for this module.
+                       // For example: `mw.loader.implement("example", function(){}, );`
+                       // @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 )
+                       ];
+                       // 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' ) {
+                                       args.splice( i, 1 );
+                               } else {
+                                       break;
                                }
-                       } );
+                       }
 
-                       return payload;
+                       return $.byteLength( args.join( ',' ) );
                },
 
                /**
index 0bd190b..6468646 100644 (file)
@@ -75,6 +75,7 @@ return [
                        'tests/qunit/suites/resources/mediawiki/mediawiki.test.js',
                        'tests/qunit/suites/resources/mediawiki/mediawiki.loader.test.js',
                        'tests/qunit/suites/resources/mediawiki/mediawiki.html.test.js',
+                       'tests/qunit/suites/resources/mediawiki/mediawiki.inspect.test.js',
                        'tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js',
                        'tests/qunit/suites/resources/mediawiki/mediawiki.toc.test.js',
                        'tests/qunit/suites/resources/mediawiki/mediawiki.track.test.js',
@@ -142,6 +143,7 @@ return [
                        'mediawiki.cldr',
                        'mediawiki.cookie',
                        'mediawiki.experiments',
+                       'mediawiki.inspect',
                        'test.mediawiki.qunit.testrunner',
                ],
        ]
diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.inspect.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.inspect.test.js
new file mode 100644 (file)
index 0000000..3bd15c4
--- /dev/null
@@ -0,0 +1,77 @@
+( function ( mw ) {
+       // Whitespace and serialisation of function bodies
+       // different in browsers.
+       var functionSize = String( function () {} ).length;
+
+       QUnit.module( 'mediawiki.inspect' );
+
+       QUnit.test( '.getModuleSize() - scripts', function ( assert ) {
+               mw.loader.implement(
+                       'test.inspect.script',
+                       function () { 'example'; }
+               );
+
+               return mw.loader.using( 'test.inspect.script' ).then( function () {
+                       assert.equal(
+                               mw.inspect.getModuleSize( 'test.inspect.script' ) - functionSize,
+                               // name, script function
+                               32,
+                               'test.inspect.script'
+                       );
+               } );
+       } );
+
+       QUnit.test( '.getModuleSize() - scripts, styles', function ( assert ) {
+               mw.loader.implement(
+                       'test.inspect.both',
+                       function () { 'example'; },
+                       { css: [ '.example {}' ] }
+               );
+
+               return mw.loader.using( 'test.inspect.both' ).then( function () {
+                       assert.equal(
+                               mw.inspect.getModuleSize( 'test.inspect.both' ) - functionSize,
+                               // name, script function, styles object
+                               54,
+                               'test.inspect.both'
+                       );
+               } );
+       } );
+
+       QUnit.test( '.getModuleSize() - scripts, messages', function ( assert ) {
+               mw.loader.implement(
+                       'test.inspect.scriptmsg',
+                       function () { 'example'; },
+                       {},
+                       { example: 'Hello world.' }
+               );
+
+               return mw.loader.using( 'test.inspect.scriptmsg' ).then( function () {
+                       assert.equal(
+                               mw.inspect.getModuleSize( 'test.inspect.scriptmsg' ) - functionSize,
+                               // name, script function, empty styles object, messages object
+                               65,
+                               'test.inspect.scriptmsg'
+                       );
+               } );
+       } );
+
+       QUnit.test( '.getModuleSize() - scripts, styles, messages, templates', function ( assert ) {
+               mw.loader.implement(
+                       'test.inspect.all',
+                       function () { 'example'; },
+                       { css: [ '.example {}' ] },
+                       { example: 'Hello world.' },
+                       { 'example.html': '<p>Hello world.<p>' }
+               );
+
+               return mw.loader.using( 'test.inspect.all' ).then( function () {
+                       assert.equal(
+                               mw.inspect.getModuleSize( 'test.inspect.all' ) - functionSize,
+                               // name, script function, styles object, messages object, templates object
+                               118,
+                               'test.inspect.all'
+                       );
+               } );
+       } );
+}( mediaWiki ) );