In JavaScript, all objects inherit from the same base class. While typical use of objects is through inheritance of a consistent "shape", when using an object as a key/value map, the shape changes constantly. V8 attempts to detect this by foregoing its "implicit class" (or "hidden class") model in favour of a hashtable. However it seems to be failing (when tracing v8 through Chrome, it's optimiser repeatedly warns about this but never seems to kick in).
Main offenders of key/value "objects":
- mw.loader.register() when augmenting with the registry object.
- mw.loader#execute() when calling mw.messages.set() to augment its values object.
- mw.loader#sortDependencies() when augmenting the unresolved object.
As part of the V8/Wikipedia meet-up in SF, it was recommended to use a native ES6 Map or ES6 Set instead (where available). To keep the startup module light I recommend we don't ship a feature-complete polyfill but instead only abstract the minimal feature set for our internal use (not exposed publicly).
Action items:
- Create private cross-browser interface for Set.
- Use in sortDependencies().
- Deprecate mw.Map#values (as mw.config.values, mw.messages.values) - this is the only part of mw.Map that we can't feasibly polyfill.
- Create private cross-browser interface for Map.
- Use it inside mw.Map.
- Deprecate mw.Map. There is no reason for this to be public. And in the last 3 years I've yet to see first use outside mediawiki.js. For most cases, plain objects or arrays suffice. For more elaborate cases, use generic polyfill modules.