Compare commits
93 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
531d4f1937 | ||
|
|
f155bc249c | ||
|
|
452d0ef30e | ||
|
|
005754ba98 | ||
|
|
c3c4cf17e3 | ||
|
|
0866e5a403 | ||
|
|
15f5e658fc | ||
|
|
574e6da132 | ||
|
|
da6d27ed16 | ||
|
|
4e87809ff9 | ||
|
|
f4267aaab0 | ||
|
|
4f255d103a | ||
|
|
502cc13aed | ||
|
|
0a1154e6fd | ||
|
|
f5b3d72730 | ||
|
|
e9bcccffbd | ||
|
|
aaf4cbf06f | ||
|
|
5080534974 | ||
|
|
02cb397873 | ||
|
|
d9169a87ad | ||
|
|
f3b6f2fc61 | ||
|
|
04cc24ee82 | ||
|
|
f32079ef42 | ||
|
|
d1b69656ae | ||
|
|
09453a490b | ||
|
|
e2e7627f0f | ||
|
|
4fe24a9a3b | ||
|
|
d26e7ad577 | ||
|
|
571cb4928f | ||
|
|
c12e8122f8 | ||
|
|
92e7a01d14 | ||
|
|
b9ca9d42dc | ||
|
|
479c3e477a | ||
|
|
2c3d3d8105 | ||
|
|
ea03f67505 | ||
|
|
ee0c88a070 | ||
|
|
98206df864 | ||
|
|
1066a42fb2 | ||
|
|
062175586c | ||
|
|
0dc6b582a6 | ||
|
|
d8d70ba137 | ||
|
|
f23c916520 | ||
|
|
8ae4601177 | ||
|
|
9a466d3ef9 | ||
|
|
713845d14c | ||
|
|
471d60e5cd | ||
|
|
43864e0686 | ||
|
|
4c2ae5dd19 | ||
|
|
a540cbe801 | ||
|
|
34cc577fa2 | ||
|
|
c855b55133 | ||
|
|
16c86c25b7 | ||
|
|
4345f7945b | ||
|
|
f44c93add2 | ||
|
|
09e45c51a4 | ||
|
|
1a42b72b15 | ||
|
|
d30415d74a | ||
|
|
616ef8d840 | ||
|
|
56437f94bc | ||
|
|
881fa6430b | ||
|
|
b7971690f3 | ||
|
|
c01d0abbd3 | ||
|
|
7043119346 | ||
|
|
b5325df57f | ||
|
|
0fc958e0fc | ||
|
|
9cb16711dd | ||
|
|
04766b13f5 | ||
|
|
433d704739 | ||
|
|
30204d2ee6 | ||
|
|
374b7cca2c | ||
|
|
152ae388f0 | ||
|
|
04344026bb | ||
|
|
cfffaf6cdb | ||
|
|
2952d94e60 | ||
|
|
0276c3ae81 | ||
|
|
c00f8dce3f | ||
|
|
4e24ae39cf | ||
|
|
12bd6494b7 | ||
|
|
e35c7550fe | ||
|
|
e7046abe72 | ||
|
|
affa7f0c6f | ||
|
|
be650ffc61 | ||
|
|
3078d48178 | ||
|
|
0be93563dd | ||
|
|
3e55980145 | ||
|
|
470ebf3a46 | ||
|
|
b695369126 | ||
|
|
f4611469b4 | ||
|
|
68bfafe745 | ||
|
|
f72782b71c | ||
|
|
0f1f5e3565 | ||
|
|
dfe126f3d4 | ||
|
|
4c9cb957a9 |
8
.babelrc
8
.babelrc
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"experimental": true,
|
||||
"playground": true,
|
||||
"loose": true,
|
||||
"blacklist": ["es6.tailCall"]
|
||||
"stage": 0,
|
||||
"loose": ["all"],
|
||||
"blacklist": ["es6.tailCall"],
|
||||
"optional": ["optimisation.flow.forOf"]
|
||||
}
|
||||
|
||||
6
.gitmodules
vendored
6
.gitmodules
vendored
@@ -1,12 +1,6 @@
|
||||
[submodule "vendor/traceur"]
|
||||
path = vendor/traceur
|
||||
url = https://github.com/google/traceur-compiler
|
||||
[submodule "vendor/regenerator"]
|
||||
path = vendor/regenerator
|
||||
url = https://github.com/babel/regenerator-babel
|
||||
[submodule "vendor/test262"]
|
||||
path = vendor/test262
|
||||
url = https://github.com/tc39/test262
|
||||
[submodule "vendor/compat-table"]
|
||||
path = vendor/compat-table
|
||||
url = https://github.com/kangax/compat-table
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
sudo: false
|
||||
#sudo: false
|
||||
language: node_js
|
||||
cache:
|
||||
directories:
|
||||
|
||||
39
CHANGELOG.md
39
CHANGELOG.md
@@ -13,6 +13,45 @@ _Note: Gaps between patch versions are faulty/broken releases._
|
||||
|
||||
See [CHANGELOG - 6to5](CHANGELOG-6to5.md) for the pre-4.0.0 version changelog.
|
||||
|
||||
## 5.2.3
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix plugin containers being called with an undefined import. Thanks [@timbur](https://github.com/timbur)!
|
||||
* Allow Flow object separators to be commas. Thanks [@monsanto](https://github.com/monsanto)!
|
||||
* Add missing `Statement` and `Declaration` node aliases to flow types.
|
||||
|
||||
## 5.2.2
|
||||
|
||||
* **Internal**
|
||||
* Allow `util.arrayify` to take arbitrary types and coerce it into an array.
|
||||
|
||||
## 5.2.1
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix regression in `node/register` that caused `node_modules` to not be ignored.
|
||||
|
||||
## 5.2.0
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix plugin strings splitting arbitrarily on `:` which caused full paths on Windows to fail as they include `:` after the drive letter.
|
||||
* Call class property `initializer`s with their target instead of their descriptor.
|
||||
* Fix `ignore` and `only` not properly working on Windows path separators. Thanks [@stagas](https://github.com/stagas)!
|
||||
* Fix `resolveRc` running on files twice causing issues. Thanks [@lukescott](https://github.com/lukescott)!
|
||||
* Fix shorthand properties not correctly being target for `isReferenced` checks. Thanks [@monsanto](https://github.com/monsanto)!
|
||||
* **Polish**
|
||||
* Allow passing an array of globs to `babel/register` `only` and `ignore` options. Thanks [@Mark-Simulacrum](https://github.com/Mark-Simulacrum)!
|
||||
* When inferring function names that collide with upper bindings, instead of doing the wrapper, instead rename them.
|
||||
* Consider constant-like variable declaration functions to always refer to themselves so TOC can be performed.
|
||||
* Process globs manually when using `$ babel` as some shells such as Windows don't explode them. Thanks [@jden](https://github.com/jden)!
|
||||
* Add alternative way to execute plugins via a closure that's called with the current Babel instance.
|
||||
* **Internal**
|
||||
* Remove multiple internal transformers in favor of directly doing things when we need to. Previously, declarations such as `_ref` that we needed to create in specific scopes were done at the very end via the `_declarations` transformer. Now, they're done and added to the scope **right** when they're needed. This gets rid of the crappy `_declarations` property on scope nodes and fixes the crappy regenerator bug where it was creating a new `BlockStatement` so the declarations were being lost.
|
||||
* Rework transformer traversal optimisation. Turns out that calling a `check` function for **every single node** in the AST is ridiculously expensive. 300,000 nodes timesed by ~30 transformers meant that it took tens of seconds to perform while it's quicker to just do the unnecessary traversal. Seems obvious in hindsight.
|
||||
* **New Feature**
|
||||
* Add `jscript` transformer that turns named function expressions into function declarations to get around [JScript's horribly broken function expression semantics](https://kangax.github.io/nfe/#jscript-bugs). Thanks [@kondi](https://github.com/kondi)!
|
||||
* Add `@@hasInstance` support to objects when using the `es6.spec.symbols` transformer.
|
||||
* Add `retainLines` option that retains the line (but not the columns!) of the input code.
|
||||
|
||||
## 5.1.13
|
||||
|
||||
* **Polish**
|
||||
|
||||
@@ -29,16 +29,19 @@ $ cd babel
|
||||
$ make bootstrap
|
||||
```
|
||||
|
||||
Then you need to run:
|
||||
Then you can either run:
|
||||
|
||||
```sh
|
||||
$ make build-core
|
||||
```
|
||||
|
||||
to build Babel **once** or:
|
||||
|
||||
```sh
|
||||
$ make watch-core
|
||||
```
|
||||
|
||||
This will compile Babel and then sit in the background and on file modification
|
||||
recompile the necessary files. Babel itself is written in ES6. The source files
|
||||
reside in `src/` and transpile to `lib/`
|
||||
|
||||
to have Babel build itself then incrementally build files on change.
|
||||
|
||||
#### Running tests
|
||||
|
||||
|
||||
12
Makefile
12
Makefile
@@ -9,17 +9,20 @@ BABEL_CMD = node_modules/babel/bin/babel
|
||||
|
||||
export NODE_ENV = test
|
||||
|
||||
.PHONY: clean test test-cov test-clean test-travis test-simple test-all test-browser test-parser publish build bootstrap publish-core publish-runtime build-core watch-core build-core-test
|
||||
.PHONY: clean test test-cov test-clean test-travis test-simple test-all test-browser test-parser publish build bootstrap publish-core publish-runtime build-core watch-core build-core-test clean-core
|
||||
|
||||
build-core:
|
||||
build-core: clean-core
|
||||
node $(BABEL_CMD) src --out-dir lib --copy-files
|
||||
|
||||
build-core-test:
|
||||
build-core-test: clean-core
|
||||
node $(BABEL_CMD) src --out-dir lib --copy-files --auxiliary-comment "istanbul ignore next"
|
||||
|
||||
watch-core:
|
||||
watch-core: clean-core
|
||||
node $(BABEL_CMD) src --out-dir lib --watch --copy-files
|
||||
|
||||
clean-core:
|
||||
rm -rf lib
|
||||
|
||||
build:
|
||||
mkdir -p dist
|
||||
make build-core
|
||||
@@ -115,3 +118,4 @@ bootstrap:
|
||||
cd packages/babel-cli && npm install && npm link && npm link babel-core
|
||||
git submodule update --init
|
||||
cd vendor/compat-table && npm install object-assign
|
||||
make build
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "babel-core",
|
||||
"description": "Turn ES6 code into readable vanilla ES5 with source maps",
|
||||
"version": "5.1.13",
|
||||
"version": "5.2.3",
|
||||
"author": "Sebastian McKenzie <sebmck@gmail.com>",
|
||||
"homepage": "https://babeljs.io/",
|
||||
"repository": "babel/babel",
|
||||
@@ -28,6 +28,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"ast-types": "~0.7.0",
|
||||
"bluebird": "^2.9.25",
|
||||
"chalk": "^1.0.0",
|
||||
"convert-source-map": "^1.1.0",
|
||||
"core-js": "^0.9.0",
|
||||
@@ -49,6 +50,7 @@
|
||||
"regenerator": "^0.8.20",
|
||||
"regexpu": "^1.1.2",
|
||||
"repeating": "^1.1.2",
|
||||
"resolve": "^1.1.6",
|
||||
"shebang-regex": "^1.0.0",
|
||||
"slash": "^1.0.0",
|
||||
"source-map": "^0.4.0",
|
||||
@@ -59,7 +61,7 @@
|
||||
"user-home": "^1.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel": "4.7.13",
|
||||
"babel": "5.1.13",
|
||||
"browserify": "^9.0.8",
|
||||
"chai": "^2.2.0",
|
||||
"eslint": "^0.18.0",
|
||||
|
||||
@@ -8,6 +8,7 @@ var util = require("babel-core").util;
|
||||
var each = require("lodash/collection/each");
|
||||
var keys = require("lodash/object/keys");
|
||||
var fs = require("fs");
|
||||
var glob = require("glob");
|
||||
|
||||
each(options, function (option, key) {
|
||||
if (option.hidden) return;
|
||||
@@ -69,7 +70,9 @@ commander.parse(process.argv);
|
||||
|
||||
var errors = [];
|
||||
|
||||
var filenames = commander.args;
|
||||
var filenames = commander.args.reduce(function (globbed, input) {
|
||||
return globbed.concat(glob.sync(input));
|
||||
}, []);
|
||||
|
||||
each(filenames, function (filename) {
|
||||
if (!fs.existsSync(filename)) {
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
{
|
||||
"name": "babel",
|
||||
"description": "Turn ES6 code into readable vanilla ES5 with source maps",
|
||||
"version": "5.1.12",
|
||||
"version": "5.2.2",
|
||||
"author": "Sebastian McKenzie <sebmck@gmail.com>",
|
||||
"homepage": "https://babeljs.io/",
|
||||
"repository": "babel/babel",
|
||||
"preferGlobal": true,
|
||||
"dependencies": {
|
||||
"babel-core": "^5.1.12",
|
||||
"babel-core": "^5.2.2",
|
||||
"chokidar": "^1.0.0",
|
||||
"commander": "^2.6.0",
|
||||
"fs-readdir-recursive": "^0.1.0",
|
||||
"output-file-sync": "^1.1.0",
|
||||
"lodash": "^3.2.0",
|
||||
"convert-source-map": "^1.1.0",
|
||||
"source-map": "^0.4.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
"fs-readdir-recursive": "^0.1.0",
|
||||
"glob": "^5.0.5",
|
||||
"lodash": "^3.2.0",
|
||||
"output-file-sync": "^1.1.0",
|
||||
"path-is-absolute": "^1.0.0",
|
||||
"source-map": "^0.4.0"
|
||||
},
|
||||
"bin": {
|
||||
"babel": "./bin/babel/index.js",
|
||||
|
||||
1
packages/babel-cli/register-without-polyfill.js
Normal file
1
packages/babel-cli/register-without-polyfill.js
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require("babel-core/register-without-polyfill");
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "babel-runtime",
|
||||
"description": "babel selfContained runtime",
|
||||
"version": "5.1.12",
|
||||
"version": "5.2.2",
|
||||
"repository": "babel/babel",
|
||||
"author": "Sebastian McKenzie <sebmck@gmail.com>",
|
||||
"dependencies": {
|
||||
|
||||
1
register-without-polyfill.js
Normal file
1
register-without-polyfill.js
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require("./lib/babel/api/register/node");
|
||||
@@ -1 +1 @@
|
||||
module.exports = require("./lib/babel/api/register/node");
|
||||
module.exports = require("./lib/babel/api/register/node-polyfill");
|
||||
|
||||
3
src/acorn/index.js
Normal file
3
src/acorn/index.js
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from "./src/index";
|
||||
import "./plugins/flow";
|
||||
import "./plugins/jsx";
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "acorn",
|
||||
"description": "ECMAScript parser",
|
||||
"homepage": "https://github.com/marijnh/acorn",
|
||||
"main": "src/index.js",
|
||||
"main": "index.js",
|
||||
"version": "1.0.0",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var acorn = require("..")
|
||||
var acorn = require("../src/index")
|
||||
|
||||
var pp = acorn.Parser.prototype
|
||||
var tt = acorn.tokTypes
|
||||
@@ -322,7 +322,7 @@ pp.flow_parseObjectType = function (allowStatic) {
|
||||
}
|
||||
|
||||
pp.flow_objectTypeSemicolon = function () {
|
||||
if (!this.eat(tt.semi) && this.type !== tt.braceR) {
|
||||
if (!this.eat(tt.semi) && !this.eat(tt.comma) && this.type !== tt.braceR) {
|
||||
this.unexpected()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var acorn = require("..")
|
||||
var acorn = require("../src/index")
|
||||
|
||||
var tt = acorn.tokTypes;
|
||||
var tc = acorn.tokContexts;
|
||||
|
||||
@@ -38,9 +38,6 @@ export {isIdentifierChar, isIdentifierStart} from "./identifier"
|
||||
export {Token} from "./tokenize"
|
||||
export {isNewLine, lineBreak, lineBreakG} from "./whitespace"
|
||||
|
||||
import "../plugins/flow";
|
||||
import "../plugins/jsx";
|
||||
|
||||
export const version = "1.0.0"
|
||||
|
||||
// The main exported interface (under `self.acorn` when in the
|
||||
|
||||
@@ -11,7 +11,7 @@ transform.run = function (code, opts = {}) {
|
||||
};
|
||||
|
||||
transform.load = function (url, callback, opts = {}, hold) {
|
||||
opts.filename ||= url;
|
||||
opts.filename = opts.filename || url;
|
||||
|
||||
var xhr = global.ActiveXObject ? new global.ActiveXObject("Microsoft.XMLHTTP") : new global.XMLHttpRequest();
|
||||
xhr.open("GET", url, true);
|
||||
|
||||
@@ -9,6 +9,7 @@ export { canCompile } from "../util";
|
||||
|
||||
export { default as options } from "../transformation/file/options";
|
||||
export { default as Transformer } from "../transformation/transformer";
|
||||
export { default as Pipeline } from "../transformation/transformer-pipeline";
|
||||
export { default as traverse } from "../traversal";
|
||||
export { default as buildExternalHelpers } from "../tools/build-external-helpers";
|
||||
export { version } from "../../../package";
|
||||
@@ -17,7 +18,7 @@ import * as t from "../types";
|
||||
export { t as types };
|
||||
|
||||
export function register(opts?: Object) {
|
||||
var callback = require("./register/node");
|
||||
var callback = require("./register/node-polyfill");
|
||||
if (opts != null) callback(opts);
|
||||
return callback;
|
||||
}
|
||||
|
||||
2
src/babel/api/register/node-polyfill.js
Normal file
2
src/babel/api/register/node-polyfill.js
Normal file
@@ -0,0 +1,2 @@
|
||||
import "../../polyfill";
|
||||
export { default } from "./node";
|
||||
@@ -1,4 +1,3 @@
|
||||
import "../../polyfill";
|
||||
import sourceMapSupport from "source-map-support";
|
||||
import * as registerCache from "./cache";
|
||||
import resolveRc from "../../tools/resolve-rc";
|
||||
@@ -32,8 +31,10 @@ var cache = registerCache.get();
|
||||
//
|
||||
|
||||
var transformOpts = {};
|
||||
var ignoreRegex = /node_modules/;
|
||||
var onlyRegex;
|
||||
|
||||
var ignore;
|
||||
var only;
|
||||
|
||||
var oldHandlers = {};
|
||||
var maps = {};
|
||||
|
||||
@@ -77,8 +78,11 @@ var compile = function (filename) {
|
||||
};
|
||||
|
||||
var shouldIgnore = function (filename) {
|
||||
filename = slash(filename);
|
||||
return (ignoreRegex && ignoreRegex.test(filename)) || (onlyRegex && !onlyRegex.test(filename));
|
||||
if (!ignore && !only) {
|
||||
return /node_modules/.test(filename);
|
||||
} else {
|
||||
return util.shouldIgnore(filename, ignore || [], only || []);
|
||||
}
|
||||
};
|
||||
|
||||
var istanbulMonkey = {};
|
||||
@@ -144,8 +148,8 @@ var hookExtensions = function (_exts) {
|
||||
hookExtensions(util.canCompile.EXTENSIONS);
|
||||
|
||||
export default function (opts = {}) {
|
||||
if (opts.only != null) onlyRegex = util.regexify(opts.only);
|
||||
if (opts.ignore != null) ignoreRegex = util.regexify(opts.ignore);
|
||||
if (opts.only != null) only = util.arrayify(opts.only, util.regexify);
|
||||
if (opts.ignore != null) ignore = util.arrayify(opts.ignore, util.regexify);
|
||||
|
||||
if (opts.extensions) hookExtensions(util.arrayify(opts.extensions));
|
||||
|
||||
|
||||
@@ -70,14 +70,14 @@ export default class Buffer {
|
||||
}
|
||||
|
||||
newline(i, removeLast) {
|
||||
if (this.format.compact) return;
|
||||
if (this.format.compact || this.format.retainLines) return;
|
||||
|
||||
if (this.format.concise) {
|
||||
this.space();
|
||||
return;
|
||||
}
|
||||
|
||||
removeLast ||= false;
|
||||
removeLast = removeLast || false;
|
||||
|
||||
if (isNumber(i)) {
|
||||
i = Math.min(2, i);
|
||||
|
||||
@@ -13,7 +13,7 @@ export function BlockStatement(node, print) {
|
||||
this.push("{");
|
||||
this.newline();
|
||||
print.sequence(node.body, { indent: true });
|
||||
this.removeLast("\n");
|
||||
if (!this.format.retainLines) this.removeLast("\n");
|
||||
this.rightBrace();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import * as t from "../types";
|
||||
|
||||
class CodeGenerator {
|
||||
constructor(ast, opts, code) {
|
||||
opts ||= {};
|
||||
opts = opts || {};
|
||||
|
||||
this.comments = ast.comments || [];
|
||||
this.tokens = ast.tokens || [];
|
||||
@@ -34,9 +34,10 @@ class CodeGenerator {
|
||||
}
|
||||
|
||||
var format = {
|
||||
retainLines: opts.retainLines,
|
||||
comments: opts.comments == null || opts.comments,
|
||||
compact: opts.compact,
|
||||
quotes: CodeGenerator.findCommonStringDelimeter(code, tokens),
|
||||
quotes: CodeGenerator.findCommonStringDelimiter(code, tokens),
|
||||
indent: {
|
||||
adjustMultilineComment: true,
|
||||
style: style,
|
||||
@@ -48,14 +49,14 @@ class CodeGenerator {
|
||||
format.compact = code.length > 100000; // 100KB
|
||||
|
||||
if (format.compact) {
|
||||
console.error(messages.get("codeGeneratorDeopt", opts.filename, "100KB"));
|
||||
console.error("[BABEL] " + messages.get("codeGeneratorDeopt", opts.filename, "100KB"));
|
||||
}
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
static findCommonStringDelimeter(code, tokens) {
|
||||
static findCommonStringDelimiter(code, tokens) {
|
||||
var occurences = {
|
||||
single: 0,
|
||||
double: 0
|
||||
@@ -146,6 +147,22 @@ class CodeGenerator {
|
||||
return print;
|
||||
}
|
||||
|
||||
catchUp(node, parent) {
|
||||
// catch up to this nodes newline if we're behind
|
||||
if (node.loc && this.format.retainLines && this.buffer.buf) {
|
||||
var needsParens = false;
|
||||
if (parent && this.position.line < node.loc.start.line && t.isTerminatorless(parent)) {
|
||||
needsParens = true;
|
||||
this._push("(");
|
||||
}
|
||||
while (this.position.line < node.loc.start.line) {
|
||||
this._push("\n");
|
||||
}
|
||||
return needsParens;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
print(node, parent, opts = {}) {
|
||||
if (!node) return;
|
||||
|
||||
@@ -197,6 +214,8 @@ class CodeGenerator {
|
||||
|
||||
this.printLeadingComments(node, parent);
|
||||
|
||||
var needsParensFromCatchup = this.catchUp(node, parent);
|
||||
|
||||
newline(true);
|
||||
|
||||
if (opts.before) opts.before();
|
||||
@@ -208,7 +227,7 @@ class CodeGenerator {
|
||||
this.newline();
|
||||
this.dedent();
|
||||
}
|
||||
if (needsParens) this.push(")");
|
||||
if (needsParens || needsParensFromCatchup) this.push(")");
|
||||
|
||||
this.map.mark(node, "end");
|
||||
if (opts.after) opts.after();
|
||||
@@ -328,6 +347,8 @@ class CodeGenerator {
|
||||
|
||||
if (skip) return;
|
||||
|
||||
this.catchUp(comment);
|
||||
|
||||
// whitespace before
|
||||
this.newline(this.whitespace.getNewlinesBefore(comment));
|
||||
|
||||
@@ -340,7 +361,6 @@ class CodeGenerator {
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
if (comment.type === "Block" && this.format.indent.adjustMultilineComment) {
|
||||
var offset = comment.loc.start.column;
|
||||
if (offset) {
|
||||
@@ -356,8 +376,13 @@ class CodeGenerator {
|
||||
val = this.getIndent() + val;
|
||||
}
|
||||
|
||||
//
|
||||
// force a newline for line comments when retainLines is set in case the next printed node
|
||||
// doesn't catch up
|
||||
if (this.format.retainLines && comment.type === "Line") {
|
||||
val += "\n";
|
||||
}
|
||||
|
||||
//
|
||||
this._push(val);
|
||||
|
||||
// whitespace after
|
||||
|
||||
@@ -85,16 +85,7 @@ export default class Node {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (t.isYieldExpression(parent) || t.isAwaitExpression(parent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (t.isContinueStatement(parent) || t.isBreakStatement(parent) ||
|
||||
t.isReturnStatement(parent) || t.isThrowStatement(parent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return t.isTerminatorless(parent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -171,4 +171,10 @@ export function ConditionalExpression(node, parent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
export { ConditionalExpression as AssignmentExpression };
|
||||
export function AssignmentExpression(node) {
|
||||
if (t.isObjectPattern(node.left)) {
|
||||
return true;
|
||||
} else {
|
||||
return ConditionalExpression(...arguments);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ function crawl(node, state = {}) {
|
||||
} else if (t.isFunction(node)) {
|
||||
state.hasFunction = true;
|
||||
} else if (t.isIdentifier(node)) {
|
||||
state.hasHelper ||= isHelper(node.callee);
|
||||
state.hasHelper = state.hasHelper || isHelper(node.callee);
|
||||
}
|
||||
|
||||
return state;
|
||||
|
||||
@@ -22,7 +22,19 @@ export const MESSAGES = {
|
||||
codeGeneratorDeopt: "Note: The code generator has deoptimised the styling of $1 as it exceeds the max of $2.",
|
||||
missingTemplatesDirectory: "no templates directory - this is most likely the result of a broken `npm publish`. Please report to https://github.com/babel/babel/issues",
|
||||
unsupportedOutputType: "Unsupported output type $1",
|
||||
illegalMethodName: "Illegal method name $1"
|
||||
illegalMethodName: "Illegal method name $1",
|
||||
traverseNeedsParent: "Must pass a scope and parentPath unless traversing a Program/File got a $1 node",
|
||||
traverseVerifyRootFunction: "You passed `traverse()` a function when it expected a visitor object, are you sure you didn't mean `{ enter: Function }`?",
|
||||
traverseVerifyVisitorFunction: "Hey! You passed \`traverse()\` a visitor object with the key $1 that's a straight up `Function` instead of `{ enter: Function }`. You need to normalise it with `traverse.explode(visitor)`.",
|
||||
traverseVerifyVisitorProperty: "You passed `traverse()` a visitor object with the property $1 that has the invalid property $2",
|
||||
|
||||
pluginIllegalKind: "Illegal kind $1 for plugin $2",
|
||||
pluginIllegalPosition: "Illegal position $1 for plugin $2",
|
||||
pluginKeyCollision: "The plugin $1 collides with another of the same name",
|
||||
pluginNotTransformer: "The plugin $1 didn't export a Transformer instance",
|
||||
pluginUnknown: "Unknown plugin $1",
|
||||
|
||||
transformerNotFile: "Transformer $1 is resolving to a different Babel version to what is doing the actual transformation..."
|
||||
};
|
||||
|
||||
export function get(key: String, ...args) {
|
||||
|
||||
@@ -55,4 +55,18 @@ def("ExportNamedDeclaration")
|
||||
)])
|
||||
.field("source", or(def("ModuleSpecifier"), null));
|
||||
|
||||
def("ExportNamespaceSpecifier")
|
||||
.bases("Specifier")
|
||||
.field("exported", def("Identifier"));
|
||||
|
||||
def("ExportDefaultSpecifier")
|
||||
.bases("Specifier")
|
||||
.field("exported", def("Identifier"));
|
||||
|
||||
def("ExportAllDeclaration")
|
||||
.bases("Declaration")
|
||||
.build("exported", "source")
|
||||
.field("exported", def("Identifier"))
|
||||
.field("source", def("Literal"));
|
||||
|
||||
types.finalize();
|
||||
|
||||
@@ -33,7 +33,7 @@ export default function (loc, opts = {}) {
|
||||
var json;
|
||||
|
||||
try {
|
||||
json = jsons[content] ||= JSON.parse(stripJsonComments(content));
|
||||
json = jsons[content] = jsons[content] || JSON.parse(stripJsonComments(content));
|
||||
} catch (err) {
|
||||
err.message = `${file}: ${err.message}`;
|
||||
throw err;
|
||||
@@ -47,7 +47,7 @@ export default function (loc, opts = {}) {
|
||||
var c = a.slice(0);
|
||||
for (var v of b) {
|
||||
if (a.indexOf(v) < 0) {
|
||||
c.push(v);
|
||||
c.push(v);
|
||||
}
|
||||
}
|
||||
return c;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import convertSourceMap from "convert-source-map";
|
||||
import * as optionParsers from "./option-parsers";
|
||||
import moduleFormatters from "../modules";
|
||||
import PluginManager from "./plugin-manager";
|
||||
import shebangRegex from "shebang-regex";
|
||||
import TraversalPath from "../../traversal/path";
|
||||
import isFunction from "lodash/lang/isFunction";
|
||||
@@ -18,38 +20,40 @@ import Scope from "../../traversal/scope";
|
||||
import slash from "slash";
|
||||
import clone from "lodash/lang/clone";
|
||||
import * as util from "../../util";
|
||||
import * as api from "../../api/node";
|
||||
import path from "path";
|
||||
import each from "lodash/collection/each";
|
||||
import * as t from "../../types";
|
||||
|
||||
var checkTransformerVisitor = {
|
||||
enter(node, parent, scope, state) {
|
||||
checkNode(state.stack, node, scope);
|
||||
exit(node, parent, scope, state) {
|
||||
checkPath(state.stack, this);
|
||||
}
|
||||
};
|
||||
|
||||
function checkNode(stack, node, scope) {
|
||||
function checkPath(stack, path) {
|
||||
each(stack, function (pass) {
|
||||
if (pass.shouldRun || pass.ran) return;
|
||||
pass.checkNode(node, scope);
|
||||
pass.checkPath(path);
|
||||
});
|
||||
}
|
||||
|
||||
export default class File {
|
||||
constructor(opts = {}) {
|
||||
constructor(opts = {}, pipeline) {
|
||||
this.dynamicImportTypes = {};
|
||||
this.dynamicImportIds = {};
|
||||
this.dynamicImports = [];
|
||||
|
||||
this.usedHelpers = {};
|
||||
this.dynamicData = {};
|
||||
this.data = {};
|
||||
this.uids = {};
|
||||
this.declarations = {};
|
||||
this.usedHelpers = {};
|
||||
this.dynamicData = {};
|
||||
this.data = {};
|
||||
this.uids = {};
|
||||
|
||||
this.lastStatements = [];
|
||||
this.log = new Logger(this, opts.filename || "unknown");
|
||||
this.opts = this.normalizeOptions(opts);
|
||||
this.ast = {};
|
||||
this.pipeline = pipeline;
|
||||
this.log = new Logger(this, opts.filename || "unknown");
|
||||
this.opts = this.normalizeOptions(opts);
|
||||
this.ast = {};
|
||||
|
||||
this.buildTransformers();
|
||||
}
|
||||
@@ -85,6 +89,7 @@ export default class File {
|
||||
"temporal-assert-defined",
|
||||
"self-global",
|
||||
"default-props",
|
||||
"instanceof",
|
||||
|
||||
// legacy
|
||||
"interop-require",
|
||||
@@ -130,10 +135,10 @@ export default class File {
|
||||
}
|
||||
|
||||
var optionParser = optionParsers[option.type];
|
||||
if (optionParser) val = optionParser(key, val);
|
||||
if (optionParser) val = optionParser(key, val, this.pipeline);
|
||||
|
||||
if (option.alias) {
|
||||
opts[option.alias] ||= val;
|
||||
opts[option.alias] = opts[option.alias] || val;
|
||||
} else {
|
||||
opts[key] = val;
|
||||
}
|
||||
@@ -197,7 +202,7 @@ export default class File {
|
||||
var stack = [];
|
||||
|
||||
// build internal transformers
|
||||
each(transform.transformers, function (transformer, key) {
|
||||
each(this.pipeline.transformers, function (transformer, key) {
|
||||
var pass = transformers[key] = transformer.buildPass(file);
|
||||
|
||||
if (pass.canTransform()) {
|
||||
@@ -216,8 +221,14 @@ export default class File {
|
||||
// init plugins!
|
||||
var beforePlugins = [];
|
||||
var afterPlugins = [];
|
||||
var pluginManager = new PluginManager({
|
||||
file: this,
|
||||
transformers: this.transformers,
|
||||
before: beforePlugins,
|
||||
after: afterPlugins
|
||||
});
|
||||
for (var i = 0; i < file.opts.plugins.length; i++) {
|
||||
this.addPlugin(file.opts.plugins[i], beforePlugins, afterPlugins);
|
||||
pluginManager.add(file.opts.plugins[i]);
|
||||
}
|
||||
stack = beforePlugins.concat(stack, afterPlugins);
|
||||
|
||||
@@ -226,7 +237,7 @@ export default class File {
|
||||
}
|
||||
|
||||
getModuleFormatter(type: string) {
|
||||
var ModuleFormatter = isFunction(type) ? type : transform.moduleFormatters[type];
|
||||
var ModuleFormatter = isFunction(type) ? type : moduleFormatters[type];
|
||||
|
||||
if (!ModuleFormatter) {
|
||||
var loc = util.resolveRelative(type);
|
||||
@@ -240,60 +251,6 @@ export default class File {
|
||||
return new ModuleFormatter(this);
|
||||
}
|
||||
|
||||
addPlugin(name, before, after) {
|
||||
var position = "before";
|
||||
var plugin;
|
||||
|
||||
if (name) {
|
||||
if (typeof name === "object" && name.transformer) {
|
||||
plugin = name.transformer;
|
||||
position = name.position || position;
|
||||
} else if (typeof name === "string") {
|
||||
// this is a plugin in the form of "foobar" or "foobar:after"
|
||||
// where the optional colon is the delimiter for plugin position in the transformer stack
|
||||
|
||||
[name, position = "before"] = name.split(":");
|
||||
|
||||
var loc = util.resolveRelative(name) || util.resolveRelative(`babel-plugin-${name}`);
|
||||
if (loc) {
|
||||
plugin = require(loc)
|
||||
} else {
|
||||
throw new ReferenceError(`Unknown plugin ${JSON.stringify(name)}`);
|
||||
}
|
||||
} else {
|
||||
// not a string so we'll just assume that it's a direct Transformer instance, if not then
|
||||
// the checks later on will complain
|
||||
plugin = name;
|
||||
}
|
||||
} else {
|
||||
throw new TypeError(`Ilegal kind ${typeof name} for plugin name ${JSON.stringify(name)}`);
|
||||
}
|
||||
|
||||
// validate position
|
||||
if (position !== "before" && position !== "after") {
|
||||
throw new TypeError(`Plugin ${JSON.stringify(name)} has an illegal position of ${JSON.stringify(position)}`);
|
||||
}
|
||||
|
||||
// validate transformer key
|
||||
var key = plugin.key;
|
||||
if (this.transformers[key]) {
|
||||
throw new ReferenceError(`The key for plugin ${JSON.stringify(name)} of ${key} collides with an existing plugin`);
|
||||
}
|
||||
|
||||
// validate Transformer instance
|
||||
if (!plugin.buildPass || plugin.constructor.name !== "Transformer") {
|
||||
throw new TypeError(`Plugin ${JSON.stringify(name)} didn't export a default Transformer instance`);
|
||||
}
|
||||
|
||||
// build!
|
||||
var pass = this.transformers[key] = plugin.buildPass(this);
|
||||
if (pass.canTransform()) {
|
||||
var stack = before;
|
||||
if (position === "after") stack = after;
|
||||
stack.push(pass);
|
||||
}
|
||||
}
|
||||
|
||||
parseInputSourceMap(code: string) {
|
||||
var opts = this.opts;
|
||||
|
||||
@@ -348,7 +305,7 @@ export default class File {
|
||||
}
|
||||
|
||||
addImport(source: string, name?: string, type?: string): Object {
|
||||
name ||= source;
|
||||
name = name || source;
|
||||
var id = this.dynamicImportIds[name];
|
||||
|
||||
if (!id) {
|
||||
@@ -360,7 +317,7 @@ export default class File {
|
||||
declar._blockHoist = 3;
|
||||
|
||||
if (type) {
|
||||
var modules = this.dynamicImportTypes[type] ||= [];
|
||||
var modules = this.dynamicImportTypes[type] = this.dynamicImportTypes[type] || [];
|
||||
modules.push(declar);
|
||||
}
|
||||
|
||||
@@ -375,14 +332,10 @@ export default class File {
|
||||
return id;
|
||||
}
|
||||
|
||||
isConsequenceExpressionStatement(node: Object): boolean {
|
||||
return t.isExpressionStatement(node) && this.lastStatements.indexOf(node) >= 0;
|
||||
}
|
||||
|
||||
attachAuxiliaryComment(node: Object): Object {
|
||||
var comment = this.opts.auxiliaryComment;
|
||||
if (comment) {
|
||||
node.leadingComments ||= [];
|
||||
node.leadingComments = node.leadingComments || [];
|
||||
node.leadingComments.push({
|
||||
type: "Line",
|
||||
value: " " + comment
|
||||
@@ -400,8 +353,8 @@ export default class File {
|
||||
|
||||
var program = this.ast.program;
|
||||
|
||||
var declar = program._declarations && program._declarations[name];
|
||||
if (declar) return declar.id;
|
||||
var declar = this.declarations[name];
|
||||
if (declar) return declar;
|
||||
|
||||
this.usedHelpers[name] = true;
|
||||
|
||||
@@ -418,11 +371,11 @@ export default class File {
|
||||
|
||||
var ref = util.template("helper-" + name);
|
||||
ref._compact = true;
|
||||
var uid = this.scope.generateUidIdentifier(name);
|
||||
var uid = this.declarations[name] = this.scope.generateUidIdentifier(name);
|
||||
this.scope.push({
|
||||
key: name,
|
||||
id: uid,
|
||||
init: ref
|
||||
init: ref,
|
||||
unique: true
|
||||
});
|
||||
return uid;
|
||||
}
|
||||
@@ -479,9 +432,12 @@ export default class File {
|
||||
parseOpts.strictMode = features.strict;
|
||||
parseOpts.sourceType = "module";
|
||||
|
||||
this.log.debug("Parse start");
|
||||
|
||||
//
|
||||
|
||||
return parse(parseOpts, code, (tree) => {
|
||||
this.log.debug("Parse stop");
|
||||
this.transform(tree);
|
||||
return this.generate();
|
||||
});
|
||||
@@ -504,25 +460,25 @@ export default class File {
|
||||
}
|
||||
|
||||
transform(ast) {
|
||||
this.log.debug();
|
||||
|
||||
this.log.debug("Start set AST");
|
||||
this.setAst(ast);
|
||||
this.log.debug("End set AST");
|
||||
|
||||
this.lastStatements = t.getLastStatements(ast.program);
|
||||
this.log.debug("Start prepass");
|
||||
this.checkPath(this.path);
|
||||
this.log.debug("End prepass");
|
||||
|
||||
this.log.debug("Start module formatter init");
|
||||
var modFormatter = this.moduleFormatter = this.getModuleFormatter(this.opts.modules);
|
||||
if (modFormatter.init && this.transformers["es6.modules"].canTransform()) {
|
||||
modFormatter.init();
|
||||
}
|
||||
|
||||
this.checkNode(ast);
|
||||
this.log.debug("End module formatter init");
|
||||
|
||||
this.call("pre");
|
||||
|
||||
each(this.transformerStack, function (pass) {
|
||||
pass.transform();
|
||||
});
|
||||
|
||||
this.call("post");
|
||||
}
|
||||
|
||||
@@ -535,20 +491,19 @@ export default class File {
|
||||
}
|
||||
}
|
||||
|
||||
checkNode(node, scope) {
|
||||
if (Array.isArray(node)) {
|
||||
for (var i = 0; i < node.length; i++) {
|
||||
this.checkNode(node[i], scope);
|
||||
checkPath(path) {
|
||||
if (Array.isArray(path)) {
|
||||
for (var i = 0; i < path.length; i++) {
|
||||
this.checkPath(path[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var stack = this.transformerStack;
|
||||
scope ||= this.scope;
|
||||
|
||||
checkNode(stack, node, scope);
|
||||
checkPath(stack, path);
|
||||
|
||||
scope.traverse(node, checkTransformerVisitor, {
|
||||
path.traverse(checkTransformerVisitor, {
|
||||
stack: stack
|
||||
});
|
||||
}
|
||||
@@ -598,10 +553,14 @@ export default class File {
|
||||
if (opts.ast) result.ast = ast;
|
||||
if (!opts.code) return result;
|
||||
|
||||
this.log.debug("Generation start");
|
||||
|
||||
var _result = generate(ast, opts, this.code);
|
||||
result.code = _result.code;
|
||||
result.map = _result.map;
|
||||
|
||||
this.log.debug("Generation end");
|
||||
|
||||
if (this.shebang) {
|
||||
// add back shebang
|
||||
result.code = `${this.shebang}\n${result.code}`;
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import transform from "./../index";
|
||||
import * as util from "../../util";
|
||||
|
||||
export function transformerList(key, val) {
|
||||
export function transformerList(key, val, pipeline) {
|
||||
val = util.arrayify(val);
|
||||
|
||||
if (val.indexOf("all") >= 0 || val.indexOf(true) >= 0) {
|
||||
val = Object.keys(transform.transformers);
|
||||
val = Object.keys(pipeline.transformers);
|
||||
}
|
||||
|
||||
return transform._ensureTransformerNames(key, val);
|
||||
return pipeline._ensureTransformerNames(key, val);
|
||||
}
|
||||
|
||||
export function number(key, val) {
|
||||
|
||||
@@ -25,6 +25,13 @@
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
"retainLines": {
|
||||
"hidden": true,
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "retain line numbers - will result in really ugly code"
|
||||
},
|
||||
|
||||
"nonStandard": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
@@ -212,5 +219,4 @@
|
||||
"hidden": true,
|
||||
"description": "do not load the same .babelrc file twice"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
105
src/babel/transformation/file/plugin-manager.js
Normal file
105
src/babel/transformation/file/plugin-manager.js
Normal file
@@ -0,0 +1,105 @@
|
||||
import * as node from "../../api/node";
|
||||
import * as messages from "../../messages";
|
||||
import * as util from "../../util";
|
||||
|
||||
export default class PluginManager {
|
||||
static memoisedPlugins = [];
|
||||
|
||||
static memoisePluginContainer(fn) {
|
||||
for (var i = 0; i < PluginManager.memoisedPlugins.length; i++) {
|
||||
var plugin = PluginManager.memoisedPlugins[i];
|
||||
if (plugin.container === fn) return plugin.transformer;
|
||||
}
|
||||
|
||||
var transformer = fn(node);
|
||||
PluginManager.memoisedPlugins.push({
|
||||
container: fn,
|
||||
transformer: transformer
|
||||
});
|
||||
return transformer;
|
||||
}
|
||||
|
||||
static positions = ["before", "after"];
|
||||
|
||||
constructor({ file, transformers, before, after } = { transformers: {}, before: [], after: [] }) {
|
||||
this.transformers = transformers;
|
||||
this.file = file;
|
||||
this.before = before;
|
||||
this.after = after;
|
||||
}
|
||||
|
||||
subnormaliseString(name, position) {
|
||||
// this is a plugin in the form of "foobar" or "foobar:after"
|
||||
// where the optional colon is the delimiter for plugin position in the transformer stack
|
||||
|
||||
var match = name.match(/^(.*?):(after|before)$/);
|
||||
if (match) [, name, position] = match;
|
||||
|
||||
var loc = util.resolveRelative(name) || util.resolveRelative(`babel-plugin-${name}`);
|
||||
if (loc) {
|
||||
return {
|
||||
position: position,
|
||||
plugin: require(loc)
|
||||
};
|
||||
} else {
|
||||
throw new ReferenceError(messages.get("pluginUnknown", name));
|
||||
}
|
||||
}
|
||||
|
||||
validate(name, plugin) {
|
||||
// validate transformer key
|
||||
var key = plugin.key;
|
||||
if (this.transformers[key]) {
|
||||
throw new ReferenceError(messages.get("pluginKeyCollision", key));
|
||||
}
|
||||
|
||||
// validate Transformer instance
|
||||
if (!plugin.buildPass || plugin.constructor.name !== "Transformer") {
|
||||
throw new TypeError(messages.get("pluginNotTransformer", name));
|
||||
}
|
||||
}
|
||||
|
||||
add(name) {
|
||||
var position;
|
||||
var plugin;
|
||||
|
||||
if (name) {
|
||||
if (typeof name === "object" && name.transformer) {
|
||||
({ plugin: name, position } = name);
|
||||
} else if (typeof name !== "string") {
|
||||
// not a string so we'll just assume that it's a direct Transformer instance, if not then
|
||||
// the checks later on will complain
|
||||
plugin = name;
|
||||
}
|
||||
|
||||
if (typeof name === "string") {
|
||||
({ plugin, position } = this.subnormaliseString(name, position));
|
||||
}
|
||||
} else {
|
||||
throw new TypeError(messages.get("pluginIllegalKind", typeof name, name));
|
||||
}
|
||||
|
||||
// default position
|
||||
position = position || "before";
|
||||
|
||||
// validate position
|
||||
if (PluginManager.positions.indexOf(position) < 0) {
|
||||
throw new TypeError(messages.get("pluginIllegalPosition", position, name));
|
||||
}
|
||||
|
||||
// allow plugin containers to be specified so they don't have to manually require
|
||||
if (typeof plugin === "function") {
|
||||
plugin = PluginManager.memoisePluginContainer(plugin);
|
||||
}
|
||||
|
||||
//
|
||||
this.validate(name, plugin);
|
||||
|
||||
// build!
|
||||
var pass = this.transformers[plugin.key] = plugin.buildPass(this.file);
|
||||
if (pass.canTransform()) {
|
||||
var stack = position === "before" ? this.before : this.after;
|
||||
stack.push(pass);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,9 +10,13 @@ export default function (exports, opts) {
|
||||
return t.assignmentExpression("=", left, right);
|
||||
};
|
||||
|
||||
exports.shouldVisit = function (node) {
|
||||
return node.operator && (node.operator === opts.operator || node.operator === opts.operator + "=");
|
||||
};
|
||||
|
||||
exports.ExpressionStatement = function (node, parent, scope, file) {
|
||||
// hit the `AssignmentExpression` one below
|
||||
if (file.isConsequenceExpressionStatement(node)) return;
|
||||
if (this.isCompletionRecord()) return;
|
||||
|
||||
var expr = node.expression;
|
||||
if (!isAssignment(expr)) return;
|
||||
|
||||
@@ -8,7 +8,7 @@ export default function (exports, opts) {
|
||||
|
||||
exports.ExpressionStatement = function (node, parent, scope, file) {
|
||||
// hit the `AssignmentExpression` one below
|
||||
if (file.isConsequenceExpressionStatement(node)) return;
|
||||
if (this.isCompletionRecord()) return;
|
||||
|
||||
var expr = node.expression;
|
||||
if (!opts.is(expr, file)) return;
|
||||
|
||||
@@ -15,7 +15,7 @@ export function push(mutatorMap, node, kind, file) {
|
||||
|
||||
//
|
||||
|
||||
map._inherits ||= [];
|
||||
map._inherits = map._inherits || [];
|
||||
map._inherits.push(node);
|
||||
|
||||
map._key = node.key;
|
||||
@@ -25,7 +25,7 @@ export function push(mutatorMap, node, kind, file) {
|
||||
}
|
||||
|
||||
if (node.decorators) {
|
||||
var decorators = map.decorators ||= t.arrayExpression([]);
|
||||
var decorators = map.decorators = map.decorators || t.arrayExpression([]);
|
||||
decorators.elements = decorators.elements.concat(node.decorators.map(dec => dec.expression));
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,11 @@ export default function (decorators, scope) {
|
||||
[ref]
|
||||
));
|
||||
|
||||
decorator.expression = t.sequenceExpression(nodes);
|
||||
if (nodes.length === 1) {
|
||||
decorator.expression = nodes[0];
|
||||
} else {
|
||||
decorator.expression = t.sequenceExpression(nodes);
|
||||
}
|
||||
}
|
||||
|
||||
return decorators;
|
||||
|
||||
@@ -20,27 +20,32 @@ var visitor = {
|
||||
|
||||
var wrap = function (state, method, id, scope) {
|
||||
if (state.selfReference) {
|
||||
var templateName = "property-method-assignment-wrapper";
|
||||
if (method.generator) templateName += "-generator";
|
||||
var template = util.template(templateName, {
|
||||
FUNCTION: method,
|
||||
FUNCTION_ID: id,
|
||||
FUNCTION_KEY: scope.generateUidIdentifier(id.name)
|
||||
});
|
||||
template.callee._skipModulesRemap = true;
|
||||
if (scope.hasBinding(id.name)) {
|
||||
// we can just munge the local binding
|
||||
scope.rename(id.name);
|
||||
} else {
|
||||
// need to add a wrapper since we can't change the references
|
||||
var templateName = "property-method-assignment-wrapper";
|
||||
if (method.generator) templateName += "-generator";
|
||||
var template = util.template(templateName, {
|
||||
FUNCTION: method,
|
||||
FUNCTION_ID: id,
|
||||
FUNCTION_KEY: scope.generateUidIdentifier(id.name)
|
||||
});
|
||||
template.callee._skipModulesRemap = true;
|
||||
|
||||
// shim in dummy params to retain function arity, if you try to read the
|
||||
// source then you'll get the original since it's proxied so it's all good
|
||||
var params = template.callee.body.body[0].params;
|
||||
for (var i = 0, len = getFunctionArity(method); i < len; i++) {
|
||||
params.push(scope.generateUidIdentifier("x"));
|
||||
// shim in dummy params to retain function arity, if you try to read the
|
||||
// source then you'll get the original since it's proxied so it's all good
|
||||
var params = template.callee.body.body[0].params;
|
||||
for (var i = 0, len = getFunctionArity(method); i < len; i++) {
|
||||
params.push(scope.generateUidIdentifier("x"));
|
||||
}
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
return template;
|
||||
} else {
|
||||
method.id = id;
|
||||
return method;
|
||||
}
|
||||
|
||||
method.id = id;
|
||||
};
|
||||
|
||||
var visit = function (node, name, scope) {
|
||||
@@ -82,7 +87,7 @@ var visit = function (node, name, scope) {
|
||||
// so we can safely just set the id and move along as it shadows the
|
||||
// bound function id
|
||||
}
|
||||
} else {
|
||||
} else if (state.outerDeclar || scope.hasGlobal(name)) {
|
||||
scope.traverse(node, visitor, state);
|
||||
}
|
||||
|
||||
@@ -96,7 +101,7 @@ export function custom(node, id, scope) {
|
||||
|
||||
export function property(node, file, scope) {
|
||||
var key = t.toComputedKey(node, node.key);
|
||||
if (!t.isLiteral(key)) return node; // we can't set a function id with this
|
||||
if (!t.isLiteral(key)) return; // we can't set a function id with this
|
||||
|
||||
var name = t.toIdentifier(key.value);
|
||||
if (name === "eval" || name === "arguments") name = "_" + name;
|
||||
@@ -104,12 +109,12 @@ export function property(node, file, scope) {
|
||||
|
||||
var method = node.value;
|
||||
var state = visit(method, name, scope);
|
||||
node.value = wrap(state, method, id, scope);
|
||||
node.value = wrap(state, method, id, scope) || method;
|
||||
}
|
||||
|
||||
export function bare(node, parent, scope) {
|
||||
// has an `id` so we don't need to infer one
|
||||
if (node.id) return node;
|
||||
if (node.id) return;
|
||||
|
||||
var id;
|
||||
if (t.isProperty(parent) && parent.kind === "init" && (!parent.computed || t.isLiteral(parent.key))) {
|
||||
@@ -118,8 +123,17 @@ export function bare(node, parent, scope) {
|
||||
} else if (t.isVariableDeclarator(parent)) {
|
||||
// var foo = function () {};
|
||||
id = parent.id;
|
||||
|
||||
if (t.isIdentifier(id)) {
|
||||
var bindingInfo = scope.parent.getBinding(id.name);
|
||||
if (bindingInfo && bindingInfo.constant && scope.getBinding(id.name) === bindingInfo) {
|
||||
// always going to reference this method
|
||||
node.id = id;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return node;
|
||||
return;
|
||||
}
|
||||
|
||||
var name;
|
||||
|
||||
@@ -20,7 +20,7 @@ var referenceVisitor = {
|
||||
enter(node, parent, scope, state) {
|
||||
var name = state.id.name;
|
||||
if (t.isReferencedIdentifier(node, parent, { name: name }) && scope.bindingIdentifierEquals(name, state.id)) {
|
||||
return state.ref ||= scope.generateUidIdentifier(name);
|
||||
return state.ref = state.ref || scope.generateUidIdentifier(name);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -218,7 +218,7 @@ export default class ReplaceSupers {
|
||||
return this.setSuperProperty(node.left.property, node.right, node.left.computed, getThisReference());
|
||||
} else {
|
||||
// super.age += 2; -> var _ref = super.age; super.age = _ref + 2;
|
||||
ref ||= path.scope.generateUidIdentifier("ref");
|
||||
ref = ref || path.scope.generateUidIdentifier("ref");
|
||||
return [
|
||||
t.variableDeclaration("var", [
|
||||
t.variableDeclarator(ref, node.left)
|
||||
|
||||
@@ -1,68 +1,34 @@
|
||||
import normalizeAst from "../helpers/normalize-ast";
|
||||
import Transformer from "./transformer";
|
||||
import object from "../helpers/object";
|
||||
import File from "./file";
|
||||
import each from "lodash/collection/each";
|
||||
import Pipeline from "./transformer-pipeline";
|
||||
|
||||
export default function transform(code: string, opts?: Object) {
|
||||
var file = new File(opts);
|
||||
return file.parse(code);
|
||||
}
|
||||
var pipeline = new Pipeline;
|
||||
|
||||
transform.fromAst = function (ast, code, opts) {
|
||||
ast = normalizeAst(ast);
|
||||
//
|
||||
|
||||
var file = new File(opts);
|
||||
file.addCode(code);
|
||||
file.transform(ast);
|
||||
return file.generate();
|
||||
};
|
||||
import transformers from "./transformers";
|
||||
pipeline.addTransformers(transformers);
|
||||
|
||||
transform._ensureTransformerNames = function (type: string, rawKeys: Array<string>) {
|
||||
var keys = [];
|
||||
//
|
||||
|
||||
for (var i = 0; i < rawKeys.length; i++) {
|
||||
var key = rawKeys[i];
|
||||
import deprecated from "./transformers/deprecated";
|
||||
pipeline.addDeprecated(deprecated);
|
||||
|
||||
var deprecatedKey = transform.deprecatedTransformerMap[key];
|
||||
var aliasKey = transform.aliasTransformerMap[key];
|
||||
if (aliasKey) {
|
||||
keys.push(aliasKey);
|
||||
} else if (deprecatedKey) {
|
||||
// deprecated key, remap it to the new one
|
||||
console.error(`The transformer ${key} has been renamed to ${deprecatedKey}`);
|
||||
rawKeys.push(deprecatedKey);
|
||||
} else if (transform.transformers[key]) {
|
||||
// valid key
|
||||
keys.push(key);
|
||||
} else if (transform.namespaces[key]) {
|
||||
// namespace, append all transformers within this namespace
|
||||
keys = keys.concat(transform.namespaces[key]);
|
||||
} else {
|
||||
// invalid key
|
||||
throw new ReferenceError(`Unknown transformer ${key} specified in ${type}`);
|
||||
}
|
||||
}
|
||||
//
|
||||
|
||||
return keys;
|
||||
};
|
||||
import aliases from "./transformers/aliases";
|
||||
pipeline.addDeprecated(aliases);
|
||||
|
||||
transform.transformerNamespaces = object();
|
||||
transform.transformers = object();
|
||||
transform.namespaces = object();
|
||||
//
|
||||
|
||||
transform.deprecatedTransformerMap = require("./transformers/deprecated");
|
||||
transform.aliasTransformerMap = require("./transformers/aliases");
|
||||
transform.moduleFormatters = require("./modules");
|
||||
import * as filters from "./transformers/filters";
|
||||
pipeline.addFilter(filters.internal);
|
||||
pipeline.addFilter(filters.blacklist);
|
||||
pipeline.addFilter(filters.whitelist);
|
||||
pipeline.addFilter(filters.stage);
|
||||
pipeline.addFilter(filters.optional);
|
||||
|
||||
import rawTransformers from "./transformers";
|
||||
//
|
||||
|
||||
each(rawTransformers, function (transformer, key) {
|
||||
var namespace = key.split(".")[0];
|
||||
|
||||
transform.namespaces[namespace] ||= [];
|
||||
transform.namespaces[namespace].push(key);
|
||||
transform.transformerNamespaces[key] = namespace;
|
||||
|
||||
transform.transformers[key] = new Transformer(key, transformer);
|
||||
});
|
||||
var transform = pipeline.transform.bind(pipeline);
|
||||
transform.fromAst = pipeline.transformFromAst.bind(pipeline);
|
||||
transform.pipeline = pipeline;
|
||||
export default transform;
|
||||
|
||||
@@ -166,7 +166,7 @@ export default class DefaultFormatter {
|
||||
}
|
||||
|
||||
_addExport(name, exported) {
|
||||
var info = this.localExports[name] ||= {
|
||||
var info = this.localExports[name] = this.localExports[name] || {
|
||||
binding: this.scope.getBindingIdentifier(name),
|
||||
exported: []
|
||||
};
|
||||
|
||||
@@ -20,7 +20,7 @@ export default class CommonJSFormatter extends DefaultFormatter {
|
||||
if (this.file.isLoose("es6.modules")) templateName += "-loose";
|
||||
var declar = util.template(templateName, true);
|
||||
declar._blockHoist = 3;
|
||||
file.ast.program.body.unshift(declar);
|
||||
file.path.unshiftContainer("body", [declar]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ export default class CommonJSFormatter extends DefaultFormatter {
|
||||
uid = this.scope.generateUidBasedOnNode(node, "import");
|
||||
}
|
||||
|
||||
uid ||= node.specifiers[0].local;
|
||||
uid = uid || node.specifiers[0].local;
|
||||
|
||||
var declar = t.variableDeclaration("var", [
|
||||
t.variableDeclarator(uid, call)
|
||||
|
||||
@@ -77,11 +77,11 @@ var runnerSettersVisitor = {
|
||||
|
||||
export default class SystemFormatter extends AMDFormatter {
|
||||
constructor(file) {
|
||||
super(file);
|
||||
|
||||
this.exportIdentifier = file.scope.generateUidIdentifier("export");
|
||||
this.noInteropRequireExport = true;
|
||||
this.noInteropRequireImport = true;
|
||||
|
||||
DefaultFormatter.apply(this, arguments);
|
||||
}
|
||||
|
||||
_addImportSource(node, exportNode) {
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (descriptor.initializer) {
|
||||
if (descriptor.initializer !== undefined) {
|
||||
initializers[key] = descriptor;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -26,9 +26,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
descriptor.value = descriptor.initializer();
|
||||
|
||||
Object.defineProperty(target, key, descriptor);
|
||||
if (descriptor.initializer) {
|
||||
descriptor.value = descriptor.initializer.call(target);
|
||||
Object.defineProperty(target, key, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
for (var _key in _descriptor) descriptor[_key] = _descriptor[_key];
|
||||
|
||||
// initialize it
|
||||
descriptor.value = descriptor.initializer();
|
||||
if (!descriptor.initializer) return;
|
||||
descriptor.value = descriptor.initializer.call(target);
|
||||
|
||||
Object.defineProperty(target, key, descriptor);
|
||||
})
|
||||
|
||||
7
src/babel/transformation/templates/helper-instanceof.js
Normal file
7
src/babel/transformation/templates/helper-instanceof.js
Normal file
@@ -0,0 +1,7 @@
|
||||
(function (left, right) {
|
||||
if (right != null && right[Symbol.hasInstance]) {
|
||||
return right[Symbol.hasInstance](left);
|
||||
} else {
|
||||
return left instanceof right;
|
||||
}
|
||||
});
|
||||
@@ -3,7 +3,7 @@
|
||||
return obj;
|
||||
} else {
|
||||
var newObj = {};
|
||||
if (typeof obj === "object" && obj !== null) {
|
||||
if (obj != null) {
|
||||
for (var key in obj) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key];
|
||||
}
|
||||
|
||||
@@ -8,58 +8,35 @@ import traverse from "../traversal";
|
||||
|
||||
export default class TransformerPass {
|
||||
constructor(file: File, transformer: Transformer) {
|
||||
this.transformer = transformer;
|
||||
this.shouldRun = !transformer.check;
|
||||
this.handlers = transformer.handlers;
|
||||
this.file = file;
|
||||
this.ran = false;
|
||||
this.shouldTransform = !transformer.shouldVisit;
|
||||
this.transformer = transformer;
|
||||
this.handlers = transformer.handlers;
|
||||
this.skipKey = transformer.skipKey;
|
||||
this.file = file;
|
||||
this.ran = false;
|
||||
}
|
||||
|
||||
canTransform(): boolean {
|
||||
var transformer = this.transformer;
|
||||
|
||||
var opts = this.file.opts;
|
||||
var key = transformer.key;
|
||||
|
||||
// internal
|
||||
if (key[0] === "_") return true;
|
||||
|
||||
// blacklist
|
||||
var blacklist = opts.blacklist;
|
||||
if (blacklist.length && includes(blacklist, key)) return false;
|
||||
|
||||
// whitelist
|
||||
var whitelist = opts.whitelist;
|
||||
if (whitelist) return includes(whitelist, key);
|
||||
|
||||
// stage
|
||||
var stage = transformer.metadata.stage;
|
||||
if (stage != null && stage >= opts.stage) return true;
|
||||
|
||||
// optional
|
||||
if (transformer.metadata.optional && !includes(opts.optional, key)) return false;
|
||||
|
||||
return true;
|
||||
return this.file.pipeline.canTransform(this.transformer, this.file.opts);
|
||||
}
|
||||
|
||||
checkNode(node: Object): boolean {
|
||||
var check = this.transformer.check;
|
||||
if (check) {
|
||||
return this.shouldRun = check(node);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
checkPath(path: TraversalPath): boolean {
|
||||
if (this.shouldTransform || this.ran) return;
|
||||
|
||||
this.shouldTransform = this.transformer.shouldVisit(path.node);
|
||||
}
|
||||
|
||||
transform() {
|
||||
if (!this.shouldRun) return;
|
||||
if (!this.shouldTransform) return;
|
||||
|
||||
var file = this.file;
|
||||
|
||||
file.log.debug(`Running transformer ${this.transformer.key}`);
|
||||
file.log.debug(`Start transformer ${this.transformer.key}`);
|
||||
|
||||
traverse(file.ast, this.handlers, file.scope, file);
|
||||
|
||||
file.log.debug(`Finish transformer ${this.transformer.key}`);
|
||||
|
||||
this.ran = true;
|
||||
}
|
||||
}
|
||||
|
||||
100
src/babel/transformation/transformer-pipeline.js
Normal file
100
src/babel/transformation/transformer-pipeline.js
Normal file
@@ -0,0 +1,100 @@
|
||||
import Transformer from "./transformer";
|
||||
import normalizeAst from "../helpers/normalize-ast";
|
||||
import assign from "lodash/object/assign";
|
||||
import object from "../helpers/object";
|
||||
import File from "./file";
|
||||
|
||||
export default class TransformerPipeline {
|
||||
constructor() {
|
||||
this.transformers = object();
|
||||
this.namespaces = object();
|
||||
this.deprecated = object();
|
||||
this.aliases = object();
|
||||
this.filters = [];
|
||||
}
|
||||
|
||||
addTransformers(transformers) {
|
||||
for (var key in transformers) {
|
||||
this.addTransformer(key, transformers[key]);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
addTransformer(key, transformer) {
|
||||
if (this.transformers[key]) throw new Error(); // todo: error
|
||||
|
||||
var namespace = key.split(".")[0];
|
||||
this.namespaces[namespace] = this.namespaces[namespace] || [];
|
||||
this.namespaces[namespace].push(key);
|
||||
this.namespaces[key] = namespace;
|
||||
|
||||
this.transformers[key] = new Transformer(key, transformer);
|
||||
}
|
||||
|
||||
addAliases(names) {
|
||||
assign(this.aliases, names);
|
||||
return this;
|
||||
}
|
||||
|
||||
addDeprecated(names) {
|
||||
assign(this.deprecated, names);
|
||||
return this;
|
||||
}
|
||||
|
||||
addFilter(filter: Function) {
|
||||
this.filters.push(filter);
|
||||
return this;
|
||||
}
|
||||
|
||||
canTransform(transformer, fileOpts) {
|
||||
for (var filter of (this.filters: Array)) {
|
||||
var result = filter(transformer, fileOpts);
|
||||
if (result != null) return result;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
transform(code: string, opts?: Object) {
|
||||
var file = new File(opts, this);
|
||||
return file.parse(code);
|
||||
}
|
||||
|
||||
transformFromAst(ast, code, opts) {
|
||||
ast = normalizeAst(ast);
|
||||
|
||||
var file = new File(opts, this);
|
||||
file.addCode(code);
|
||||
file.transform(ast);
|
||||
return file.generate();
|
||||
}
|
||||
|
||||
_ensureTransformerNames(type: string, rawKeys: Array<string>) {
|
||||
var keys = [];
|
||||
|
||||
for (var i = 0; i < rawKeys.length; i++) {
|
||||
var key = rawKeys[i];
|
||||
|
||||
var deprecatedKey = this.deprecated[key];
|
||||
var aliasKey = this.aliases[key];
|
||||
if (aliasKey) {
|
||||
keys.push(aliasKey);
|
||||
} else if (deprecatedKey) {
|
||||
// deprecated key, remap it to the new one
|
||||
console.error(`The transformer ${key} has been renamed to ${deprecatedKey}`);
|
||||
rawKeys.push(deprecatedKey);
|
||||
} else if (this.transformers[key]) {
|
||||
// valid key
|
||||
keys.push(key);
|
||||
} else if (this.namespaces[key]) {
|
||||
// namespace, append all transformers within this namespace
|
||||
keys = keys.concat(this.namespaces[key]);
|
||||
} else {
|
||||
// invalid key
|
||||
throw new ReferenceError(`Unknown transformer ${key} specified in ${type}`);
|
||||
}
|
||||
}
|
||||
|
||||
return keys;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import TransformerPass from "./transformer-pass";
|
||||
import * as messages from "../messages";
|
||||
import isFunction from "lodash/lang/isFunction";
|
||||
import traverse from "../traversal";
|
||||
import isObject from "lodash/lang/isObject";
|
||||
@@ -14,7 +15,7 @@ import each from "lodash/collection/each";
|
||||
*/
|
||||
|
||||
export default class Transformer {
|
||||
constructor(transformerKey: key, transformer: Object, opts: Object) {
|
||||
constructor(transformerKey: string, transformer: Object) {
|
||||
transformer = assign({}, transformer);
|
||||
|
||||
var take = function (key) {
|
||||
@@ -24,19 +25,34 @@ export default class Transformer {
|
||||
};
|
||||
|
||||
this.manipulateOptions = take("manipulateOptions");
|
||||
this.shouldVisit = take("shouldVisit");
|
||||
this.metadata = take("metadata") || {};
|
||||
this.parser = take("parser");
|
||||
this.check = take("check");
|
||||
this.post = take("post");
|
||||
this.pre = take("pre");
|
||||
|
||||
//
|
||||
|
||||
if (this.metadata.stage != null) {
|
||||
this.metadata.optional = true;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
this.handlers = this.normalize(transformer);
|
||||
this.opts ||= {};
|
||||
this.key = transformerKey;
|
||||
|
||||
//
|
||||
|
||||
if (!this.shouldVisit) {
|
||||
var types = Object.keys(this.handlers);
|
||||
this.shouldVisit = function (node) {
|
||||
for (var i = 0; i < types.length; i++) {
|
||||
if (node.type === types[i]) return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
normalize(transformer: Object): Object {
|
||||
@@ -71,7 +87,7 @@ export default class Transformer {
|
||||
buildPass(file: File): TransformerPass {
|
||||
// validate Transformer instance
|
||||
if (!(file instanceof File)) {
|
||||
throw new TypeError(`Transformer ${this.key} is resolving to a different Babel version to what is doing the actual transformation...`);
|
||||
throw new TypeError(messages.get("transformerNotFile", this.key));
|
||||
}
|
||||
|
||||
return new TransformerPass(file, this);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as defineMap from "../../helpers/define-map";
|
||||
import * as t from "../../../types";
|
||||
|
||||
export function check(node) {
|
||||
export function shouldVisit(node) {
|
||||
return t.isProperty(node) && (node.kind === "get" || node.kind === "set");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as t from "../../../types";
|
||||
|
||||
export var check = t.isArrowFunctionExpression;
|
||||
export var shouldVisit = t.isArrowFunctionExpression;
|
||||
|
||||
export function ArrowFunctionExpression(node) {
|
||||
t.ensureBlock(node);
|
||||
|
||||
@@ -14,7 +14,7 @@ function isLet(node, parent) {
|
||||
if (isLetInitable(node, parent)) {
|
||||
for (var i = 0; i < node.declarations.length; i++) {
|
||||
var declar = node.declarations[i];
|
||||
declar.init ||= t.identifier("undefined");
|
||||
declar.init = declar.init || t.identifier("undefined");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ function standardizeLets(declars) {
|
||||
}
|
||||
}
|
||||
|
||||
export function check(node) {
|
||||
export function shouldVisit(node) {
|
||||
return t.isVariableDeclaration(node) && (node.kind === "let" || node.kind === "const");
|
||||
}
|
||||
|
||||
@@ -139,7 +139,12 @@ var hoistVarDeclarationsVisitor = {
|
||||
enter(node, parent, scope, self) {
|
||||
if (this.isForStatement()) {
|
||||
if (isVar(node.init, node)) {
|
||||
node.init = t.sequenceExpression(self.pushDeclar(node.init));
|
||||
var nodes = self.pushDeclar(node.init);
|
||||
if (nodes.length === 1) {
|
||||
node.init = nodes[0];
|
||||
} else {
|
||||
node.init = t.sequenceExpression(nodes);
|
||||
}
|
||||
}
|
||||
} else if (this.isFor()) {
|
||||
if (isVar(node.left, node)) {
|
||||
@@ -606,7 +611,7 @@ class BlockScoping {
|
||||
for (var i = 0; i < cases.length; i++) {
|
||||
var caseConsequent = cases[i].consequent[0];
|
||||
if (t.isBreakStatement(caseConsequent) && !caseConsequent.label) {
|
||||
caseConsequent.label = this.loopLabel ||= this.file.scope.generateUidIdentifier("loop");
|
||||
caseConsequent.label = this.loopLabel = this.loopLabel || this.file.scope.generateUidIdentifier("loop");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import * as t from "../../../types";
|
||||
|
||||
const PROPERTY_COLLISION_METHOD_NAME = "__initializeProperties";
|
||||
|
||||
export var check = t.isClass;
|
||||
export var shouldVisit = t.isClass;
|
||||
|
||||
export function ClassDeclaration(node, parent, scope, file) {
|
||||
return t.variableDeclaration("let", [
|
||||
@@ -245,7 +245,7 @@ class ClassTransformer {
|
||||
if (body.length === 1) return t.toExpression(body[0]);
|
||||
} else {
|
||||
// infer class name if this is a nameless class expression
|
||||
constructor = nameMethod.bare(constructor, this.parent, this.scope);
|
||||
constructor = nameMethod.bare(constructor, this.parent, this.scope) || constructor;
|
||||
|
||||
body.unshift(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(classRef, constructor)
|
||||
@@ -347,7 +347,7 @@ class ClassTransformer {
|
||||
if (this.isNativeSuper) helperName = "class-super-native-constructor-call";
|
||||
constructorBody.body.push(util.template(helperName, {
|
||||
NATIVE_REF: this.nativeSuperRef,
|
||||
CLASS_NAME: className,
|
||||
CLASS_NAME: this.classRef,
|
||||
SUPER_NAME: this.superName
|
||||
}, true));
|
||||
}
|
||||
@@ -550,19 +550,23 @@ class ClassTransformer {
|
||||
|
||||
if (node.decorators) {
|
||||
var body = [];
|
||||
if (node.value) body.push(t.returnStatement(node.value));
|
||||
node.value = t.functionExpression(null, [], t.blockStatement(body));
|
||||
if (node.value) {
|
||||
body.push(t.returnStatement(node.value));
|
||||
node.value = t.functionExpression(null, [], t.blockStatement(body));
|
||||
} else {
|
||||
node.value = t.literal(null);
|
||||
}
|
||||
this.pushToMap(node, true, "initializer");
|
||||
|
||||
var initializers;
|
||||
var body;
|
||||
var target;
|
||||
if (node.static) {
|
||||
initializers = this.staticInitializersId ||= this.scope.generateUidIdentifier("staticInitializers");
|
||||
initializers = this.staticInitializersId = this.staticInitializersId || this.scope.generateUidIdentifier("staticInitializers");
|
||||
body = this.staticPropBody;
|
||||
target = this.classRef;
|
||||
} else {
|
||||
initializers = this.instanceInitializersId ||= this.scope.generateUidIdentifier("instanceInitializers");
|
||||
initializers = this.instanceInitializersId = this.instanceInitializersId || this.scope.generateUidIdentifier("instanceInitializers");
|
||||
body = this.instancePropBody;
|
||||
target = t.thisExpression();
|
||||
}
|
||||
@@ -575,7 +579,7 @@ class ClassTransformer {
|
||||
])
|
||||
));
|
||||
} else {
|
||||
node.value ||= t.identifier("undefined");
|
||||
if (!node.value && !node.decorators) return;
|
||||
|
||||
if (node.static) {
|
||||
// can just be added to the static map
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as messages from "../../../messages";
|
||||
import * as t from "../../../types";
|
||||
|
||||
export function check(node) {
|
||||
export function shouldVisit(node) {
|
||||
return t.isVariableDeclaration(node, { kind: "const" }) || t.isImportDeclaration(node);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as messages from "../../../messages";
|
||||
import * as t from "../../../types";
|
||||
|
||||
export var check = t.isPattern;
|
||||
export var shouldVisit = t.isPattern;
|
||||
|
||||
export function ForOfStatement(node, parent, scope, file) {
|
||||
var left = node.left;
|
||||
@@ -78,11 +78,11 @@ exports.Function = function (node, parent, scope, file) {
|
||||
|
||||
if (!hasDestructuring) return;
|
||||
|
||||
file.checkNode(nodes);
|
||||
t.ensureBlock(node);
|
||||
|
||||
var block = node.body;
|
||||
block.body = nodes.concat(block.body);
|
||||
return node;
|
||||
};
|
||||
|
||||
export function CatchClause(node, parent, scope, file) {
|
||||
@@ -111,7 +111,7 @@ export function ExpressionStatement(node, parent, scope, file) {
|
||||
var expr = node.expression;
|
||||
if (expr.type !== "AssignmentExpression") return;
|
||||
if (!t.isPattern(expr.left)) return;
|
||||
if (file.isConsequenceExpressionStatement(node)) return;
|
||||
if (this.isCompletionRecord()) return;
|
||||
|
||||
var destructuring = new DestructuringTransformer({
|
||||
operator: expr.operator,
|
||||
@@ -200,7 +200,7 @@ export function VariableDeclaration(node, parent, scope, file) {
|
||||
|
||||
for (i = 0; i < nodes.length; i++) {
|
||||
node = nodes[i];
|
||||
declar ||= t.variableDeclaration(node.kind, []);
|
||||
declar = declar || t.variableDeclaration(node.kind, []);
|
||||
|
||||
if (!t.isVariableDeclaration(node) && declar.kind !== node.kind) {
|
||||
throw file.errorWithNode(node, messages.get("invalidParentForThisNode"));
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as messages from "../../../messages";
|
||||
import * as util from "../../../util";
|
||||
import * as t from "../../../types";
|
||||
|
||||
export var check = t.isForOfStatement;
|
||||
export var shouldVisit = t.isForOfStatement;
|
||||
|
||||
export function ForOfStatement(node, parent, scope, file) {
|
||||
if (this.get("right").isArrayExpression()) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import ReplaceSupers from "../../helpers/replace-supers";
|
||||
import * as t from "../../../types";
|
||||
|
||||
export var check = t.isSuper;
|
||||
export var shouldVisit = t.isSuper;
|
||||
|
||||
function Property(path, node, scope, getObjectRef, file) {
|
||||
if (!node.method) return;
|
||||
@@ -32,7 +32,7 @@ function Property(path, node, scope, getObjectRef, file) {
|
||||
|
||||
export function ObjectExpression(node, parent, scope, file) {
|
||||
var objectRef;
|
||||
var getObjectRef = () => objectRef ||= scope.generateUidIdentifier("obj");
|
||||
var getObjectRef = () => objectRef = objectRef || scope.generateUidIdentifier("obj");
|
||||
|
||||
var propPaths = this.get("properties");
|
||||
for (var i = 0; i < node.properties.length; i++) {
|
||||
|
||||
@@ -2,7 +2,7 @@ import callDelegate from "../../helpers/call-delegate";
|
||||
import * as util from "../../../util";
|
||||
import * as t from "../../../types";
|
||||
|
||||
export function check(node) {
|
||||
export function shouldVisit(node) {
|
||||
return t.isFunction(node) && hasDefaults(node);
|
||||
}
|
||||
|
||||
@@ -45,7 +45,6 @@ exports.Function = function (node, parent, scope, file) {
|
||||
ARGUMENT_KEY: t.literal(i),
|
||||
ARGUMENTS: argsIdentifier
|
||||
}, true);
|
||||
file.checkNode(defNode);
|
||||
defNode._blockHoist = node.params.length - i;
|
||||
body.push(defNode);
|
||||
};
|
||||
@@ -97,4 +96,6 @@ exports.Function = function (node, parent, scope, file) {
|
||||
} else {
|
||||
node.body.body = body.concat(node.body.body);
|
||||
}
|
||||
|
||||
return node;
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@ import isNumber from "lodash/lang/isNumber";
|
||||
import * as util from "../../../util";
|
||||
import * as t from "../../../types";
|
||||
|
||||
export var check = t.isRestElement;
|
||||
export var shouldVisit = t.isRestElement;
|
||||
|
||||
var memberExpressionOptimisationVisitor = {
|
||||
enter(node, parent, scope, state) {
|
||||
@@ -74,7 +74,6 @@ exports.Function = function (node, parent, scope, file) {
|
||||
var accessExpr = t.memberExpression(rest, t.literal(index), true);
|
||||
return t.variableDeclarator(elem, accessExpr);
|
||||
}));
|
||||
file.checkNode(declar);
|
||||
node.body.body.unshift(declar);
|
||||
}
|
||||
|
||||
@@ -97,7 +96,7 @@ exports.Function = function (node, parent, scope, file) {
|
||||
candidate.replaceWith(argsId);
|
||||
optimizeMemberExpression(candidate.parent, node.params.length);
|
||||
}
|
||||
return;
|
||||
return node;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -138,4 +137,5 @@ exports.Function = function (node, parent, scope, file) {
|
||||
});
|
||||
loop._blockHoist = node.params.length + 1;
|
||||
node.body.body.unshift(loop);
|
||||
return node;
|
||||
};
|
||||
|
||||
@@ -84,7 +84,7 @@ function spec(node, body, objId, initProps, file) {
|
||||
}
|
||||
}
|
||||
|
||||
export function check(node) {
|
||||
export function shouldVisit(node) {
|
||||
return t.isProperty(node) && node.computed;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as t from "../../../types";
|
||||
|
||||
export function check(node) {
|
||||
export function shouldVisit(node) {
|
||||
return t.isProperty(node) && (node.method || node.shorthand);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as regex from "../../helpers/regex";
|
||||
import * as t from "../../../types";
|
||||
|
||||
export function check(node) {
|
||||
export function shouldVisit(node) {
|
||||
return regex.is(node, "y");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import rewritePattern from "regexpu/rewrite-pattern";
|
||||
import * as regex from "../../helpers/regex";
|
||||
|
||||
export function check(node) {
|
||||
export function shouldVisit(node) {
|
||||
return regex.is(node, "u");
|
||||
}
|
||||
|
||||
|
||||
@@ -5,14 +5,16 @@ export var metadata = {
|
||||
};
|
||||
|
||||
export function UnaryExpression(node, parent, scope, file) {
|
||||
this.skip();
|
||||
if (node._ignoreSpecSymbols) return;
|
||||
|
||||
if (node.operator === "typeof") {
|
||||
var call = t.callExpression(file.addHelper("typeof"), [node.argument]);
|
||||
if (this.get("argument").isIdentifier()) {
|
||||
var undefLiteral = t.literal("undefined");
|
||||
var unary = t.unaryExpression("typeof", node.argument);
|
||||
unary._ignoreSpecSymbols = true;
|
||||
return t.conditionalExpression(
|
||||
t.binaryExpression("===", t.unaryExpression("typeof", node.argument), undefLiteral),
|
||||
t.binaryExpression("===", unary, undefLiteral),
|
||||
undefLiteral,
|
||||
call
|
||||
);
|
||||
@@ -21,3 +23,13 @@ export function UnaryExpression(node, parent, scope, file) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function BinaryExpression(node, parent, scope, file) {
|
||||
if (node.operator === "instanceof") {
|
||||
return t.callExpression(file.addHelper("instanceof"), [node.left, node.right]);
|
||||
}
|
||||
}
|
||||
|
||||
export function VariableDeclaration(node) {
|
||||
if (node._generated) this.skip();
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ function build(props, scope) {
|
||||
return nodes;
|
||||
}
|
||||
|
||||
export var check = t.isSpreadElement;
|
||||
export var shouldVisit = t.isSpreadElement;
|
||||
|
||||
export function ArrayExpression(node, parent, scope) {
|
||||
var elements = node.elements;
|
||||
|
||||
@@ -101,23 +101,23 @@ class TailCallTransformer {
|
||||
}
|
||||
|
||||
getArgumentsId() {
|
||||
return this.argumentsId ||= this.scope.generateUidIdentifier("arguments");
|
||||
return this.argumentsId = this.argumentsId || this.scope.generateUidIdentifier("arguments");
|
||||
}
|
||||
|
||||
getThisId() {
|
||||
return this.thisId ||= this.scope.generateUidIdentifier("this");
|
||||
return this.thisId = this.thisId || this.scope.generateUidIdentifier("this");
|
||||
}
|
||||
|
||||
getLeftId() {
|
||||
return this.leftId ||= this.scope.generateUidIdentifier("left");
|
||||
return this.leftId = this.leftId || this.scope.generateUidIdentifier("left");
|
||||
}
|
||||
|
||||
getFunctionId() {
|
||||
return this.functionId ||= this.scope.generateUidIdentifier("function");
|
||||
return this.functionId = this.functionId || this.scope.generateUidIdentifier("function");
|
||||
}
|
||||
|
||||
getAgainId() {
|
||||
return this.againId ||= this.scope.generateUidIdentifier("again");
|
||||
return this.againId = this.againId || this.scope.generateUidIdentifier("again");
|
||||
}
|
||||
|
||||
getParams() {
|
||||
|
||||
@@ -4,7 +4,7 @@ var buildBinaryExpression = function (left, right) {
|
||||
return t.binaryExpression("+", left, right);
|
||||
};
|
||||
|
||||
export function check(node) {
|
||||
export function shouldVisit(node) {
|
||||
return t.isTemplateLiteral(node) || t.isTaggedTemplateExpression(node);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,6 @@ export var metadata = {
|
||||
stage: 1
|
||||
};
|
||||
|
||||
export function check() {
|
||||
export function shouldVisit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,6 @@ export var metadata = {
|
||||
stage: 0
|
||||
};
|
||||
|
||||
export function check() {
|
||||
export function shouldVisit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ export var metadata = {
|
||||
stage: 1
|
||||
};
|
||||
|
||||
export function check(node) {
|
||||
export function shouldVisit(node) {
|
||||
return !!node.decorators;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ export var metadata = {
|
||||
stage: 0
|
||||
};
|
||||
|
||||
export var check = t.isDoExpression;
|
||||
export var shouldVisit = t.isDoExpression;
|
||||
|
||||
export function DoExpression(node) {
|
||||
var body = node.body.body;
|
||||
|
||||
@@ -6,7 +6,7 @@ export var metadata = {
|
||||
stage: 1
|
||||
};
|
||||
|
||||
export function check(node) {
|
||||
export function shouldVisit(node) {
|
||||
return t.isExportDefaultSpecifier(node) || t.isExportNamespaceSpecifier(node);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,6 @@ export var metadata = {
|
||||
stage: 1
|
||||
};
|
||||
|
||||
export function check() {
|
||||
export function shouldVisit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
24
src/babel/transformation/transformers/filters.js
Normal file
24
src/babel/transformation/transformers/filters.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import includes from "lodash/collection/includes";
|
||||
|
||||
export function internal(transformer, opts) {
|
||||
if (transformer.key[0] === "_") return true;
|
||||
}
|
||||
|
||||
export function blacklist(transformer, opts) {
|
||||
var blacklist = opts.blacklist;
|
||||
if (blacklist.length && includes(blacklist, transformer.key)) return false;
|
||||
}
|
||||
|
||||
export function whitelist(transformer, opts) {
|
||||
var whitelist = opts.whitelist;
|
||||
if (whitelist) return includes(whitelist, transformer.key);
|
||||
}
|
||||
|
||||
export function stage(transformer, opts) {
|
||||
var stage = transformer.metadata.stage;
|
||||
if (stage != null && stage >= opts.stage) return true;
|
||||
}
|
||||
|
||||
export function optional(transformer, opts) {
|
||||
if (transformer.metadata.optional && !includes(opts.optional, transformer.key)) return false;
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
export default {
|
||||
_modules: require("./internal/modules"),
|
||||
|
||||
"es7.classProperties": require("./es7/class-properties"),
|
||||
"es7.trailingFunctionCommas": require("./es7/trailing-function-commas"),
|
||||
"es7.asyncFunctions": require("./es7/async-functions"),
|
||||
@@ -24,8 +26,6 @@ export default {
|
||||
reactCompat: require("./other/react-compat"),
|
||||
react: require("./other/react"),
|
||||
|
||||
_modules: require("./internal/modules"),
|
||||
|
||||
// needs to be before `regenerator` due to generator comprehensions
|
||||
// needs to be before `_shadowFunctions`
|
||||
"es7.comprehensions": require("./es7/comprehensions"),
|
||||
@@ -94,8 +94,6 @@ export default {
|
||||
|
||||
"spec.protoToAssign": require("./spec/proto-to-assign"),
|
||||
|
||||
_declarations: require("./internal/declarations"),
|
||||
|
||||
_shadowFunctions: require("./internal/shadow-functions"),
|
||||
|
||||
"es7.doExpressions": require("./es7/do-expressions"),
|
||||
@@ -117,6 +115,6 @@ export default {
|
||||
"utility.inlineExpressions": require("./utility/inline-expressions"),
|
||||
"utility.deadCodeElimination": require("./utility/dead-code-elimination"),
|
||||
|
||||
flow: require("./other/flow"),
|
||||
_cleanUp: require("./internal/cleanup")
|
||||
jscript: require("./other/jscript"),
|
||||
flow: require("./other/flow")
|
||||
};
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
export var SequenceExpression = {
|
||||
exit(node) {
|
||||
if (node.expressions.length === 1) {
|
||||
return node.expressions[0];
|
||||
} else if (!node.expressions.length) {
|
||||
this.remove();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export var ExpressionStatement = {
|
||||
exit(node) {
|
||||
if (!node.expression) this.remove();
|
||||
}
|
||||
};
|
||||
|
||||
export var Binary = {
|
||||
exit(node) {
|
||||
var right = node.right;
|
||||
var left = node.left;
|
||||
|
||||
if (!left && !right) {
|
||||
this.remove();
|
||||
} else if (!left) {
|
||||
return right;
|
||||
} else if (!right) {
|
||||
return left;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,37 +0,0 @@
|
||||
import * as strict from "../../helpers/strict";
|
||||
import * as t from "../../../types";
|
||||
|
||||
export var metadata = {
|
||||
secondPass: true
|
||||
};
|
||||
|
||||
export function BlockStatement(node, parent, scope, file) {
|
||||
if (!node._declarations) return;
|
||||
|
||||
strict.wrap(node, function () {
|
||||
var kinds = {};
|
||||
var kind;
|
||||
|
||||
for (var i in node._declarations) {
|
||||
var declar = node._declarations[i];
|
||||
|
||||
kind = declar.kind || "var";
|
||||
var declarNode = t.variableDeclarator(declar.id, declar.init);
|
||||
|
||||
if (declar.init) {
|
||||
node.body.unshift(file.attachAuxiliaryComment(t.variableDeclaration(kind, [declarNode])));
|
||||
} else {
|
||||
kinds[kind] ||= [];
|
||||
kinds[kind].push(declarNode);
|
||||
}
|
||||
}
|
||||
|
||||
for (kind in kinds) {
|
||||
node.body.unshift(file.attachAuxiliaryComment(t.variableDeclaration(kind, kinds[kind])));
|
||||
}
|
||||
|
||||
node._declarations = null;
|
||||
});
|
||||
}
|
||||
|
||||
export { BlockStatement as Program };
|
||||
@@ -1,6 +1,8 @@
|
||||
import * as strict from "../../helpers/strict";
|
||||
|
||||
export function Program(program, parent, scope, file) {
|
||||
this.stop();
|
||||
|
||||
strict.wrap(program, function () {
|
||||
program.body = file.dynamicImports.concat(program.body);
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import * as t from "../../../types";
|
||||
|
||||
export function check(node) {
|
||||
export function shouldVisit(node) {
|
||||
return t.isImportDeclaration(node) || t.isExportDeclaration(node);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,11 +52,11 @@ function aliasFunction(getBody, path, scope) {
|
||||
|
||||
var state = {
|
||||
getArgumentsId() {
|
||||
return argumentsId ||= scope.generateUidIdentifier("arguments");
|
||||
return argumentsId = argumentsId || scope.generateUidIdentifier("arguments");
|
||||
},
|
||||
|
||||
getThisId() {
|
||||
return thisId ||= scope.generateUidIdentifier("this");
|
||||
return thisId = thisId || scope.generateUidIdentifier("this");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -67,7 +67,7 @@ function aliasFunction(getBody, path, scope) {
|
||||
var body;
|
||||
|
||||
var pushDeclaration = function (id, init) {
|
||||
body ||= getBody();
|
||||
body = body || getBody();
|
||||
body.unshift(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(id, init)
|
||||
]));
|
||||
@@ -82,6 +82,10 @@ function aliasFunction(getBody, path, scope) {
|
||||
}
|
||||
};
|
||||
|
||||
export function shouldVisit(node) {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function Program(node, parent, scope) {
|
||||
aliasFunction(function () {
|
||||
return node.body;
|
||||
|
||||
@@ -13,6 +13,6 @@ export function Program(program, parent, scope, file) {
|
||||
}
|
||||
}
|
||||
|
||||
program.body.unshift(directive);
|
||||
this.unshiftContainer("body", [directive]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ export function MethodDefinition(node) {
|
||||
var isConstructor = !node.computed && t.isIdentifier(node.key, { name: "constructor" });
|
||||
|
||||
// get ["constructor"]() {}
|
||||
isConstructor ||= t.isLiteral(node.key, { value: "constructor" });
|
||||
isConstructor = isConstructor || t.isLiteral(node.key, { value: "constructor" });
|
||||
|
||||
if (isConstructor) {
|
||||
throw this.errorWithNode(messages.get("classesIllegalConstructorKind"));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { _ForOfStatementArray } from "../es6/for-of";
|
||||
import * as t from "../../../types";
|
||||
|
||||
export var check = t.isForOfStatement;
|
||||
export var shouldVisit = t.isForOfStatement;
|
||||
export var optional = true;
|
||||
|
||||
export function ForOfStatement(node, parent, scope, file) {
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import * as t from "../../../types";
|
||||
|
||||
export function shouldVisit(node) {
|
||||
return node.isType || node.optional || node.implements || node.typeAnnotation || t.isFlow(node);
|
||||
}
|
||||
|
||||
export function Flow(node) {
|
||||
this.remove();
|
||||
}
|
||||
|
||||
18
src/babel/transformation/transformers/other/jscript.js
Normal file
18
src/babel/transformation/transformers/other/jscript.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import * as t from "../../../types";
|
||||
|
||||
export var metadata = {
|
||||
optional: true
|
||||
};
|
||||
|
||||
export function FunctionExpression(node, print) {
|
||||
if (!node.id) return;
|
||||
node._ignoreUserWhitespace = true;
|
||||
|
||||
return t.callExpression(
|
||||
t.functionExpression(null, [], t.blockStatement([
|
||||
t.toStatement(node),
|
||||
t.returnStatement(node.id)
|
||||
])),
|
||||
[]
|
||||
);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import regenerator from "regenerator";
|
||||
import * as t from "../../../types";
|
||||
|
||||
export function check(node) {
|
||||
export function shouldVisit(node) {
|
||||
return t.isFunction(node) && (node.async || node.generator);
|
||||
}
|
||||
|
||||
@@ -9,5 +9,6 @@ export var Program = {
|
||||
enter(ast) {
|
||||
regenerator.transform(ast);
|
||||
this.stop();
|
||||
return ast; // force a checkPath, this really needs to be optimised
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import * as t from "../../../types";
|
||||
|
||||
function statementList(key, node, file) {
|
||||
for (var i = 0; i < node[key].length; i++) {
|
||||
var func = node[key][i];
|
||||
function statementList(key, path, file) {
|
||||
var paths = path.get(key);
|
||||
|
||||
for (var i = 0; i < paths.length; i++) {
|
||||
var path = paths[i];
|
||||
|
||||
var func = path.node;
|
||||
if (!t.isFunctionDeclaration(func)) continue;
|
||||
|
||||
var declar = t.variableDeclaration("let", [
|
||||
@@ -15,20 +19,33 @@ function statementList(key, node, file) {
|
||||
// todo: name this
|
||||
func.id = null;
|
||||
|
||||
node[key][i] = declar;
|
||||
|
||||
file.checkNode(declar);
|
||||
path.replaceWith(declar);
|
||||
}
|
||||
}
|
||||
|
||||
export function shouldVisit(node) {
|
||||
var body;
|
||||
if (node.type === "SwitchCase") {
|
||||
body = node.consequent;
|
||||
} else if (node.type === "BlockStatement") {
|
||||
body = node.body;
|
||||
}
|
||||
if (body) {
|
||||
for (var i = 0; i < body.length; i++) {
|
||||
if (body[i].type === "FunctionDeclaration") return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function BlockStatement(node, parent, scope, file) {
|
||||
if ((t.isFunction(parent) && parent.body === node) || t.isExportDeclaration(parent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
statementList("body", node, file);
|
||||
statementList("body", this, file);
|
||||
}
|
||||
|
||||
export function SwitchCase(node, parent, scope, file) {
|
||||
statementList("consequent", node, file);
|
||||
statementList("consequent", this, file);
|
||||
}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
export { bare as FunctionExpression } from "../../helpers/name-method";
|
||||
export { bare as ArrowFunctionExpression } from "../../helpers/name-method";
|
||||
export { bare as FunctionExpression, bare as ArrowFunctionExpression } from "../../helpers/name-method";
|
||||
|
||||
@@ -21,6 +21,38 @@ export var metadata = {
|
||||
optional: true
|
||||
};
|
||||
|
||||
export function Identifier(node, parent, scope) {
|
||||
if (!this.isReferenced()) return;
|
||||
|
||||
var binding = scope.getBinding(node.name);
|
||||
if (!binding || binding.references > 1 || !binding.constant) return;
|
||||
|
||||
var replacement = binding.path.node;
|
||||
if (t.isVariableDeclarator(replacement)) {
|
||||
replacement = replacement.init;
|
||||
}
|
||||
t.toExpression(replacement);
|
||||
|
||||
scope.removeBinding(node.name);
|
||||
|
||||
binding.path.remove();
|
||||
return replacement;
|
||||
}
|
||||
|
||||
export function FunctionDeclaration(node, parent, scope) {
|
||||
var bindingInfo = scope.getBinding(node.id.name);
|
||||
if (bindingInfo && !bindingInfo.referenced) {
|
||||
this.remove();
|
||||
}
|
||||
}
|
||||
|
||||
export { FunctionDeclaration as ClassDeclaration };
|
||||
|
||||
export function VariableDeclarator(node, parent, scope) {
|
||||
if (!t.isIdentifier(node.id) || !scope.isPure(node.init)) return;
|
||||
FunctionDeclaration.apply(this, arguments);
|
||||
}
|
||||
|
||||
export function ConditionalExpression(node, parent, scope) {
|
||||
var evaluateTest = this.get("test").evaluateTruthy();
|
||||
if (evaluateTest === true) {
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
import * as messages from "../../../messages";
|
||||
import * as t from "../../../types";
|
||||
|
||||
export var metadata = {
|
||||
readOnly: true
|
||||
};
|
||||
|
||||
export function shouldVisit(node) {
|
||||
return t.isModuleDeclaration(node) || (t.isCallExpression(node) && t.isIdentifier(node.callee, { name: "require" }));
|
||||
}
|
||||
|
||||
// check if the input Literal `source` is an alternate casing of "react"
|
||||
function check(source, file) {
|
||||
if (t.isLiteral(source)) {
|
||||
|
||||
@@ -2,7 +2,8 @@ import levenshtein from "leven";
|
||||
import * as messages from "../../../messages";
|
||||
|
||||
export var metadata = {
|
||||
optional: true
|
||||
optional: true,
|
||||
readOnly: true
|
||||
};
|
||||
|
||||
export function Identifier(node, parent, scope, file) {
|
||||
|
||||
@@ -3,6 +3,8 @@ import * as t from "../types";
|
||||
export default class Binding {
|
||||
constructor({ identifier, scope, path, kind }) {
|
||||
this.identifier = identifier;
|
||||
this.references = 0;
|
||||
this.referenced = false;
|
||||
this.constant = true;
|
||||
this.scope = scope;
|
||||
this.path = path;
|
||||
@@ -58,6 +60,15 @@ export default class Binding {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
|
||||
reference() {
|
||||
this.referenced = true;
|
||||
this.references++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
|
||||
@@ -32,9 +32,10 @@ export default class TraversalContext {
|
||||
for (let i = 0; i < queue.length; i++) {
|
||||
var path = queue[i];
|
||||
if (visited.indexOf(path.node) >= 0) continue;
|
||||
|
||||
visited.push(path.node);
|
||||
|
||||
path.setContext(this.parentPath, this, path.key);
|
||||
|
||||
if (path.visit()) {
|
||||
stop = true;
|
||||
break;
|
||||
|
||||
19
src/babel/traversal/explode.js
Normal file
19
src/babel/traversal/explode.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import * as t from "../types";
|
||||
|
||||
export default function (obj) {
|
||||
for (var type in obj) {
|
||||
var fns = obj[type];
|
||||
if (typeof fns === "function") {
|
||||
obj[type] = fns = { enter: fns };
|
||||
}
|
||||
|
||||
var aliases = t.FLIPPED_ALIAS_KEYS[type];
|
||||
if (aliases) {
|
||||
for (var i = 0; i < aliases.length; i++) {
|
||||
var alias = aliases[i];
|
||||
obj[alias] = obj[alias] || fns;
|
||||
}
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
import TraversalContext from "./context";
|
||||
import explode from "./explode";
|
||||
import * as messages from "../messages";
|
||||
import includes from "lodash/collection/includes";
|
||||
import * as t from "../types";
|
||||
|
||||
@@ -7,13 +9,12 @@ export default function traverse(parent, opts, scope, state, parentPath) {
|
||||
|
||||
if (!opts.noScope && !scope) {
|
||||
if (parent.type !== "Program" && parent.type !== "File") {
|
||||
throw new Error(`Must pass a scope and parentPath unless traversing a Program/File got a ${parent.type} node`);
|
||||
throw new Error(messages.get("traverseNeedsParent", parent.type));
|
||||
}
|
||||
}
|
||||
|
||||
if (!opts) opts = {};
|
||||
if (!opts.enter) opts.enter = function () { };
|
||||
if (!opts.exit) opts.exit = function () { };
|
||||
traverse.verify(opts);
|
||||
|
||||
// array of nodes
|
||||
if (Array.isArray(parent)) {
|
||||
@@ -25,6 +26,43 @@ export default function traverse(parent, opts, scope, state, parentPath) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Quickly iterate over some traversal options and validate them.
|
||||
*/
|
||||
|
||||
traverse.verify = function (opts) {
|
||||
if (opts._verified) return;
|
||||
|
||||
if (typeof opts === "function") {
|
||||
throw new Error(messages.get("traverseVerifyRootFunction"));
|
||||
}
|
||||
|
||||
if (!opts.enter) opts.enter = function () { };
|
||||
if (!opts.exit) opts.exit = function () { };
|
||||
if (!opts.shouldSkip) opts.shouldSkip = function () { return false; };
|
||||
|
||||
for (var key in opts) {
|
||||
// it's all good
|
||||
if (key === "blacklist") continue;
|
||||
|
||||
var opt = opts[key];
|
||||
|
||||
if (typeof opt === "function") {
|
||||
// it's all good, it's fine for this key to be a function
|
||||
if (key === "enter" || key === "exit" || key === "shouldSkip") continue;
|
||||
|
||||
throw new Error(messages.get("traverseVerifyVisitorFunction", key));
|
||||
} else if (typeof opt === "object") {
|
||||
for (var key2 in opt) {
|
||||
if (key2 === "enter" || key2 === "exit") continue;
|
||||
throw new Error(messages.get("traverseVerifyVisitorProperty", key, key2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
opts._verified = true;
|
||||
};
|
||||
|
||||
traverse.node = function (node, opts, scope, state, parentPath) {
|
||||
var keys = t.VISITOR_KEYS[node.type];
|
||||
if (!keys) return;
|
||||
@@ -39,7 +77,7 @@ traverse.node = function (node, opts, scope, state, parentPath) {
|
||||
|
||||
const CLEAR_KEYS = [
|
||||
"trailingComments", "leadingComments", "extendedRange",
|
||||
"_declarations", "_scopeInfo" ,"_paths",
|
||||
"_scopeInfo" ,"_paths",
|
||||
"tokens", "range", "start", "end", "loc", "raw"
|
||||
];
|
||||
|
||||
@@ -75,22 +113,7 @@ traverse.removeProperties = function (tree) {
|
||||
return tree;
|
||||
};
|
||||
|
||||
traverse.explode = function (obj) {
|
||||
for (var type in obj) {
|
||||
var fns = obj[type];
|
||||
if (typeof fns === "function") {
|
||||
obj[type] = fns = { enter: fns };
|
||||
}
|
||||
|
||||
var aliases = t.FLIPPED_ALIAS_KEYS[type];
|
||||
if (aliases) {
|
||||
for (var i = 0; i < aliases.length; i++) {
|
||||
obj[aliases[i]] ||= fns;
|
||||
}
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
traverse.explode = explode;
|
||||
|
||||
function hasBlacklistedType(node, parent, scope, state) {
|
||||
if (node.type === state.type) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user