mw.loader.store: decline to store items > 100 kB
authorOri Livneh <ori@wikimedia.org>
Fri, 5 Jun 2015 00:06:49 +0000 (17:06 -0700)
committerOri Livneh <ori@wikimedia.org>
Fri, 5 Jun 2015 00:34:26 +0000 (17:34 -0700)
If the length of the string representation of a module exceeds 100,000
characters, decline to store it in localStorage, due to bug T66721.
(While it is true that string length !== byte length, the skew introduced by
counting multi-byte characters as single bytes is not important enough to merit
the use of $.byteLength).

Based on my analysis, the modules that would be ineligible for caching in local
storage under the new schema are:

- ext.visualEditor.core (624 kB)
- oojs-ui (179 kB)
- oojs-ui.styles.icons (132 kB)

To fix this bug, it is not enough to not store new items; we must also ensure
that any old values cached prior to the introduction of a limit are purged. So
update mw.loader.store#prune to do that, too.

Bug: T66721
Change-Id: Ie45467fc0b2db7cc283f30626af7d587da24bd90

resources/src/mediawiki/mediawiki.js

index 0c24720..ec3c0c3 100644 (file)
                                        // Whether the store is in use on this page.
                                        enabled: null,
 
+                                       // Modules whose string representation exceeds 100 kB are ineligible
+                                       // for storage due to bug T66721.
+                                       MODULE_SIZE_MAX: 100000,
+
                                        // The contents of the store, mapping '[module name]@[version]' keys
                                        // to module implementations.
                                        items: {},
                                         * @param {Object} descriptor The module's descriptor as set in the registry
                                         */
                                        set: function ( module, descriptor ) {
-                                               var args, key;
+                                               var args, key, src;
 
                                                if ( !mw.loader.store.enabled ) {
                                                        return false;
                                                        return;
                                                }
 
-                                               mw.loader.store.items[key] = 'mw.loader.implement(' + args.join( ',' ) + ');';
+                                               src = 'mw.loader.implement(' + args.join( ',' ) + ');';
+                                               if ( src.length > mw.loader.store.MODULE_SIZE_MAX ) {
+                                                       return false;
+                                               }
+                                               mw.loader.store.items[key] = src;
                                                mw.loader.store.update();
                                        },
 
                                                        if ( mw.loader.store.getModuleKey( module ) !== key ) {
                                                                mw.loader.store.stats.expired++;
                                                                delete mw.loader.store.items[key];
+                                                       } else if ( mw.loader.store.items[key].length > mw.loader.store.MODULE_SIZE_MAX ) {
+                                                               // This value predates the enforcement of a size limit on cached modules.
+                                                               delete mw.loader.store.items[key];
                                                        }
                                                }
                                        },