Show More
Commit Description:
merge
Commit Description:
merge
References:
File last commit:
Show/Diff file:
Action:
node_modules/amdefine/amdefine.js
| 301 lines
| 9.7 KiB
| application/javascript
| JavascriptLexer
|
r789 | /** vim: et:ts=4:sw=4:sts=4 | |||
* @license amdefine 1.0.1 Copyright (c) 2011-2016, The Dojo Foundation All Rights Reserved. | ||||
* Available via the MIT or new BSD license. | ||||
* see: http://github.com/jrburke/amdefine for details | ||||
*/ | ||||
/*jslint node: true */ | ||||
/*global module, process */ | ||||
'use strict'; | ||||
/** | ||||
* Creates a define for node. | ||||
* @param {Object} module the "module" object that is defined by Node for the | ||||
* current module. | ||||
* @param {Function} [requireFn]. Node's require function for the current module. | ||||
* It only needs to be passed in Node versions before 0.5, when module.require | ||||
* did not exist. | ||||
* @returns {Function} a define function that is usable for the current node | ||||
* module. | ||||
*/ | ||||
function amdefine(module, requireFn) { | ||||
'use strict'; | ||||
var defineCache = {}, | ||||
loaderCache = {}, | ||||
alreadyCalled = false, | ||||
path = require('path'), | ||||
makeRequire, stringRequire; | ||||
/** | ||||
* Trims the . and .. from an array of path segments. | ||||
* It will keep a leading path segment if a .. will become | ||||
* the first path segment, to help with module name lookups, | ||||
* which act like paths, but can be remapped. But the end result, | ||||
* all paths that use this function should look normalized. | ||||
* NOTE: this method MODIFIES the input array. | ||||
* @param {Array} ary the array of path segments. | ||||
*/ | ||||
function trimDots(ary) { | ||||
var i, part; | ||||
for (i = 0; ary[i]; i+= 1) { | ||||
part = ary[i]; | ||||
if (part === '.') { | ||||
ary.splice(i, 1); | ||||
i -= 1; | ||||
} else if (part === '..') { | ||||
if (i === 1 && (ary[2] === '..' || ary[0] === '..')) { | ||||
//End of the line. Keep at least one non-dot | ||||
//path segment at the front so it can be mapped | ||||
//correctly to disk. Otherwise, there is likely | ||||
//no path mapping for a path starting with '..'. | ||||
//This can still fail, but catches the most reasonable | ||||
//uses of .. | ||||
break; | ||||
} else if (i > 0) { | ||||
ary.splice(i - 1, 2); | ||||
i -= 2; | ||||
} | ||||
} | ||||
} | ||||
} | ||||
function normalize(name, baseName) { | ||||
var baseParts; | ||||
//Adjust any relative paths. | ||||
if (name && name.charAt(0) === '.') { | ||||
//If have a base name, try to normalize against it, | ||||
//otherwise, assume it is a top-level require that will | ||||
//be relative to baseUrl in the end. | ||||
if (baseName) { | ||||
baseParts = baseName.split('/'); | ||||
baseParts = baseParts.slice(0, baseParts.length - 1); | ||||
baseParts = baseParts.concat(name.split('/')); | ||||
trimDots(baseParts); | ||||
name = baseParts.join('/'); | ||||
} | ||||
} | ||||
return name; | ||||
} | ||||
/** | ||||
* Create the normalize() function passed to a loader plugin's | ||||
* normalize method. | ||||
*/ | ||||
function makeNormalize(relName) { | ||||
return function (name) { | ||||
return normalize(name, relName); | ||||
}; | ||||
} | ||||
function makeLoad(id) { | ||||
function load(value) { | ||||
loaderCache[id] = value; | ||||
} | ||||
load.fromText = function (id, text) { | ||||
//This one is difficult because the text can/probably uses | ||||
//define, and any relative paths and requires should be relative | ||||
//to that id was it would be found on disk. But this would require | ||||
//bootstrapping a module/require fairly deeply from node core. | ||||
//Not sure how best to go about that yet. | ||||
throw new Error('amdefine does not implement load.fromText'); | ||||
}; | ||||
return load; | ||||
} | ||||
makeRequire = function (systemRequire, exports, module, relId) { | ||||
function amdRequire(deps, callback) { | ||||
if (typeof deps === 'string') { | ||||
//Synchronous, single module require('') | ||||
return stringRequire(systemRequire, exports, module, deps, relId); | ||||
} else { | ||||
//Array of dependencies with a callback. | ||||
//Convert the dependencies to modules. | ||||
deps = deps.map(function (depName) { | ||||
return stringRequire(systemRequire, exports, module, depName, relId); | ||||
}); | ||||
//Wait for next tick to call back the require call. | ||||
if (callback) { | ||||
process.nextTick(function () { | ||||
callback.apply(null, deps); | ||||
}); | ||||
} | ||||
} | ||||
} | ||||
amdRequire.toUrl = function (filePath) { | ||||
if (filePath.indexOf('.') === 0) { | ||||
return normalize(filePath, path.dirname(module.filename)); | ||||
} else { | ||||
return filePath; | ||||
} | ||||
}; | ||||
return amdRequire; | ||||
}; | ||||
//Favor explicit value, passed in if the module wants to support Node 0.4. | ||||
requireFn = requireFn || function req() { | ||||
return module.require.apply(module, arguments); | ||||
}; | ||||
function runFactory(id, deps, factory) { | ||||
var r, e, m, result; | ||||
if (id) { | ||||
e = loaderCache[id] = {}; | ||||
m = { | ||||
id: id, | ||||
uri: __filename, | ||||
exports: e | ||||
}; | ||||
r = makeRequire(requireFn, e, m, id); | ||||
} else { | ||||
//Only support one define call per file | ||||
if (alreadyCalled) { | ||||
throw new Error('amdefine with no module ID cannot be called more than once per file.'); | ||||
} | ||||
alreadyCalled = true; | ||||
//Use the real variables from node | ||||
//Use module.exports for exports, since | ||||
//the exports in here is amdefine exports. | ||||
e = module.exports; | ||||
m = module; | ||||
r = makeRequire(requireFn, e, m, module.id); | ||||
} | ||||
//If there are dependencies, they are strings, so need | ||||
//to convert them to dependency values. | ||||
if (deps) { | ||||
deps = deps.map(function (depName) { | ||||
return r(depName); | ||||
}); | ||||
} | ||||
//Call the factory with the right dependencies. | ||||
if (typeof factory === 'function') { | ||||
result = factory.apply(m.exports, deps); | ||||
} else { | ||||
result = factory; | ||||
} | ||||
if (result !== undefined) { | ||||
m.exports = result; | ||||
if (id) { | ||||
loaderCache[id] = m.exports; | ||||
} | ||||
} | ||||
} | ||||
stringRequire = function (systemRequire, exports, module, id, relId) { | ||||
//Split the ID by a ! so that | ||||
var index = id.indexOf('!'), | ||||
originalId = id, | ||||
prefix, plugin; | ||||
if (index === -1) { | ||||
id = normalize(id, relId); | ||||
//Straight module lookup. If it is one of the special dependencies, | ||||
//deal with it, otherwise, delegate to node. | ||||
if (id === 'require') { | ||||
return makeRequire(systemRequire, exports, module, relId); | ||||
} else if (id === 'exports') { | ||||
return exports; | ||||
} else if (id === 'module') { | ||||
return module; | ||||
} else if (loaderCache.hasOwnProperty(id)) { | ||||
return loaderCache[id]; | ||||
} else if (defineCache[id]) { | ||||
runFactory.apply(null, defineCache[id]); | ||||
return loaderCache[id]; | ||||
} else { | ||||
if(systemRequire) { | ||||
return systemRequire(originalId); | ||||
} else { | ||||
throw new Error('No module with ID: ' + id); | ||||
} | ||||
} | ||||
} else { | ||||
//There is a plugin in play. | ||||
prefix = id.substring(0, index); | ||||
id = id.substring(index + 1, id.length); | ||||
plugin = stringRequire(systemRequire, exports, module, prefix, relId); | ||||
if (plugin.normalize) { | ||||
id = plugin.normalize(id, makeNormalize(relId)); | ||||
} else { | ||||
//Normalize the ID normally. | ||||
id = normalize(id, relId); | ||||
} | ||||
if (loaderCache[id]) { | ||||
return loaderCache[id]; | ||||
} else { | ||||
plugin.load(id, makeRequire(systemRequire, exports, module, relId), makeLoad(id), {}); | ||||
return loaderCache[id]; | ||||
} | ||||
} | ||||
}; | ||||
//Create a define function specific to the module asking for amdefine. | ||||
function define(id, deps, factory) { | ||||
if (Array.isArray(id)) { | ||||
factory = deps; | ||||
deps = id; | ||||
id = undefined; | ||||
} else if (typeof id !== 'string') { | ||||
factory = id; | ||||
id = deps = undefined; | ||||
} | ||||
if (deps && !Array.isArray(deps)) { | ||||
factory = deps; | ||||
deps = undefined; | ||||
} | ||||
if (!deps) { | ||||
deps = ['require', 'exports', 'module']; | ||||
} | ||||
//Set up properties for this module. If an ID, then use | ||||
//internal cache. If no ID, then use the external variables | ||||
//for this node module. | ||||
if (id) { | ||||
//Put the module in deep freeze until there is a | ||||
//require call for it. | ||||
defineCache[id] = [id, deps, factory]; | ||||
} else { | ||||
runFactory(id, deps, factory); | ||||
} | ||||
} | ||||
//define.require, which has access to all the values in the | ||||
//cache. Useful for AMD modules that all have IDs in the file, | ||||
//but need to finally export a value to node based on one of those | ||||
//IDs. | ||||
define.require = function (id) { | ||||
if (loaderCache[id]) { | ||||
return loaderCache[id]; | ||||
} | ||||
if (defineCache[id]) { | ||||
runFactory.apply(null, defineCache[id]); | ||||
return loaderCache[id]; | ||||
} | ||||
}; | ||||
define.amd = {}; | ||||
return define; | ||||
} | ||||
module.exports = amdefine; | ||||