react / react-0.13.3 / examples / basic-commonjs / node_modules / reactify / node_modules / react-tools / node_modules / commoner / node_modules / install / install.js
81164 views(function(global, undefined) {1// Defining the `install` function more than once leads to mayhem, so2// return immedately if a property called `install` is already defined on3// the global object.4if (global.install)5return;67// The `installed` object maps absolute module identifiers to module8// definitions available for requirement.9var installed = {};1011// I make frequent use of `hasOwn.call` to test for the presence of object12// properties without traversing the prototype chain.13var hasOwn = installed.hasOwnProperty;1415// Anonymous modules are pushed onto a queue so that (when ready) they can16// be executed in order of installation.17var qhead = {};18var qtail = qhead;1920// Define the `install` function globally.21global.install = function(id, module) {22// To install a named module, pass an absolute module identifier23// string followed by a module definition. Note that named modules are24// not evaluated until they are required for the first time.25if (typeof id === "string" && module) {26if (!hasOwn.call(installed, id)) {27installed[module.id = id] = module;28flushQueue();29}30// To install an anonymous module, pass a module definition without an31// identifier. Anonymous modules are executed in order of32// installation, as soon as their requirements have been installed.33} else if (id && typeof id.call === "function") {34qtail = qtail.next = { module: id };35if (qhead.next === qtail)36flushQueue();37}38};3940// The `require` function takes an absolute module identifier and returns41// the `exports` object defined by that module. An error is thrown if no42// module with the given identifier is installed.43function require(moduleId) {44if (hasOwn.call(installed, moduleId)) {45var module = installed[moduleId];46if (!hasOwn.call(module, "exports")) {47// Each module receives a version of `require` that knows how48// to `absolutize` relative module identifiers with respect to49// `moduleId`.50module.call(global, function(id) {51return require(absolutize(id, moduleId));52}, module.exports = {}, module);53}54// Note that `module.exports` may be redefined during evaluation55// of the module.56return module.exports;57}58// Since modules are evaluated only after all their requirements have59// been installed, this error generally means that `require` was60// called with an identifier that was not seen (or was not understood)61// by the dependency scanner.62throw new Error('module "' + moduleId + '" not installed');63}6465// Given two module identifiers `id` and `baseId`, the `absolutize`66// function returns the absolute form of `id`, as if `id` were required67// from a module with the identifier `baseId`. For more information about68// relative identifiers, refer to the69// [spec](http://wiki.commonjs.org/wiki/Modules/1.1#Module_Identifiers).70var pathNormExp = /\/(\.?|[^\/]+\/\.\.)\//;71function absolutize(id, baseId) {72if (id.charAt(0) === ".") {73// Note: if `baseId` is omitted, then `"/undefined/../" + id` will74// be the starting point for normalization, which works just fine!75id = "/" + baseId + "/../" + id;76while (id != (baseId = id.replace(pathNormExp, "/")))77id = baseId;78id = id.replace(/^\//, "");79}80return id;81}8283// The `flushQueue` function attempts to evaluate the oldest module in the84// queue, provided all of its dependencies have been installed. This85// provision is important because it ensures that the module can call86// `require` without fear of missing dependencies.87function flushQueue() {88var next = qhead.next, module;89if (next && !flushing && ready(module = next.module)) {90flushing = qhead = next;91// Module evaluation might throw an exception, so we need to92// schedule the next call to `flushQueue` before invoking93// `module.call`. The `setTimeout` function allows the stack to94// unwind before flushing resumes, so that the browser has a chance95// to report exceptions and/or handle other events.96global.setTimeout(resume, 0);97module.call(global, require);98flushing = undefined;99}100}101102// If `install` is called during the evaluation of a queued module,103// `flushQueue` could be invoked recursively. To prevent double evaluation,104// `flushQueue` sets `flushing` to a truthy value before it evaluates a105// module and refuses to evaluate any modules if `flushing` is truthy106// already.107var flushing;108109// Since `resume` is only ever invoked from `setTimeout`, there is no risk110// that `flushQueue` is already executing, so it is safe to clear the111// `flushing` flag unconditionally.112function resume() {113flushing = undefined;114flushQueue();115}116117// To be recognized as dependencies, calls to `require` must use string118// literal identifiers.119var requireExp = /\brequire\(['"]([^'"]+)['"]\)/g;120121// A module is `ready` to be evaluated if122//123// 1. it has an `.exports` property (indicating that it has already begun to be evaluated) or124// 1. all of its direct dependencies are installed and `ready` to be evaluated.125//126// Note that the above definition is recursive.127function ready(module) {128var deps, code, match, id, result = true;129130if (!module.seen &&131!hasOwn.call(module, "exports"))132{133// Here's a little secret: module definitions don't have to be134// functions, as long as they have a suitable `.toString` and135// `.call` methods. If you have a really long module that you136// don't want to waste time scanning, just override its137// `.toString` function to return something equivalent (with138// regard to dependencies) but shorter.139deps = module.deps;140if (!deps) {141code = module + "";142deps = module.deps = {};143requireExp.lastIndex = 0;144while ((match = requireExp.exec(code)))145deps[absolutize(match[1], module.id)] = true;146}147148// There may be cycles in the dependency graph, so we must be149// careful that the recursion always terminates. Each module we150// check is temporarily marked as `.seen` before its dependencies151// are traversed, so that if we encounter the same module again we152// can immediately return `true`.153module.seen = true;154155for (id in deps) {156if (hasOwn.call(deps, id)) {157// Once a dependency is determined to be satisfied, we158// remove its identifier from `module.deps`, so that we159// can avoid considering it again if `ready` is called160// multiple times.161if (hasOwn.call(installed, id) && ready(installed[id])) {162delete deps[id];163// If any dependency is missing or not `ready`, then the164// current module is not yet `ready`. The `break` is not165// strictly necessary here, but immediately terminating166// the loop postpones work that can be done later.167} else {168result = false;169break;170}171}172}173174// Ordinarily I would be more paranoid about always resetting175// `module.seen` to `false`, but if you thoroughly examine the code176// above, you'll find that the only real threat of exceptions comes177// from evaluating `code = module + ""` in a recursive call to178// `ready`. So if you decide to override the `.toString` method of a179// module for performance reasons, get it right.180module.seen = false;181}182183return result;184}185186// The most reliable way to get the global object:187// [http://stackoverflow.com/a/3277192/128454](http://stackoverflow.com/a/3277192/128454)188}(Function("return this")()));189190191