PSA: Major ChromeUtils.import() API change

Kris Maglione kmaglione at
Tue Jan 29 00:50:28 UTC 2019

As of bug 1514594, the behavior ChromeUtils.import() API has changed in 
order to avoid touching the caller's global scope, or returning the imported 
module's global scope. In short, where you previously wrote:


You should now write something like:

  const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");

We've made this change for a lot of reasons. The obvious ones include making 
it obvious to readers exactly what symbols are imported, and making it 
easier for tooling to analyze such imports.

The less obvious, and arguably more important reason, though, is that we 
would like to start loading JSMs as ES6 modules. The major stumbling block 
to that effort is that our JSM import and export APIs rely on modules being 
loaded into global-like objects that we can return, and our caller APIs 
likewise rely on callers being loaded into objects where we can define 
properties. Neither of these assumptions are compatible with ES6 module 
scripts, which have lexical scopes, but no global or pseudo-global objects 
of their own.

Changing the ChromeUtils.import() API to stop relying on these assumptions 
is the first step down this road. In the near future, we're going to need to 
make similar changes to our lazy getter and lazy import APIs to stop 
defining properties on the `this` object (which will be going away), and to 
a large number of unit tests which rely on mangling module globals.

Once all of this is done, we'll change our JSM loading infrastructure to use 
the `export` keyword rather than the `EXPORTED_SYMBOLS` array, and rewrite 
our existing code to comply with the new behavior. Whatever else this whole 
process accomplishes, it will have the major side-effect of making our 
system JS code much more JIT-friendly, and in many cases, some orders of 
magnitude faster.


More information about the firefox-dev mailing list