162 lines
7.2 KiB
JavaScript
162 lines
7.2 KiB
JavaScript
|
/*
|
||
|
* Extension to detect ES6 and auto-load Traceur or Babel for processing
|
||
|
*/
|
||
|
(function() {
|
||
|
// good enough ES6 module detection regex - format detections not designed to be accurate, but to handle the 99% use case
|
||
|
var esmRegEx = /(^\s*|[}\);\n]\s*)(import\s*(['"]|(\*\s+as\s+)?[^"'\(\)\n;]+\s*from\s*['"]|\{)|export\s+\*\s+from\s+["']|export\s*(\{|default|function|class|var|const|let|async\s+function))/;
|
||
|
|
||
|
var traceurRuntimeRegEx = /\$traceurRuntime\s*\./;
|
||
|
var babelHelpersRegEx = /babelHelpers\s*\./;
|
||
|
|
||
|
hook('translate', function(translate) {
|
||
|
return function(load) {
|
||
|
var loader = this;
|
||
|
var args = arguments;
|
||
|
return translate.apply(loader, args)
|
||
|
.then(function(source) {
|
||
|
// detect & transpile ES6
|
||
|
if (load.metadata.format == 'esm' || load.metadata.format == 'es6' || !load.metadata.format && source.match(esmRegEx)) {
|
||
|
if (load.metadata.format == 'es6')
|
||
|
warn.call(loader, 'Module ' + load.name + ' has metadata setting its format to "es6", which is deprecated.\nThis should be updated to "esm".');
|
||
|
|
||
|
load.metadata.format = 'esm';
|
||
|
|
||
|
if (load.metadata.deps) {
|
||
|
var depInject = '';
|
||
|
for (var i = 0; i < load.metadata.deps.length; i++)
|
||
|
depInject += 'import "' + load.metadata.deps[i] + '"; ';
|
||
|
load.source = depInject + source;
|
||
|
}
|
||
|
|
||
|
if (loader.transpiler === false) {
|
||
|
// we accept translation to esm for builds though to enable eg rollup optimizations
|
||
|
if (loader.builder)
|
||
|
return source;
|
||
|
throw new TypeError('Unable to dynamically transpile ES module as SystemJS.transpiler set to false.');
|
||
|
}
|
||
|
|
||
|
// setting _loader.loadedTranspiler = false tells the next block to
|
||
|
// do checks for setting transpiler metadata
|
||
|
loader._loader.loadedTranspiler = loader._loader.loadedTranspiler || false;
|
||
|
if (loader.pluginLoader)
|
||
|
loader.pluginLoader._loader.loadedTranspiler = loader._loader.loadedTranspiler || false;
|
||
|
|
||
|
// do transpilation
|
||
|
return (loader._loader.transpilerPromise || (
|
||
|
loader._loader.transpilerPromise = Promise.resolve(
|
||
|
__global[loader.transpiler == 'typescript' ? 'ts' : loader.transpiler] || (loader.pluginLoader || loader).normalize(loader.transpiler)
|
||
|
.then(function(normalized) {
|
||
|
loader._loader.transpilerNormalized = normalized;
|
||
|
return (loader.pluginLoader || loader).load(normalized)
|
||
|
.then(function() {
|
||
|
return (loader.pluginLoader || loader).get(normalized);
|
||
|
});
|
||
|
})
|
||
|
))).then(function(transpiler) {
|
||
|
loader._loader.loadedTranspilerRuntime = true;
|
||
|
|
||
|
// translate hooks means this is a transpiler plugin instead of a raw implementation
|
||
|
if (transpiler.translate) {
|
||
|
// if transpiler is the same as the plugin loader, then don't run twice
|
||
|
if (transpiler == load.metadata.loaderModule)
|
||
|
return load.source;
|
||
|
load.metadata.loaderModule = transpiler;
|
||
|
load.metadata.loader = loader._loader.transpilerNormalized;
|
||
|
|
||
|
// convert the source map into an object for transpilation chaining
|
||
|
if (typeof load.metadata.sourceMap == 'string')
|
||
|
load.metadata.sourceMap = JSON.parse(load.metadata.sourceMap);
|
||
|
|
||
|
return Promise.resolve(transpiler.translate.apply(loader, args))
|
||
|
.then(function(source) {
|
||
|
// sanitize sourceMap if an object not a JSON string
|
||
|
var sourceMap = load.metadata.sourceMap;
|
||
|
if (sourceMap && typeof sourceMap == 'object') {
|
||
|
var originalName = load.address.split('!')[0];
|
||
|
|
||
|
// force set the filename of the original file
|
||
|
if (!sourceMap.file || sourceMap.file == load.address)
|
||
|
sourceMap.file = originalName + '!transpiled';
|
||
|
|
||
|
// force set the sources list if only one source
|
||
|
if (!sourceMap.sources || sourceMap.sources.length <= 1 && (!sourceMap.sources[0] || sourceMap.sources[0] == load.address))
|
||
|
sourceMap.sources = [originalName];
|
||
|
}
|
||
|
|
||
|
if (load.metadata.format == 'esm' && !loader.builder && detectRegisterFormat(source))
|
||
|
load.metadata.format = 'register';
|
||
|
return source;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
// legacy builder support
|
||
|
if (loader.builder)
|
||
|
load.metadata.originalSource = load.source;
|
||
|
|
||
|
// defined in es6-module-loader/src/transpile.js
|
||
|
return transpile.call(loader, load)
|
||
|
.then(function(source) {
|
||
|
// clear sourceMap as transpiler embeds it
|
||
|
load.metadata.sourceMap = undefined;
|
||
|
return source;
|
||
|
});
|
||
|
}, function(err) {
|
||
|
throw addToError(err, 'Unable to load transpiler to transpile ' + load.name);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
// skip transpiler and transpiler runtime loading when transpiler is disabled
|
||
|
if (loader.transpiler === false)
|
||
|
return source;
|
||
|
|
||
|
// load the transpiler correctly
|
||
|
if (loader._loader.loadedTranspiler === false && (loader.transpiler == 'traceur' || loader.transpiler == 'typescript' || loader.transpiler == 'babel')
|
||
|
&& load.name == loader.normalizeSync(loader.transpiler)) {
|
||
|
|
||
|
// always load transpiler as a global
|
||
|
if (source.length > 100 && !load.metadata.format) {
|
||
|
load.metadata.format = 'global';
|
||
|
|
||
|
if (loader.transpiler === 'traceur')
|
||
|
load.metadata.exports = 'traceur';
|
||
|
if (loader.transpiler === 'typescript')
|
||
|
load.metadata.exports = 'ts';
|
||
|
}
|
||
|
|
||
|
loader._loader.loadedTranspiler = true;
|
||
|
}
|
||
|
|
||
|
// load the transpiler runtime correctly
|
||
|
if (loader._loader.loadedTranspilerRuntime === false) {
|
||
|
if (load.name == loader.normalizeSync('traceur-runtime')
|
||
|
|| load.name == loader.normalizeSync('babel/external-helpers*')) {
|
||
|
if (source.length > 100)
|
||
|
load.metadata.format = load.metadata.format || 'global';
|
||
|
|
||
|
loader._loader.loadedTranspilerRuntime = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// detect transpiler runtime usage to load runtimes
|
||
|
if ((load.metadata.format == 'register' || load.metadata.bundle) && loader._loader.loadedTranspilerRuntime !== true) {
|
||
|
if (loader.transpiler == 'traceur' && !__global.$traceurRuntime && load.source.match(traceurRuntimeRegEx)) {
|
||
|
loader._loader.loadedTranspilerRuntime = loader._loader.loadedTranspilerRuntime || false;
|
||
|
return loader['import']('traceur-runtime').then(function() {
|
||
|
return source;
|
||
|
});
|
||
|
}
|
||
|
if (loader.transpiler == 'babel' && !__global.babelHelpers && load.source.match(babelHelpersRegEx)) {
|
||
|
loader._loader.loadedTranspilerRuntime = loader._loader.loadedTranspilerRuntime || false;
|
||
|
return loader['import']('babel/external-helpers').then(function() {
|
||
|
return source;
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return source;
|
||
|
});
|
||
|
};
|
||
|
});
|
||
|
|
||
|
})();
|