traceur
Version:
ES6 to ES5 compiler
476 lines (475 loc) • 16.7 kB
JavaScript
"use strict";
function $__interopRequire(id) {
id = require(id);
return id && id.__esModule && id || {default: id};
}
Object.defineProperties(module.exports, {
__esModule: {value: true},
InternalLoader: {
enumerable: true,
get: function() {
return InternalLoader;
}
},
internals: {
enumerable: true,
get: function() {
return internals;
}
}
});
var $__createClass = $__interopRequire("traceur/dist/commonjs/runtime/modules/createClass.js").default;
var $__superConstructor = $__interopRequire("traceur/dist/commonjs/runtime/modules/superConstructor.js").default;
var assert = require("../util/assert.js").assert;
var LoaderCompiler = require("./LoaderCompiler.js").LoaderCompiler;
var ExportsList = require("../codegeneration/module/ModuleSymbol.js").ExportsList;
var $__15 = require("../util/url.js"),
isAbsolute = $__15.isAbsolute,
resolveUrl = $__15.resolveUrl;
var Options = require("../Options.js").Options;
var NOT_STARTED = 0;
var LOADING = 1;
var LOADED = 2;
var PARSED = 3;
var TRANSFORMING = 4;
var TRANSFORMED = 5;
var COMPLETE = 6;
var ERROR = 7;
function mapToValues(map) {
var array = [];
map.forEach(function(v) {
array.push(v);
});
return array;
}
var LoaderError = function($__super) {
function LoaderError(msg, tree) {
$__superConstructor(LoaderError).call(this);
this.message = msg;
this.tree = tree;
this.name = 'LoaderError';
}
return ($__createClass)(LoaderError, {}, {}, $__super);
}(Error);
var CodeUnit = function() {
function CodeUnit(loaderCompiler, normalizedName, type, state, name, referrerName, address) {
var $__8 = this;
this.promise = new Promise(function(res, rej) {
$__8.loaderCompiler = loaderCompiler;
$__8.normalizedName = normalizedName;
$__8.type = type;
$__8.name_ = name;
$__8.referrerName_ = referrerName;
$__8.address = address;
$__8.state_ = state || NOT_STARTED;
$__8.error = null;
$__8.result = null;
$__8.metadata_ = {};
$__8.dependencies = [];
$__8.resolve = res;
$__8.reject = rej;
});
}
return ($__createClass)(CodeUnit, {
get state() {
return this.state_;
},
set state(value) {
if (value < this.state_) {
throw new Error('Invalid state change');
}
this.state_ = value;
},
get metadata() {
return this.metadata_;
},
set metadata(value) {
assert(value);
this.metadata_ = value;
},
nameTrace: function() {
var trace = this.specifiedAs();
if (isAbsolute(this.name_)) {
return trace + 'An absolute name.\n';
}
if (this.referrerName_) {
return trace + this.importedBy() + this.normalizesTo();
}
return trace + this.normalizesTo();
},
specifiedAs: function() {
return ("Specified as " + this.name_ + ".\n");
},
importedBy: function() {
return ("Imported by " + this.referrerName_ + ".\n");
},
normalizesTo: function() {
return 'Normalizes to ' + this.normalizedName + '\n';
}
}, {});
}();
var PreCompiledCodeUnit = function($__super) {
function PreCompiledCodeUnit(loaderCompiler, normalizedName, name, referrerName, address, module) {
$__superConstructor(PreCompiledCodeUnit).call(this, loaderCompiler, normalizedName, 'module', COMPLETE, name, referrerName, address);
this.result = module;
this.resolve(this.result);
}
return ($__createClass)(PreCompiledCodeUnit, {}, {}, $__super);
}(CodeUnit);
var BundledCodeUnit = function($__super) {
function BundledCodeUnit(loaderCompiler, normalizedName, name, referrerName, address, deps, execute, setModule) {
$__superConstructor(BundledCodeUnit).call(this, loaderCompiler, normalizedName, 'module', TRANSFORMED, name, referrerName, address);
this.deps = deps;
this.execute = execute;
}
return ($__createClass)(BundledCodeUnit, {
getModuleSpecifiers: function() {
return this.deps;
},
evaluate: function() {
var $__8 = this;
var normalizedNames = this.deps.map(function(name) {
return $__8.loader_.normalize(name);
});
var module = this.execute.apply(Reflect.global, normalizedNames);
setModule(this.normalizedName, module);
return module;
}
}, {}, $__super);
}(CodeUnit);
var HookedCodeUnit = function($__super) {
function HookedCodeUnit() {
$__superConstructor(HookedCodeUnit).apply(this, arguments);
}
return ($__createClass)(HookedCodeUnit, {
getModuleSpecifiers: function() {
return this.loaderCompiler.getModuleSpecifiers(this);
},
evaluate: function() {
return this.loaderCompiler.evaluateCodeUnit(this);
}
}, {}, $__super);
}(CodeUnit);
var LoadCodeUnit = function($__super) {
function LoadCodeUnit(loaderCompiler, normalizedName, name, referrerName, address) {
$__superConstructor(LoadCodeUnit).call(this, loaderCompiler, normalizedName, 'module', NOT_STARTED, name, referrerName, address);
}
return ($__createClass)(LoadCodeUnit, {}, {}, $__super);
}(HookedCodeUnit);
var EvalCodeUnit = function($__super) {
function EvalCodeUnit(loaderCompiler, code) {
var type = arguments[2] !== (void 0) ? arguments[2] : 'script';
var normalizedName = arguments[3];
var referrerName = arguments[4];
var address = arguments[5];
$__superConstructor(EvalCodeUnit).call(this, loaderCompiler, normalizedName, type, LOADED, null, referrerName, address);
this.source = code;
}
return ($__createClass)(EvalCodeUnit, {}, {}, $__super);
}(HookedCodeUnit);
var uniqueNameCount = 0;
var InternalLoader = function() {
function InternalLoader(loader, loaderCompiler) {
assert(loaderCompiler);
this.loader_ = loader;
this.loaderCompiler = loaderCompiler;
this.cache = new Map();
this.urlToKey = Object.create(null);
this.sync_ = false;
this.sourceMapsByURL_ = Object.create(null);
this.sourceMapsByOutputName_ = Object.create(null);
}
return ($__createClass)(InternalLoader, {
defaultMetadata_: function() {
var metadata = arguments[0] !== (void 0) ? arguments[0] : {};
var incoming = metadata.traceurOptions;
if (incoming && !(incoming instanceof Options)) {
var unknown = Options.listUnknownOptions(incoming);
if (unknown.length) {
console.warn('Unknown metadata.traceurOptions ignored: ' + unknown.join(','));
}
}
metadata.traceurOptions = incoming || new Options();
return metadata;
},
defaultModuleMetadata_: function() {
var metadata = arguments[0] !== (void 0) ? arguments[0] : {};
var metadata = this.defaultMetadata_(metadata);
metadata.traceurOptions.script = false;
return metadata;
},
getSourceMap: function(url) {
return this.sourceMapsByURL_[url] || this.sourceMapsByOutputName_[url];
},
load: function(name) {
var referrerName = arguments[1] !== (void 0) ? arguments[1] : this.loader_.baseURL;
var address = arguments[2];
var metadata = arguments[3] !== (void 0) ? arguments[3] : {};
metadata = this.defaultMetadata_(metadata);
var codeUnit = this.getOrCreateCodeUnit_(name, referrerName, address, metadata);
this.load_(codeUnit);
return codeUnit.promise.then(function() {
return codeUnit;
});
},
load_: function(codeUnit) {
var $__8 = this;
if (codeUnit.state === ERROR) {
return codeUnit;
}
if (codeUnit.state === TRANSFORMED) {
this.handleCodeUnitLoaded(codeUnit);
} else {
if (codeUnit.state !== NOT_STARTED)
return codeUnit;
codeUnit.state = LOADING;
codeUnit.address = this.loader_.locate(codeUnit);
this.loader_.fetch(codeUnit).then(function(text) {
codeUnit.source = text;
return codeUnit;
}).then(function(load) {
return $__8.loader_.translate(load);
}).then(function(source) {
codeUnit.source = source;
codeUnit.state = LOADED;
$__8.handleCodeUnitLoaded(codeUnit);
return codeUnit;
}).catch(function(err) {
try {
codeUnit.state = ERROR;
codeUnit.error = err;
$__8.handleCodeUnitLoadError(codeUnit);
} catch (ex) {
console.error('Internal Error ' + (ex.stack || ex));
}
});
}
return codeUnit;
},
module: function(code, referrerName, address, metadata) {
var codeUnit = new EvalCodeUnit(this.loaderCompiler, code, 'module', null, referrerName, address);
codeUnit.metadata = this.defaultMetadata_(metadata);
this.cache.set({}, codeUnit);
this.handleCodeUnitLoaded(codeUnit);
return codeUnit.promise;
},
define: function(normalizedName, code, address, metadata) {
var codeUnit = new EvalCodeUnit(this.loaderCompiler, code, 'module', normalizedName, null, address);
var key = this.getKey(normalizedName, 'module');
codeUnit.metadata = this.defaultMetadata_(metadata);
this.cache.set(key, codeUnit);
this.handleCodeUnitLoaded(codeUnit);
return codeUnit.promise;
},
script: function(code, name, referrerName, address, metadata) {
var normalizedName = this.loader_.normalize(name || '', referrerName, address);
var codeUnit = new EvalCodeUnit(this.loaderCompiler, code, 'script', normalizedName, referrerName, address);
var key = {};
if (name)
key = this.getKey(normalizedName, 'script');
codeUnit.metadata = this.defaultMetadata_(metadata);
this.cache.set(key, codeUnit);
this.handleCodeUnitLoaded(codeUnit);
return codeUnit.promise;
},
getKey: function(url, type) {
var combined = type + ':' + url;
if (combined in this.urlToKey) {
return this.urlToKey[combined];
}
return this.urlToKey[combined] = {};
},
getCodeUnit_: function(normalizedName, type) {
var key = this.getKey(normalizedName, type);
var codeUnit = this.cache.get(key);
return {
key: key,
codeUnit: codeUnit
};
},
getOrCreateCodeUnit_: function(name, referrerName, address, metadata) {
var normalizedName = this.loader_.normalize(name, referrerName, address);
var type = 'module';
if (metadata && metadata.traceurOptions && metadata.traceurOptions.script)
type = 'script';
var $__9 = this.getCodeUnit_(normalizedName, type),
key = $__9.key,
codeUnit = $__9.codeUnit;
if (!codeUnit) {
assert(metadata && metadata.traceurOptions);
var module = this.loader_.get(normalizedName);
if (module) {
codeUnit = new PreCompiledCodeUnit(this.loaderCompiler, normalizedName, name, referrerName, address, module);
codeUnit.type = 'module';
} else {
codeUnit = new LoadCodeUnit(this.loaderCompiler, normalizedName, name, referrerName, address);
codeUnit.type = type;
}
codeUnit.metadata = {
traceurOptions: metadata.traceurOptions,
outputName: metadata.outputName,
rootModule: metadata.rootModule
};
this.cache.set(key, codeUnit);
}
return codeUnit;
},
areAll: function(state) {
return mapToValues(this.cache).every(function(codeUnit) {
return codeUnit.state >= state;
});
},
getCodeUnitForModuleSpecifier: function(name, referrerName) {
var normalizedName = this.loader_.normalize(name, referrerName);
return this.getCodeUnit_(normalizedName, 'module').codeUnit;
},
getExportsListForModuleSpecifier: function(name, referrer) {
var codeUnit = this.getCodeUnitForModuleSpecifier(name, referrer);
var exportsList = codeUnit.metadata.moduleSymbol;
if (!exportsList) {
if (codeUnit.result) {
exportsList = new ExportsList(codeUnit.normalizedName);
exportsList.addExportsFromModule(codeUnit.result);
} else {
throw new Error(("InternalError: " + name + " is not a module, required by " + referrer));
}
}
return exportsList;
},
handleCodeUnitLoaded: function(codeUnit) {
var $__8 = this;
var referrerName = codeUnit.normalizedName;
try {
var moduleSpecifiers = codeUnit.getModuleSpecifiers();
codeUnit.state = PARSED;
if (!moduleSpecifiers) {
this.abortAll(("No module specifiers in " + referrerName));
return;
}
codeUnit.dependencies = moduleSpecifiers.map(function(name) {
return $__8.getOrCreateCodeUnit_(name, referrerName, null, $__8.defaultModuleMetadata_(codeUnit.metadata));
});
} catch (error) {
this.rejectOneAndAll(codeUnit, error);
return;
}
codeUnit.dependencies.forEach(function(dependency) {
$__8.load_(dependency);
});
if (this.areAll(PARSED)) {
try {
if (codeUnit.type === 'module')
this.analyze();
this.transform();
this.evaluate();
} catch (error) {
this.rejectOneAndAll(codeUnit, error);
}
}
},
rejectOneAndAll: function(codeUnit, error) {
codeUnit.state.ERROR;
codeUnit.error = error;
codeUnit.reject(error);
this.abortAll(error);
},
handleCodeUnitLoadError: function(codeUnit) {
var message = codeUnit.error ? String(codeUnit.error) + '\n' : ("Failed to load '" + codeUnit.address + "'.\n");
message += codeUnit.nameTrace() + this.loader_.nameTrace(codeUnit);
this.rejectOneAndAll(codeUnit, new Error(message));
},
abortAll: function(errorMessage) {
this.cache.forEach(function(codeUnit) {
if (codeUnit.state !== ERROR)
codeUnit.reject(errorMessage);
});
},
analyze: function() {
this.loaderCompiler.analyzeDependencies(mapToValues(this.cache), this);
},
transform: function() {
this.transformDependencies_(mapToValues(this.cache));
},
transformDependencies_: function(dependencies, dependentName) {
for (var i = 0; i < dependencies.length; i++) {
var codeUnit = dependencies[i];
if (codeUnit.state >= TRANSFORMED) {
continue;
}
if (codeUnit.state === TRANSFORMING) {
var cir = codeUnit.normalizedName;
var cle = dependentName;
this.rejectOneAndAll(codeUnit, new Error(("Unsupported circular dependency between " + cir + " and " + cle)));
return;
}
codeUnit.state = TRANSFORMING;
try {
this.transformCodeUnit_(codeUnit);
} catch (error) {
this.rejectOneAndAll(codeUnit, error);
return;
}
}
},
transformCodeUnit_: function(codeUnit) {
this.transformDependencies_(codeUnit.dependencies, codeUnit.normalizedName);
if (codeUnit.state === ERROR)
return;
this.loaderCompiler.transform(codeUnit);
codeUnit.state = TRANSFORMED;
this.loaderCompiler.write(codeUnit);
var info = codeUnit.metadata.compiler.sourceMapInfo;
if (info) {
this.sourceMapsByURL_[info.url] = info.map;
this.sourceMapsByOutputName_[info.outputName] = info.map;
}
this.loader_.instantiate(codeUnit);
},
orderDependencies: function() {
var visited = new Map();
var ordered = [];
function orderCodeUnits(codeUnit) {
if (visited.has(codeUnit)) {
return;
}
visited.set(codeUnit, true);
codeUnit.dependencies.forEach(orderCodeUnits);
ordered.push(codeUnit);
}
this.cache.forEach(orderCodeUnits);
return ordered;
},
evaluate: function() {
var dependencies = this.orderDependencies();
for (var i = 0; i < dependencies.length; i++) {
var codeUnit = dependencies[i];
if (codeUnit.state >= COMPLETE) {
continue;
}
var result = void 0;
try {
result = codeUnit.evaluate();
} catch (ex) {
this.rejectOneAndAll(codeUnit, ex);
return;
}
codeUnit.result = result;
codeUnit.source = null;
}
for (var i = 0; i < dependencies.length; i++) {
var codeUnit = dependencies[i];
if (codeUnit.state >= COMPLETE) {
continue;
}
codeUnit.state = COMPLETE;
codeUnit.resolve(codeUnit.result);
}
}
}, {});
}();
var internals = {
CodeUnit: CodeUnit,
EvalCodeUnit: EvalCodeUnit,
LoadCodeUnit: LoadCodeUnit,
LoaderCompiler: LoaderCompiler
};