/*
Based in part on Motorola Mobility’s Montage
Copyright (c) 2012, Motorola Mobility LLC. All Rights Reserved.
3-Clause BSD License
https://github.com/motorola-mobility/montage/blob/master/LICENSE.md
*/
/*global bootstrap,define */
(function (definition) {
// Boostrapping Browser
if (typeof bootstrap !== "undefined") {
// Window
if (typeof window !== "undefined") {
bootstrap("require", function (require, exports) {
var Promise = require("promise");
var URL = require("mini-url");
definition(exports, Promise, URL);
require("require/browser");
});
// Worker
} else {
bootstrap("require", function (require, exports) {
var Promise = require("promise").Promise;
var URL = require("mini-url");
definition(exports, Promise, URL);
});
}
// Node Server
} else if (typeof process !== "undefined") {
// the parens trick the heuristic scanner for static dependencies, so
// they are not pre-loaded by the asynchronous browser loader
var Promise = (require)("q");
var URL = (require)("url");
definition(exports, Promise, URL);
(require)("./node");
} else {
throw new Error("Can't support require on this platform");
}
})(function (Require, Promise, URL) {
if (!this)
throw new Error("Require does not work in strict mode.");
var globalEval = eval; // reassigning causes eval to not use lexical scope.
// Non-CommonJS speced extensions should be marked with an "// EXTENSION"
// comment.
Require.makeRequire = function (config) {
var require;
// Configuration defaults:
config = config || {};
config.location = URL.resolve(config.location || Require.getLocation(), "./");
config.lib = URL.resolve(config.location, config.lib || "./");
config.paths = config.paths || [config.lib];
config.mappings = config.mappings || {}; // EXTENSION
config.exposedConfigs = config.exposedConfigs || Require.exposedConfigs;
config.makeLoader = config.makeLoader || Require.makeLoader;
config.load = config.load || config.makeLoader(config);
config.makeCompiler = config.makeCompiler || Require.makeCompiler;
config.compile = config.compile || config.makeCompiler(config);
config.parseDependencies = config.parseDependencies || Require.parseDependencies;
config.read = config.read || Require.read;
// Modules: { exports, id, location, directory, factory, dependencies,
// dependees, text, type }
var modules = config.modules = config.modules || {};
// produces an entry in the module state table, which gets built
// up through loading and execution, ultimately serving as the
// ``module`` free variable inside the corresponding module.
function getModuleDescriptor(id) {
var lookupId = id.toLowerCase();
if (!has(modules, lookupId)) {
modules[lookupId] = {
id: id,
display: (config.name || config.location) + "#" + id, // EXTENSION
require: require
};
}
return modules[lookupId];
}
// for preloading modules by their id and exports, useful to
// prevent wasteful multiple instantiation if a module was loaded
// in the bootstrapping process and can be trivially injected into
// the system.
function inject(id, exports) {
var module = getModuleDescriptor(id);
module.exports = exports;
module.location = URL.resolve(config.location, id);
module.directory = URL.resolve(module.location, "./");
module.injected = true;
delete module.redirect;
delete module.mappingRedirect;
}
// Ensures a module definition is loaded, compiled, analyzed
var load = memoize(function (topId, viaId) {
var module = getModuleDescriptor(topId);
return Promise.fcall(function () {
// if not already loaded, already instantiated, or
// configured as a redirection to another module
if (
module.factory === void 0 &&
module.exports === void 0 &&
module.redirect === void 0
) {
return Promise.fcall(config.load, topId, module);
}
})
.then(function () {
// compile and analyze dependencies
config.compile(module);
var dependencies =
module.dependencies =
module.dependencies || [];
if (module.redirect !== void 0) {
dependencies.push(module.redirect);
}
if (module.extraDependencies !== void 0) {
Array.prototype.push.apply(module.dependencies, module.extraDependencies);
}
});
});
// Load a module definition, and the definitions of its transitive
// dependencies
function deepLoad(topId, viaId, loading) {
var module = getModuleDescriptor(topId);
// this is a memo of modules already being loaded so we don’t
// data-lock on a cycle of dependencies.
loading = loading || {};
// has this all happened before? will it happen again?
if (has(loading, topId))
return; // break the cycle of violence.
loading[topId] = true; // this has happened before
return load(topId, viaId)
.then(function () {
// load the transitive dependencies using the magic of
// recursion.
return Promise.all(module.dependencies.map(function (depId) {
depId = resolve(depId, topId);
// create dependees set, purely for debug purposes
var module = getModuleDescriptor(depId);
var dependees = module.dependees = module.dependees || {};
dependees[topId] = true;
return deepLoad(depId, topId, loading);
}));
}, function (error) {
module.error = error;
});
}
// Initializes a module by executing the factory function with a new
// module "exports" object.
function getExports(topId, viaId) {
var module = getModuleDescriptor(topId);
// check for consistent case convention
if (module.id !== topId) {
throw new Error(
"Can't require module " + JSON.stringify(module.id) +
" by alternate spelling " + JSON.stringify(topId)
);
}
// check for load error
if (module.error) {
var error = new Error(
"Can't require module " + JSON.stringify(module.id) +
" via " + JSON.stringify(viaId) +
" because " + module.error.message
);
error.cause = module.error;
throw error;
}
// handle redirects
if (module.redirect !== void 0) {
return getExports(module.redirect, viaId);
}
// handle cross-package linkage
if (module.mappingRedirect !== void 0) {
return module.mappingRequire(module.mappingRedirect, viaId);
}
// do not reinitialize modules
if (module.exports !== void 0) {
return module.exports;
}
// do not initialize modules that do not define a factory function
if (module.factory === void 0) {
throw new Error(
"Can't require module " + JSON.stringify(topId) +
" via " + JSON.stringify(viaId)
);
}
module.directory = URL.resolve(module.location, "./"); // EXTENSION
module.exports = {};
// Execute the factory function:
var returnValue = module.factory.call(
// in the context of the module:
void 0, // this (defaults to global)
makeRequire(topId), // require
module.exports, // exports
module // module
);
// EXTENSION
if (returnValue !== void 0) {
module.exports = returnValue;
}
return module.exports;
}
// Finds the internal identifier for a module in a subpackage
// The ``internal`` boolean parameter causes the function to return
// null instead of throwing an exception. I’m guessing that
// throwing exceptions *and* being recursive would be too much
// performance evil for one function.
function identify(id2, require2, internal) {
if (require2.location === config.location)
return id2;
var locations = {};
for (var name in config.mappings) {
var mapping = config.mappings[name];
var location = mapping.location;
if (!config.hasPackage(location))
continue;
var candidate = config.getPackage(location);
var id1 = candidate.identify(id2, require2, true);
if (id1 === null) {
continue;
} else if (id1 === "") {
return name;
} else {
return name + "/" + id1;
}
}
if (internal) {
return null;
} else {
throw new Error(
"Can't identify " + id2 + " from " + require2.location
);
}
}
// Creates a unique require function for each module that encapsulates
// that module's id for resolving relative module IDs against.
function makeRequire(viaId) {
/**
* The synchronously executing `require` function. Can only be
* used for static dependencies, or dependencies that have already
* been loaded. If you wish to require a module where the ID is
* only known at runtime, use `require.async`.
* @example
* var URL = require("mini-url");
* var other = URL.resolve("http://example.com/path", "../other");
* //...
* @param {string} id The id of the module to require.
* @return {*} The exports of the module.
* @constructor
*/
var require = function(id) {
var topId = resolve(id, viaId);
return getExports(topId, viaId);
};
/**
* Asynchronous `require` function. Can be used to dynamically
* load a dependency at runtime.
*
* @example
* require.async("mini-url")
* .then(function (URL) {
* var other = URL.resolve("http://example.com/path", "../other");
* //...
* })
* .done();
* @param {string} id The id of the module to require.
* @return {Promise.<*>} A promise for the exports of the module.
*/
require.async = function(id) {
var topId = resolve(id, viaId);
var module = getModuleDescriptor(id);
return deepLoad(topId, viaId)
.then(function () {
return require(topId);
});
};
/**
* Removes any "." and ".." parts from the given id, the ".js"
* extension if it exists and, if relative, makes absolute from
* the base ID of the require.
* @example
* // in my/sub/module
* require.resolve("../other/./sub/module") // -> my/other/sub/module
* @param {string} id The id of the module to resolve.
* @return {string} The resolved module id.
*/
require.resolve = function (id) {
return normalizeId(resolve(id, viaId));
};
require.getModule = getModuleDescriptor; // XXX deprecated, use:
/**
* Gets the module descriptor for the given id.
*
* The module descriptor is the value of the `module` free
* variable given inside the corresponding module.
*
* @param {string} id The id to get the module descriptor for.
* @return {Object} The module descriptor.
* @function
*/
require.getModuleDescriptor = getModuleDescriptor;
/**
* Ensures a module definition is loaded, compiled, analyzed.
*
* Note: this just loads the module. To load its dependencies as
* well use `require.deepLoad`.
*
* Uses the loader created by `config.makeLoader`.
*
* @param {string} id The module id to load.
* @return {Promise} A promise for the completion of the loading.
* @function
*/
require.load = load;
/**
* Loads a module definition and the definitions of its transitive
* dependencies.
* @param {string} id The module id to load.
* @return {Promise} A promise for the completion of the
* loading of the module and its dependencies.
* @function
*/
require.deepLoad = deepLoad;
/**
* Loads a package.
*
* If givenConfig is not provided then the package is loaded as
* a child of this package (which is probably what you want).
* Otherwise the package is loaded with no parent, behaving the
* same as `Require.loadPackage`.
*
* @example
* require.loadPackage({ name: "q" })
* .then(function (qRequire) {
* return qRequire.async("queue");
* })
* .then(function (queue) {
* //...
* })
* .done();
* @param {givenDependency} dependency The dependency to load.
* @param {Object} [givenConfig] The parent configuration to use.
* @return {Promise.<require>} A `require` function for the
* root of the package.
*/
require.loadPackage = function (dependency, givenConfig) {
if (givenConfig) { // explicit configuration, fresh environment
return Require.loadPackage(dependency, givenConfig);
} else { // inherited environment
return config.loadPackage(dependency, config);
}
};
/**
* Returns if this package has the given package dependency loaded.
* @param {givenDependency} dependency The package dependency to check.
* @return {boolean} `true` if the package has been
* loaded, `false` if not.
*/
require.hasPackage = function (dependency) {
return config.hasPackage(dependency);
};
/**
* Gets the `require` for the diven package dependency.
*
* The package must have been loaded (for example with
* `require.loadPackage`) prior to calling this function.
*
* @param {givenDependency} dependency The package dependency to get.
* @return {require} The package's `require`.
*/
require.getPackage = function (dependency) {
return config.getPackage(dependency);
};
/**
* Returns if this is the top-most package of this `require`.
* @return {boolean}
*/
require.isMainPackage = function () {
return require.location === config.mainPackageLocation;
};
/**
* Injects a package description directly into this `require`.
* @param {string} location The absolute path to the
* package.
* @param {Description} description The package description, as
* would usually be found in a `package.json`.
*/
require.injectPackageDescription = function (location, description) {
Require.injectPackageDescription(location, description, config);
};
/**
* Injects the location of a package decription into this
* `require`. TODO
*/
require.injectPackageDescriptionLocation = function (location, descriptionLocation) {
Require.injectPackageDescriptionLocation(location, descriptionLocation, config);
};
/**
* Injects a mapping into this `require`.
* @param {givenDependency} dependency The dependency to use for
* `name`.
* @param {string} name The name of the mapping.
*/
require.injectMapping = function (dependency, name) {
dependency = normalizeDependency(dependency, config, name);
name = name || dependency.name;
config.mappings[name] = dependency;
};
/**
* Inject a dependency, as if it was listed in the
* `package.json`'s `dependency` block.
* @param {string} name The name of the dependency.
*/
require.injectDependency = function (name) {
require.injectMapping({name: name}, name);
};
require.identify = identify;
/**
* Directly inject the exports for the given module id.
*
* Useful to prevent wasteful multiple instantiation if a module
* was loaded in the bootstrapping process and can be trivially
* injected into the system.
*
* @param {string} id The module id to inject exports for.
* @param {*} exports The exports of the module.
* @function
*/
require.inject = inject;
config.exposedConfigs.forEach(function(name) {
require[name] = config[name];
});
/**
* The configuration for this package/require.
* @type {Object}
*/
require.config = config;
/**
* Low level function that reads a location.
*
* In the browser the location should be a url, and in node it
* should be a path.
*
* @param {string} location The location to read.
* @return {Promise.<string>} A promise for the string contents of
* the file at `location`.
* @function
*/
require.read = Require.read;
return require;
}
require = makeRequire("");
return require;
};
/**
* @see require.injectPackageDescription
*/
Require.injectPackageDescription = function (location, description, config) {
var descriptions =
config.descriptions =
config.descriptions || {};
descriptions[location] = Promise.resolve(description);
};
/**
* @see require.injectPackageDescriptionLocation
*/
Require.injectPackageDescriptionLocation = function (location, descriptionLocation, config) {
var descriptionLocations =
config.descriptionLocations =
config.descriptionLocations || {};
descriptionLocations[location] = descriptionLocation;
};
Require.loadPackageDescription = function (dependency, config) {
var location = dependency.location;
var descriptions =
config.descriptions =
config.descriptions || {};
if (descriptions[location] === void 0) {
var descriptionLocations =
config.descriptionLocations =
config.descriptionLocations || {};
var descriptionLocation;
if (descriptionLocations[location]) {
descriptionLocation = descriptionLocations[location];
} else {
descriptionLocation = URL.resolve(location, "package.json");
}
descriptions[location] = Require.read(descriptionLocation)
.then(function (json) {
try {
return JSON.parse(json);
} catch (error) {
error.message = error.message + " in " + JSON.stringify(descriptionLocation)
throw error;
}
});
}
return descriptions[location];
};
/**
* @see require.loadPackage
*/
Require.loadPackage = function (dependency, config) {
dependency = normalizeDependency(dependency, config);
if (!dependency.location) {
throw new Error("Can't find dependency: " + JSON.stringify(dependency));
}
var location = dependency.location;
config = Object.create(config || null);
var loadingPackages = config.loadingPackages = config.loadingPackages || {};
var loadedPackages = config.packages = {};
var registry = config.registry = config.registry || Object.create(null);
config.mainPackageLocation = location;
config.hasPackage = function (dependency) {
dependency = normalizeDependency(dependency, config);
if (!dependency.location)
return false;
var location = dependency.location;
return !!loadedPackages[location];
};
config.getPackage = function (dependency) {
dependency = normalizeDependency(dependency, config);
if (!dependency.location) {
throw new Error("Can't find dependency: " + JSON.stringify(dependency) + " from " + config.location);
}
var location = dependency.location;
if (!loadedPackages[location]) {
if (loadingPackages[location]) {
throw new Error(
"Dependency has not finished loading: " + JSON.stringify(dependency)
);
} else {
throw new Error(
"Dependency was not loaded: " + JSON.stringify(dependency)
);
}
}
return loadedPackages[location];
};
config.loadPackage = function (dependency, viaConfig) {
dependency = normalizeDependency(dependency, viaConfig);
if (!dependency.location) {
throw new Error("Can't find dependency: " + JSON.stringify(dependency) + " from " + config.location);
}
var location = dependency.location;
if (!loadingPackages[location]) {
loadingPackages[location] = Require.loadPackageDescription(dependency, config)
.then(function (packageDescription) {
var subconfig = configurePackage(
location,
packageDescription,
config
);
var pkg = Require.makeRequire(subconfig);
loadedPackages[location] = pkg;
return pkg;
});
}
return loadingPackages[location];
};
var pkg = config.loadPackage(dependency);
pkg.location = location;
pkg.async = function (id, callback) {
return pkg.then(function (require) {
return require.async(id, callback);
});
};
return pkg;
};
/**
* A number of functions accept a dependency as an argument.
*
* If the dependency is an object, at least one of the properties must be
* given.
*
* If the dependency is a string, it is converted to an object with the
* `location` property set to the value of the string.
*
* @typedef {Object|string} givenDependency
* @property {string} [name] The name of the dependency.
*
* If only the name is given then the location is resolved relative to the
* `packagesDirectory` of the package config (generally "node_modules").
* @property {string} [location] The location of the dependency.
*
* If the location is relative it is resolved relative to the `location`
* of the package config.
*/
function normalizeDependency(dependency, config, name) {
config = config || {};
if (typeof dependency === "string") {
dependency = {
location: dependency
};
}
if (dependency.main) {
dependency.location = config.mainPackageLocation;
}
// if the named dependency has already been found at another
// location, refer to the same eventual instance
if (
dependency.name &&
config.registry &&
config.registry[dependency.name]
) {
dependency.location = config.registry[dependency.name];
}
// default location
if (!dependency.location && config.packagesDirectory && dependency.name) {
dependency.location = URL.resolve(
config.packagesDirectory,
dependency.name + "/"
);
}
if (!dependency.location)
return dependency; // partially completed
// make sure the dependency location has a trailing slash so that
// relative urls will resolve properly
if (!/\/$/.test(dependency.location)) {
dependency.location += "/";
}
// resolve the location relative to the current package
if (!Require.isAbsolute(dependency.location)) {
if (!config.location) {
throw new Error(
"Dependency locations must be fully qualified: " +
JSON.stringify(dependency)
);
}
dependency.location = URL.resolve(
config.location,
dependency.location
);
}
// register the package name so the location can be reused
if (dependency.name) {
config.registry[dependency.name] = dependency.location;
}
return dependency;
}
function configurePackage(location, description, parent) {
if (!/\/$/.test(location)) {
location += "/";
}
var config = Object.create(parent);
config.name = description.name;
config.location = location || Require.getLocation();
config.packageDescription = description;
config.useScriptInjection = description.useScriptInjection;
if (description.production !== void 0) {
config.production = description.production;
}
// explicitly mask definitions and modules, which must
// not apply to child packages
var modules = config.modules = config.modules || {};
var registry = config.registry;
if (config.name !== void 0 && !registry[config.name]) {
registry[config.name] = config.location;
}
// overlay
var overlay = description.overlay || {};
var layer;
(config.overlays || Require.overlays).forEach(function (engine) {
if (overlay[engine]) {
var layer = overlay[engine];
for (var name in layer) {
description[name] = layer[name];
}
}
});
delete description.overlay;
// directories
description.directories = description.directories || {};
description.directories.lib =
description.directories.lib === void 0 ? "./" : description.directories.lib;
var lib = description.directories.lib;
// lib
config.lib = URL.resolve(location, "./" + lib);
var packagesDirectory = description.directories.packages || "node_modules";
packagesDirectory = URL.resolve(location, packagesDirectory + "/");
config.packagesDirectory = packagesDirectory;
// The default "main" module of a package has the same name as the
// package.
if (description.main !== void 0) {
// main, injects a definition for the main module, with
// only its path. makeRequire goes through special effort
// in deepLoad to re-initialize this definition with the
// loaded definition from the given path.
modules[""] = {
id: "",
redirect: normalizeId(description.main),
location: config.location
};
if (description.name !== modules[""].redirect) {
modules[description.name] = {
id: description.name,
redirect: "",
location: URL.resolve(location, description.name)
};
}
}
//Deal with redirects
var redirects = description.redirects;
if (redirects !== void 0) {
Object.keys(redirects).forEach(function (name) {
modules[name] = {
id: name,
redirect: redirects[name],
location: URL.resolve(location, name)
};
});
}
// mappings, link this package to other packages.
var mappings = description.mappings || {};
// dependencies, devDependencies if not in production
[description.dependencies, !config.production ? description.devDependencies : null]
.forEach(function (dependencies) {
if (!dependencies)
return;
Object.keys(dependencies).forEach(function (name) {
if (!mappings[name]) {
// dependencies are equivalent to name and version mappings,
// though the version predicate string is presently ignored
// (TODO)
mappings[name] = {
name: name,
version: dependencies[name]
};
}
});
});
// mappings
Object.keys(mappings).forEach(function (name) {
var mapping = mappings[name] = normalizeDependency(
mappings[name],
config,
name
);
});
config.mappings = mappings;
return config;
}
// Helper functions:
function has(object, property) {
return Object.prototype.hasOwnProperty.call(object, property);
}
// Resolves CommonJS module IDs (not paths)
Require.resolve = resolve;
function resolve(id, baseId) {
id = String(id);
var source = id.split("/");
var target = [];
// if the source is relative append it to the parent of baseId
if (source.length && source[0] === "." || source[0] === "..") {
var parts = baseId.split("/");
parts.pop();
source.unshift.apply(source, parts);
}
for (var i = 0, ii = source.length; i < ii; i++) {
var part = source[i];
if (part === "" || part === ".") {
} else if (part === "..") {
if (target.length) {
target.pop();
}
} else {
target.push(part);
}
}
return target.join("/");
}
Require.base = function (location) {
// matches Unix basename
return String(location)
.replace(/(.+?)\/+$/, "$1")
.match(/([^\/]+$|^\/$|^$)/)[1];
};
// Tests whether the location or URL is a absolute.
Require.isAbsolute = function(location) {
return (/^[\w\-]+:/).test(location);
};
// Extracts dependencies by parsing code and looking for "require" (currently using a simple regexp)
Require.parseDependencies = function(factory) {
var o = {};
String(factory).replace(/(?:^|[^\w\$_.])require\s*\(\s*["']([^"']*)["']\s*\)/g, function(_, id) {
o[id] = true;
});
return Object.keys(o);
};
// Built-in compiler/preprocessor "middleware":
Require.DependenciesCompiler = function(config, compile) {
return function(module) {
if (!module.dependencies && module.text !== void 0) {
module.dependencies = config.parseDependencies(module.text);
}
compile(module);
if (module && !module.dependencies) {
if (module.text || module.factory) {
module.dependencies = Require.parseDependencies(module.text || module.factory);
} else {
module.dependencies = [];
}
}
return module;
};
};
// Support she-bang for shell scripts by commenting it out (it is never
// valid JavaScript syntax anyway)
Require.ShebangCompiler = function(config, compile) {
return function (module) {
if (module.text) {
module.text = module.text.replace(/^#!/, "//#!");
}
compile(module);
};
};
Require.LintCompiler = function(config, compile) {
return function(module) {
try {
compile(module);
} catch (error) {
if (config.lint) {
Promise.nextTick(function () {
config.lint(module);
});
}
throw error;
}
};
};
Require.exposedConfigs = [
"paths",
"mappings",
"location",
"packageDescription",
"packages",
"modules"
];
Require.makeCompiler = function(config) {
return Require.JsonCompiler(
config,
Require.ShebangCompiler(
config,
Require.DependenciesCompiler(
config,
Require.LintCompiler(
config,
Require.Compiler(config)
)
)
)
);
};
Require.JsonCompiler = function (config, compile) {
return function (module) {
var json = (module.location || "").match(/\.json$/);
if (json) {
module.exports = JSON.parse(module.text);
return module;
} else {
return compile(module);
}
};
};
// Built-in loader "middleware":
// Using mappings hash to load modules that match a mapping.
Require.MappingsLoader = function(config, load) {
config.mappings = config.mappings || {};
config.name = config.name;
// finds a mapping to follow, if any
return function (id, module) {
var mappings = config.mappings;
var prefixes = Object.keys(mappings);
var length = prefixes.length;
if (Require.isAbsolute(id)) {
return load(id, module);
}
// TODO: remove this when all code has been migrated off of the autonomous name-space problem
if (
config.name !== void 0 &&
id.indexOf(config.name) === 0 &&
id.charAt(config.name.length) === "/"
) {
console.warn("Package reflexive module ignored:", id);
}
var i, prefix;
for (i = 0; i < length; i++) {
prefix = prefixes[i];
if (
id === prefix ||
id.indexOf(prefix) === 0 &&
id.charAt(prefix.length) === "/"
) {
var mapping = mappings[prefix];
var rest = id.slice(prefix.length + 1);
return config.loadPackage(mapping, config)
.then(function (mappingRequire) {
module.mappingRedirect = rest;
module.mappingRequire = mappingRequire;
return mappingRequire.deepLoad(rest, config.location);
});
}
}
return load(id, module);
};
};
Require.ExtensionsLoader = function(config, load) {
var extensions = config.extensions || ["js"];
var loadWithExtension = extensions.reduceRight(function (next, extension) {
return function (id, module) {
return load(id + "." + extension, module)
.fail(function (error) {
if (/^Can't find /.test(error.message)) {
return next(id, module);
} else {
throw error;
}
});
};
}, function (id, module) {
throw new Error(
"Can't find " + JSON.stringify(id) + " with extensions " +
JSON.stringify(extensions) + " in package at " +
JSON.stringify(config.location)
);
});
return function (id, module) {
if (Require.base(id).indexOf(".") !== -1) {
// already has an extension
return load(id, module);
} else {
return loadWithExtension(id, module);
}
};
};
// Attempts to load using multiple base paths (or one absolute path) with a
// single loader.
Require.PathsLoader = function(config, load) {
var loadFromPaths = config.paths.reduceRight(function (next, path) {
return function (id, module) {
var newId = URL.resolve(path, id);
return load(newId, module)
.fail(function (error) {
if (/^Can't find /.test(error.message)) {
return next(id, module);
} else {
throw error;
}
});
};
}, function (id, module) {
throw new Error(
"Can't find " + JSON.stringify(id) + " from paths " +
JSON.stringify(config.paths) + " in package at " +
JSON.stringify(config.location)
);
});
return function(id, module) {
if (Require.isAbsolute(id)) {
// already fully qualified
return load(id, module);
} else {
return loadFromPaths(id, module);
}
};
};
Require.MemoizedLoader = function (config, load) {
var cache = config.cache = config.cache || {};
return memoize(load, cache);
};
var normalizeId = function (id) {
var match = /^(.*)\.js$/.exec(id);
if (match) {
id = match[1];
}
return id;
};
var memoize = function (callback, cache) {
cache = cache || {};
return function (key, arg) {
if (!has(cache, key)) {
cache[key] = Promise.fcall(callback, key, arg);
}
return cache[key];
};
};
});