mirror of
https://github.com/systemjs/systemjs.git
synced 2026-01-25 14:57:38 +00:00
224 lines
6.9 KiB
JavaScript
224 lines
6.9 KiB
JavaScript
/*
|
|
* SystemJS Core
|
|
* Code should be vaguely readable
|
|
*
|
|
*/
|
|
function core(loader) {
|
|
(function() {
|
|
|
|
/*
|
|
__useDefault
|
|
|
|
When a module object looks like:
|
|
Module({
|
|
__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() {}
|
|
*/
|
|
var loaderImport = loader['import'];
|
|
loader['import'] = function(name, options) {
|
|
return loaderImport.call(this, name, options).then(function(module) {
|
|
return module.__useDefault ? module['default'] : module;
|
|
});
|
|
}
|
|
|
|
// support the empty module, as a concept
|
|
loader.set('@empty', Module({}));
|
|
|
|
/*
|
|
Config
|
|
Extends 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' };
|
|
*/
|
|
loader.config = function(cfg) {
|
|
for (var c in cfg) {
|
|
var v = cfg[c];
|
|
if (typeof v == 'object') {
|
|
this[c] = this[c] || {};
|
|
for (var p in v)
|
|
this[c][p] = v[p];
|
|
}
|
|
else
|
|
this[c] = v;
|
|
}
|
|
}
|
|
|
|
// override locate to allow baseURL to be document-relative
|
|
var baseURI;
|
|
if (typeof window == 'undefined') {
|
|
baseURI = __dirname + '/';
|
|
}
|
|
else {
|
|
baseURI = document.baseURI;
|
|
if (!baseURI) {
|
|
var bases = document.getElementsByTagName('base');
|
|
baseURI = bases[0] && bases[0].href || window.location.href;
|
|
}
|
|
}
|
|
var loaderLocate = loader.locate;
|
|
var normalizedBaseURL;
|
|
loader.locate = function(load) {
|
|
if (this.baseURL != normalizedBaseURL) {
|
|
normalizedBaseURL = toAbsoluteURL(baseURI, this.baseURL);
|
|
|
|
if (normalizedBaseURL.substr(normalizedBaseURL.length - 1, 1) != '/')
|
|
normalizedBaseURL += '/';
|
|
|
|
this.baseURL = normalizedBaseURL;
|
|
}
|
|
|
|
return Promise.resolve(loaderLocate.call(this, load));
|
|
}
|
|
|
|
|
|
// Traceur conveniences
|
|
var aliasRegEx = /^\s*export\s*\*\s*from\s*(?:'([^']+)'|"([^"]+)")/;
|
|
var es6RegEx = /(?:^\s*|[}{\(\);,\n]\s*)(import\s+['"]|(import|module)\s+[^"'\(\)\n;]+\s+from\s+['"]|export\s+(\*|\{|default|function|var|const|let|[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*))/;
|
|
|
|
var loaderTranslate = loader.translate;
|
|
loader.translate = function(load) {
|
|
var loader = this;
|
|
|
|
loader.__exec = exec;
|
|
|
|
// support ES6 alias modules ("export * from 'module';") without needing Traceur
|
|
var match;
|
|
if (!loader.global.traceur && (load.metadata.format == 'es6' || !load.metadata.format) && (match = load.source.match(aliasRegEx))) {
|
|
var depName = match[1] || match[2];
|
|
load.metadata.deps = [depName];
|
|
load.metadata.execute = function(require) {
|
|
return require(depName);
|
|
}
|
|
}
|
|
|
|
// detect ES6
|
|
if (load.metadata.format == 'es6' || !load.metadata.format && load.source.match(es6RegEx)) {
|
|
console.log('load traceur');
|
|
load.metadata.format = 'es6';
|
|
|
|
// dynamically load Traceur for ES6 if necessary
|
|
if (!loader.global.traceur)
|
|
return loader['import']('@traceur').then(function() {
|
|
return loaderTranslate.call(loader, load);
|
|
});
|
|
}
|
|
|
|
return loaderTranslate.call(loader, load);
|
|
}
|
|
|
|
// always load Traceur as a global
|
|
var loaderInstantiate = loader.instantiate;
|
|
loader.instantiate = function(load) {
|
|
var loader = this;
|
|
if (load.name == '@traceur') {
|
|
loader.__exec(load);
|
|
return {
|
|
deps: [],
|
|
execute: function() {}
|
|
};
|
|
}
|
|
return loaderInstantiate.call(loader, load);
|
|
}
|
|
|
|
|
|
// define exec for easy evaluation of a load record (load.name, load.source, load.address)
|
|
// main feature is source maps support handling
|
|
var curSystem
|
|
function exec(load) {
|
|
if (load.name == '@traceur')
|
|
curSystem = System;
|
|
// support sourceMappingURL (efficiently)
|
|
var sourceMappingURL;
|
|
var lastLineIndex = load.source.lastIndexOf('\n');
|
|
if (lastLineIndex != -1) {
|
|
if (load.source.substr(lastLineIndex + 1, 21) == '//# sourceMappingURL=')
|
|
sourceMappingURL = toAbsoluteURL(load.address, load.source.substr(lastLineIndex + 22));
|
|
}
|
|
|
|
__eval(load.source, this.global, load.address, sourceMappingURL);
|
|
|
|
// traceur overwrites System - write it back
|
|
if (load.name == '@traceur') {
|
|
this.global.traceurSystem = this.global.System;
|
|
this.global.System = curSystem;
|
|
}
|
|
}
|
|
loader.__exec = exec;
|
|
|
|
// Absolute URL parsing, from https://gist.github.com/Yaffle/1088850
|
|
function parseURI(url) {
|
|
var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/);
|
|
// authority = '//' + user + ':' + pass '@' + hostname + ':' port
|
|
return (m ? {
|
|
href : m[0] || '',
|
|
protocol : m[1] || '',
|
|
authority: m[2] || '',
|
|
host : m[3] || '',
|
|
hostname : m[4] || '',
|
|
port : m[5] || '',
|
|
pathname : m[6] || '',
|
|
search : m[7] || '',
|
|
hash : m[8] || ''
|
|
} : null);
|
|
}
|
|
function toAbsoluteURL(base, href) {
|
|
function removeDotSegments(input) {
|
|
var output = [];
|
|
input.replace(/^(\.\.?(\/|$))+/, '')
|
|
.replace(/\/(\.(\/|$))+/g, '/')
|
|
.replace(/\/\.\.$/, '/../')
|
|
.replace(/\/?[^\/]*/g, function (p) {
|
|
if (p === '/..')
|
|
output.pop();
|
|
else
|
|
output.push(p);
|
|
});
|
|
return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : '');
|
|
}
|
|
|
|
href = parseURI(href || '');
|
|
base = parseURI(base || '');
|
|
|
|
return !href || !base ? null : (href.protocol || base.protocol) +
|
|
(href.protocol || href.authority ? href.authority : base.authority) +
|
|
removeDotSegments(href.protocol || href.authority || href.pathname.charAt(0) === '/' ? href.pathname : (href.pathname ? ((base.authority && !base.pathname ? '/' : '') + base.pathname.slice(0, base.pathname.lastIndexOf('/') + 1) + href.pathname) : base.pathname)) +
|
|
(href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) +
|
|
href.hash;
|
|
}
|
|
|
|
})();
|
|
|
|
function __eval(__source, __global, __address, __sourceMap) {
|
|
try {
|
|
__source = 'with(__global) { (function() { ' + __source + ' \n }).call(__global); }'
|
|
+ '\n//# sourceURL=' + __address
|
|
+ (__sourceMap ? '\n//# sourceMappingURL=' + __sourceMap : '');
|
|
eval(__source);
|
|
}
|
|
catch(e) {
|
|
if (e.name == 'SyntaxError')
|
|
e.message = 'Evaluating ' + __address + '\n\t' + e.message;
|
|
throw e;
|
|
}
|
|
}
|
|
}
|