Bug 1314861: Pre-compute path mapping function to save on runtime lookups. r=ochameau

MozReview-Commit-ID: Lc4ju1XOfgR

--HG--
extra : rebase_source : f5ab7bc0ab70945b88d3f76363107cac9c3ba256
This commit is contained in:
Kris Maglione 2017-04-13 15:40:09 -07:00
Родитель 0ee4a22385
Коммит cbfb61ba92
3 изменённых файлов: 41 добавлений и 23 удалений

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

@ -42,10 +42,6 @@ if (options.isNative) {
else {
moduleResolve = loaderModule.resolve;
}
// Build the sorted path mapping structure that resolveURI requires
var pathMapping = Object.keys(options.paths)
.sort((a, b) => b.length - a.length)
.map(p => [p, options.paths[p]]);
// Load the scripts in the child processes
var { getNewLoaderID } = require('../../framescript/FrameScriptManager.jsm');
@ -326,13 +322,12 @@ function remoteRequire(id, module = null) {
// Resolve relative to calling module if passed
if (module)
id = moduleResolve(id, module.id);
let uri = loaderModule.resolveURI(id, pathMapping);
// Don't reload the same module
if (remoteModules.has(uri))
if (remoteModules.has(id))
return;
remoteModules.add(uri);
processes.port.emit('sdk/remote/require', uri);
remoteModules.add(id);
processes.port.emit('sdk/remote/require', id);
}
exports.remoteRequire = remoteRequire;

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

@ -723,14 +723,26 @@ function addTrailingSlash(path) {
return path.replace(/\/*$/, "/");
}
const resolveURI = iced(function resolveURI(id, mapping) {
// Do not resolve if already a resource URI
if (isAbsoluteURI(id))
return normalizeExt(id);
function compileMapping(paths) {
// Make mapping array that is sorted from longest path to shortest path.
let mapping = Object.keys(paths)
.sort((a, b) => b.length - a.length)
.map(path => [path, paths[path]]);
const PATTERN = /([.\\?+*(){}[\]^$])/g;
const escapeMeta = str => str.replace(PATTERN, '\\$1')
let patterns = [];
paths = {};
for (let [path, uri] of mapping) {
// Strip off any trailing slashes to make comparisons simpler
let stripped = path.replace(/\/+$/, "");
if (path.endsWith("/")) {
path = path.slice(0, -1);
uri = uri.replace(/\/+$/, "");
}
paths[path] = uri;
// We only want to match path segments explicitly. Examples:
// * "foo/bar" matches for "foo/bar"
@ -741,11 +753,27 @@ const resolveURI = iced(function resolveURI(id, mapping) {
//
// Check for an empty path, an exact match, or a substring match
// with the next character being a forward slash.
if(stripped === "" || id === stripped || id.startsWith(stripped + "/")) {
return normalizeExt(id.replace(path, uri));
if (path == "")
patterns.push("");
else
patterns.push(`${escapeMeta(path)}(?=$|/)`);
}
}
return null;
let pattern = new RegExp(`^(${patterns.join('|')})`);
// This will replace the longest matching path mapping at the start of
// the ID string with its mapped value.
return id => {
return id.replace(pattern, (m0, m1) => paths[m1]);
};
}
const resolveURI = iced(function resolveURI(id, mapping) {
// Do not resolve if already a resource URI
if (isAbsoluteURI(id))
return normalizeExt(id);
return normalizeExt(mapping(id))
});
Loader.resolveURI = resolveURI;
@ -1093,10 +1121,7 @@ function Loader(options) {
// observer notifications.
let destructor = freeze(Object.create(null));
// Make mapping array that is sorted from longest path to shortest path.
let mapping = Object.keys(paths)
.sort((a, b) => b.length - a.length)
.map(path => [path, paths[path]]);
let mapping = compileMapping(paths);
// Define pseudo modules.
modules = override({

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

@ -419,7 +419,6 @@ exports["test require#resolve"] = function(assert) {
const localLoader = Loader({
paths: { "foo/bar": "bizzle",
"foo/bar2/": "bizzle2",
// Just to make sure this doesn't match the first entry,
// let use resolve this module
"foo/bar-bar": "foo/bar-bar" }
@ -428,7 +427,6 @@ exports["test require#resolve"] = function(assert) {
assert.equal(localRequire.resolve("foo/bar"), "bizzle.js");
assert.equal(localRequire.resolve("foo/bar/baz"), "bizzle/baz.js");
assert.equal(localRequire.resolve("foo/bar-bar"), "foo/bar-bar.js");
assert.equal(localRequire.resolve("foo/bar2/"), "bizzle2.js");
};
const modulesURI = require.resolve("toolkit/loader").replace("toolkit/loader.js", "");