Bones/node_modules/systemjs/lib/core.js

486 lines
14 KiB
JavaScript
Raw Normal View History

2017-05-17 13:45:25 -04:00
var absURLRegEx = /^[^\/]+:\/\//;
function readMemberExpression(p, value) {
var pParts = p.split('.');
while (pParts.length)
value = value[pParts.shift()];
return value;
}
var baseURLCache = {};
function getBaseURLObj() {
if (baseURLCache[this.baseURL])
return baseURLCache[this.baseURL];
// normalize baseURL if not already
if (this.baseURL[this.baseURL.length - 1] != '/')
this.baseURL += '/';
var baseURL = new URL(this.baseURL, baseURI);
this.baseURL = baseURL.href;
return (baseURLCache[this.baseURL] = baseURL);
}
function getMapMatch(map, name) {
var bestMatch, bestMatchLength = 0;
for (var p in map) {
if (name.substr(0, p.length) == p && (name.length == p.length || name[p.length] == '/')) {
var curMatchLength = p.split('/').length;
if (curMatchLength <= bestMatchLength)
continue;
bestMatch = p;
bestMatchLength = curMatchLength;
}
}
return bestMatch;
}
function setProduction(isProduction) {
this.set('@system-env', this.newModule({
browser: isBrowser,
node: !!this._nodeRequire,
production: isProduction,
'default': true
}));
}
var baseURIObj = new URL(baseURI);
hookConstructor(function(constructor) {
return function() {
constructor.call(this);
// support baseURL
this.baseURL = baseURI.substr(0, baseURI.lastIndexOf('/') + 1);
// support map and paths
this.map = {};
this.paths = {};
// global behaviour flags
this.warnings = false;
this.defaultJSExtensions = false;
this.pluginFirst = false;
this.loaderErrorStack = false;
// by default load ".json" files as json
// leading * meta doesn't need normalization
// NB add this in next breaking release
// this.meta['*.json'] = { format: 'json' };
// support the empty module, as a concept
this.set('@empty', this.newModule({}));
setProduction.call(this, false);
};
});
// include the node require since we're overriding it
if (typeof require != 'undefined' && typeof process != 'undefined' && !process.browser)
SystemJSLoader.prototype._nodeRequire = require;
var nodeCoreModules = ['assert', 'buffer', 'child_process', 'cluster', 'console', 'constants',
'crypto', 'dgram', 'dns', 'domain', 'events', 'fs', 'http', 'https', 'module', 'net', 'os', 'path',
'process', 'punycode', 'querystring', 'readline', 'repl', 'stream', 'string_decoder', 'sys', 'timers',
'tls', 'tty', 'url', 'util', 'vm', 'zlib'];
/*
Core SystemJS Normalization
If a name is relative, we apply URL normalization to the page
If a name is an absolute URL, we leave it as-is
Plain names (neither of the above) run through the map and paths
normalization phases.
The paths normalization phase applies last (paths extension), which
defines the `decanonicalize` function and normalizes everything into
a URL.
*/
function isPlain(name) {
return (name[0] != '.' || (!!name[1] && name[1] != '/' && name[1] != '.')) && name[0] != '/' && !name.match(absURLRegEx);
}
function urlResolve(name, parent) {
if (parent)
parent = parent.replace(/#/g, '%05');
return new URL(name, parent || baseURIObj).href.replace(/%05/g, '#');
}
// only applies to plain names
function baseURLResolve(loader, name) {
return new URL(name, getBaseURLObj.call(loader)).href;
}
function coreResolve(name, parentName) {
// standard URL resolution
if (!isPlain(name))
return urlResolve(name, parentName);
// plain names not starting with './', '://' and '/' go through custom resolution
var mapMatch = getMapMatch(this.map, name);
if (mapMatch) {
name = this.map[mapMatch] + name.substr(mapMatch.length);
if (!isPlain(name))
return urlResolve(name);
}
if (this.has(name))
return name;
// dynamically load node-core modules when requiring `@node/fs` for example
if (name.substr(0, 6) == '@node/' && nodeCoreModules.indexOf(name.substr(6)) != -1) {
if (!this._nodeRequire)
throw new TypeError('Error loading ' + name + '. Can only load node core modules in Node.');
this.set(name, this.newModule(getESModule(this._nodeRequire(name.substr(6)))));
return name;
}
var pathed = applyPaths(this.paths, name);
if (pathed && !isPlain(pathed))
return urlResolve(pathed);
return baseURLResolve(this, pathed || name);
}
hook('normalize', function(normalize) {
return function(name, parentName, skipExt) {
var resolved = coreResolve.call(this, name, parentName);
if (!skipExt && this.defaultJSExtensions && resolved.substr(resolved.length - 3, 3) != '.js' && !isPlain(resolved))
resolved += '.js';
return resolved;
};
});
// percent encode just '#' in urls if using HTTP requests
var httpRequest = typeof XMLHttpRequest != 'undefined';
hook('locate', function(locate) {
return function(load) {
return Promise.resolve(locate.call(this, load))
.then(function(address) {
if (httpRequest)
return address.replace(/#/g, '%23');
return address;
});
};
});
/*
* Fetch with authorization
*/
hook('fetch', function() {
return function(load) {
return new Promise(function(resolve, reject) {
fetchTextFromURL(load.address, load.metadata.authorization, resolve, reject);
});
};
});
/*
__useDefault
When a module object looks like:
newModule(
__useDefault: true,
default: 'some-module'
})
Then importing that module provides the 'some-module'
result directly instead of the full module.
Useful for eg module.exports = function() {}
*/
hook('import', function(systemImport) {
return function(name, parentName, parentAddress) {
if (parentName && parentName.name)
warn.call(this, 'SystemJS.import(name, { name: parentName }) is deprecated for SystemJS.import(name, parentName), while importing ' + name + ' from ' + parentName.name);
return systemImport.call(this, name, parentName, parentAddress).then(function(module) {
return module.__useDefault ? module['default'] : module;
});
};
});
/*
* Allow format: 'detect' meta to enable format detection
*/
hook('translate', function(systemTranslate) {
return function(load) {
if (load.metadata.format == 'detect')
load.metadata.format = undefined;
return systemTranslate.call(this, load);
};
});
/*
* JSON format support
*
* Supports loading JSON files as a module format itself
*
* Usage:
*
* SystemJS.config({
* meta: {
* '*.json': { format: 'json' }
* }
* });
*
* Module is returned as if written:
*
* export default {JSON}
*
* No named exports are provided
*
* Files ending in ".json" are treated as json automatically by SystemJS
*/
hook('instantiate', function(instantiate) {
return function(load) {
if (load.metadata.format == 'json' && !this.builder) {
var entry = load.metadata.entry = createEntry();
entry.deps = [];
entry.execute = function() {
try {
return JSON.parse(load.source);
}
catch(e) {
throw new Error("Invalid JSON file " + load.name);
}
};
}
};
})
/*
Extend config merging one deep only
loader.config({
some: 'random',
config: 'here',
deep: {
config: { too: 'too' }
}
});
<=>
loader.some = 'random';
loader.config = 'here'
loader.deep = loader.deep || {};
loader.deep.config = { too: 'too' };
Normalizes meta and package configs allowing for:
SystemJS.config({
meta: {
'./index.js': {}
}
});
To become
SystemJS.meta['https://thissite.com/index.js'] = {};
For easy normalization canonicalization with latest URL support.
*/
SystemJSLoader.prototype.env = 'development';
var curCurScript;
SystemJSLoader.prototype.config = function(cfg) {
var loader = this;
if ('loaderErrorStack' in cfg) {
curCurScript = $__curScript;
if (cfg.loaderErrorStack)
$__curScript = undefined;
else
$__curScript = curCurScript;
}
if ('warnings' in cfg)
loader.warnings = cfg.warnings;
// transpiler deprecation path
if (cfg.transpilerRuntime === false)
loader._loader.loadedTranspilerRuntime = true;
// always configure baseURL first
if (cfg.baseURL) {
var hasConfig = false;
function checkHasConfig(obj) {
for (var p in obj)
if (hasOwnProperty.call(obj, p))
return true;
}
if (checkHasConfig(loader.packages) || checkHasConfig(loader.meta) || checkHasConfig(loader.depCache) || checkHasConfig(loader.bundles) || checkHasConfig(loader.packageConfigPaths))
throw new TypeError('Incorrect configuration order. The baseURL must be configured with the first SystemJS.config call.');
loader.baseURL = cfg.baseURL;
// sanitize baseURL
getBaseURLObj.call(loader);
}
if (cfg.defaultJSExtensions) {
loader.defaultJSExtensions = cfg.defaultJSExtensions;
warn.call(loader, 'The defaultJSExtensions configuration option is deprecated, use packages configuration instead.');
}
if (cfg.pluginFirst)
loader.pluginFirst = cfg.pluginFirst;
if (cfg.production)
setProduction.call(loader, true);
if (cfg.paths) {
for (var p in cfg.paths)
loader.paths[p] = cfg.paths[p];
}
if (cfg.map) {
var objMaps = '';
for (var p in cfg.map) {
var v = cfg.map[p];
// object map backwards-compat into packages configuration
if (typeof v !== 'string') {
objMaps += (objMaps.length ? ', ' : '') + '"' + p + '"';
var defaultJSExtension = loader.defaultJSExtensions && p.substr(p.length - 3, 3) != '.js';
var prop = loader.decanonicalize(p);
if (defaultJSExtension && prop.substr(prop.length - 3, 3) == '.js')
prop = prop.substr(0, prop.length - 3);
// if a package main, revert it
var pkgMatch = '';
for (var pkg in loader.packages) {
if (prop.substr(0, pkg.length) == pkg
&& (!prop[pkg.length] || prop[pkg.length] == '/')
&& pkgMatch.split('/').length < pkg.split('/').length)
pkgMatch = pkg;
}
if (pkgMatch && loader.packages[pkgMatch].main)
prop = prop.substr(0, prop.length - loader.packages[pkgMatch].main.length - 1);
var pkg = loader.packages[prop] = loader.packages[prop] || {};
pkg.map = v;
}
else {
loader.map[p] = v;
}
}
if (objMaps)
warn.call(loader, 'The map configuration for ' + objMaps + ' uses object submaps, which is deprecated in global map.\nUpdate this to use package contextual map with configs like SystemJS.config({ packages: { "' + p + '": { map: {...} } } }).');
}
if (cfg.packageConfigPaths) {
var packageConfigPaths = [];
for (var i = 0; i < cfg.packageConfigPaths.length; i++) {
var path = cfg.packageConfigPaths[i];
var packageLength = Math.max(path.lastIndexOf('*') + 1, path.lastIndexOf('/'));
var defaultJSExtension = loader.defaultJSExtensions && path.substr(packageLength - 3, 3) != '.js';
var normalized = loader.decanonicalize(path.substr(0, packageLength));
if (defaultJSExtension && normalized.substr(normalized.length - 3, 3) == '.js')
normalized = normalized.substr(0, normalized.length - 3);
packageConfigPaths[i] = normalized + path.substr(packageLength);
}
loader.packageConfigPaths = packageConfigPaths;
}
if (cfg.bundles) {
for (var p in cfg.bundles) {
var bundle = [];
for (var i = 0; i < cfg.bundles[p].length; i++) {
var defaultJSExtension = loader.defaultJSExtensions && cfg.bundles[p][i].substr(cfg.bundles[p][i].length - 3, 3) != '.js';
var normalizedBundleDep = loader.decanonicalize(cfg.bundles[p][i]);
if (defaultJSExtension && normalizedBundleDep.substr(normalizedBundleDep.length - 3, 3) == '.js')
normalizedBundleDep = normalizedBundleDep.substr(0, normalizedBundleDep.length - 3);
bundle.push(normalizedBundleDep);
}
loader.bundles[p] = bundle;
}
}
if (cfg.packages) {
for (var p in cfg.packages) {
if (p.match(/^([^\/]+:)?\/\/$/))
throw new TypeError('"' + p + '" is not a valid package name.');
var prop = coreResolve.call(loader, p);
// allow trailing slash in packages
if (prop[prop.length - 1] == '/')
prop = prop.substr(0, prop.length - 1);
loader.packages[prop] = loader.packages[prop] || {};
var pkg = cfg.packages[p];
// meta backwards compatibility
if (pkg.modules) {
warn.call(loader, 'Package ' + p + ' is configured with "modules", which is deprecated as it has been renamed to "meta".');
pkg.meta = pkg.modules;
delete pkg.modules;
}
if (typeof pkg.main == 'object') {
pkg.map = pkg.map || {};
pkg.map['./@main'] = pkg.main;
pkg.main['default'] = pkg.main['default'] || './';
pkg.main = '@main';
}
for (var q in pkg)
if (indexOf.call(packageProperties, q) == -1)
warn.call(loader, '"' + q + '" is not a valid package configuration option in package ' + p);
extendMeta(loader.packages[prop], pkg);
}
}
for (var c in cfg) {
var v = cfg[c];
if (c == 'baseURL' || c == 'map' || c == 'packages' || c == 'bundles' || c == 'paths' || c == 'warnings' || c == 'packageConfigPaths' || c == 'loaderErrorStack')
continue;
if (typeof v != 'object' || v instanceof Array) {
loader[c] = v;
}
else {
loader[c] = loader[c] || {};
for (var p in v) {
// base-level wildcard meta does not normalize to retain catch-all quality
if (c == 'meta' && p[0] == '*') {
loader[c][p] = v[p];
}
else if (c == 'meta') {
// meta can go through global map, with defaultJSExtensions adding
var resolved = coreResolve.call(loader, p);
if (loader.defaultJSExtensions && resolved.substr(resolved.length - 3, 3) != '.js' && !isPlain(resolved))
resolved += '.js';
loader[c][resolved] = v[p];
}
else if (c == 'depCache') {
var defaultJSExtension = loader.defaultJSExtensions && p.substr(p.length - 3, 3) != '.js';
var prop = loader.decanonicalize(p);
if (defaultJSExtension && prop.substr(prop.length - 3, 3) == '.js')
prop = prop.substr(0, prop.length - 3);
loader[c][prop] = v[p];
}
else {
loader[c][p] = v[p];
}
}
}
}
};