From 1c7fabdd6d650f352a512a33a792eb1339364aa7 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Tue, 31 Mar 2015 01:20:14 +1100 Subject: [PATCH] add runtimeES3 transformer --- .gitignore | 7 +- package.json | 2 +- packages/babel-runtime/es3/core-js.js | 4 + packages/babel-runtime/es5/core-js.js | 4 + packages/babel-runtime/helpers/.gitkeep | 0 packages/babel-runtime/package.json | 2 +- packages/babel-runtime/regenerator/.gitkeep | 0 packages/build-runtime.js | 93 +++++++++------- .../helpers/build-runtime-transformer.js | 101 +++++++++++++++++ .../transformation/transformers/aliases.json | 3 +- .../transformation/transformers/index.js | 1 + .../transformers/other/runtime-es3.js | 4 + .../transformers/other/runtime.js | 103 +----------------- 13 files changed, 176 insertions(+), 148 deletions(-) create mode 100644 packages/babel-runtime/es3/core-js.js create mode 100644 packages/babel-runtime/es5/core-js.js delete mode 100644 packages/babel-runtime/helpers/.gitkeep delete mode 100644 packages/babel-runtime/regenerator/.gitkeep create mode 100644 src/babel/transformation/helpers/build-runtime-transformer.js create mode 100644 src/babel/transformation/transformers/other/runtime-es3.js diff --git a/.gitignore b/.gitignore index 6a8948c435..fe3e360527 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,8 @@ test/core/tmp coverage dist .package.json -packages/babel-runtime/*.js -packages/babel-runtime/helpers/*.js -packages/babel-runtime/regenerator/*.js +packages/babel-runtime/es5/helpers/*.js +packages/babel-runtime/es5/regenerator/*.js +packages/babel-runtime/es3/helpers/*.js +packages/babel-runtime/es3/regenerator/*.js lib diff --git a/package.json b/package.json index fa6a6db0f7..ae8f382e6e 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "chokidar": "^0.12.6", "commander": "^2.6.0", "convert-source-map": "^0.5.0", - "core-js": "^0.6.1", + "core-js": "^0.7.0", "debug": "^2.1.1", "detect-indent": "^3.0.0", "estraverse": "^1.9.1", diff --git a/packages/babel-runtime/es3/core-js.js b/packages/babel-runtime/es3/core-js.js new file mode 100644 index 0000000000..263d7c1fbe --- /dev/null +++ b/packages/babel-runtime/es3/core-js.js @@ -0,0 +1,4 @@ +module.exports = { + "default": require("core-js/client/library"), + __esModule: true +}; diff --git a/packages/babel-runtime/es5/core-js.js b/packages/babel-runtime/es5/core-js.js new file mode 100644 index 0000000000..7d5664380a --- /dev/null +++ b/packages/babel-runtime/es5/core-js.js @@ -0,0 +1,4 @@ +module.exports = { + "default": require("core-js/library"), + __esModule: true +}; diff --git a/packages/babel-runtime/helpers/.gitkeep b/packages/babel-runtime/helpers/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/packages/babel-runtime/package.json b/packages/babel-runtime/package.json index aac56f1fb2..8b67ea3c84 100644 --- a/packages/babel-runtime/package.json +++ b/packages/babel-runtime/package.json @@ -5,6 +5,6 @@ "repository": "babel/babel", "author": "Sebastian McKenzie ", "dependencies": { - "core-js": "^0.6.1" + "core-js": "^0.7.0" } } \ No newline at end of file diff --git a/packages/babel-runtime/regenerator/.gitkeep b/packages/babel-runtime/regenerator/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/packages/build-runtime.js b/packages/build-runtime.js index e2d8d5b075..1533e5bf9b 100644 --- a/packages/build-runtime.js +++ b/packages/build-runtime.js @@ -1,24 +1,19 @@ "use strict"; -var transform = require("../lib/babel/transformation"); -var each = require("lodash/collection/each"); -var File = require("../lib/babel/transformation/file"); -var util = require("../lib/babel/util"); -var fs = require("fs"); -var t = require("../lib/babel/types"); -var _ = require("lodash"); +var outputFile = require("output-file-sync"); +var transform = require("../lib/babel/transformation"); +var each = require("lodash/collection/each"); +var File = require("../lib/babel/transformation/file"); +var util = require("../lib/babel/util"); +var fs = require("fs"); +var t = require("../lib/babel/types"); +var _ = require("lodash"); -var relative = function (filename) { +function relative(filename) { return __dirname + "/babel-runtime/" + filename; -}; +} -var writeFile = function (filename, content) { - filename = relative(filename); - console.log(filename); - fs.writeFileSync(filename, content); -}; - -var readFile = function (filename, defaultify) { +function readFile(filename, defaultify) { var file = fs.readFileSync(require.resolve(filename), "utf8"); if (defaultify) { @@ -26,41 +21,57 @@ var readFile = function (filename, defaultify) { } return file; -}; +} -var updatePackage = function () { +function updatePackage() { var pkgLoc = relative("package.json"); var pkg = require(pkgLoc); var mainPkg = require("../package.json"); pkg.version = mainPkg.version; - writeFile("package.json", JSON.stringify(pkg, null, 2)); -}; + writeRootFile("package.json", JSON.stringify(pkg, null, 2)); +} -var selfContainify = function (code) { - return transform(code, { - optional: ["runtime"] - }).code; -}; +function writeRootFile(filename, content) { + filename = relative(filename); + console.log(filename); + outputFile(filename, content); +} -var buildHelper = function (helperName) { - var tree = t.program( - util.template("self-contained-helpers-head", { - HELPER: util.template("helper-" + helperName) - }) - ); +function doVersion(version) { + var transformer = "runtime" + version.toUpperCase(); - return transform.fromAst(tree, null, { - optional: ["runtime"] - }).code; -}; + function writeFile(filename, content) { + return writeRootFile(version + "/" + filename, content); + } -each(File.helpers, function (helperName) { - writeFile("helpers/" + helperName + ".js", buildHelper(helperName)); -}); + function selfContainify(code) { + return transform(code, { + optional: [transformer] + }).code; + } -writeFile("core-js.js", readFile("core-js/library", true)); -writeFile("regenerator/index.js", readFile("regenerator-babel/runtime-module", true)); -writeFile("regenerator/runtime.js", selfContainify(readFile("regenerator-babel/runtime"))); + function buildHelper(helperName) { + var tree = t.program( + util.template("self-contained-helpers-head", { + HELPER: util.template("helper-" + helperName) + }) + ); + + return transform.fromAst(tree, null, { + optional: [transformer] + }).code; + } + + each(File.helpers, function (helperName) { + writeFile("helpers/" + helperName + ".js", buildHelper(helperName)); + }); + + writeFile("regenerator/index.js", readFile("regenerator-babel/runtime-module", true)); + writeFile("regenerator/runtime.js", selfContainify(readFile("regenerator-babel/runtime"))); +} + +doVersion("es3"); +doVersion("es5"); updatePackage(); diff --git a/src/babel/transformation/helpers/build-runtime-transformer.js b/src/babel/transformation/helpers/build-runtime-transformer.js new file mode 100644 index 0000000000..0a24a75b9a --- /dev/null +++ b/src/babel/transformation/helpers/build-runtime-transformer.js @@ -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"); + } + }; +}; diff --git a/src/babel/transformation/transformers/aliases.json b/src/babel/transformation/transformers/aliases.json index fd7d5b6b8a..4cec66af73 100644 --- a/src/babel/transformation/transformers/aliases.json +++ b/src/babel/transformation/transformers/aliases.json @@ -1,3 +1,4 @@ { - "useStrict": "strict" + "useStrict": "strict", + "runtimeES5": "runtime" } diff --git a/src/babel/transformation/transformers/index.js b/src/babel/transformation/transformers/index.js index 410261a302..b942489aab 100644 --- a/src/babel/transformation/transformers/index.js +++ b/src/babel/transformation/transformers/index.js @@ -83,6 +83,7 @@ export default { // 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 before `es6.modules` due to dynamic imports + runtimeES3: require("./other/runtime-es3"), runtime: require("./other/runtime"), // needs to be before `_blockHoist` due to function hoisting etc diff --git a/src/babel/transformation/transformers/other/runtime-es3.js b/src/babel/transformation/transformers/other/runtime-es3.js new file mode 100644 index 0000000000..f258307c44 --- /dev/null +++ b/src/babel/transformation/transformers/other/runtime-es3.js @@ -0,0 +1,4 @@ +import core from "core-js/client/library"; +import buildRuntimeTransformer from "../../helpers/build-runtime-transformer"; + +buildRuntimeTransformer(exports, core, "es3"); diff --git a/src/babel/transformation/transformers/other/runtime.js b/src/babel/transformation/transformers/other/runtime.js index 55a609707a..6d775a93f0 100644 --- a/src/babel/transformation/transformers/other/runtime.js +++ b/src/babel/transformation/transformers/other/runtime.js @@ -1,103 +1,4 @@ -import includes from "lodash/collection/includes"; -import * as util from "../../../util"; import core from "core-js/library"; -import has from "lodash/object/has"; -import * as t from "../../../types"; +import buildRuntimeTransformer from "../../helpers/build-runtime-transformer"; -var isSymbolIterator = t.buildMatchMemberExpression("Symbol.iterator"); - -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"); - } -} +buildRuntimeTransformer(exports, core, "es5");