Skip to content
This repository has been archived by the owner on Feb 26, 2022. It is now read-only.

Commit

Permalink
Merge pull request #1723 from Gozala/bug/require-toolkit-loader
Browse files Browse the repository at this point in the history
Bug 1102107 - fix require("toolkit/loader") r=@jsantell
  • Loading branch information
Gozala committed Nov 20, 2014
2 parents 5a40033 + 7a3ae5b commit 1a0010e
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 48 deletions.
83 changes: 37 additions & 46 deletions lib/toolkit/loader.js
Expand Up @@ -2,28 +2,18 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

;(function(id, factory) { // Module boilerplate :(
if (typeof(define) === 'function') { // RequireJS
define(factory);
} else if (typeof(require) === 'function') { // CommonJS
factory.call(this, require, exports, module);
;(function(factory) { // Module boilerplate :(
if (typeof(require) === 'function') { // CommonJS
require("chrome").Cu.import(module.uri, exports);
} else if (~String(this).indexOf('BackstagePass')) { // JSM
this[factory.name] = {};
factory(function require(uri) {
var imports = {};
this['Components'].utils.import(uri, imports);
return imports;
}, this[factory.name], { uri: __URI__, id: id });
this.EXPORTED_SYMBOLS = [factory.name];
} else if (~String(this).indexOf('Sandbox')) { // Sandbox
factory(function require(uri) {}, this, { uri: __URI__, id: id });
} else { // Browser or alike
var globals = this
factory(function require(id) {
return globals[id];
}, (globals[id] = {}), { uri: document.location.href + '#' + id, id: id });
let module = { uri: __URI__, id: "toolkit/loader", exports: Object.create(null) }
factory(module);
Object.assign(this, module.exports);
this.EXPORTED_SYMBOLS = Object.getOwnPropertyNames(module.exports);
} else {
throw Error("Loading environment is not supported");
}
}).call(this, 'loader', function Loader(require, exports, module) {
})(function(module) {

'use strict';

Expand Down Expand Up @@ -90,7 +80,7 @@ const descriptor = iced(function descriptor(object) {
});
return value;
});
exports.descriptor = descriptor;
Loader.descriptor = descriptor;

// Freeze important built-ins so they can't be used by untrusted code as a
// message passing channel.
Expand Down Expand Up @@ -127,15 +117,15 @@ const override = iced(function override(target, source) {
});
return define({}, properties);
});
exports.override = override;
Loader.override = override;

function sourceURI(uri) { return String(uri).split(" -> ").pop(); }
exports.sourceURI = iced(sourceURI);
Loader.sourceURI = iced(sourceURI);

function isntLoaderFrame(frame) { return frame.fileName !== module.uri }

function parseURI(uri) { return String(uri).split(" -> ").pop(); }
exports.parseURI = parseURI;
Loader.parseURI = parseURI;

function parseStack(stack) {
let lines = String(stack).split("\n");
Expand All @@ -158,7 +148,7 @@ function parseStack(stack) {
return frames;
}, []);
}
exports.parseStack = parseStack;
Loader.parseStack = parseStack;

function serializeStack(frames) {
return frames.reduce(function(stack, frame) {
Expand All @@ -169,7 +159,7 @@ function serializeStack(frames) {
stack;
}, "");
}
exports.serializeStack = serializeStack;
Loader.serializeStack = serializeStack;

function readURI(uri) {
let stream = NetUtil.newChannel(uri, 'UTF-8', null).open();
Expand All @@ -194,7 +184,7 @@ function join (...paths) {
resolved = resolved.replace(/^chrome\:\/([^\/])/, 'chrome://$1');
return resolved;
}
exports.join = join;
Loader.join = join;

// Function takes set of options and returns a JS sandbox. Function may be
// passed set of options:
Expand Down Expand Up @@ -246,7 +236,7 @@ const Sandbox = iced(function Sandbox(options) {

return sandbox;
});
exports.Sandbox = Sandbox;
Loader.Sandbox = Sandbox;

// Evaluates code from the given `uri` into given `sandbox`. If
// `options.source` is passed, then that code is evaluated instead.
Expand All @@ -266,7 +256,7 @@ const evaluate = iced(function evaluate(sandbox, uri, options) {
return source ? Cu.evalInSandbox(source, sandbox, version, uri, line)
: loadSubScript(uri, sandbox, encoding);
});
exports.evaluate = evaluate;
Loader.evaluate = evaluate;

// Populates `exports` of the given CommonJS `module` object, in the context
// of the given `loader` by evaluating code associated with it.
Expand Down Expand Up @@ -359,7 +349,7 @@ const load = iced(function load(loader, module) {

return module;
});
exports.load = load;
Loader.load = load;

// Utility function to normalize module `uri`s so they have `.js` extension.
function normalizeExt (uri) {
Expand Down Expand Up @@ -396,7 +386,7 @@ const resolve = iced(function resolve(id, base) {

return resolved;
});
exports.resolve = resolve;
Loader.resolve = resolve;

// Node-style module lookup
// Takes an id and path and attempts to load a file using node's resolving
Expand All @@ -405,7 +395,7 @@ exports.resolve = resolve;
// http://nodejs.org/api/modules.html#modules_all_together
const nodeResolve = iced(function nodeResolve(id, requirer, { rootURI }) {
// Resolve again
id = exports.resolve(id, requirer);
id = Loader.resolve(id, requirer);

// we assume that extensions are correct, i.e., a directory doesnt't have '.js'
// and a js file isn't named 'file.json.js'
Expand Down Expand Up @@ -434,7 +424,7 @@ const nodeResolve = iced(function nodeResolve(id, requirer, { rootURI }) {
// with `resolveURI` -- if during runtime, then `resolve` will throw.
return void 0;
});
exports.nodeResolve = nodeResolve;
Loader.nodeResolve = nodeResolve;

// Attempts to load `path` and then `path.js`
// Returns `path` with valid file, or `undefined` otherwise
Expand Down Expand Up @@ -531,7 +521,7 @@ const resolveURI = iced(function resolveURI(id, mapping) {
}
return void 0; // otherwise we raise a warning, see bug 910304
});
exports.resolveURI = resolveURI;
Loader.resolveURI = resolveURI;

// 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
Expand Down Expand Up @@ -645,7 +635,7 @@ const Require = iced(function Require(loader, requirer) {
// found in the paths most likely, like `sdk/tabs`, which should
// be resolved relatively if needed using traditional resolve
if (!requirement) {
requirement = isRelative(id) ? exports.resolve(id, requirer.id) : id;
requirement = isRelative(id) ? Loader.resolve(id, requirer.id) : id;
}
} else {
// Resolve `id` to its requirer if it's relative.
Expand All @@ -672,7 +662,7 @@ const Require = iced(function Require(loader, requirer) {
require.main = loader.main === requirer ? requirer : undefined;
return iced(require);
});
exports.Require = Require;
Loader.Require = Require;

const main = iced(function main(loader, id) {
// If no main entry provided, and native loader is used,
Expand All @@ -683,7 +673,7 @@ const main = iced(function main(loader, id) {
let module = loader.main = loader.modules[uri] = Module(id, uri);
return loader.load(loader, module).exports;
});
exports.main = main;
Loader.main = main;

// Makes module object that is made available to CommonJS modules when they
// are evaluated, along with `exports` and `require`.
Expand All @@ -694,7 +684,7 @@ const Module = iced(function Module(id, uri) {
uri: { value: uri }
});
});
exports.Module = Module;
Loader.Module = Module;

// Takes `loader`, and unload `reason` string and notifies all observers that
// they should cleanup after them-self.
Expand All @@ -709,7 +699,7 @@ const unload = iced(function unload(loader, reason) {
let subject = { wrappedJSObject: loader.destructor };
notifyObservers(subject, 'sdk:loader:destroy', reason);
});
exports.unload = unload;
Loader.unload = unload;

// Function makes new loader that can be used to load CommonJS modules
// described by a given `options.manifest`. Loader takes following options:
Expand All @@ -724,7 +714,7 @@ exports.unload = unload;
// module object (that has `uri` property) and `baseURI` of the loader.
// If `resolve` does not returns `uri` string exception will be thrown by
// an associated `require` call.
const Loader = iced(function Loader(options) {
function Loader(options) {
let console = new ConsoleAPI({
consoleID: options.id ? "addon/" + options.id : ""
});
Expand All @@ -740,8 +730,8 @@ const Loader = iced(function Loader(options) {
},
resolve: options.isNative ?
// Make the returned resolve function have the same signature
(id, requirer) => exports.nodeResolve(id, requirer, { rootURI: rootURI }) :
exports.resolve,
(id, requirer) => Loader.nodeResolve(id, requirer, { rootURI: rootURI }) :
Loader.resolve,
sharedGlobalBlacklist: ["sdk/indexed-db"]
}, options);

Expand Down Expand Up @@ -839,8 +829,8 @@ const Loader = iced(function Loader(options) {
}

return freeze(create(null, returnObj));
});
exports.Loader = Loader;
};
Loader.Loader = Loader;

let isJSONURI = uri => uri.substr(-5) === '.json';
let isJSMURI = uri => uri.substr(-4) === '.jsm';
Expand All @@ -853,7 +843,7 @@ let isRelative = id => id[0] === '.'
const generateMap = iced(function generateMap(options, callback) {
let { rootURI, resolve, paths } = override({
paths: {},
resolve: exports.nodeResolve
resolve: Loader.nodeResolve
}, options);

rootURI = addTrailingSlash(rootURI);
Expand All @@ -875,7 +865,7 @@ const generateMap = iced(function generateMap(options, callback) {
}, {}, callback);

});
exports.generateMap = generateMap;
Loader.generateMap = generateMap;

// Default `main` entry to './index.js' and ensure is relative,
// since node allows 'lib/index.js' without relative `./`
Expand Down Expand Up @@ -981,4 +971,5 @@ function isRequire (node) {
&& node.arguments[0].type === 'Literal';
}

module.exports = iced(Loader);
});
24 changes: 22 additions & 2 deletions test/test-loader.js
Expand Up @@ -5,7 +5,8 @@
'use strict';

let {
Loader, main, unload, parseStack, generateMap, resolve, join
Loader, main, unload, parseStack, generateMap, resolve, join,
Require, Module
} = require('toolkit/loader');
let { readURI } = require('sdk/net/url');

Expand Down Expand Up @@ -331,7 +332,7 @@ exports['test console global by default'] = function (assert) {
let uri = root + '/fixtures/loader/globals/';
let loader = Loader({ paths: { '': uri }});
let program = main(loader, 'main');

assert.ok(typeof program.console === 'object', 'global `console` exists');
assert.ok(typeof program.console.log === 'function', 'global `console.log` exists');

Expand Down Expand Up @@ -374,4 +375,23 @@ exports["test require#resolve"] = function(assert) {
assert.equal(foundRoot + "toolkit/loader.js", require.resolve("toolkit/loader"), "correct resolution of sdk module");
};

const modulesURI = require.resolve("toolkit/loader").replace("toolkit/loader.js", "");
exports["test loading a loader"] = function(assert) {
const loader = Loader({ paths: { "": modulesURI } });

const require = Require(loader, module);

const requiredLoader = require("toolkit/loader");

assert.equal(requiredLoader.Loader, Loader,
"got the same Loader instance");

const jsmLoader = Cu.import(require.resolve("toolkit/loader"), {}).Loader;

assert.equal(jsmLoader.Loader, requiredLoader.Loader,
"loading loader via jsm returns same loader");

unload(loader);
};

require('test').run(exports);

0 comments on commit 1a0010e

Please sign in to comment.