add runtimeES3 transformer

This commit is contained in:
Sebastian McKenzie 2015-03-31 01:20:14 +11:00
parent 12f8fa229d
commit 1c7fabdd6d
13 changed files with 176 additions and 148 deletions

7
.gitignore vendored
View File

@ -11,7 +11,8 @@ test/core/tmp
coverage coverage
dist dist
.package.json .package.json
packages/babel-runtime/*.js packages/babel-runtime/es5/helpers/*.js
packages/babel-runtime/helpers/*.js packages/babel-runtime/es5/regenerator/*.js
packages/babel-runtime/regenerator/*.js packages/babel-runtime/es3/helpers/*.js
packages/babel-runtime/es3/regenerator/*.js
lib lib

View File

@ -41,7 +41,7 @@
"chokidar": "^0.12.6", "chokidar": "^0.12.6",
"commander": "^2.6.0", "commander": "^2.6.0",
"convert-source-map": "^0.5.0", "convert-source-map": "^0.5.0",
"core-js": "^0.6.1", "core-js": "^0.7.0",
"debug": "^2.1.1", "debug": "^2.1.1",
"detect-indent": "^3.0.0", "detect-indent": "^3.0.0",
"estraverse": "^1.9.1", "estraverse": "^1.9.1",

View File

@ -0,0 +1,4 @@
module.exports = {
"default": require("core-js/client/library"),
__esModule: true
};

View File

@ -0,0 +1,4 @@
module.exports = {
"default": require("core-js/library"),
__esModule: true
};

View File

@ -5,6 +5,6 @@
"repository": "babel/babel", "repository": "babel/babel",
"author": "Sebastian McKenzie <sebmck@gmail.com>", "author": "Sebastian McKenzie <sebmck@gmail.com>",
"dependencies": { "dependencies": {
"core-js": "^0.6.1" "core-js": "^0.7.0"
} }
} }

View File

@ -1,5 +1,6 @@
"use strict"; "use strict";
var outputFile = require("output-file-sync");
var transform = require("../lib/babel/transformation"); var transform = require("../lib/babel/transformation");
var each = require("lodash/collection/each"); var each = require("lodash/collection/each");
var File = require("../lib/babel/transformation/file"); var File = require("../lib/babel/transformation/file");
@ -8,17 +9,11 @@ var fs = require("fs");
var t = require("../lib/babel/types"); var t = require("../lib/babel/types");
var _ = require("lodash"); var _ = require("lodash");
var relative = function (filename) { function relative(filename) {
return __dirname + "/babel-runtime/" + filename; return __dirname + "/babel-runtime/" + filename;
}; }
var writeFile = function (filename, content) { function readFile(filename, defaultify) {
filename = relative(filename);
console.log(filename);
fs.writeFileSync(filename, content);
};
var readFile = function (filename, defaultify) {
var file = fs.readFileSync(require.resolve(filename), "utf8"); var file = fs.readFileSync(require.resolve(filename), "utf8");
if (defaultify) { if (defaultify) {
@ -26,25 +21,38 @@ var readFile = function (filename, defaultify) {
} }
return file; return file;
}; }
var updatePackage = function () { function updatePackage() {
var pkgLoc = relative("package.json"); var pkgLoc = relative("package.json");
var pkg = require(pkgLoc); var pkg = require(pkgLoc);
var mainPkg = require("../package.json"); var mainPkg = require("../package.json");
pkg.version = mainPkg.version; pkg.version = mainPkg.version;
writeFile("package.json", JSON.stringify(pkg, null, 2)); writeRootFile("package.json", JSON.stringify(pkg, null, 2));
}; }
var selfContainify = function (code) { function writeRootFile(filename, content) {
filename = relative(filename);
console.log(filename);
outputFile(filename, content);
}
function doVersion(version) {
var transformer = "runtime" + version.toUpperCase();
function writeFile(filename, content) {
return writeRootFile(version + "/" + filename, content);
}
function selfContainify(code) {
return transform(code, { return transform(code, {
optional: ["runtime"] optional: [transformer]
}).code; }).code;
}; }
var buildHelper = function (helperName) { function buildHelper(helperName) {
var tree = t.program( var tree = t.program(
util.template("self-contained-helpers-head", { util.template("self-contained-helpers-head", {
HELPER: util.template("helper-" + helperName) HELPER: util.template("helper-" + helperName)
@ -52,15 +60,18 @@ var buildHelper = function (helperName) {
); );
return transform.fromAst(tree, null, { return transform.fromAst(tree, null, {
optional: ["runtime"] optional: [transformer]
}).code; }).code;
}; }
each(File.helpers, function (helperName) { each(File.helpers, function (helperName) {
writeFile("helpers/" + helperName + ".js", buildHelper(helperName)); writeFile("helpers/" + helperName + ".js", buildHelper(helperName));
}); });
writeFile("core-js.js", readFile("core-js/library", true));
writeFile("regenerator/index.js", readFile("regenerator-babel/runtime-module", true)); writeFile("regenerator/index.js", readFile("regenerator-babel/runtime-module", true));
writeFile("regenerator/runtime.js", selfContainify(readFile("regenerator-babel/runtime"))); writeFile("regenerator/runtime.js", selfContainify(readFile("regenerator-babel/runtime")));
}
doVersion("es3");
doVersion("es5");
updatePackage(); updatePackage();

View File

@ -0,0 +1,101 @@
import includes from "lodash/collection/includes";
import * as util from "../../util";
import has from "lodash/object/has";
import * as t from "../../types";
var isSymbolIterator = t.buildMatchMemberExpression("Symbol.iterator");
var ALIASABLE_CONSTRUCTORS = [
"Symbol",
"Promise",
"Map",
"WeakMap",
"Set",
"WeakSet"
];
export default function (exports, core, prefix) {
var moduleName = `babel-runtime/${prefix}`;
function coreHas(node) {
return node.name !== "_" && has(core, node.name);
}
var astVisitor = {
enter(node, parent, scope, file) {
var prop;
if (this.isMemberExpression() && this.isReferenced()) {
// Array.from -> _core.Array.from
var obj = node.object;
prop = node.property;
if (!t.isReferenced(obj, node)) return;
if (!node.computed && coreHas(obj) && has(core[obj.name], prop.name) && !scope.getBindingIdentifier(obj.name)) {
this.skip();
return t.prependToMemberExpression(node, file.get("coreIdentifier"));
}
} else if (this.isReferencedIdentifier() && !t.isMemberExpression(parent) && includes(ALIASABLE_CONSTRUCTORS, node.name) && !scope.getBindingIdentifier(node.name)) {
// Symbol() -> _core.Symbol(); new Promise -> new _core.Promise
return t.memberExpression(file.get("coreIdentifier"), node);
} else if (this.isCallExpression()) {
// arr[Symbol.iterator]() -> _core.$for.getIterator(arr)
var callee = node.callee;
if (node.arguments.length) return false;
if (!t.isMemberExpression(callee)) return false;
if (!callee.computed) return false;
prop = callee.property;
if (!isSymbolIterator(prop)) return false;
return util.template("corejs-iterator", {
CORE_ID: file.get("coreIdentifier"),
VALUE: callee.object
});
} else if (this.isBinaryExpression()) {
// Symbol.iterator in arr -> core.$for.isIterable(arr)
if (node.operator !== "in") return;
var left = node.left;
if (!isSymbolIterator(left)) return;
return util.template("corejs-is-iterator", {
CORE_ID: file.get("coreIdentifier"),
VALUE: node.right
});
}
}
};
exports.metadata = {
optional: true
};
exports.Program = function (node, parent, scope, file) {
this.traverse(astVisitor, file);
};
exports.pre = function (file) {
file.set("helperGenerator", function (name) {
return file.addImport(`${moduleName}/helpers/${name}`, name);
});
file.setDynamic("coreIdentifier", function () {
return file.addImport(`${moduleName}/core-js`, "core");
});
file.setDynamic("regeneratorIdentifier", function () {
return file.addImport(`${moduleName}/regenerator`, "regeneratorRuntime");
});
};
exports.Identifier = function (node, parent, scope, file) {
if (this.isReferencedIdentifier({ name: "regeneratorRuntime" })) {
return file.get("regeneratorIdentifier");
}
};
};

View File

@ -1,3 +1,4 @@
{ {
"useStrict": "strict" "useStrict": "strict",
"runtimeES5": "runtime"
} }

View File

@ -83,6 +83,7 @@ export default {
// needs to be after `regenerator` due to needing `regeneratorRuntime` references // needs to be after `regenerator` due to needing `regeneratorRuntime` references
// needs to be after `es6.forOf` due to needing `Symbol.iterator` references // needs to be after `es6.forOf` due to needing `Symbol.iterator` references
// needs to be before `es6.modules` due to dynamic imports // needs to be before `es6.modules` due to dynamic imports
runtimeES3: require("./other/runtime-es3"),
runtime: require("./other/runtime"), runtime: require("./other/runtime"),
// needs to be before `_blockHoist` due to function hoisting etc // needs to be before `_blockHoist` due to function hoisting etc

View File

@ -0,0 +1,4 @@
import core from "core-js/client/library";
import buildRuntimeTransformer from "../../helpers/build-runtime-transformer";
buildRuntimeTransformer(exports, core, "es3");

View File

@ -1,103 +1,4 @@
import includes from "lodash/collection/includes";
import * as util from "../../../util";
import core from "core-js/library"; import core from "core-js/library";
import has from "lodash/object/has"; import buildRuntimeTransformer from "../../helpers/build-runtime-transformer";
import * as t from "../../../types";
var isSymbolIterator = t.buildMatchMemberExpression("Symbol.iterator"); buildRuntimeTransformer(exports, core, "es5");
var coreHas = function (node) {
return node.name !== "_" && has(core, node.name);
};
var ALIASABLE_CONSTRUCTORS = [
"Symbol",
"Promise",
"Map",
"WeakMap",
"Set",
"WeakSet"
];
var astVisitor = {
enter(node, parent, scope, file) {
var prop;
if (this.isMemberExpression() && this.isReferenced()) {
// Array.from -> _core.Array.from
var obj = node.object;
prop = node.property;
if (!t.isReferenced(obj, node)) return;
if (!node.computed && coreHas(obj) && has(core[obj.name], prop.name) && !scope.getBindingIdentifier(obj.name)) {
this.skip();
return t.prependToMemberExpression(node, file.get("coreIdentifier"));
}
} else if (this.isReferencedIdentifier() && !t.isMemberExpression(parent) && includes(ALIASABLE_CONSTRUCTORS, node.name) && !scope.getBindingIdentifier(node.name)) {
// Symbol() -> _core.Symbol(); new Promise -> new _core.Promise
return t.memberExpression(file.get("coreIdentifier"), node);
} else if (this.isCallExpression()) {
// arr[Symbol.iterator]() -> _core.$for.getIterator(arr)
var callee = node.callee;
if (node.arguments.length) return false;
if (!t.isMemberExpression(callee)) return false;
if (!callee.computed) return false;
prop = callee.property;
if (!isSymbolIterator(prop)) return false;
return util.template("corejs-iterator", {
CORE_ID: file.get("coreIdentifier"),
VALUE: callee.object
});
} else if (this.isBinaryExpression()) {
// Symbol.iterator in arr -> core.$for.isIterable(arr)
if (node.operator !== "in") return;
var left = node.left;
if (!isSymbolIterator(left)) return;
return util.template("corejs-is-iterator", {
CORE_ID: file.get("coreIdentifier"),
VALUE: node.right
});
}
}
};
export var metadata = {
optional: true,
react: true
};
export function manipulateOptions(opts) {
if (opts.whitelist) opts.whitelist.push("es6.modules");
}
export function Program(node, parent, scope, file) {
this.traverse(astVisitor, file);
}
export function pre(file) {
file.set("helperGenerator", function (name) {
return file.addImport("babel-runtime/helpers/" + name, name);
});
file.setDynamic("coreIdentifier", function () {
return file.addImport("babel-runtime/core-js", "core");
});
file.setDynamic("regeneratorIdentifier", function () {
return file.addImport("babel-runtime/regenerator", "regeneratorRuntime");
});
}
export function Identifier(node, parent, scope, file) {
if (this.isReferencedIdentifier({ name: "regeneratorRuntime" })) {
return file.get("regeneratorIdentifier");
}
}