systemjs-builder
Version:
SystemJS Build Tool ===
176 lines (152 loc) • 6.82 kB
JavaScript
var traceur = require('traceur');
var ParseTreeTransformer = traceur.get('codegeneration/ParseTreeTransformer.js').ParseTreeTransformer;
var parseStatements = traceur.get('codegeneration/PlaceholderParser.js').parseStatements;
var parseStatement = traceur.get('codegeneration/PlaceholderParser.js').parseStatement;
var Script = traceur.get('syntax/trees/ParseTrees.js').Script;
// wraps global scripts
function GlobalTransformer(name, deps, exportName, init) {
this.name = name;
this.deps = deps;
this.exportName = exportName;
this.varGlobals = [];
this.init = init;
this.inOuterScope = true;
return ParseTreeTransformer.call(this);
}
GlobalTransformer.prototype = Object.create(ParseTreeTransformer.prototype);
GlobalTransformer.prototype.transformVariableDeclarationList = function(tree) {
this.isVarDeclaration = tree.declarationType == 'var';
return ParseTreeTransformer.prototype.transformVariableDeclarationList.call(this, tree);
}
GlobalTransformer.prototype.transformVariableDeclaration = function(tree) {
tree = ParseTreeTransformer.prototype.transformVariableDeclaration.call(this, tree);
if (!this.inOuterScope || !this.isVarDeclaration)
return tree;
var varName = tree.lvalue.identifierToken.value;
if (this.varGlobals.indexOf(varName) == -1)
this.varGlobals.push(varName);
return tree;
}
GlobalTransformer.prototype.enterScope = function() {
var revert = this.inOuterScope;
this.inOuterScope = false;
return revert;
}
GlobalTransformer.prototype.exitScope = function(revert) {
if (revert)
this.inOuterScope = true;
}
GlobalTransformer.prototype.transformFunctionDeclaration = function(tree) {
var revert = this.enterScope();
tree = ParseTreeTransformer.prototype.transformFunctionDeclaration.call(this, tree);
this.exitScope(revert);
return tree;
}
GlobalTransformer.prototype.transformFunctionExpression = function(tree) {
var revert = this.enterScope();
tree = ParseTreeTransformer.prototype.transformFunctionExpression.call(this, tree);
this.exitScope(revert);
return tree;
}
GlobalTransformer.prototype.transformScript = function(tree) {
tree = ParseTreeTransformer.prototype.transformScript.call(this, tree);
// for globals defined as "var x = 5;" in outer scope, add "this.x = x;" at end
var scriptItemList = this.varGlobals.map(function(g) {
return parseStatement(['var ' + g + ' = this["' + g + '"];']);
}).concat(tree.scriptItemList).concat(this.varGlobals.map(function(g) {
return parseStatement(['this["' + g + '"] = ' + g + ';']);
}));
return new Script(tree.location, parseStatements([
'System.register("' + this.name + '", ' + JSON.stringify(this.deps) + ', false, function(__require, __exports, __module) {\n'
+ ' System.get("@@global-helpers").prepareGlobal(__module.id, ' + JSON.stringify(this.deps) + ');\n'
+ ' (function() {',
' }).call(System.global);'
+ ' return System.get("@@global-helpers").retrieveGlobal(__module.id, ' + (this.exportName ? '"' + this.exportName + '"' : 'false') + (this.init ? ', ' + this.init.toString().replace(/\n/g, '\n ') : '') + ');\n'
+ '});'], scriptItemList));
}
exports.compile = function(load, opts, loader) {
var options = { script: true };
if (opts.sourceMaps)
options.sourceMaps = 'memory';
if (opts.lowResSourceMaps)
options.lowResolutionSourceMap = true;
if (load.metadata.sourceMap)
options.inputSourceMap = load.metadata.sourceMap;
var compiler = new traceur.Compiler(options);
var tree = compiler.parse(load.source, load.address);
var deps = opts.normalize ? load.metadata.deps.map(function(dep) { return load.depMap[dep]; }) : load.metadata.deps;
var transformer = new GlobalTransformer(load.name, deps, load.metadata.exports, load.metadata.init);
tree = transformer.transformAny(tree);
var output = compiler.write(tree, load.address);
return Promise.resolve({
source: output,
sourceMap: compiler.getSourceMap()
});
};
exports.sfx = function(loader) {
return '(function() {\n'
+ ' var loader = System;\n'
+ ' var hasOwnProperty = loader.global.hasOwnProperty;\n'
+ ' var moduleGlobals = {};\n'
+ ' var curGlobalObj;\n'
+ ' var ignoredGlobalProps;\n'
+ ' if (typeof indexOf == \'undefined\')\n'
+ ' indexOf = Array.prototype.indexOf;\n'
+ ' System.set("@@global-helpers", System.newModule({\n'
+ ' prepareGlobal: function(moduleName, deps) {\n'
+ ' for (var i = 0; i < deps.length; i++) {\n'
+ ' var moduleGlobal = moduleGlobals[deps[i]];\n'
+ ' if (moduleGlobal)\n'
+ ' for (var m in moduleGlobal)\n'
+ ' loader.global[m] = moduleGlobal[m];\n'
+ ' }\n'
+ ' curGlobalObj = {};\n'
+ ' ignoredGlobalProps = ["indexedDB", "sessionStorage", "localStorage", "clipboardData", "frames", "webkitStorageInfo"];\n'
+ ' for (var g in loader.global) {\n'
+ ' if (indexOf.call(ignoredGlobalProps, g) != -1) { continue; }\n'
+ ' if (!hasOwnProperty || loader.global.hasOwnProperty(g)) {\n'
+ ' try {\n'
+ ' curGlobalObj[g] = loader.global[g];\n'
+ ' } catch (e) {\n'
+ ' ignoredGlobalProps.push(g);\n'
+ ' }\n'
+ ' }\n'
+ ' }\n'
+ ' },\n'
+ ' retrieveGlobal: function(moduleName, exportName, init) {\n'
+ ' var singleGlobal;\n'
+ ' var multipleExports;\n'
+ ' var exports = {};\n'
+ ' if (init) {\n'
+ ' var depModules = [];\n'
+ ' for (var i = 0; i < deps.length; i++)\n'
+ ' depModules.push(require(deps[i]));\n'
+ ' singleGlobal = init.apply(loader.global, depModules);\n'
+ ' }\n'
+ ' else if (exportName) {\n'
+ ' var firstPart = exportName.split(".")[0];\n'
+ ' singleGlobal = eval.call(loader.global, exportName);\n'
+ ' exports[firstPart] = loader.global[firstPart];\n'
+ ' }\n'
+ ' else {\n'
+ ' for (var g in loader.global) {\n'
+ ' if (indexOf.call(ignoredGlobalProps, g) != -1)\n'
+ ' continue;\n'
+ ' if ((!hasOwnProperty || loader.global.hasOwnProperty(g)) && g != loader.global && curGlobalObj[g] != loader.global[g]) {\n'
+ ' exports[g] = loader.global[g];\n'
+ ' if (singleGlobal) {\n'
+ ' if (singleGlobal !== loader.global[g])\n'
+ ' multipleExports = true;\n'
+ ' }\n'
+ ' else if (singleGlobal !== false) {\n'
+ ' singleGlobal = loader.global[g];\n'
+ ' }\n'
+ ' }\n'
+ ' }\n'
+ ' }\n'
+ ' moduleGlobals[moduleName] = exports;\n'
+ ' return multipleExports ? exports : singleGlobal;\n'
+ ' }\n'
+ ' }));\n'
+ '})();\n'
}