Bug 1314861: Add defineLazyGetter global to SDK loader modules. r=ochameau

MozReview-Commit-ID: L1NShFpnb2S

--HG--
extra : rebase_source : 8d4b132da64a3af03a120f45f160731295a8b086
This commit is contained in:
Kris Maglione 2017-04-14 13:28:02 -07:00
Родитель b13ea15e1c
Коммит 04e16d2f2a
2 изменённых файлов: 136 добавлений и 1 удалений

Просмотреть файл

@ -41,7 +41,9 @@ 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, {});
@ -476,6 +478,14 @@ const load = iced(function load(loader, module) {
descriptors[name] = getOwnPropertyDescriptor(globals, name)
descriptors[name].configurable = true;
});
descriptors.lazyRequire = {
configurable: true,
value: lazyRequire.bind(sandbox),
};
descriptors.lazyRequireModule = {
configurable: true,
value: lazyRequireModule.bind(sandbox),
};
Object.defineProperties(sandbox, descriptors);
}
else {
@ -730,6 +740,56 @@ const resolveURI = iced(function resolveURI(id, mapping) {
});
Loader.resolveURI = resolveURI;
/**
* Defines lazy getters on the given object, which lazily require the
* given module the first time they are accessed, and then resolve that
* module's exported properties.
*
* @param {object} obj
* The target object on which to define the lazy getters.
* @param {string} moduleId
* The ID of the module to require, as passed to require().
* @param {Array<string | object>} args
* Any number of properties to import from the module. A string
* will cause the property to be defined which resolves to the
* same property in the module's exports. An object will define a
* lazy getter for every value in the object which corresponds to
* the given key in the module's exports, as in an ordinary
* destructuring assignment.
*/
function lazyRequire(obj, moduleId, ...args) {
let module;
let getModule = () => {
if (!module)
module = this.require(moduleId);
return module;
};
for (let props of args) {
if (typeof props !== "object")
props = {[props]: props};
for (let [fromName, toName] of Object.entries(props))
defineLazyGetter(obj, toName, () => getModule()[fromName]);
}
}
/**
* Defines a lazy getter on the given object which causes a module to be
* lazily imported the first time it is accessed.
*
* @param {object} obj
* The target object on which to define the lazy getter.
* @param {string} moduleId
* The ID of the module to require, as passed to require().
* @param {string} [prop = moduleId]
* The name of the lazy getter property to define.
*/
function lazyRequireModule(obj, moduleId, prop = moduleId) {
defineLazyGetter(obj, prop, () => this.require(moduleId));
}
// 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

Просмотреть файл

@ -123,6 +123,79 @@ function createModule(id) {
});
}
function defineLazyGetter(object, prop, getter) {
let redefine = (obj, value) => {
Object.defineProperty(obj, prop, {
configurable: true,
writable: true,
value,
});
return value;
};
Object.defineProperty(object, prop, {
configurable: true,
get() {
return redefine(this, getter.call(this));
},
set(value) {
redefine(this, value);
}
});
}
/**
* Defines lazy getters on the given object, which lazily require the
* given module the first time they are accessed, and then resolve that
* module's exported properties.
*
* @param {object} obj
* The target object on which to define the lazy getters.
* @param {string} moduleId
* The ID of the module to require, as passed to require().
* @param {Array<string | object>} args
* Any number of properties to import from the module. A string
* will cause the property to be defined which resolves to the
* same property in the module's exports. An object will define a
* lazy getter for every value in the object which corresponds to
* the given key in the module's exports, as in an ordinary
* destructuring assignment.
*/
function lazyRequire(obj, moduleId, ...args) {
let module;
let getModule = () => {
if (!module) {
module = this.require(moduleId);
}
return module;
};
for (let props of args) {
if (typeof props !== "object") {
props = {[props]: props};
}
for (let [fromName, toName] of Object.entries(props)) {
defineLazyGetter(obj, toName, () => getModule()[fromName]);
}
}
}
/**
* Defines a lazy getter on the given object which causes a module to be
* lazily imported the first time it is accessed.
*
* @param {object} obj
* The target object on which to define the lazy getter.
* @param {string} moduleId
* The ID of the module to require, as passed to require().
* @param {string} [prop = moduleId]
* The name of the lazy getter property to define.
*/
function lazyRequireModule(obj, moduleId, prop = moduleId) {
defineLazyGetter(obj, prop, () => this.require(moduleId));
}
/**
* Create a CommonJS loader with the following options:
* - createSandbox:
@ -491,6 +564,8 @@ this.worker = new WorkerDebuggerLoader({
"rpc": rpc,
"URL": URL,
"setImmediate": setImmediate,
"lazyRequire": lazyRequire,
"lazyRequireModule": lazyRequireModule,
"retrieveConsoleEvents": this.retrieveConsoleEvents,
"setConsoleEventHandler": this.setConsoleEventHandler,
},