Bug 1314861: Add defineLazyGetter global to SDK loader modules. r?ochameau draft
authorKris Maglione <maglione.k@gmail.com>
Sun, 30 Oct 2016 17:10:38 -0700
changeset 433085 315fcf2dbe58a869089db1ec233188e24fca18ed
parent 433084 f0a1a66c3875ce2d77e364aea88ff88fa57fd91c
child 433086 3663dd9d459571ae95841d4245fecc3886108fda
push id34481
push usermaglione.k@gmail.com
push dateThu, 03 Nov 2016 03:45:04 +0000
reviewersochameau
bugs1314861
milestone52.0a1
Bug 1314861: Add defineLazyGetter global to SDK loader modules. r?ochameau MozReview-Commit-ID: L1NShFpnb2S
addon-sdk/source/lib/toolkit/loader.js
--- a/addon-sdk/source/lib/toolkit/loader.js
+++ b/addon-sdk/source/lib/toolkit/loader.js
@@ -36,17 +36,19 @@ const { join: pathJoin, normalize, dirna
 
 XPCOMUtils.defineLazyServiceGetter(this, "resProto",
                                    "@mozilla.org/network/protocol;1?name=resource",
                                    "nsIResProtocolHandler");
 XPCOMUtils.defineLazyServiceGetter(this, "zipCache",
                                    "@mozilla.org/libjar/zip-reader-cache;1",
                                    "nsIZipReaderCache");
 
-XPCOMUtils.defineLazyGetter(this, "XulApp", () => {
+const { defineLazyGetter } = XPCOMUtils;
+
+defineLazyGetter(this, "XulApp", () => {
   let xulappURI = module.uri.replace("toolkit/loader.js",
                                      "sdk/system/xul-app.jsm");
   return Cu.import(xulappURI, {});
 });
 
 // Define some shortcuts.
 const bind = Function.call.bind(Function.bind);
 const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
@@ -471,16 +473,20 @@ const load = iced(function load(loader, 
     // Create a new object in this sandbox, that will be used as
     // the scope object for this particular module
     sandbox = new loader.sharedGlobalSandbox.Object();
     // Inject all expected globals in the scope object
     getOwnIdentifiers(globals).forEach(function(name) {
       descriptors[name] = getOwnPropertyDescriptor(globals, name)
       descriptors[name].configurable = true;
     });
+    descriptors.lazyRequire = {
+      configurable: true,
+      value: lazyRequire.bind(sandbox),
+    };
     Object.defineProperties(sandbox, descriptors);
   }
   else {
     sandbox = Sandbox({
       name: module.uri,
       prototype: Object.create(globals, descriptors),
       wantXrays: false,
       wantGlobalProperties: module.id == "sdk/indexed-db" ? ["indexedDB"] : [],
@@ -722,16 +728,41 @@ const resolveURI = iced(function resolve
     if(stripped === "" || id === stripped || id.startsWith(stripped + "/")) {
       return normalizeExt(id.replace(path, uri));
     }
   }
   return null;
 });
 Loader.resolveURI = resolveURI;
 
+let moduleMap = new WeakMap();
+
+function lazyRequire(module, ...args) {
+  if (typeof module === "object") {
+    for (let [moduleId, prop] of Object.entries(module))
+      defineLazyGetter(this, prop, () => this.require(moduleId));
+
+    return;
+  }
+
+  if (!moduleMap.has(this))
+    moduleMap.set(this, {});
+  let modules = moduleMap.get(this);
+
+  defineLazyGetter(modules, module, () => this.require(module));
+
+  for (let props of args) {
+    if (typeof props !== "object")
+      props = {[props]: props};
+
+    for (let [fromName, toName] of Object.entries(props))
+      defineLazyGetter(this, toName, () => modules[module][fromName]);
+  }
+}
+
 // Creates version of `require` that will be exposed to the given `module`
 // in the context of the given `loader`. Each module gets own limited copy
 // of `require` that is allowed to load only a modules that are associated
 // with it during link time.
 const Require = iced(function Require(loader, requirer) {
   let {
     modules, mapping, resolve: loaderResolve, load,
     manifest, rootURI, isNative, requireMap,