Compare commits

...

108 Commits

Author SHA1 Message Date
Sebastian McKenzie
5f931525bc v5.3.1 2015-05-13 03:20:33 +01:00
Sebastian McKenzie
b86545a320 update 5.3.1 changelog 2015-05-13 03:19:39 +01:00
Sebastian McKenzie
06e75c42bf update module call remap tests 2015-05-13 03:18:55 +01:00
Sebastian McKenzie
05dd65244d add 5.3.1 changelog 2015-05-13 03:16:43 +01:00
Sebastian McKenzie
c4ebfeb0fa fix explosion of modules and colliding identifiers 2015-05-13 03:16:03 +01:00
Sebastian McKenzie
1aa0bbfac9 add TraversalPath#equals 2015-05-13 03:13:27 +01:00
Sebastian McKenzie
58f1e6cbc6 remove incorrect es6.tailCall visitor comment 2015-05-13 03:13:20 +01:00
Sebastian McKenzie
83e0be3038 make import calls sequence expressions - fixes #1514 2015-05-13 03:13:10 +01:00
Sebastian McKenzie
5fc242e4ec upgrade bable dev dependency to 5.3.0 2015-05-13 03:12:32 +01:00
Sebastian McKenzie
dc101adad3 more es6.tailCall transformer cleanup 2015-05-13 01:13:08 +01:00
Sebastian McKenzie
faade72787 optimise and clean up es6.tailCall transformer 2015-05-13 01:11:26 +01:00
Sebastian McKenzie
2a78ae9889 5.3.0 2015-05-13 01:07:11 +01:00
Sebastian McKenzie
9840639843 v5.3.0 2015-05-13 00:13:14 +01:00
Sebastian McKenzie
82c21a901e clean up es6.tailCall thirdPass visitor 2015-05-13 00:11:19 +01:00
Sebastian McKenzie
e1c83144c1 add 5.3.0 changelog 2015-05-13 00:11:08 +01:00
Sebastian McKenzie
ef2ac73215 fix export scope tracking reference counter - fixes #1513 2015-05-12 23:21:30 +01:00
Sebastian McKenzie
735d8955bf sync with upstream acorn 2015-05-12 23:21:30 +01:00
Sebastian McKenzie
3abee0a4fa fix switch case breaks not being correctly transformed when non top-level - fixes #1200 2015-05-12 23:21:30 +01:00
Sebastian McKenzie
b6f18b4f2b Merge pull request #1200 from lukasmlady/regenerator-let-fn-if-bug
Add failing tests that document ES 6 generators bug
2015-05-12 23:21:17 +01:00
Sebastian McKenzie
85cd0465fa Merge pull request #1511 from amasad/trailing-methods
Trailing commas in methods
2015-05-12 21:46:18 +01:00
Amjad Masad
0452e0fdd2 Allow trailing commas in methods 2015-05-12 13:20:36 -07:00
Amjad Masad
462ff572b3 Add failing test for trailing commas in methods 2015-05-12 13:19:21 -07:00
Sebastian McKenzie
d11099bb2b Merge branch 'master' of github.com:babel/babel 2015-05-12 19:13:53 +01:00
Sebastian McKenzie
f5c4684d3e force default parameter IIFE on reference to eval 2015-05-12 19:13:32 +01:00
Sebastian McKenzie
876a22578b Merge pull request #1506 from sverrejoh/patch-1
Added missing license field to package.json
2015-05-12 09:06:55 +01:00
Sverre Johansen
9f5e8b296b Added missing license field to package.json
Project says MIT, but license field missing in package.json
2015-05-12 08:54:56 +02:00
Sebastian McKenzie
d9deb02edc register as inside a type when parsing type aliases to avoid ambiguous jsx parsing - fixes #1378 2015-05-11 23:44:22 +01:00
Sebastian McKenzie
a402d0cdeb ensure that uids don't collide with **any** bindings contained in the program - fixes #1328 2015-05-11 23:37:31 +01:00
Sebastian McKenzie
683fb62505 fix acorn hacky lookahead with token contexts - fixes #1349 2015-05-11 23:20:51 +01:00
Sebastian McKenzie
941474983d clean up es6.objectSuper transformer - fixes #1502 2015-05-11 22:34:08 +01:00
Sebastian McKenzie
2b42773e01 explode duplicate identifiers in export/import specifiers and property shorthand - fixes #1458 2015-05-11 22:08:38 +01:00
Sebastian McKenzie
8277a532f4 skip loose mode for class methods when using decorators, addresses #1501 2015-05-11 17:40:36 +01:00
Sebastian McKenzie
539784b640 add Scope#moveBindingTo method and change more for array loops to for...of 2015-05-11 17:25:09 +01:00
Sebastian McKenzie
f373f8f003 refactor _shadowFunctions transformer to not do an entire traverse per function 2015-05-11 11:38:22 +01:00
Sebastian McKenzie
8605e835eb add exit visitor existence to unvisitable node shortcircuiting 2015-05-11 01:52:19 +01:00
Sebastian McKenzie
b4ace2043a fix shortcircuting of unvisitable nodes 2015-05-11 01:43:18 +01:00
Sebastian McKenzie
444a64e934 remove incorrect no eval in strict mode 2015-05-10 20:01:13 +01:00
Sebastian McKenzie
8ea2ae924d add existence check for ast.comments 2015-05-10 20:00:38 +01:00
Sebastian McKenzie
4ceb1d6f5e short circuit unnecessary visits 2015-05-10 20:00:26 +01:00
Sebastian McKenzie
3c81899ca7 add --harmony_generators to list of node flags - closes #1474, closes #1473 2015-05-10 20:00:12 +01:00
Sebastian McKenzie
ab59fd08e5 fix array type inferrence for file#toArray from being so wonky - fixes #1355 2015-05-10 19:35:41 +01:00
Sebastian McKenzie
19b05b5e61 change some manual array for loops to for..of 2015-05-10 19:35:05 +01:00
Sebastian McKenzie
65a44a1e13 remove use of exports 2015-05-10 16:09:43 +01:00
Sebastian McKenzie
d38f18af40 create null object when clearing internalRemap instead of using an object inherited plain object - fixes #1489 2015-05-09 18:39:59 +01:00
Sebastian McKenzie
2744b9f31f only print misisng ast.comments when available 2015-05-09 17:32:47 +01:00
Sebastian McKenzie
4deed35212 fix syntax errors introduced with previous lodash each removal 2015-05-09 17:27:33 +01:00
Sebastian McKenzie
bc9ae5ea8b remove many instances of lodash each in favor of for of loops 2015-05-09 17:22:01 +01:00
Sebastian McKenzie
87d879e236 Merge branch 'master' of github.com:babel/babel 2015-05-09 16:53:05 +01:00
Sebastian McKenzie
f657598c72 remove noop traversal visitors methods 2015-05-09 16:52:57 +01:00
Sebastian McKenzie
2a5cb9d21b move some utility transformers to minification 2015-05-09 16:52:31 +01:00
Sebastian McKenzie
cf7d6b655e Merge pull request #1487 from amasad/trailing-commas
[es7.trailingFunctionCommas] Allow in new expressions
2015-05-09 03:16:18 +01:00
Amjad Masad
6d2723eec5 New expressions is allowed to have trailing commas in es7 proposal 2015-05-08 19:12:53 -07:00
Amjad Masad
6834cc5b46 Add failing tests for trailing commas in new expressions 2015-05-08 19:12:10 -07:00
Sebastian McKenzie
9b949e574f use block scoped variables in es6.blockScoping transformer 2015-05-09 01:25:36 +01:00
Sebastian McKenzie
a75af0a5d2 optimise es6.constants transformer to use the same traversal path instead of spawning another one 2015-05-09 01:25:21 +01:00
Sebastian McKenzie
080b26769c remove compat-table 2015-05-09 00:09:19 +01:00
Sebastian McKenzie
e037ae7bc9 automatically explode visitors 2015-05-09 00:07:08 +01:00
Sebastian McKenzie
c60ad89937 add verbose mode to logging 2015-05-09 00:06:55 +01:00
Sebastian McKenzie
4194857086 fix system modules test to reflect strict hoisting behaviour 2015-05-08 23:58:25 +01:00
Sebastian McKenzie
1179c44c5b share comments with siblings when nodes are removed - fixes #1484 2015-05-08 23:57:12 +01:00
Sebastian McKenzie
f6d9b270c9 update to tracuer master 2015-05-08 23:48:30 +01:00
Sebastian McKenzie
1be0159b01 Merge pull request #1484 from amasad/type-comment-print
[Flow] Add failing tests for printing comments w/ type alias
2015-05-08 23:46:18 +01:00
Sebastian McKenzie
61ba8ad997 Merge pull request #1472 from babel/single-pass
Merge internal transformers into single traversal pass
2015-05-08 23:36:29 +01:00
Sebastian McKenzie
89e31085d2 ensure dynamic imports are hoisted 2015-05-08 23:33:30 +01:00
Sebastian McKenzie
920c84a1f2 move shadow function visitors to entrance instead of exit 2015-05-08 23:33:20 +01:00
Amjad Masad
ed56fecd04 [Flow] Add failing tests for printing comments w/ type alias 2015-05-08 15:33:00 -07:00
Sebastian McKenzie
f0bfdfb699 skip traversing back into ReturnStatement replacement when rewriting loops in the es6.blockScoping transformer 2015-05-08 23:13:27 +01:00
Sebastian McKenzie
b02a1112bc change ClassExpression visitor to enter instead of exist in the es6.classes transformer 2015-05-08 23:10:02 +01:00
Sebastian McKenzie
590a165776 move hoistDirectives transformer to builtin-setup 2015-05-08 23:09:45 +01:00
Sebastian McKenzie
2fd1b2a484 rename category metadata option to group 2015-05-08 22:54:15 +01:00
Sebastian McKenzie
8f9d02d689 further work splitting up transformers into their own "category" in order of what they need and what they actually do 2015-05-08 22:53:31 +01:00
Sebastian McKenzie
b376b6b33b store uncollapsed transformer pass stack so we have access to it when calling pre and post methods 2015-05-08 22:53:03 +01:00
Sebastian McKenzie
8292d6d8ad fix replacement requeue exiting too early 2015-05-08 22:52:38 +01:00
Sebastian McKenzie
d6a5c39079 update classes to reflect new transformer precedence 2015-05-08 22:52:19 +01:00
Sebastian McKenzie
2a9a59f784 remove incomplete ludicrous transformer 2015-05-08 22:52:02 +01:00
Sebastian McKenzie
abf4a5495a don't pretty print variable declarators in concise mode 2015-05-08 22:51:47 +01:00
Sebastian McKenzie
f8b8723bef Merge pull request #1483 from jquense/patch-1
Fix plugin api typo when an object is passed in
2015-05-08 22:26:45 +01:00
Jason Quense
6b9686f2dd Fix plugin api typo when an object is passed in 2015-05-08 17:25:14 -04:00
Sebastian McKenzie
4a439d8c8e update flow strip type annotations test 2015-05-08 15:52:08 +01:00
Sebastian McKenzie
c526a3eb04 move shadow-functions internal transformer to builtin-cleanup category 2015-05-08 15:51:56 +01:00
Sebastian McKenzie
ba516901af restructure transformers into multiple categories 2015-05-08 15:26:00 +01:00
Sebastian McKenzie
8f52229a86 add get function name to source map classes test 2015-05-08 15:25:50 +01:00
Sebastian McKenzie
5b793f8882 fix TraversalPath#_getPattern incorrectly iterating over the parts 2015-05-08 15:25:34 +01:00
Sebastian McKenzie
b31c14c52a Merge branch 'master' into single-pass 2015-05-08 00:24:33 +01:00
Sebastian McKenzie
78b72512cb better verify the type of the new node before requeueing it and also stop current node traversal on skip 2015-05-08 00:24:04 +01:00
Sebastian McKenzie
2fbb3cad9f add isUser and isGenerated path methods 2015-05-08 00:23:28 +01:00
Sebastian McKenzie
2621081a13 merge in astVisitor in runtime transformer - unsure why this was separate in the first place 2015-05-08 00:23:00 +01:00
Sebastian McKenzie
8daf95bf59 name additional methods that are now covered since the naming is done in tandem 2015-05-08 00:22:43 +01:00
Sebastian McKenzie
6e8ab16b25 run es6.spec.blockScoping transformer on exit rather than enter 2015-05-08 00:22:23 +01:00
Sebastian McKenzie
a5cda5caa7 hoist param declaration when performing tco - fixes #1478 2015-05-07 23:14:03 +01:00
Sebastian McKenzie
13a6c69668 add node existence check to each visitor call 2015-05-07 23:02:40 +01:00
Sebastian McKenzie
380293d030 add transformer dependencies - fixes #1477 2015-05-07 21:35:12 +01:00
Sebastian McKenzie
0b15a97013 Merge branch 'master' into single-pass 2015-05-07 20:15:34 +01:00
Sebastian McKenzie
11af066956 5.2.17 2015-05-07 20:15:17 +01:00
Sebastian McKenzie
d7b4d342c3 v5.2.17 2015-05-07 20:12:47 +01:00
Sebastian McKenzie
77aeebe2a8 add Super node type to ast-types patch 2015-05-07 20:11:37 +01:00
Sebastian McKenzie
c3a08d413f attach auxiliary comment to function declaration helpers - fixes #1476 2015-05-07 20:11:31 +01:00
Sebastian McKenzie
23ac2319af add Super node type to ast-types patch 2015-05-07 20:11:14 +01:00
Sebastian McKenzie
a1bc0704ab attach auxiliary comment to function declaration helpers - fixes #1476 2015-05-07 20:11:02 +01:00
Sebastian McKenzie
0bbfd427af do module formatter on program exit rather than entrance 2015-05-07 16:23:47 +01:00
Sebastian McKenzie
f17b268a71 do member expression and property literal conversion to computed on exit rather than on entrance 2015-05-07 16:23:33 +01:00
Sebastian McKenzie
9ffc265bea don't requeue node unless the type has changed 2015-05-07 16:01:00 +01:00
Sebastian McKenzie
6f664ca64e merge internal transformers into single traversal pass 2015-05-07 15:53:22 +01:00
Sebastian McKenzie
8a4a76000d correctly arrayify commander extensions - closes #1470, fixes #1460 2015-05-07 13:55:12 +01:00
Sebastian McKenzie
e83daf87d4 add this.stop() to secondary strict transformer #1465 2015-05-07 08:38:46 +01:00
Sebastian McKenzie
8ed90d3af2 ignore parameter bindings in minification.deadCodeElimination transformer - fixes #1464 2015-05-07 01:58:54 +01:00
Sebastian McKenzie
0bb311f8ce 5.2.16 2015-05-06 16:45:32 +01:00
Lukáš Mladý
6491018c21 Add failing tests that document ES 6 generators bug 2015-04-08 14:14:45 +02:00
171 changed files with 1372 additions and 1277 deletions

3
.gitmodules vendored
View File

@@ -1,6 +1,3 @@
[submodule "vendor/traceur"]
path = vendor/traceur
url = https://github.com/google/traceur-compiler
[submodule "vendor/compat-table"]
path = vendor/compat-table
url = https://github.com/kangax/compat-table

View File

@@ -13,6 +13,41 @@ _Note: Gaps between patch versions are faulty/broken releases._
See [CHANGELOG - 6to5](CHANGELOG-6to5.md) for the pre-4.0.0 version changelog.
## 5.3.1
* **Bug Fix**
* Fix unique export specifiers not being cloned when exploding class and function exports,
* **Polish**
* Turn import remaps to sequence expressions to remove their context and improve performance.
## 5.3.0
**Speeeeeeed**
![gifs lol](https://31.media.tumblr.com/568205a0e37ae15eca510fa639589a59/tumblr_n8kw8kpcSb1sg6cg8o1_500.gif)
* **Spec Compliancy**
* Allow trailing param commas for methods when using the `es7.trailingCommas` transformer.
* **Bug Fix**
* Fix `es6.blockScoping` transformer not properly ignoring `break` in `SwitchCase`.
* Fix lookahead context saving to avoid weird tokenizer state.
* Explode duplicate identifiers in export/import specifiers and property shorthand to create unique objects.
* Skip loose mode for class methods when they have decorators.
* When removing nodes, share their comments with their siblings.
* Properly hoist temp param declarations when doing TCO.
* **Internal**
* Add `--harmony_generators` flag to `$ babel-node`.
* **Polish**
* Move many `utility` transformers to `minification`.
## 5.2.17
* **Bug Fix**
* Fix auxiliary comments not properly being attached to function declaration helpers.
* Add `Super` node type to `ast-types` patch.
* Ignore parameter bindings when attempting to inline them in the `minification.deadCodeElimination` transformer.
* Correct `extensions` arguments when using the Babel CLI.
## 5.2.16
* **Bug Fix**

View File

@@ -122,5 +122,4 @@ bootstrap:
npm link
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

View File

@@ -1,9 +1,10 @@
{
"name": "babel-core",
"description": "Turn ES6 code into readable vanilla ES5 with source maps",
"version": "5.2.16",
"version": "5.3.1",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://babeljs.io/",
"license": "MIT",
"repository": "babel/babel",
"main": "lib/babel/api/node.js",
"browser": {
@@ -63,7 +64,7 @@
"user-home": "^1.1.1"
},
"devDependencies": {
"babel": "5.1.13",
"babel": "5.3.0",
"browserify": "^9.0.8",
"chai": "^2.2.0",
"eslint": "^0.18.0",

View File

@@ -56,6 +56,7 @@ babelArgs.forEach(function(arg){
case "--harmony_object_literals":
case "--harmony_templates":
case "--harmony_rest_parameters":
case "--harmony_generators":
case "--compiled_keyed_generic_loads":
case "--pretenuring_call_new":
case "--allocation_site_pretenuring":

View File

@@ -30,7 +30,7 @@ module.exports = function (commander, filenames, opts) {
var handleFile = function (src, filename) {
if (util.shouldIgnore(src)) return;
if (util.canCompile(filename, opts.extensions)) {
if (util.canCompile(filename, commander.extensions)) {
write(src, filename);
} else if (commander.copyFiles) {
outputFileSync(path.join(commander.outDir, filename), fs.readFileSync(src));

View File

@@ -70,6 +70,12 @@ commander.parse(process.argv);
//
if (commander.extensions) {
commander.extensions = util.arrayify(commander.extensions);
}
//
var errors = [];
var filenames = commander.args.reduce(function (globbed, input) {

View File

@@ -1,13 +1,13 @@
{
"name": "babel",
"description": "Turn ES6 code into readable vanilla ES5 with source maps",
"version": "5.2.15",
"version": "5.3.0",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://babeljs.io/",
"repository": "babel/babel",
"preferGlobal": true,
"dependencies": {
"babel-core": "^5.2.15",
"babel-core": "^5.3.0",
"chokidar": "^1.0.0",
"commander": "^2.6.0",
"convert-source-map": "^1.1.0",

View File

@@ -1,7 +1,7 @@
{
"name": "babel-runtime",
"description": "babel selfContained runtime",
"version": "5.2.15",
"version": "5.3.0",
"repository": "babel/babel",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"dependencies": {

View File

@@ -153,10 +153,15 @@ pp.flow_parseTypeAlias = function (node) {
node.typeParameters = null
}
var oldInType = this.inType;
this.inType = true;
this.expect(tt.eq)
node.right = this.flow_parseType()
this.inType = oldInType;
this.semicolon()
return this.finishNode(node, "TypeAlias")

View File

@@ -474,7 +474,10 @@ pp.parseNew = function() {
}
let start = this.markPosition()
node.callee = this.parseSubscripts(this.parseExprAtom(), start, true)
if (this.eat(tt.parenL)) node.arguments = this.parseExprList(tt.parenR, false)
if (this.eat(tt.parenL)) node.arguments = this.parseExprList(
tt.parenR,
this.options.features["es7.trailingFunctionCommas"]
)
else node.arguments = empty
return this.finishNode(node, "NewExpression")
}
@@ -632,7 +635,7 @@ pp.parseMethod = function(isGenerator, isAsync) {
let node = this.startNode()
this.initFunction(node, isAsync)
this.expect(tt.parenL)
node.params = this.parseBindingList(tt.parenR, false, false)
node.params = this.parseBindingList(tt.parenR, false, this.options.features["es7.trailingFunctionCommas"])
if (this.options.ecmaVersion >= 6) {
node.generator = isGenerator
}

View File

@@ -14,7 +14,11 @@ var STATE_KEYS = [
"pos",
"end",
"type",
"value"
"value",
"exprAllowed",
"potentialArrowAt",
"currLine",
"input"
];
pp.getState = function () {
@@ -23,6 +27,7 @@ pp.getState = function () {
var key = STATE_KEYS[i]
state[key] = this[key]
}
state.context = this.context.slice()
return state
};

View File

@@ -283,7 +283,7 @@ pp.readToken_lt_gt = function(code) { // '<>'
}
if (next == 33 && code == 60 && this.input.charCodeAt(this.pos + 2) == 45 &&
this.input.charCodeAt(this.pos + 3) == 45) {
if (this.inModule) unexpected()
if (this.inModule) this.unexpected()
// `<!--`, an XML-style comment that should be interpreted as a line comment
this.skipLineComment(4)
this.skipSpace()

View File

@@ -43,13 +43,13 @@ export function JSXElement(node, print) {
if (open.selfClosing) return;
this.indent();
each(node.children, (child) => {
for (var child of (node.children: Array)) {
if (t.isLiteral(child)) {
this.push(child.value, true);
} else {
print(child);
}
});
}
this.dedent();
print(node.closingElement);

View File

@@ -3,7 +3,7 @@ import * as t from "../../types";
export function ImportSpecifier(node, print) {
print(node.imported);
if (node.local && node.local !== node.imported) {
if (node.local && node.local.name !== node.imported.name) {
this.push(" as ");
print(node.local);
}
@@ -19,7 +19,7 @@ export function ExportDefaultSpecifier(node, print) {
export function ExportSpecifier(node, print) {
print(node.local);
if (node.exported && node.local !== node.exported) {
if (node.exported && node.local.name !== node.exported.name) {
this.push(" as ");
print(node.exported);
}

View File

@@ -182,8 +182,8 @@ export function VariableDeclaration(node, print, parent) {
var hasInits = false;
// don't add whitespace to loop heads
if (!t.isFor(parent)) {
for (var i = 0; i < node.declarations.length; i++) {
if (node.declarations[i].init) {
for (var declar of (node.declarations: Array)) {
if (declar.init) {
// has an init so let's split it up over multiple lines
hasInits = true;
}
@@ -191,7 +191,7 @@ export function VariableDeclaration(node, print, parent) {
}
var sep = ",";
if (!this.format.compact && hasInits && !this.format.retainLines) {
if (!this.format.compact && !this.format.concise && hasInits && !this.format.retainLines) {
sep += `\n${repeating(" ", node.kind.length + 1)}`;
} else {
sep += " ";

View File

@@ -15,15 +15,15 @@ export function TemplateLiteral(node, print) {
var quasis = node.quasis;
var len = quasis.length;
each(quasis, (quasi, i) => {
print(quasi);
for (var i = 0; i < len; i++) {
print(quasis[i]);
if (i + 1 < len) {
this.push("${ ");
print(node.expressions[i]);
this.push(" }");
}
});
}
this._push("`");
}

View File

@@ -1,4 +1,5 @@
import each from "lodash/collection/each";
import * as t from "../../types";
export function Identifier(node) {
this.push(node.name);
@@ -39,7 +40,14 @@ export function Property(node, print) {
this.push("]");
} else {
print(node.key);
if (node.shorthand) return;
// shorthand!
if (node.shorthand &&
(t.isIdentifier(node.key) &&
t.isIdentifier(node.value) &&
node.key.name === node.value.name)) {
return;
}
}
this.push(":");
@@ -54,7 +62,8 @@ export function ArrayExpression(node, print) {
this.push("[");
each(elems, (elem, i) => {
for (var i = 0; i < elems.length; i++) {
var elem = elems[i];
if (!elem) {
// If the array expression ends with a hole, that hole
// will be ignored by the interpreter, but if it ends with
@@ -67,7 +76,7 @@ export function ArrayExpression(node, print) {
print(elem);
if (i < len - 1) this.push(",");
}
});
}
this.push("]");
}

View File

@@ -105,11 +105,13 @@ class CodeGenerator {
this.print(ast);
var comments = [];
each(ast.comments, function (comment) {
if (!comment._displayed) comments.push(comment);
});
this._printComments(comments);
if (ast.comments) {
var comments = [];
for (var comment of (ast.comments: Array)) {
if (!comment._displayed) comments.push(comment);
}
this._printComments(comments);
}
return {
map: this.map.get(),
@@ -249,7 +251,8 @@ class CodeGenerator {
if (opts.indent) this.indent();
each(nodes, (node, i) => {
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i];
print(node, {
statement: opts.statement,
addNewlines: opts.addNewlines,
@@ -263,7 +266,7 @@ class CodeGenerator {
}
}
});
});
}
if (opts.indent) this.dedent();
}
@@ -314,9 +317,9 @@ class CodeGenerator {
nodes.push(node.argument);
}
each(nodes, (node) => {
for (var node of (nodes: Array)) {
comments = comments.concat(this._getComments(key, node));
});
}
return comments;
}
@@ -331,19 +334,21 @@ class CodeGenerator {
if (!this.format.comments) return;
if (!comments || !comments.length) return;
each(comments, (comment) => {
for (var comment of (comments: Array)) {
var skip = false;
// find the original comment in the ast and set it as displayed
each(this.ast.comments, function (origComment) {
if (origComment.start === comment.start) {
// comment has already been output
if (origComment._displayed) skip = true;
if (this.ast.comments) {
// find the original comment in the ast and set it as displayed
for (var origComment of (this.ast.comments: Array)) {
if (origComment.start === comment.start) {
// comment has already been output
if (origComment._displayed) skip = true;
origComment._displayed = true;
return false;
origComment._displayed = true;
break;
}
}
});
}
if (skip) return;
@@ -387,7 +392,7 @@ class CodeGenerator {
// whitespace after
this.newline(this.whitespace.getNewlinesAfter(comment));
});
}
}
}

View File

@@ -18,7 +18,6 @@ export const MESSAGES = {
modulesIllegalExportName: "Illegal export $1",
unknownForHead: "Unknown node type $1 in ForStatement",
didYouMean: "Did you mean $1?",
evalInStrictMode: "eval is not allowed in strict mode",
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",
@@ -26,7 +25,6 @@ export const MESSAGES = {
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: "You passed \`traverse()\` a visitor object with the key $1 that's a `Function` instead of `{ enter: Function }`. You need to normalise your visitor with `traverse.explode(visitor)`.",
traverseVerifyVisitorProperty: "You passed `traverse()` a visitor object with the property $1 that has the invalid property $2",
traverseVerifyNodeType: "You gave us a visitor for the node type $1 but it's not a valid type",

View File

@@ -33,6 +33,9 @@ def("DoExpression")
.build("body")
.field("body", [def("Statement")]);
def("Super")
.bases("Expression");
def("ExportDefaultDeclaration")
.bases("Declaration")
.build("declaration")

View File

@@ -4,6 +4,7 @@ import moduleFormatters from "../modules";
import PluginManager from "./plugin-manager";
import shebangRegex from "shebang-regex";
import TraversalPath from "../../traversal/path";
import Transformer from "../transformer";
import isFunction from "lodash/lang/isFunction";
import isAbsolute from "path-is-absolute";
import resolveRc from "../../tools/resolve-rc";
@@ -23,24 +24,12 @@ 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 = {
exit(node, parent, scope, state) {
checkPath(state.stack, this);
}
};
function checkPath(stack, path) {
each(stack, function (pass) {
if (pass.shouldRun || pass.ran) return;
pass.checkPath(path);
});
}
export default class File {
constructor(opts = {}, pipeline) {
this.transformerDependencies = {};
this.dynamicImportTypes = {};
this.dynamicImportIds = {};
this.dynamicImports = [];
@@ -49,7 +38,6 @@ export default class File {
this.usedHelpers = {};
this.dynamicData = {};
this.data = {};
this.uids = {};
this.pipeline = pipeline;
this.log = new Logger(this, opts.filename || "unknown");
@@ -96,10 +84,7 @@ export default class File {
"interop-require",
];
static soloHelpers = [
"ludicrous-proxy-create",
"ludicrous-proxy-directory"
];
static soloHelpers = [];
static options = require("./options");
@@ -203,7 +188,8 @@ export default class File {
var stack = [];
// build internal transformers
each(this.pipeline.transformers, function (transformer, key) {
for (var key in this.pipeline.transformers) {
var transformer = this.pipeline.transformers[key];
var pass = transformers[key] = transformer.buildPass(file);
if (pass.canTransform()) {
@@ -217,7 +203,7 @@ export default class File {
transformer.manipulateOptions(file.opts, file);
}
}
});
}
// init plugins!
var beforePlugins = [];
@@ -233,8 +219,55 @@ export default class File {
}
stack = beforePlugins.concat(stack, afterPlugins);
// register
this.transformerStack = stack.concat(secondaryStack);
// build transformer stack
this.uncollapsedTransformerStack = stack = stack.concat(secondaryStack);
// build dependency graph
for (var pass of (stack: Array)) {
for (var dep of (pass.transformer.dependencies: Array)) {
this.transformerDependencies[dep] = pass.key;
}
}
// collapse stack categories
this.transformerStack = this.collapseStack(stack);
}
collapseStack(_stack) {
var stack = [];
var ignore = [];
for (let pass of (_stack: Array)) {
// been merged
if (ignore.indexOf(pass) >= 0) continue;
var group = pass.transformer.metadata.group;
// can't merge
if (!pass.canTransform() || !group) {
stack.push(pass);
continue;
}
var mergeStack = [];
for (let pass of (_stack: Array)) {
if (pass.transformer.metadata.group === group) {
mergeStack.push(pass);
ignore.push(pass);
}
}
var visitors = [];
for (let pass of (mergeStack: Array)) {
visitors.push(pass.handlers);
}
var visitor = traverse.visitors.merge(visitors);
var mergeTransformer = new Transformer(group, visitor);
//console.log(mergeTransformer);
stack.push(mergeTransformer.buildPass(this));
}
return stack;
}
set(key: string, val): any {
@@ -337,6 +370,7 @@ export default class File {
ref._generated = true;
ref.id = uid;
ref.type = "FunctionDeclaration";
this.attachAuxiliaryComment(ref);
this.path.unshiftContainer("body", ref);
} else {
ref._compact = true;
@@ -357,23 +391,6 @@ export default class File {
return err;
}
checkPath(path) {
if (Array.isArray(path)) {
for (var i = 0; i < path.length; i++) {
this.checkPath(path[i]);
}
return;
}
var stack = this.transformerStack;
checkPath(stack, path);
path.traverse(checkTransformerVisitor, {
stack: stack
});
}
mergeSourceMap(map: Object) {
var opts = this.opts;
@@ -461,10 +478,6 @@ export default class File {
this._addAst(ast);
this.log.debug("End set AST");
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()) {
@@ -473,9 +486,9 @@ export default class File {
this.log.debug("End module formatter init");
this.call("pre");
each(this.transformerStack, function (pass) {
for (var pass of (this.transformerStack: Array)) {
pass.transform();
});
}
this.call("post");
}
@@ -540,10 +553,8 @@ export default class File {
}
call(key: string) {
var stack = this.transformerStack;
for (var i = 0; i < stack.length; i++) {
var transformer = stack[i].transformer;
var fn = transformer[key];
for (var pass of (this.uncollapsedTransformerStack: Array)) {
var fn = pass.transformer[key];
if (fn) fn(this);
}
}

View File

@@ -1,4 +1,7 @@
import * as util from "../../util";
import buildDebug from "debug/node";
var verboseDebug = buildDebug("babel:verbose");
var generalDebug = buildDebug("babel");
export default class Logger {
constructor(file: File, filename: string) {
@@ -22,11 +25,15 @@ export default class Logger {
}
}
verbose(msg: string) {
if (verboseDebug.enabled) verboseDebug(this._buildMessage(msg));
}
debug(msg: string) {
util.debug(this._buildMessage(msg));
if (generalDebug.enabled) generalDebug(this._buildMessage(msg));
}
deopt(node: Object, msg: string) {
util.debug(this._buildMessage(msg));
this.debug(msg);
}
}

View File

@@ -68,7 +68,7 @@ export default class PluginManager {
if (name) {
if (typeof name === "object" && name.transformer) {
({ plugin: name, position } = name);
({ transformer: plugin, 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

View File

@@ -1,7 +1,9 @@
import explode from "./explode-assignable-expression";
import * as t from "../../types";
export default function (exports, opts) {
export default function (opts) {
var exports = {};
var isAssignment = function (node) {
return node.operator === opts.operator + "=";
};
@@ -10,10 +12,6 @@ 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 (this.isCompletionRecord()) return;
@@ -44,4 +42,6 @@ export default function (exports, opts) {
if (node.operator !== opts.operator) return;
return opts.build(node.left, node.right);
};
return exports;
};

View File

@@ -10,12 +10,6 @@ import * as react from "./react";
import * as t from "../../types";
export default function (exports, opts) {
exports.shouldVisit = function (node) {
if (t.isJSX(node)) return true;
if (react.isCreateClass(node)) return true;
return false;
};
exports.JSXIdentifier = function (node, parent) {
if (node.name === "this" && this.isReferenced()) {
return t.thisExpression();

View File

@@ -5,6 +5,13 @@ var pipeline = new Pipeline;
//
import transformers from "./transformers";
for (var key in transformers) {
var transformer = transformers[key];
var metadata = transformer.metadata = transformer.metadata || {};
metadata.group = metadata.group || "builtin-basic";
}
pipeline.addTransformers(transformers);
//

View File

@@ -5,19 +5,23 @@ import object from "../../helpers/object";
import * as util from "../../util";
import * as t from "../../types";
var remapVisitor = traverse.explode({
var remapVisitor = {
enter(node, parent, scope, formatter) {
if (node._skipModulesRemap) {
return this.skip();
}
},
Identifier(node, parent, scope, formatter) {
ReferencedIdentifier(node, parent, scope, formatter) {
var remap = formatter.internalRemap[node.name];
if (this.isReferencedIdentifier() && remap && node !== remap) {
if (remap && node !== remap) {
if (!scope.hasBinding(node.name) || scope.bindingIdentifierEquals(node.name, formatter.localImports[node.name])) {
return remap;
if (this.key === "callee" && this.parentPath.isCallExpression()) {
return t.sequenceExpression([t.literal(0), remap]);
} else {
return remap;
}
}
}
},
@@ -63,7 +67,7 @@ var remapVisitor = traverse.explode({
return t.sequenceExpression(nodes);
}
});
};
var importsVisitor = {
ImportDeclaration: {
@@ -74,7 +78,7 @@ var importsVisitor = {
}
};
var exportsVisitor = traverse.explode({
var exportsVisitor = {
ExportDeclaration: {
enter(node, parent, scope, formatter) {
formatter.hasLocalExports = true;
@@ -106,7 +110,7 @@ var exportsVisitor = traverse.explode({
}
}
}
});
};
export default class DefaultFormatter {
constructor(file) {

View File

@@ -1,5 +1,6 @@
import DefaultFormatter from "./_default";
import AMDFormatter from "./amd";
import object from "../../helpers/object";
import * as util from "../../util";
import last from "lodash/array/last";
import each from "lodash/collection/each";
@@ -60,12 +61,12 @@ var runnerSettersVisitor = {
enter(node, parent, scope, state) {
if (node._importSource === state.source) {
if (t.isVariableDeclaration(node)) {
each(node.declarations, function (declar) {
for (var declar of (node.declarations: Array)) {
state.hoistDeclarators.push(t.variableDeclarator(declar.id));
state.nodes.push(t.expressionStatement(
t.assignmentExpression("=", declar.id, declar.init)
));
});
}
} else {
state.nodes.push(node);
}
@@ -143,7 +144,7 @@ export default class SystemFormatter extends AMDFormatter {
]));
}
this.internalRemap = {};
this.internalRemap = object();
this._addImportSource(last(nodes), node);
}

View File

@@ -1 +0,0 @@
Object(RIGHT)[LEFT] !== undefined;

View File

@@ -1,4 +0,0 @@
(function (proxy, directory) {
directory.push(proxy);
return proxy;
})

View File

@@ -8,34 +8,26 @@ import traverse from "../traversal";
export default class TransformerPass {
constructor(file: File, transformer: Transformer) {
this.shouldTransform = !transformer.shouldVisit;
this.transformer = transformer;
this.handlers = transformer.handlers;
this.skipKey = transformer.skipKey;
this.file = file;
this.ran = false;
this.transformer = transformer;
this.handlers = transformer.handlers;
this.file = file;
this.ran = false;
this.key = transformer.key;
}
canTransform(): boolean {
return this.file.pipeline.canTransform(this.transformer, this.file.opts);
}
checkPath(path: TraversalPath): boolean {
if (this.shouldTransform || this.ran) return;
this.shouldTransform = this.transformer.shouldVisit(path.node);
return this.file.transformerDependencies[this.key] ||
this.file.pipeline.canTransform(this.transformer, this.file.opts);
}
transform() {
if (!this.shouldTransform) return;
var file = this.file;
file.log.debug(`Start transformer ${this.transformer.key}`);
file.log.debug(`Start transformer ${this.key}`);
traverse(file.ast, this.handlers, file.scope, file);
file.log.debug(`Finish transformer ${this.transformer.key}`);
file.log.debug(`Finish transformer ${this.key}`);
this.ran = true;
}

View File

@@ -25,8 +25,8 @@ export default class Transformer {
};
this.manipulateOptions = take("manipulateOptions");
this.shouldVisit = take("shouldVisit");
this.metadata = take("metadata") || {};
this.dependencies = this.metadata.dependencies || [];
this.parser = take("parser");
this.post = take("post");
this.pre = take("pre");
@@ -41,18 +41,6 @@ export default class Transformer {
this.handlers = this.normalize(transformer);
this.key = transformerKey;
//
if (!this.shouldVisit && !this.handlers.enter && !this.handlers.exit) {
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 {

View File

@@ -5,7 +5,8 @@
"es6.symbols": "es6.spec.symbols",
"es6.blockScopingTDZ": "es6.spec.blockScoping",
"utility.inlineExpressions": "minification.inlineExpressions",
"utility.deadCodeElimination": "minification.deadCodeElimination",
"minification.removeConsoleCalls": "utility.removeConsole",
"minification.removeDebugger": "utility.removeDebugger"
"utility.removeConsoleCalls": "minification.removeConsole",
"utility.removeDebugger": "minification.removeDebugger"
}

View File

@@ -1,10 +1,16 @@
import * as t from "../../../types";
export function MemberExpression(node) {
var prop = node.property;
if (!node.computed && t.isIdentifier(prop) && !t.isValidIdentifier(prop.name)) {
// foo.default -> foo["default"]
node.property = t.literal(prop.name);
node.computed = true;
export var metadata = {
group: "builtin-trailing"
};
export var MemberExpression = {
exit(node) {
var prop = node.property;
if (!node.computed && t.isIdentifier(prop) && !t.isValidIdentifier(prop.name)) {
// foo.default -> foo["default"]
node.property = t.literal(prop.name);
node.computed = true;
}
}
}
};

View File

@@ -1,9 +1,15 @@
import * as t from "../../../types";
export function Property(node) {
var key = node.key;
if (!node.computed && t.isIdentifier(key) && !t.isValidIdentifier(key.name)) {
// default: "bar" -> "default": "bar"
node.key = t.literal(key.name);
export var metadata = {
group: "builtin-trailing"
};
export var Property = {
exit(node) {
var key = node.key;
if (!node.computed && t.isIdentifier(key) && !t.isValidIdentifier(key.name)) {
// default: "bar" -> "default": "bar"
node.key = t.literal(key.name);
}
}
}
};

View File

@@ -1,10 +1,6 @@
import * as defineMap from "../../helpers/define-map";
import * as t from "../../../types";
export function shouldVisit(node) {
return t.isProperty(node) && (node.kind === "get" || node.kind === "set");
}
export function ObjectExpression(node, parent, scope, file) {
var mutatorMap = {};
var hasAny = false;

View File

@@ -1,7 +1,5 @@
import * as t from "../../../types";
export var shouldVisit = t.isArrowFunctionExpression;
export function ArrowFunctionExpression(node) {
t.ensureBlock(node);

View File

@@ -32,14 +32,14 @@ function isVar(node, parent) {
}
function standardizeLets(declars) {
for (var i = 0; i < declars.length; i++) {
delete declars[i]._let;
for (var declar of (declars: Array)) {
delete declar._let;
}
}
export function shouldVisit(node) {
return t.isVariableDeclaration(node) && (node.kind === "let" || node.kind === "const");
}
export var metadata = {
group: "builtin-advanced"
};
export function VariableDeclaration(node, parent, scope, file) {
if (!isLet(node, parent)) return;
@@ -109,19 +109,14 @@ function traverseReplace(node, parent, scope, remaps) {
}
var letReferenceBlockVisitor = {
enter(node, parent, scope, state) {
if (this.isFunction()) {
this.traverse(letReferenceFunctionVisitor, state);
return this.skip();
}
Function(node, parent, scope, state) {
this.traverse(letReferenceFunctionVisitor, state);
return this.skip();
}
};
var letReferenceFunctionVisitor = {
enter(node, parent, scope, state) {
// not a direct reference
if (!this.isReferencedIdentifier()) return;
ReferencedIdentifier(node, parent, scope, state) {
var ref = state.letReferences[node.name];
// not a part of our scope
@@ -159,10 +154,8 @@ var hoistVarDeclarationsVisitor = {
};
var loopLabelVisitor = {
enter(node, parent, scope, state) {
if (this.isLabeledStatement()) {
state.innerLabels.push(node.label.name);
}
LabeledStatement(node, parent, scope, state) {
state.innerLabels.push(node.label.name);
}
};
@@ -187,19 +180,28 @@ var loopNodeTo = function (node) {
};
var loopVisitor = {
Loop(node, parent, scope, state) {
var oldIgnoreLabeless = state.ignoreLabeless;
state.ignoreLabeless = true;
this.traverse(loopVisitor, state);
state.ignoreLabeless = oldIgnoreLabeless;
this.skip();
},
Function() {
this.skip();
},
SwitchCase(node, parent, scope, state) {
var oldInSwitchCase = state.inSwitchCase;
state.inSwitchCase = true;
this.traverse(loopVisitor, state);
state.inSwitchCase = oldInSwitchCase;
this.skip();
},
enter(node, parent, scope, state) {
var replace;
if (this.isLoop()) {
state.ignoreLabeless = true;
this.traverse(loopVisitor, state);
state.ignoreLabeless = false;
}
if (this.isFunction() || this.isLoop()) {
return this.skip();
}
var loopText = loopNodeTo(node);
if (loopText) {
@@ -215,6 +217,9 @@ var loopVisitor = {
// they don't refer to the actual loop we're scopifying
if (state.ignoreLabeless) return;
//
if (state.inSwitchCase) return;
// break statements mean something different in this context
if (t.isBreakStatement(node) && t.isSwitchCase(parent)) return;
}
@@ -233,6 +238,7 @@ var loopVisitor = {
if (replace) {
replace = t.returnStatement(replace);
this.skip();
return t.inherits(replace, node);
}
}
@@ -467,18 +473,17 @@ class BlockScoping {
var block = this.block;
var declarators = block._letDeclarators || [];
var declar;
//
for (let i = 0; i < declarators.length; i++) {
declar = declarators[i];
let declar = declarators[i];
extend(this.outsideLetReferences, t.getBindingIdentifiers(declar));
}
//
if (block.body) {
for (let i = 0; i < block.body.length; i++) {
declar = block.body[i];
let declar = block.body[i];
if (isLet(declar, block)) {
declarators = declarators.concat(declar.declarations);
}
@@ -487,7 +492,7 @@ class BlockScoping {
//
for (let i = 0; i < declarators.length; i++) {
declar = declarators[i];
let declar = declarators[i];
var keys = t.getBindingIdentifiers(declar);
extend(this.letReferences, keys);
this.hasLetReferences = true;
@@ -524,6 +529,7 @@ class BlockScoping {
var state = {
hasBreakContinue: false,
ignoreLabeless: false,
inSwitchCase: false,
innerLabels: [],
hasReturn: false,
isLoop: !!this.loop,

View File

@@ -11,8 +11,6 @@ import * as t from "../../../types";
const PROPERTY_COLLISION_METHOD_NAME = "__initializeProperties";
export var shouldVisit = t.isClass;
export function ClassDeclaration(node, parent, scope, file) {
return t.variableDeclaration("let", [
t.variableDeclarator(node.id, t.toExpression(node))
@@ -37,7 +35,7 @@ var collectPropertyReferencesVisitor = {
}
};
var constructorVisitor = traverse.explode({
var constructorVisitor = {
ThisExpression: {
enter(node, parent, scope, ref) {
return ref;
@@ -51,9 +49,9 @@ var constructorVisitor = traverse.explode({
}
}
}
});
};
var verifyConstructorVisitor = traverse.explode({
var verifyConstructorVisitor = {
MethodDefinition: {
enter() {
this.skip();
@@ -98,7 +96,7 @@ var verifyConstructorVisitor = traverse.explode({
}
}
}
});
};
class ClassTransformer {
@@ -481,7 +479,7 @@ class ClassTransformer {
if (node.kind === "method") {
nameMethod.property(node, this.file, path ? path.get("value").scope : this.scope);
if (this.isLoose) {
if (this.isLoose && !node.decorators) {
// use assignments instead of define properties for loose classes
var classRef = this.classRef;

View File

@@ -1,48 +1,31 @@
import * as messages from "../../../messages";
import * as t from "../../../types";
export function shouldVisit(node) {
return t.isVariableDeclaration(node, { kind: "const" }) || t.isImportDeclaration(node);
}
export function AssignmentExpression(node, parent, scope, file) {
var ids = this.getBindingIdentifiers();
var visitor = {
enter(node, parent, scope, state) {
if (this.isAssignmentExpression() || this.isUpdateExpression()) {
var ids = this.getBindingIdentifiers();
for (var name in ids) {
var id = ids[name];
for (var name in ids) {
var id = ids[name];
var binding = scope.getBinding(name);
var constant = state.constants[name];
// no binding exists
if (!binding) continue;
// no constant exists
if (!constant) continue;
// not a constant
if (binding.kind !== "const" && binding.kind !== "module") continue;
var constantIdentifier = constant.identifier;
// check if the assignment id matches the constant declaration id
// if it does then it was the id used to initially declare the
// constant so we can just ignore it
if (binding.identifier === id) continue;
// check if the assignment id matches the constant declaration id
// if it does then it was the id used to initially declare the
// constant so we can just ignore it
if (id === constantIdentifier) continue;
// check if there's been a local binding that shadows this constant
if (!scope.bindingIdentifierEquals(name, constantIdentifier)) continue;
throw state.file.errorWithNode(id, messages.get("readOnly", name));
}
} else if (this.isScope()) {
this.skip();
}
throw file.errorWithNode(id, messages.get("readOnly", name));
}
};
export function Scopable(node, parent, scope, file) {
this.traverse(visitor, {
constants: scope.getAllBindingsOfKind("const", "module"),
file: file
});
}
export { AssignmentExpression as UpdateExpression };
export function VariableDeclaration(node) {
if (node.kind === "const") node.kind = "let";
}

View File

@@ -1,7 +1,9 @@
import * as messages from "../../../messages";
import * as t from "../../../types";
export var shouldVisit = t.isPattern;
export var metadata = {
group: "builtin-advanced"
};
export function ForOfStatement(node, parent, scope, file) {
var left = node.left;
@@ -53,7 +55,7 @@ export function ForOfStatement(node, parent, scope, file) {
export { ForOfStatement as ForInStatement };
exports.Function = function (node, parent, scope, file) {
export function Func(node, parent, scope, file) {
var nodes = [];
var hasDestructuring = false;
@@ -83,8 +85,7 @@ exports.Function = function (node, parent, scope, file) {
var block = node.body;
block.body = nodes.concat(block.body);
this.checkSelf();
};
}
export function CatchClause(node, parent, scope, file) {
var pattern = node.param;
@@ -104,8 +105,6 @@ export function CatchClause(node, parent, scope, file) {
destructuring.init(pattern, ref);
node.body.body = nodes.concat(node.body.body);
this.checkSelf();
}
export function ExpressionStatement(node, parent, scope, file) {

View File

@@ -2,8 +2,6 @@ import * as messages from "../../../messages";
import * as util from "../../../util";
import * as t from "../../../types";
export var shouldVisit = t.isForOfStatement;
export function ForOfStatement(node, parent, scope, file) {
if (this.get("right").isArrayExpression()) {
return _ForOfStatementArray.call(this, node, scope, file);

View File

@@ -1,7 +1,5 @@
import * as t from "../../../types";
export { shouldVisit } from "../internal/modules";
function keepBlockHoist(node, nodes) {
if (node._blockHoist) {
for (let i = 0; i < nodes.length; i++) {
@@ -10,6 +8,10 @@ function keepBlockHoist(node, nodes) {
}
}
export var metadata = {
group: "builtin-modules"
};
export function ImportDeclaration(node, parent, scope, file) {
// flow type
if (node.isType) return;

View File

@@ -1,33 +1,20 @@
import ReplaceSupers from "../../helpers/replace-supers";
import * as t from "../../../types";
export var shouldVisit = t.isSuper;
function Property(path, node, scope, getObjectRef, file) {
if (!node.method) return;
var value = node.value;
var thisExpr = scope.generateUidIdentifier("this");
if (!node.method && node.kind === "init") return;
if (!t.isFunction(node.value)) return;
var replaceSupers = new ReplaceSupers({
topLevelThisReference: thisExpr,
getObjectRef: getObjectRef,
methodNode: node,
methodPath: path,
isStatic: true,
scope: scope,
file: file
getObjectRef: getObjectRef,
methodNode: node,
methodPath: path,
isStatic: true,
scope: scope,
file: file
});
replaceSupers.replace();
if (replaceSupers.hasSuper) {
value.body.body.unshift(
t.variableDeclaration("var", [
t.variableDeclarator(thisExpr, t.thisExpression())
])
);
}
}
export function ObjectExpression(node, parent, scope, file) {

View File

@@ -3,10 +3,6 @@ import * as util from "../../../util";
import traverse from "../../../traversal";
import * as t from "../../../types";
export function shouldVisit(node) {
return t.isFunction(node) && hasDefaults(node);
}
var hasDefaults = function (node) {
for (var i = 0; i < node.params.length; i++) {
if (!t.isIdentifier(node.params[i])) return true;
@@ -14,17 +10,19 @@ var hasDefaults = function (node) {
return false;
};
var iifeVisitor = traverse.explode({
var iifeVisitor = {
ReferencedIdentifier(node, parent, scope, state) {
if (!state.scope.hasOwnBinding(node.name)) return;
if (state.scope.bindingIdentifierEquals(node.name, node)) return;
if (node.name !== "eval") {
if (!state.scope.hasOwnBinding(node.name)) return;
if (state.scope.bindingIdentifierEquals(node.name, node)) return;
}
state.iife = true;
this.stop();
}
});
};
exports.Function = function (node, parent, scope, file) {
export function Func(node, parent, scope, file) {
if (!hasDefaults(node)) return;
t.ensureBlock(node);
@@ -96,6 +94,4 @@ exports.Function = function (node, parent, scope, file) {
} else {
node.body.body = body.concat(node.body.body);
}
this.checkSelf();
};
}

View File

@@ -2,8 +2,6 @@ import isNumber from "lodash/lang/isNumber";
import * as util from "../../../util";
import * as t from "../../../types";
export var shouldVisit = t.isRestElement;
var memberExpressionOptimisationVisitor = {
enter(node, parent, scope, state) {
// check if this scope has a local binding that will shadow the rest parameter
@@ -55,7 +53,7 @@ var hasRest = function (node) {
return t.isRestElement(node.params[node.params.length - 1]);
};
exports.Function = function (node, parent, scope, file) {
export function Func(node, parent, scope, file) {
if (!hasRest(node)) return;
var rest = node.params.pop().argument;
@@ -96,7 +94,6 @@ exports.Function = function (node, parent, scope, file) {
candidate.replaceWith(argsId);
optimizeMemberExpression(candidate.parent, node.params.length);
}
this.checkSelf();
return;
}
@@ -138,5 +135,4 @@ exports.Function = function (node, parent, scope, file) {
});
loop._blockHoist = node.params.length + 1;
node.body.body.unshift(loop);
this.checkSelf();
};
}

View File

@@ -63,42 +63,40 @@ function spec(node, body, objId, initProps, file) {
}
}
export function shouldVisit(node) {
return t.isProperty(node) && node.computed;
}
export var ObjectExpression = {
exit(node, parent, scope, file) {
var hasComputed = false;
export function ObjectExpression(node, parent, scope, file) {
var hasComputed = false;
for (var prop of (node.properties: Array)) {
hasComputed = t.isProperty(prop, { computed: true, kind: "init" });
if (hasComputed) break;
}
for (var i = 0; i < node.properties.length; i++) {
hasComputed = t.isProperty(node.properties[i], { computed: true, kind: "init" });
if (hasComputed) break;
if (!hasComputed) return;
var initProps = [];
var objId = scope.generateUidBasedOnNode(parent);
//
var body = [];
//
var callback = spec;
if (file.isLoose("es6.properties.computed")) callback = loose;
var result = callback(node, body, objId, initProps, file);
if (result) return result;
//
body.unshift(t.variableDeclaration("var", [
t.variableDeclarator(objId, t.objectExpression(initProps))
]));
body.push(t.expressionStatement(objId));
return body;
}
if (!hasComputed) return;
var initProps = [];
var objId = scope.generateUidBasedOnNode(parent);
//
var body = [];
//
var callback = spec;
if (file.isLoose("es6.properties.computed")) callback = loose;
var result = callback(node, body, objId, initProps, file);
if (result) return result;
//
body.unshift(t.variableDeclaration("var", [
t.variableDeclarator(objId, t.objectExpression(initProps))
]));
body.push(t.expressionStatement(objId));
return body;
}
};

View File

@@ -1,9 +1,3 @@
import * as t from "../../../types";
export function shouldVisit(node) {
return t.isProperty(node) && (node.method || node.shorthand);
}
export function Property(node) {
if (node.method) {
node.method = false;
@@ -11,6 +5,5 @@ export function Property(node) {
if (node.shorthand) {
node.shorthand = false;
node.key = t.removeComments(t.clone(node.key));
}
}

View File

@@ -1,10 +1,6 @@
import * as regex from "../../helpers/regex";
import * as t from "../../../types";
export function shouldVisit(node) {
return regex.is(node, "y");
}
export function Literal(node) {
if (!regex.is(node, "y")) return;
return t.newExpression(t.identifier("RegExp"), [

View File

@@ -1,10 +1,6 @@
import rewritePattern from "regexpu/rewrite-pattern";
import * as regex from "../../helpers/regex";
export function shouldVisit(node) {
return regex.is(node, "u");
}
export function Literal(node) {
if (!regex.is(node, "u")) return;
node.regex.pattern = rewritePattern(node.regex.pattern, node.regex.flags);

View File

@@ -1,7 +1,7 @@
import traverse from "../../../traversal";
import * as t from "../../../types";
var visitor = traverse.explode({
var visitor = {
ReferencedIdentifier(node, parent, scope, state) {
if (t.isFor(parent) && parent.left === node) return;
@@ -25,20 +25,23 @@ var visitor = traverse.explode({
return t.logicalExpression("&&", assert, node);
}
}
});
export var metadata = {
optional: true
};
export function BlockStatement(node, parent, scope, file) {
var letRefs = node._letReferences;
if (!letRefs) return;
export var metadata = {
optional: true,
group: "builtin-advanced"
};
this.traverse(visitor, {
letRefs: letRefs,
file: file
});
}
export var BlockStatement = {
exit(node, parent, scope, file) {
var letRefs = node._letReferences;
if (!letRefs) return;
this.traverse(visitor, {
letRefs: letRefs,
file: file
});
}
};
export { BlockStatement as Program, BlockStatement as Loop };

View File

@@ -44,8 +44,6 @@ function build(props, scope) {
return nodes;
}
export var shouldVisit = t.isSpreadElement;
export function ArrayExpression(node, parent, scope) {
var elements = node.elements;
if (!hasSpread(elements)) return;

View File

@@ -6,18 +6,21 @@ import * as util from "../../../util";
import map from "lodash/collection/map";
import * as t from "../../../types";
exports.Function = function (node, parent, scope, file) {
export var metadata = {
group: "builtin-trailing"
};
export function Func(node, parent, scope, file) {
if (node.generator || node.async) return;
var tailCall = new TailCallTransformer(this, scope, file);
tailCall.run();
};
}
function returnBlock(expr) {
return t.blockStatement([t.returnStatement(expr)]);
}
// looks for and replaces tail recursion calls
var firstPass = traverse.explode({
var visitor = {
enter(node, parent, scope, state) {
if (t.isTryStatement(parent)) {
if (node === parent.block) {
@@ -29,7 +32,6 @@ var firstPass = traverse.explode({
},
ReturnStatement(node, parent, scope, state) {
this.skip();
return state.subTransform(node.argument);
},
@@ -38,61 +40,35 @@ var firstPass = traverse.explode({
},
VariableDeclaration(node, parent, scope, state) {
this.skip();
state.vars.push(node);
}
});
},
// hoists up function declarations, replaces `this` and `arguments` and marks
// them as needed
var secondPass = traverse.explode({
ThisExpression(node, parent, scope, state) {
state.needsThis = true;
return state.getThisId();
state.thisPaths.push(this);
},
ReferencedIdentifier(node, parent, scope, state) {
if (node.name !== "arguments") return;
state.needsArguments = true;
return state.getArgumentsId();
},
Function(node, parent, scope, state) {
this.skip();
if (this.isFunctionDeclaration()) {
node = t.variableDeclaration("var", [
t.variableDeclarator(node.id, t.toExpression(node))
]);
node._blockHoist = 2;
return node;
if (node.name === "arguments") {
state.needsArguments = true;
state.argumentsPaths.push(this);
}
}
});
// optimizes recursion by removing `this` and `arguments` if they aren't used
var thirdPass = traverse.explode({
ExpressionStatement(node, parent, scope, state) {
var expr = node.expression;
if (!t.isAssignmentExpression(expr)) return;
if (!state.needsThis && expr.left === state.getThisId()) {
this.remove();
} else if (!state.needsArguments && expr.left === state.getArgumentsId() && t.isArrayExpression(expr.right)) {
return map(expr.right.elements, function (elem) {
return t.expressionStatement(elem);
});
}
}
});
};
class TailCallTransformer {
constructor(path, scope, file) {
this.hasTailRecursion = false;
this.needsArguments = false;
this.setsArguments = false;
this.needsThis = false;
this.ownerId = path.node.id;
this.vars = [];
this.needsArguments = false;
this.argumentsPaths = [];
this.setsArguments = false;
this.needsThis = false;
this.thisPaths = [];
this.ownerId = path.node.id;
this.vars = [];
this.scope = scope;
this.path = path;
@@ -158,10 +134,12 @@ class TailCallTransformer {
if (!ownerId) return;
// traverse the function and look for tail recursion
this.path.traverse(firstPass, this);
this.path.traverse(visitor, this);
// has no tail call recursion
if (!this.hasTailRecursion) return;
// the function binding isn't constant so we can't be sure that it's the same function :(
if (this.hasDeopt()) {
this.file.log.deopt(node, messages.get("tailCallReassignmentDeopt"));
return;
@@ -169,21 +147,27 @@ class TailCallTransformer {
//
this.path.traverse(secondPass, this);
if (!this.needsThis || !this.needsArguments) {
this.path.traverse(thirdPass, this);
}
var body = t.ensureBlock(node).body;
for (var i = 0; i < body.length; i++) {
var bodyNode = body[i];
if (!t.isFunctionDeclaration(bodyNode)) continue;
bodyNode = body[i] = t.variableDeclaration("var", [
t.variableDeclarator(bodyNode.id, t.toExpression(bodyNode))
]);
bodyNode._blockHoist = 2;
}
if (this.vars.length > 0) {
var declarations = flatten(map(this.vars, function (decl) {
return decl.declarations;
}));
var assignment = reduceRight(declarations, function (expr, decl) {
return t.assignmentExpression("=", decl.id, expr);
}, t.identifier("undefined"));
var statement = t.expressionStatement(assignment);
statement._blockHoist = Infinity;
body.unshift(statement);
@@ -191,7 +175,9 @@ class TailCallTransformer {
var paramDecls = this.paramDecls;
if (paramDecls.length > 0) {
body.unshift(t.variableDeclaration("var", paramDecls));
var paramDecl = t.variableDeclaration("var", paramDecls);
paramDecl._blockHoist = Infinity;
body.unshift(paramDecl);
}
body.unshift(t.expressionStatement(
@@ -199,22 +185,28 @@ class TailCallTransformer {
);
node.body = util.template("tail-call-body", {
AGAIN_ID: this.getAgainId(),
THIS_ID: this.thisId,
ARGUMENTS_ID: this.argumentsId,
FUNCTION_ID: this.getFunctionId(),
BLOCK: node.body
FUNCTION_ID: this.getFunctionId(),
AGAIN_ID: this.getAgainId(),
BLOCK: node.body
});
var topVars = [];
if (this.needsThis) {
for (var path of (this.thisPaths: Array)) {
path.replaceWith(this.getThisId());
}
topVars.push(t.variableDeclarator(this.getThisId(), t.thisExpression()));
}
if (this.needsArguments || this.setsArguments) {
var decl = t.variableDeclarator(this.getArgumentsId());
if (this.needsArguments) {
for (var path of (this.argumentsPaths: Array)) {
path.replaceWith(this.argumentsId);
}
var decl = t.variableDeclarator(this.argumentsId);
if (this.argumentsId) {
decl.init = t.identifier("arguments");
}
topVars.push(decl);
@@ -327,7 +319,7 @@ class TailCallTransformer {
var body = [];
if (!t.isThisExpression(thisBinding)) {
if (this.needsThis && !t.isThisExpression(thisBinding)) {
body.push(t.expressionStatement(t.assignmentExpression(
"=",
this.getThisId(),
@@ -340,29 +332,35 @@ class TailCallTransformer {
}
var argumentsId = this.getArgumentsId();
var params = this.getParams();
var params = this.getParams();
body.push(t.expressionStatement(t.assignmentExpression(
"=",
argumentsId,
args
)));
var i, param;
if (this.needsArguments) {
body.push(t.expressionStatement(t.assignmentExpression(
"=",
argumentsId,
args
)));
}
if (t.isArrayExpression(args)) {
var elems = args.elements;
for (i = 0; i < elems.length && i < params.length; i++) {
param = params[i];
for (let i = 0; i < elems.length && i < params.length; i++) {
let param = params[i];
var elem = elems[i] || (elems[i] = t.identifier("undefined"));
if (!param._isDefaultPlaceholder) {
elems[i] = t.assignmentExpression("=", param, elem);
}
}
if (!this.needsArguments) {
for (var elem of (elems: Array)) {
body.push(t.expressionStatement(elem));
}
}
} else {
this.setsArguments = true;
for (i = 0; i < params.length; i++) {
param = params[i];
for (let i = 0; i < params.length; i++) {
let param = params[i];
if (!param._isDefaultPlaceholder) {
body.push(t.expressionStatement(t.assignmentExpression(
"=",
@@ -376,6 +374,7 @@ class TailCallTransformer {
body.push(t.expressionStatement(
t.assignmentExpression("=", this.getAgainId(), t.literal(true))
));
body.push(t.continueStatement(this.getFunctionId()));
return body;

View File

@@ -4,10 +4,6 @@ var buildBinaryExpression = function (left, right) {
return t.binaryExpression("+", left, right);
};
export function shouldVisit(node) {
return t.isTemplateLiteral(node) || t.isTaggedTemplateExpression(node);
}
export function TaggedTemplateExpression(node, parent, scope, file) {
var quasi = node.quasi;
var args = [];

View File

@@ -1,7 +1,3 @@
export var metadata = {
stage: 1
};
export function shouldVisit() {
return false;
}

View File

@@ -1,7 +1,4 @@
export var metadata = {
stage: 0
stage: 0,
dependencies: ["es6.classes"]
};
export function shouldVisit() {
return false;
}

View File

@@ -3,14 +3,11 @@ import * as defineMap from "../../helpers/define-map";
import * as t from "../../../types";
export var metadata = {
dependencies: ["es6.classes"],
optional: true,
stage: 1
};
export function shouldVisit(node) {
return !!node.decorators;
}
export function ObjectExpression(node, parent, scope, file) {
var hasDecorators = false;
for (var i = 0; i < node.properties.length; i++) {

View File

@@ -5,8 +5,6 @@ export var metadata = {
stage: 0
};
export var shouldVisit = t.isDoExpression;
export function DoExpression(node) {
var body = node.body.body;
if (body.length) {

View File

@@ -9,10 +9,20 @@ export var metadata = {
var MATH_POW = t.memberExpression(t.identifier("Math"), t.identifier("pow"));
build(exports, {
var {
ExpressionStatement,
AssignmentExpression,
BinaryExpression
} = build({
operator: "**",
build(left, right) {
return t.callExpression(MATH_POW, [left, right]);
}
});
export {
ExpressionStatement,
AssignmentExpression,
BinaryExpression
};

View File

@@ -6,10 +6,6 @@ export var metadata = {
stage: 1
};
export function shouldVisit(node) {
return t.isExportDefaultSpecifier(node) || t.isExportNamespaceSpecifier(node);
}
function build(node, nodes, scope) {
var first = node.specifiers[0];
if (!t.isExportNamespaceSpecifier(first) && !t.isExportDefaultSpecifier(first)) return;

View File

@@ -3,13 +3,10 @@
import * as t from "../../../types";
export var metadata = {
stage: 1
stage: 1,
dependencies: ["es6.destructuring"]
};
export function manipulateOptions(opts) {
if (opts.whitelist) opts.whitelist.push("es6.destructuring");
}
var hasSpread = function (node) {
for (var i = 0; i < node.properties.length; i++) {
if (t.isSpreadProperty(node.properties[i])) {

View File

@@ -1,7 +1,3 @@
export var metadata = {
stage: 1
};
export function shouldVisit() {
return false;
}

View File

@@ -1,124 +1,85 @@
export default {
"utility.removeDebugger": require("./utility/remove-debugger"),
"utility.removeConsole": require("./utility/remove-console"),
//- builtin-setup
_explode: require("./internal/explode"),
_validation: require("./internal/validation"),
_hoistDirectives: require("./internal/hoist-directives"),
"minification.removeDebugger": require("./minification/remove-debugger"),
"minification.removeConsole": require("./minification/remove-console"),
"utility.inlineEnvironmentVariables": require("./utility/inline-environment-variables"),
"utility.inlineExpressions": require("./utility/inline-expressions"),
"minification.inlineExpressions": require("./minification/inline-expressions"),
"minification.deadCodeElimination": require("./minification/dead-code-elimination"),
_modules: require("./internal/modules"),
"spec.functionName": require("./spec/function-name"),
//- builtin-basic
// this is where the bulk of the ES6 transformations take place, none of them require traversal state
// so they can all be concatenated together for performance
"es7.classProperties": require("./es7/class-properties"),
"es7.trailingFunctionCommas": require("./es7/trailing-function-commas"),
"es7.asyncFunctions": require("./es7/async-functions"),
"es7.decorators": require("./es7/decorators"),
strict: require("./other/strict"),
_validation: require("./internal/validation"),
"validation.undeclaredVariableCheck": require("./validation/undeclared-variable-check"),
"validation.react": require("./validation/react"),
// this goes at the start so we only transform the original user code
"spec.functionName": require("./spec/function-name"),
// needs to be before `_shadowFunctions`
"es6.arrowFunctions": require("./es6/arrow-functions"),
"spec.blockScopedFunctions": require("./spec/block-scoped-functions"),
"optimisation.react.constantElements": require("./optimisation/react.constant-elements"),
"optimisation.react.inlineElements": require("./optimisation/react.inline-elements"),
reactCompat: require("./other/react-compat"),
react: require("./other/react"),
// needs to be before `regenerator` due to generator comprehensions
// needs to be before `_shadowFunctions`
"es7.comprehensions": require("./es7/comprehensions"),
"es6.classes": require("./es6/classes"),
asyncToGenerator: require("./other/async-to-generator"),
bluebirdCoroutines: require("./other/bluebird-coroutines"),
"es6.objectSuper": require("./es6/object-super"),
"es7.objectRestSpread": require("./es7/object-rest-spread"),
"es7.exponentiationOperator": require("./es7/exponentiation-operator"),
"es6.spec.templateLiterals": require("./es6/spec.template-literals"),
"es6.templateLiterals": require("./es6/template-literals"),
"es5.properties.mutators": require("./es5/properties.mutators"),
"es6.properties.shorthand": require("./es6/properties.shorthand"),
// needs to be before `_shadowFunctions` due to define property closure
"es6.properties.computed": require("./es6/properties.computed"),
"optimisation.flow.forOf": require("./optimisation/flow.for-of"),
"es6.forOf": require("./es6/for-of"),
"es6.regex.sticky": require("./es6/regex.sticky"),
"es6.regex.unicode": require("./es6/regex.unicode"),
"es6.constants": require("./es6/constants"),
// needs to be before `es6.parameters.default` as default parameters will destroy the rest param
"es6.parameters.rest": require("./es6/parameters.rest"),
// needs to be after `es6.parameters.rest` as we use `toArray` and avoid turning an already known array into one
"es6.spread": require("./es6/spread"),
// needs to be before `es6.blockScoping` as default parameters have a TDZ
"es6.parameters.default": require("./es6/parameters.default"),
"es7.exportExtensions": require("./es7/export-extensions"),
"spec.protoToAssign": require("./spec/proto-to-assign"),
"es7.doExpressions": require("./es7/do-expressions"),
"es6.spec.symbols": require("./es6/spec.symbols"),
"spec.undefinedToVoid": require("./spec/undefined-to-void"),
jscript: require("./other/jscript"),
flow: require("./other/flow"),
// needs to be before `es6.blockScoping` as let variables may be produced
//- builtin-advanced
"es6.destructuring": require("./es6/destructuring"),
// needs to be before `_shadowFunctions` due to block scopes sometimes being wrapped in a
// closure
"es6.blockScoping": require("./es6/block-scoping"),
// needs to be after `es6.blockScoping` due to needing `letReferences` set on blocks
"es6.spec.blockScoping": require("./es6/spec.block-scoping"),
// needs to be after `es6.parameters.*` and `es6.blockScoping` due to needing pure
// identifiers in parameters and variable declarators
"es6.tailCall": require("./es6/tail-call"),
// es6 syntax transformation is **forbidden** past this point since regenerator will chuck a massive
// hissy fit
//- regenerator
regenerator: require("./other/regenerator"),
// needs to be after `regenerator` due to needing `regeneratorRuntime` references
// needs to be after `es6.forOf` due to needing `Symbol.iterator` references
// needs to be before `es6.modules` due to dynamic imports
runtime: require("./other/runtime"),
// needs to be before `_blockHoist` due to function hoisting etc
"es7.exportExtensions": require("./es7/export-extensions"),
//- builtin-modules
runtime: require("./other/runtime"),
"es6.modules": require("./es6/modules"),
_blockHoist: require("./internal/block-hoist"),
"spec.protoToAssign": require("./spec/proto-to-assign"),
_shadowFunctions: require("./internal/shadow-functions"),
"es7.doExpressions": require("./es7/do-expressions"),
"es6.spec.symbols": require("./es6/spec.symbols"),
ludicrous: require("./other/ludicrous"),
"spec.undefinedToVoid": require("./spec/undefined-to-void"),
_strict: require("./internal/strict"),
_moduleFormatter: require("./internal/module-formatter"),
//- builtin-trailing
// these clean up the output and do finishing up transformations, it's important to note that by this
// stage you can't import any new modules or insert new ES6 as all those transformers have already
// been ran
"es6.tailCall": require("./es6/tail-call"),
_shadowFunctions: require("./internal/shadow-functions"),
"es3.propertyLiterals": require("./es3/property-literals"),
"es3.memberExpressionLiterals": require("./es3/member-expression-literals"),
"minification.memberExpressionLiterals": require("./minification/member-expression-literals"),
"minification.propertyLiterals": require("./minification/property-literals"),
jscript: require("./other/jscript"),
flow: require("./other/flow")
_blockHoist: require("./internal/block-hoist"),
};

View File

@@ -1,5 +1,9 @@
import sortBy from "lodash/collection/sortBy";
export var metadata = {
group: "builtin-trailing"
};
// Priority:
//
// - 0 We want this to be at the **very** bottom

View File

@@ -0,0 +1,30 @@
import clone from "lodash/lang/clone";
import * as t from "../../../types";
export var metadata = {
group: "builtin-setup"
};
function buildClone(bindingKey, refKey) {
return function (node) {
if (node[bindingKey] === node[refKey]) {
node[refKey] = t.removeComments(clone(node[refKey]));
}
};
}
function buildListClone(listKey, bindingKey, refKey) {
var clone = buildClone(bindingKey, refKey);
return function (node) {
if (!node[listKey]) return;
for (var subNode of (node[listKey]: Array)) {
clone(subNode);
}
};
}
export var Property = buildClone("value", "key");
export var ExportDeclaration = buildListClone("specifiers", "local", "exported");
export var ImportDeclaration = buildListClone("specifiers", "local", "imported");

View File

@@ -0,0 +1,20 @@
import * as t from "../../../types";
export var metadata = {
group: "builtin-setup"
};
export var BlockStatement = {
exit(node) {
for (var i = 0; i < node.body.length; i++) {
var bodyNode = node.body[i];
if (t.isExpressionStatement(bodyNode) && t.isLiteral(bodyNode.expression)) {
bodyNode._blockHoist = Infinity;
} else {
return;
}
}
}
};
export { BlockStatement as Program };

View File

@@ -1,15 +1,24 @@
import * as strict from "../../helpers/strict";
export function Program(program, parent, scope, file) {
this.stop();
export var metadata = {
group: "builtin-modules"
};
strict.wrap(program, function () {
program.body = file.dynamicImports.concat(program.body);
});
export var Program = {
exit(program, parent, scope, file) {
strict.wrap(program, function () {
// ensure that these are at the top, just like normal imports
for (var node of (file.dynamicImports: Array)) {
node._blockHoist = 3;
}
if (!file.transformers["es6.modules"].canTransform()) return;
program.body = file.dynamicImports.concat(program.body);
});
if (file.moduleFormatter.transform) {
file.moduleFormatter.transform(program);
if (!file.transformers["es6.modules"].canTransform()) return;
if (file.moduleFormatter.transform) {
file.moduleFormatter.transform(program);
}
}
}
};

View File

@@ -4,11 +4,12 @@
// a generator function as a default then regenerator will destroy the export
// declaration and leave a variable declaration in it's place... yeah, handy.
import clone from "lodash/lang/clone";
import * as t from "../../../types";
export function shouldVisit(node) {
return t.isImportDeclaration(node) || t.isExportDeclaration(node);
}
export var metadata = {
group: "builtin-setup"
};
export function ImportDeclaration(node, parent, scope, file) {
if (node.source) {
@@ -48,6 +49,10 @@ export function ExportDefaultDeclaration(node, parent, scope) {
}
}
function buildExportSpecifier(id) {
return t.exportSpecifier(clone(id), clone(id));
}
export function ExportNamedDeclaration(node, parent, scope) {
ImportDeclaration.apply(this, arguments);
@@ -60,12 +65,12 @@ export function ExportNamedDeclaration(node, parent, scope) {
if (t.isClassDeclaration(declar)) {
// export class Foo {}
node.specifiers = [t.exportSpecifier(declar.id, declar.id)];
node.specifiers = [buildExportSpecifier(declar.id)];
node.declaration = null;
return [getDeclar(), node];
} else if (t.isFunctionDeclaration(declar)) {
// export function Foo() {}
node.specifiers = [t.exportSpecifier(declar.id, declar.id)];
node.specifiers = [buildExportSpecifier(declar.id)];
node.declaration = null;
node._blockHoist = 2;
return [getDeclar(), node];
@@ -74,8 +79,7 @@ export function ExportNamedDeclaration(node, parent, scope) {
var specifiers = [];
var bindings = this.get("declaration").getBindingIdentifiers();
for (var key in bindings) {
var id = bindings[key];
specifiers.push(t.exportSpecifier(id, id));
specifiers.push(buildExportSpecifier(bindings[key]));
}
return [declar, t.exportNamedDeclaration(null, specifiers)];
}

View File

@@ -1,102 +1,33 @@
import * as t from "../../../types";
var functionChildrenVisitor = {
enter(node, parent, scope, state) {
if (this.isClass(node)) {
return this.skip();
}
if (this.isFunction() && !node.shadow) {
return this.skip();
}
if (node._shadowedFunctionLiteral) return this.skip();
var getId;
if (this.isIdentifier() && node.name === "arguments") {
getId = state.getArgumentsId;
} else if (this.isThisExpression()) {
getId = state.getThisId;
} else {
return;
}
if (this.isReferenced()) return getId();
}
export var metadata = {
group: "builtin-trailing"
};
var functionVisitor = {
enter(node, parent, scope, state) {
if (!node.shadow) {
if (this.isFunction()) {
// stop traversal of this node as it'll be hit again by this transformer
return this.skip();
} else {
return;
}
}
function remap(path, key, create) {
// ensure that we're shadowed
if (!path.inShadow()) return;
// traverse all child nodes of this function and find `arguments` and `this`
this.traverse(functionChildrenVisitor, state);
var fnPath = path.findParent((node, path) => !node.shadow && (path.isFunction() || path.isProgram()));
node.shadow = false;
var cached = fnPath.getData(key);
if (cached) return cached;
return this.skip();
}
};
var init = create();
var id = path.scope.generateUidIdentifier(key);
function aliasFunction(getBody, path, scope) {
var argumentsId;
var thisId;
fnPath.setData(key, id);
fnPath.scope.push({ id, init });
var state = {
getArgumentsId() {
return argumentsId = argumentsId || scope.generateUidIdentifier("arguments");
},
getThisId() {
return thisId = thisId || scope.generateUidIdentifier("this");
}
};
// traverse the function and find all alias functions so we can alias
// `arguments` and `this` if necessary
path.traverse(functionVisitor, state);
var body;
var pushDeclaration = function (id, init) {
body = body || getBody();
body.unshift(t.variableDeclaration("var", [
t.variableDeclarator(id, init)
]));
};
if (argumentsId) {
pushDeclaration(argumentsId, t.identifier("arguments"));
}
if (thisId) {
pushDeclaration(thisId, t.thisExpression());
}
};
export function shouldVisit(node) {
return true;
return id;
}
export function Program(node, parent, scope) {
aliasFunction(function () {
return node.body;
}, this, scope);
};
export function FunctionDeclaration(node, parent, scope) {
aliasFunction(function () {
t.ensureBlock(node);
return node.body.body;
}, this, scope);
export function ThisExpression() {
return remap(this, "this", () => t.thisExpression());
}
export { FunctionDeclaration as FunctionExpression };
export function ReferencedIdentifier(node) {
if (node.name === "arguments" && !node._shadowedFunctionLiteral) {
return remap(this, "arguments", () => t.identifier("arguments"));
}
}

View File

@@ -1,18 +0,0 @@
import * as t from "../../../types";
export function Program(program, parent, scope, file) {
if (file.transformers.strict.canTransform()) {
var directive = file.get("existingStrictDirective");
if (!directive) {
directive = t.expressionStatement(t.literal("use strict"));
var first = program.body[0];
if (first) {
directive.leadingComments = first.leadingComments;
first.leadingComments = [];
}
}
this.unshiftContainer("body", [directive]);
}
}

View File

@@ -2,7 +2,7 @@ import * as messages from "../../../messages";
import * as t from "../../../types";
export var metadata = {
readOnly: true
group: "builtin-setup"
};
export function ForOfStatement(node, parent, scope, file) {
@@ -43,16 +43,3 @@ export function Property(node, parent, scope, file) {
}
}
}
export function BlockStatement(node) {
for (var i = 0; i < node.body.length; i++) {
var bodyNode = node.body[i];
if (t.isExpressionStatement(bodyNode) && t.isLiteral(bodyNode.expression)) {
bodyNode._blockHoist = Infinity;
} else {
return;
}
}
}
export { BlockStatement as Program };

View File

@@ -18,7 +18,8 @@ function toStatements(node) {
}
export var metadata = {
optional: true
optional: true,
group: "builtin-setup"
};
export function Identifier(node, parent, scope) {
@@ -26,6 +27,7 @@ export function Identifier(node, parent, scope) {
var binding = scope.getBinding(node.name);
if (!binding || binding.references > 1 || !binding.constant) return;
if (binding.kind === "param") return;
var replacement = binding.path.node;
if (t.isVariableDeclarator(replacement)) {

View File

@@ -1,7 +1,8 @@
import * as t from "../../../types";
export var metadata = {
optional: true
optional: true,
group: "builtin-setup"
};
export function Expression(node, parent, scope) {

View File

@@ -1,14 +1,17 @@
import * as t from "../../../types";
export var metadata = {
optional: true
optional: true,
group: "builtin-trailing"
};
export function MemberExpression(node) {
var prop = node.property;
if (node.computed && t.isLiteral(prop) && t.isValidIdentifier(prop.value)) {
// foo["bar"] => foo.bar
node.property = t.identifier(prop.value);
node.computed = false;
export var MemberExpression = {
exit(node) {
var prop = node.property;
if (node.computed && t.isLiteral(prop) && t.isValidIdentifier(prop.value)) {
// foo["bar"] => foo.bar
node.property = t.identifier(prop.value);
node.computed = false;
}
}
}
};

View File

@@ -1,14 +1,17 @@
import * as t from "../../../types";
export var metadata = {
optional: true
optional: true,
group: "builtin-trailing"
};
export function Property(node) {
var key = node.key;
if (t.isLiteral(key) && t.isValidIdentifier(key.value)) {
// "foo": "bar" -> foo: "bar"
node.key = t.identifier(key.value);
node.computed = false;
export var Property = {
exit(node) {
var key = node.key;
if (t.isLiteral(key) && t.isValidIdentifier(key.value)) {
// "foo": "bar" -> foo: "bar"
node.key = t.identifier(key.value);
node.computed = false;
}
}
}
};

View File

@@ -1,7 +1,8 @@
import * as t from "../../../types";
export var metadata = {
optional: true
optional: true,
group: "builtin-setup"
};
export function CallExpression(node, parent) {

View File

@@ -1,7 +1,8 @@
import * as t from "../../../types";
export var metadata = {
optional: true
optional: true,
group: "builtin-setup"
};
export function ExpressionStatement(node) {

View File

@@ -1,7 +1,6 @@
import { _ForOfStatementArray } from "../es6/for-of";
import * as t from "../../../types";
export var shouldVisit = t.isForOfStatement;
export var metadata = {
optional: true
};

View File

@@ -3,11 +3,12 @@ import remapAsyncToGenerator from "../../helpers/remap-async-to-generator";
export { manipulateOptions } from "./bluebird-coroutines";
export var metadata = {
optional: true
optional: true,
dependencies: ["es7.asyncFunctions", "es6.classes"]
};
exports.Function = function (node, parent, scope, file) {
export function Func(node, parent, scope, file) {
if (!node.async || node.generator) return;
return remapAsyncToGenerator(node, file.addHelper("async-to-generator"), scope);
};
}

View File

@@ -2,15 +2,15 @@ import remapAsyncToGenerator from "../../helpers/remap-async-to-generator";
import * as t from "../../../types";
export function manipulateOptions(opts) {
opts.optional.push("es7.asyncFunctions");
opts.blacklist.push("regenerator");
}
export var metadata = {
optional: true
optional: true,
dependencies: ["es7.asyncFunctions", "es6.classes"]
};
exports.Function = function (node, parent, scope, file) {
export function Func(node, parent, scope, file) {
if (!node.async || node.generator) return;
return remapAsyncToGenerator(
@@ -18,4 +18,4 @@ exports.Function = function (node, parent, scope, file) {
t.memberExpression(file.addImport("bluebird", null, "absolute"), t.identifier("coroutine")),
scope
);
};
}

View File

@@ -1,28 +1,23 @@
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();
}
export function ClassProperty(node) {
node.typeAnnotation = null;
if (!node.value) this.remove();
}
export function Class(node) {
node.implements = null;
}
exports.Function = function (node) {
export function Func(node) {
for (var i = 0; i < node.params.length; i++) {
var param = node.params[i];
param.optional = false;
}
};
}
export function TypeCastExpression(node) {
return node.expression;

View File

@@ -1,66 +0,0 @@
import * as t from "../../../types";
import * as util from "../../../util";
export var metadata = {
optional: true
};
// foo in bar
export function BinaryExpression(node) {
if (node.operator === "in") {
return util.template("ludicrous-in", {
LEFT: node.left,
RIGHT: node.right
});
}
}
// { 1: "foo" }
export function Property(node) {
var key = node.key;
if (t.isLiteral(key) && typeof key.value === "number") {
key.value = "" + key.value;
}
}
// /foobar/g
export function Literal(node) {
if (node.regex) {
node.regex.pattern = "foobar";
node.regex.flags = "";
}
}
// foo.bar
export function MemberExpression(node) {
}
// Object.setPrototypeOf
// Object.preventExtensions
// Object.keys
// Object.isExtensible
// Object.getOwnPropertyDescriptor
// Object.defineProperty
export function CallExpression(node) {
}
// delete foo.bar
export function UnaryExpression(node) {
}
// foo.bar = bar;
export function AssignmentExpression(node) {
}
// new Proxy
export function NewExpression(node, parent, scope, file) {
if (this.get("callee").isIdentifier({ name: "Proxy" })) {
return t.callExpression(file.addHelper("proxy-create"), [node.arguments[0], file.addHelper("proxy-directory")]);
} else {
// possible proxy constructor
}
}

View File

@@ -1,14 +1,10 @@
import regenerator from "regenerator";
import * as t from "../../../types";
export function shouldVisit(node) {
return t.isFunction(node) && (node.async || node.generator);
}
export var Program = {
enter(ast) {
regenerator.transform(ast);
this.stop();
this.checkSelf();
}
export var metadata = {
group: "regenerator"
};
export function Program(ast) {
regenerator.transform(ast);
}

View File

@@ -9,98 +9,12 @@ var isSymbolIterator = t.buildMatchMemberExpression("Symbol.iterator");
const RUNTIME_MODULE_NAME = "babel-runtime";
var astVisitor = traverse.explode({
Identifier(node, parent, scope, file) {
if (!this.isReferenced()) return;
if (t.isMemberExpression(parent)) return;
if (!has(definitions.builtins, node.name)) return;
if (scope.getBindingIdentifier(node.name)) return;
// Symbol() -> _core.Symbol(); new Promise -> new _core.Promise
var modulePath = definitions.builtins[node.name];
return file.addImport(`${RUNTIME_MODULE_NAME}/core-js/${modulePath}`, node.name, "absoluteDefault");
},
CallExpression(node, parent, scope, file) {
// arr[Symbol.iterator]() -> _core.$for.getIterator(arr)
var callee = node.callee;
if (node.arguments.length) return;
if (!t.isMemberExpression(callee)) return;
if (!callee.computed) return;
var prop = callee.property;
if (!isSymbolIterator(prop)) return;
return t.callExpression(file.addImport(`${RUNTIME_MODULE_NAME}/core-js/get-iterator`, "getIterator", "absoluteDefault"), [callee.object]);
},
BinaryExpression(node, parent, scope, file) {
// Symbol.iterator in arr -> core.$for.isIterable(arr)
if (node.operator !== "in") return;
var left = node.left;
if (!isSymbolIterator(left)) return;
return t.callExpression(
file.addImport(`${RUNTIME_MODULE_NAME}/core-js/is-iterable`, "isIterable", "absoluteDefault"),
[node.right]
);
},
MemberExpression: {
enter(node, parent, scope, file) {
// Array.from -> _core.Array.from
if (!this.isReferenced()) return;
var obj = node.object;
var prop = node.property;
if (!t.isReferenced(obj, node)) return;
if (node.computed) return;
if (!has(definitions.methods, obj.name)) return;
var methods = definitions.methods[obj.name];
if (!has(methods, prop.name)) return;
if (scope.getBindingIdentifier(obj.name)) return;
var modulePath = methods[prop.name];
return file.addImport(`${RUNTIME_MODULE_NAME}/core-js/${modulePath}`, `${obj.name}$${prop.name}`, "absoluteDefault");
},
exit(node, parent, scope, file) {
if (!this.isReferenced()) return;
var prop = node.property;
var obj = node.object;
if (!has(definitions.builtins, obj.name)) return;
if (scope.getBindingIdentifier(obj.name)) return;
var modulePath = definitions.builtins[obj.name];
return t.memberExpression(
file.addImport(`${RUNTIME_MODULE_NAME}/core-js/${modulePath}`, `${obj.name}`, "absoluteDefault"),
prop
);
}
}
});
exports.metadata = {
optional: true
export var metadata = {
optional: true,
group: "builtin-post-modules"
};
exports.Program = function (node, parent, scope, file) {
this.traverse(astVisitor, file);
};
exports.pre = function (file) {
export function pre(file) {
file.set("helperGenerator", function (name) {
return file.addImport(`${RUNTIME_MODULE_NAME}/helpers/${name}`, name, "absoluteDefault");
});
@@ -108,10 +22,84 @@ exports.pre = function (file) {
file.setDynamic("regeneratorIdentifier", function () {
return file.addImport(`${RUNTIME_MODULE_NAME}/regenerator`, "regeneratorRuntime", "absoluteDefault");
});
};
}
exports.Identifier = function (node, parent, scope, file) {
if (this.isReferencedIdentifier({ name: "regeneratorRuntime" })) {
export function ReferencedIdentifier(node, parent, scope, file) {
if (node.name === "regeneratorRuntime") {
return file.get("regeneratorIdentifier");
}
if (t.isMemberExpression(parent)) return;
if (!has(definitions.builtins, node.name)) return;
if (scope.getBindingIdentifier(node.name)) return;
// Symbol() -> _core.Symbol(); new Promise -> new _core.Promise
var modulePath = definitions.builtins[node.name];
return file.addImport(`${RUNTIME_MODULE_NAME}/core-js/${modulePath}`, node.name, "absoluteDefault");
}
export function CallExpression(node, parent, scope, file) {
// arr[Symbol.iterator]() -> _core.$for.getIterator(arr)
if (node.arguments.length) return;
var callee = node.callee;
if (!t.isMemberExpression(callee)) return;
if (!callee.computed) return;
if (!this.get("callee.property").matchesPattern("Symbol.iterator")) return;
return t.callExpression(file.addImport(`${RUNTIME_MODULE_NAME}/core-js/get-iterator`, "getIterator", "absoluteDefault"), [callee.object]);
}
export function BinaryExpression(node, parent, scope, file) {
// Symbol.iterator in arr -> core.$for.isIterable(arr)
if (node.operator !== "in") return;
if (!this.get("left").matchesPattern("Symbol.iterator")) return;
return t.callExpression(
file.addImport(`${RUNTIME_MODULE_NAME}/core-js/is-iterable`, "isIterable", "absoluteDefault"),
[node.right]
);
}
export var MemberExpression = {
enter(node, parent, scope, file) {
// Array.from -> _core.Array.from
if (!this.isReferenced()) return;
var obj = node.object;
var prop = node.property;
if (!t.isReferenced(obj, node)) return;
if (node.computed) return;
if (!has(definitions.methods, obj.name)) return;
var methods = definitions.methods[obj.name];
if (!has(methods, prop.name)) return;
if (scope.getBindingIdentifier(obj.name)) return;
var modulePath = methods[prop.name];
return file.addImport(`${RUNTIME_MODULE_NAME}/core-js/${modulePath}`, `${obj.name}$${prop.name}`, "absoluteDefault");
},
exit(node, parent, scope, file) {
if (!this.isReferenced()) return;
var prop = node.property;
var obj = node.object;
if (!has(definitions.builtins, obj.name)) return;
if (scope.getBindingIdentifier(obj.name)) return;
var modulePath = definitions.builtins[obj.name];
return t.memberExpression(
file.addImport(`${RUNTIME_MODULE_NAME}/core-js/${modulePath}`, `${obj.name}`, "absoluteDefault"),
prop
);
}
};

View File

@@ -1,26 +1,29 @@
import * as messages from "../../../messages";
import * as t from "../../../types";
export function Program(program, parent, scope, file) {
var first = program.body[0];
if (t.isExpressionStatement(first) && t.isLiteral(first.expression, { value: "use strict" })) {
file.set("existingStrictDirective", program.body.shift());
const THIS_BREAK_KEYS = ["FunctionExpression", "FunctionDeclaration", "ClassExpression", "ClassDeclaration"];
export var Program = {
enter(program, parent, scope, file) {
var first = program.body[0];
var directive;
if (t.isExpressionStatement(first) && t.isLiteral(first.expression, { value: "use strict" })) {
directive = first;
} else {
directive = t.expressionStatement(t.literal("use strict"));
this.unshiftContainer("body", directive);
if (first) {
directive.leadingComments = first.leadingComments;
first.leadingComments = [];
}
}
directive._blockHoist = Infinity;
}
}
export function FunctionExpression() {
this.skip();
}
export { FunctionExpression as FunctionDeclaration };
export { FunctionExpression as Class };
export function ThisExpression() {
return t.identifier("undefined");
}
export function CallExpression(node, parent, scope, file) {
if (t.isIdentifier(node.callee, { name: "eval" })) {
throw file.errorWithNode(node, messages.get("evalInStrictMode"));
if (!this.findParent((node) => !node.shadow && THIS_BREAK_KEYS.indexOf(node.type) >= 0)) {
return t.identifier("undefined");
}
}

View File

@@ -23,21 +23,6 @@ function statementList(key, path, file) {
}
}
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;

View File

@@ -1 +1,11 @@
export { bare as FunctionExpression, bare as ArrowFunctionExpression } from "../../helpers/name-method";
import { bare } from "../../helpers/name-method";
export var metadata = {
group: "builtin-setup"
};
export var FunctionExpression = {
exit: bare
};
export { FunctionExpression as ArrowFunctionExpression };

View File

@@ -1,7 +1,8 @@
import * as t from "../../../types";
export var metadata = {
optional: true
optional: true,
group: "builtin-setup"
};
var match = t.buildMatchMemberExpression("process.env");

View File

@@ -1,14 +1,6 @@
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)) {

View File

@@ -2,8 +2,7 @@ import levenshtein from "leven";
import * as messages from "../../../messages";
export var metadata = {
optional: true,
readOnly: true
optional: true
};
export function Identifier(node, parent, scope, file) {

View File

@@ -10,6 +10,11 @@ export default class TraversalContext {
this.opts = opts;
}
shouldVisit(node) {
var keys = t.VISITOR_KEYS[node.type];
return !!(this.opts.enter || this.opts.exit || this.opts[node.type] || (keys && keys.length));
}
create(node, obj, key) {
return TraversalPath.get(this.parentPath, this, node, obj, key);
}
@@ -25,7 +30,10 @@ export default class TraversalContext {
// build up initial queue
for (let i = 0; i < nodes.length; i++) {
if (nodes[i]) queue.push(this.create(node, nodes, i));
var self = nodes[i];
if (self && this.shouldVisit(self)) {
queue.push(this.create(node, nodes, i));
}
}
// visit the queue
@@ -42,16 +50,13 @@ export default class TraversalContext {
}
}
// clear context from queued paths
for (let i = 0; i < queue.length; i++) {
//queue[i].clearContext();
}
return stop;
}
visitSingle(node, key) {
return this.create(node, node, key).visit();
if (this.shouldVisit(node[key])) {
return this.create(node, node, key).visit();
}
}
visit(node, key) {

View File

@@ -1,5 +1,5 @@
import TraversalContext from "./context";
import { explode, verify } from "./visitors";
import * as visitors from "./visitors";
import * as messages from "../messages";
import includes from "lodash/collection/includes";
import * as t from "../types";
@@ -14,7 +14,9 @@ export default function traverse(parent, opts, scope, state, parentPath) {
}
if (!opts) opts = {};
verify(opts);
visitors.verify(opts);
visitors.explode(opts);
// array of nodes
if (Array.isArray(parent)) {
@@ -26,8 +28,9 @@ export default function traverse(parent, opts, scope, state, parentPath) {
}
}
traverse.verify = verify;
traverse.explode = explode;
traverse.visitors = visitors;
traverse.verify = visitors.verify;
traverse.explode = visitors.explode;
traverse.node = function (node, opts, scope, state, parentPath) {
var keys = t.VISITOR_KEYS[node.type];

View File

@@ -22,14 +22,14 @@ var hoistVariablesVisitor = explode({
VariableDeclaration(node, parent, scope) {
if (node.kind !== "var") return;
var bindings = this.getBindingIdentifiers();
var bindings = this.getBindingIdentifiers();
for (var key in bindings) {
scope.push({ id: bindings[key] });
}
var exprs = [];
for (var i = 0; i < node.declarations.length; i++) {
for (var declar of (node.declarations: Array)) {
var declar = node.declarations[i];
if (declar.init) {
exprs.push(t.expressionStatement(
@@ -107,12 +107,78 @@ export default class TraversalPath {
return ancestry;
}
/**
* Description
*/
inType(types) {
if (!Array.isArray(types)) types = [types];
var path = this;
while (path) {
for (var type of (types: Array)) {
if (path.node.type === type) return true;
}
path = path.parentPath;
}
return false;
}
/**
* Description
*/
inShadow() {
var path = this;
while (path) {
if (path.isFunction()) {
if (path.node.shadow) {
return path;
} else {
return null;
}
}
path = path.parentPath;
}
return null;
}
/**
* Check whether this node was a part of the original AST.
*/
isUser() {
return this.node && !!this.node.loc;
}
/**
* Check whether this node was generated by us and not a part of the original AST.
*/
isGenerated() {
return !this.isUser();
}
/**
* Description
*/
findParent(callback) {
var path = this;
while (path) {
if (callback(path.node, path)) return path;
path = path.parentPath;
}
return null;
}
/**
* Description
*/
queueNode(path) {
if (this.context) {
if (this.context && this.context.queue) {
this.context.queue.push(path);
}
}
@@ -136,7 +202,6 @@ export default class TraversalPath {
} else if (this.isStatementOrBlock()) {
if (this.node) nodes.push(this.node);
this.container[this.key] = t.blockStatement(nodes);
this.checkSelf();
} else {
throw new Error("We don't know what to do with this node type. We were previously a Statement but we can't fit in here?");
}
@@ -163,8 +228,6 @@ export default class TraversalPath {
paths.push(TraversalPath.get(this, null, node, this.container, to));
}
}
this.checkPaths(paths);
}
_containerInsertBefore(nodes) {
@@ -234,7 +297,6 @@ export default class TraversalPath {
} else if (this.isStatementOrBlock()) {
if (this.node) nodes.unshift(this.node);
this.container[this.key] = t.blockStatement(nodes);
this.checkSelf();
} else {
throw new Error("We don't know what to do with this node type. We were previously a Statement but we can't fit in here?");
}
@@ -318,12 +380,44 @@ export default class TraversalPath {
if (log) file.log.debug("End scope building");
}
_remove() {
if (Array.isArray(this.container)) {
this.container.splice(this.key, 1);
this.updateSiblingKeys(this.key, -1);
/**
* Share comments amongst siblings.
*/
shareCommentsWithSiblings() {
var node = this.node;
if (!node) return;
var trailing = node.trailingComments;
var leading = node.leadingComments;
if (!trailing && !leading) return;
var prev = this.getSibling(this.key - 1);
var next = this.getSibling(this.key + 1);
if (!prev.node) prev = next;
if (!next.node) next = prev;
prev.giveComments("trailing", leading);
next.giveComments("leading", trailing);
}
/**
* Give node `comments` of the specified `type`.
*/
giveComments(type: string, comments: Array) {
if (!comments) return;
var node = this.node;
if (!node) return;
var key = `${type}Comments`;
if (node[key]) {
node[key] = node[key].concat(comments);
} else {
this.container[this.key] = null;
node[key] = comments;
}
}
@@ -332,6 +426,7 @@ export default class TraversalPath {
*/
remove() {
this.shareCommentsWithSiblings();
this._remove();
this.removed = true;
@@ -366,6 +461,15 @@ export default class TraversalPath {
}
}
_remove() {
if (Array.isArray(this.container)) {
this.container.splice(this.key, 1);
this.updateSiblingKeys(this.key, -1);
} else {
this.container[this.key] = null;
}
}
/**
* Description
*/
@@ -528,7 +632,7 @@ export default class TraversalPath {
}
if (this.node === replacement) {
return this.checkSelf();
return;
}
// normalise inserting an entire AST
@@ -572,26 +676,6 @@ export default class TraversalPath {
// potentially create new scope
this.setScope();
this.checkSelf();
}
/**
* Description
*/
checkSelf() {
this.checkPaths(this);
}
/**
* Description
*/
checkPaths(paths) {
var scope = this.scope;
var file = scope && scope.file;
if (file) file.checkPath(paths);
}
/**
@@ -680,20 +764,31 @@ export default class TraversalPath {
if (!node) return;
var opts = this.opts;
var fns = [].concat(opts[key]);
if (!opts[key] && !opts[node.type]) return;
if (opts[node.type]) {
fns = fns.concat(opts[node.type][key]);
}
var fns = [].concat(opts[key]);
if (opts[node.type]) fns = fns.concat(opts[node.type][key]);
for (var fn of (fns: Array)) {
if (!fn) continue;
var node = this.node;
if (!node) return;
// call the function with the params (node, parent, scope, state)
var replacement = fn.call(this, node, this.parent, this.scope, this.state);
if (replacement) this.replaceWith(replacement, true);
var previousType = this.type;
if (this.shouldStop) break;
if (replacement) {
this.replaceWith(replacement, true);
}
if (this.shouldStop || this.shouldSkip || this.removed) return;
if (replacement && previousType !== this.type) {
this.queueNode(this);
return;
}
}
}
@@ -712,7 +807,7 @@ export default class TraversalPath {
visit(): boolean {
if (this.isBlacklisted()) return false;
if (this.opts.shouldSkip(this)) return false;
if (this.opts.shouldSkip && this.opts.shouldSkip(this)) return false;
this.call("enter");
@@ -784,8 +879,7 @@ export default class TraversalPath {
_getPattern(parts) {
var path = this;
for (var i = 0; i > parts.length; i++) {
var part = parts[i];
for (var part of (parts: Array)) {
if (part === ".") {
path = path.parentPath;
} else {
@@ -828,6 +922,14 @@ export default class TraversalPath {
return !this.has(key);
}
/**
* Description
*/
equals(key, value): boolean {
return this.node[key] === value;
}
/**
* Description
*/
@@ -973,7 +1075,7 @@ export default class TraversalPath {
var type = typeInfo.annotation;
if (!type) return false;
if (type.inferred && opts.inference === false) {
if (typeInfo.inferred && opts.inference === false) {
return false;
}

View File

@@ -14,10 +14,10 @@ import * as t from "../types";
var functionVariableVisitor = {
enter(node, parent, scope, state) {
if (t.isFor(node)) {
each(t.FOR_INIT_KEYS, (key) => {
for (var key of (t.FOR_INIT_KEYS: Array)) {
var declar = this.get(key);
if (declar.isVar()) state.scope.registerBinding("var", declar);
});
}
}
// this block is a function so we'll stop since none of the variables
@@ -48,13 +48,24 @@ var programReferenceVisitor = explode({
}
},
ExportDeclaration(node, parent, scope, state) {
var declar = node.declaration;
if (t.isClassDeclaration(declar) || t.isFunctionDeclaration(declar)) {
scope.getBinding(declar.id.name).reference();
} else if (t.isVariableDeclaration(declar)) {
for (var decl of (declar.declarations: Array)) {
scope.getBinding(decl.id.name).reference();
Scopable(node, parent, scope, state) {
for (var name in scope.bindings) {
state.references[name] = true;
}
},
ExportDeclaration: {
exit(node, parent, scope, state) {
var declar = node.declaration;
if (t.isClassDeclaration(declar) || t.isFunctionDeclaration(declar)) {
scope.getBinding(declar.id.name).reference();
} else if (t.isVariableDeclaration(declar)) {
for (var decl of (declar.declarations: Array)) {
var ids = t.getBindingIdentifiers(decl);
for (var name in ids) {
scope.getBinding(name).reference();
}
}
}
}
},
@@ -90,50 +101,13 @@ var blockVariableVisitor = explode({
var renameVisitor = explode({
ReferencedIdentifier(node, parent, scope, state) {
if (node.name !== state.oldName) return;
if (this.parentPath.isProperty() && this.key === "key" && parent.shorthand) {
var value = t.identifier(state.newName);;
if (parent.value === state.binding) {
state.info.identifier = state.binding = value;
}
parent.shorthand = false;
parent.value = value;
parent.key = t.identifier(state.oldName);
} else {
if (node.name === state.oldName) {
node.name = state.newName;
}
},
Declaration(node, parent, scope, state) {
var ids = {};
var matchesLocal = (node, key) => {
return node.local === node[key] && (node.local.name === state.oldName || node.local.name === state.newName);
};
if (this.isExportDeclaration() && this.has("specifiers")) {
var specifiers = this.get("specifiers");
for (var specifier of (specifiers: Array)) {
if (specifier.isExportSpecifier() && matchesLocal(specifier.node, "exported")) {
specifier.get("exported").replaceWith(t.identifier(state.oldName));
}
}
} else if (this.isImportDeclaration() && this.has("specifiers")) {
var specifiers = this.get("specifiers");
for (var specifier of (specifiers: Array)) {
if (specifier.isImportSpecifier() && matchesLocal(specifier.node, "imported")) {
state.binding = state.info.identifier = t.identifier(state.newName);
specifier.get("local").replaceWith(state.binding);
} else {
extend(ids, specifier.getBindingIdentifiers());
}
}
} else {
ids = this.getBindingIdentifiers();
}
var ids = this.getBindingIdentifiers();;
for (var name in ids) {
if (name === state.oldName) ids[name].name = state.newName;
@@ -219,8 +193,13 @@ export default class Scope {
do {
uid = this._generateUid(name, i);
i++;
} while (this.hasBinding(uid) || this.hasGlobal(uid) || this.hasUid(uid));
this.file.uids[uid] = true;
} while (this.hasBinding(uid) || this.hasGlobal(uid) || this.hasReference(uid));
var program = this.getProgramParent();
program.references[uid] = true;
program.uids[uid] = true;
return uid;
}
@@ -230,19 +209,6 @@ export default class Scope {
return `_${id}`;
}
/**
* Description
*/
hasUid(name): boolean {
var scope = this;
do {
if (scope.file.uids[name]) return true;
scope = scope.parent;
} while (scope);
return false;
}
/*
* Description
*/
@@ -265,8 +231,8 @@ export default class Scope {
if (node.source) {
add(node.source);
} else if (node.specifiers && node.specifiers.length) {
for (var i = 0; i < node.specifiers.length; i++) {
add(node.specifiers[i]);
for (var specifier of (node.specifiers: Array)) {
add(specifier);
}
} else if (node.declaration) {
add(node.declaration);
@@ -283,8 +249,7 @@ export default class Scope {
} else if (t.isCallExpression(node)) {
add(node.callee);
} else if (t.isObjectExpression(node) || t.isObjectPattern(node)) {
for (var i = 0; i < node.properties.length; i++) {
var prop = node.properties[i];
for (var prop of (node.properties: Array)) {
add(prop.key || prop.argument);
}
}
@@ -398,7 +363,7 @@ export default class Scope {
if (t.isIdentifier(node)) {
var binding = this.getBinding(node.name);
if (binding && binding.isTypeGeneric("Array", { inference: false })) return node;
if (binding && binding.constant && binding.isTypeGeneric("Array")) return node;
}
if (t.isArrayExpression(node)) {
@@ -431,8 +396,8 @@ export default class Scope {
this.registerBinding("hoisted", path);
} else if (t.isVariableDeclaration(node)) {
var declarations = path.get("declarations");
for (var i = 0; i < declarations.length; i++) {
this.registerBinding(node.kind, declarations[i]);
for (var declar of (declarations: Array)) {
this.registerBinding(node.kind, declar);
}
} else if (t.isClassDeclaration(node)) {
this.registerBinding("let", path);
@@ -491,6 +456,20 @@ export default class Scope {
this.globals[node.name] = node;
}
/**
* Description
*/
hasUid(name): boolean {
var scope = this;
do {
if (scope.uids[name]) return true;
} while (scope = scope.parent);
return false;
}
/**
* Description
*/
@@ -505,6 +484,20 @@ export default class Scope {
return false;
}
/**
* Description
*/
hasReference(name: string): boolean {
var scope = this;
do {
if (scope.references[name]) return true;
} while (scope = scope.parent);
return false;
}
/**
* Description
*/
@@ -540,8 +533,10 @@ export default class Scope {
if (info) return extend(this, info);
info = this.block._scopeInfo = {
bindings: object(),
globals: object()
references: object(),
bindings: object(),
globals: object(),
uids: object(),
};
extend(this, info);
@@ -549,8 +544,8 @@ export default class Scope {
// ForStatement - left, init
if (path.isLoop()) {
for (let i = 0; i < t.FOR_INIT_KEYS.length; i++) {
var node = path.get(t.FOR_INIT_KEYS[i]);
for (let key of (t.FOR_INIT_KEYS: Array)) {
var node = path.get(key);
if (node.isBlockScoped()) this.registerBinding(node.node.kind, node);
}
}
@@ -573,8 +568,8 @@ export default class Scope {
if (path.isFunction()) {
var params = path.get("params");
for (let i = 0; i < params.length; i++) {
this.registerBinding("param", params[i]);
for (let param of (params: Array)) {
this.registerBinding("param", param);
}
this.traverse(path.get("body").node, blockVariableVisitor, this);
}
@@ -649,6 +644,18 @@ export default class Scope {
declar.declarations.push(t.variableDeclarator(opts.id, opts.init));
}
/**
* Walk up to the top of the scope tree and get the `Program`.
*/
getProgramParent() {
var scope = this;
while (scope.parent) {
scope = scope.parent;
}
return scope;
}
/**
* Walk up the scope tree until we hit either a Function or reach the
* very top and hit Program.
@@ -698,8 +705,7 @@ export default class Scope {
getAllBindingsOfKind(): Object {
var ids = object();
for (let i = 0; i < arguments.length; i++) {
var kind = arguments[i];
for (let kind of (arguments: Array)) {
var scope = this;
do {
for (var name in scope.bindings) {
@@ -776,7 +782,7 @@ export default class Scope {
if (!name) return false;
if (this.hasOwnBinding(name)) return true;
if (this.parentHasBinding(name)) return true;
if (this.file.uids[name]) return true;
if (this.hasUid(name)) return true;
if (includes(Scope.globals, name)) return true;
if (includes(Scope.contextVariables, name)) return true;
return false;
@@ -790,6 +796,19 @@ export default class Scope {
return this.parent && this.parent.hasBinding(name);
}
/**
* Move a binding of `name` to another `scope`.
*/
moveBindingTo(name, scope) {
var info = this.getBinding(name);
if (info) {
info.scope.removeOwnBinding(name);
info.scope = scope;
scope.bindings[name] = info;
}
}
/**
* Description
*/

View File

@@ -4,6 +4,9 @@ import * as t from "../types";
import esquery from "esquery";
export function explode(visitor, mergeConflicts) {
if (visitor._exploded) return visitor;
visitor._exploded = true;
// make sure there's no __esModule type since this is because we're using loose mode
// and it sets __esModule to be enumerable on all modules :(
delete visitor.__esModule;
@@ -36,12 +39,12 @@ export function explode(visitor, mergeConflicts) {
if (wrapper.type) {
// merge the visitor if necessary or just put it back in
if (visitor[wrapper.type]) {
merge(visitor[wrapper.type], fns);
mergePair(visitor[wrapper.type], fns);
} else {
visitor[wrapper.type] = fns;
}
} else {
merge(visitor, fns);
mergePair(visitor, fns);
}
}
@@ -61,7 +64,7 @@ export function explode(visitor, mergeConflicts) {
var existing = visitor[alias];
if (existing) {
if (mergeConflicts) {
merge(existing, fns);
mergePair(existing, fns);
}
} else {
visitor[alias] = fns;
@@ -79,22 +82,15 @@ export function verify(visitor) {
throw new Error(messages.get("traverseVerifyRootFunction"));
}
if (!visitor.enter) visitor.enter = function () { };
if (!visitor.exit) visitor.exit = function () { };
if (!visitor.shouldSkip) visitor.shouldSkip = function () { return false; };
for (var nodeType in visitor) {
if (shouldIgnoreKey(nodeType)) continue;
if (t.TYPES.indexOf(nodeType) < 0) {
if (t.TYPES.indexOf(nodeType) < 0 && !virtualTypes[nodeType]) {
throw new Error(messages.get("traverseVerifyNodeType", nodeType));
}
var visitors = visitor[nodeType];
if (typeof visitors === "function") {
throw new Error(messages.get("traverseVerifyVisitorFunction", nodeType));
} else if (typeof visitors === "object") {
if (typeof visitors === "object") {
for (var visitorKey in visitors) {
if (visitorKey === "enter" || visitorKey === "exit") continue;
throw new Error(messages.get("traverseVerifyVisitorProperty", nodeType, visitorKey));
@@ -105,6 +101,19 @@ export function verify(visitor) {
visitor._verified = true;
}
export function merge(visitors) {
var rootVisitor = {};
for (var visitor of (visitors: Array)) {
for (var type in visitor) {
var nodeVisitor = rootVisitor[type] = rootVisitor[type] || {};
mergePair(nodeVisitor, visitor[type]);
}
}
return rootVisitor;
}
function ensureEntranceObjects(obj) {
for (let key in obj) {
if (shouldIgnoreKey(key)) continue;
@@ -135,7 +144,7 @@ function addSelector(visitor, selector, fns) {
};
}
merge(visitor, fns);
mergePair(visitor, fns);
}
function wrapCheck(wrapper, fn) {
@@ -159,7 +168,7 @@ function shouldIgnoreKey(key) {
return false;
}
function merge(dest, src) {
function mergePair(dest, src) {
for (var key in src) {
dest[key] = (dest[key] || []).concat(src[key]);
}

View File

@@ -26,9 +26,9 @@
"ExportNamedDeclaration": ["Statement", "Declaration", "ModuleDeclaration", "ExportDeclaration"],
"ImportDeclaration": ["Statement", "Declaration", "ModuleDeclaration"],
"ArrowFunctionExpression": ["Scopable", "Function", "Expression", "Pure"],
"FunctionDeclaration": ["Scopable", "Function", "Statement", "Pure", "Declaration"],
"FunctionExpression": ["Scopable", "Function", "Expression", "Pure"],
"ArrowFunctionExpression": ["Scopable", "Function", "Func", "Expression", "Pure"],
"FunctionDeclaration": ["Scopable", "Function", "Func", "Statement", "Pure", "Declaration"],
"FunctionExpression": ["Scopable", "Function", "Func", "Expression", "Pure"],
"BlockStatement": ["Scopable", "Statement"],
"Program": ["Scopable"],

View File

@@ -51,7 +51,7 @@ export function toSequenceExpression(nodes: Array<Object>, scope: Scope): Object
} else if (t.isVariableDeclaration(node)) {
if (node.kind !== "var") return bailed = true; // bailed
each(node.declarations, function (declar) {
for (var declar of (node.declarations: Array)) {
var bindings = t.getBindingIdentifiers(declar);
for (var key in bindings) {
declars.push({
@@ -63,7 +63,7 @@ export function toSequenceExpression(nodes: Array<Object>, scope: Scope): Object
if (declar.init) {
exprs.push(t.assignmentExpression("=", declar.id, declar.init));
}
});
}
ensureLastUndefined = true;
continue;

View File

@@ -79,6 +79,8 @@ export function isType(nodeType, targetType) {
var aliases = t.FLIPPED_ALIAS_KEYS[targetType];
if (aliases) {
if (aliases[0] === nodeType) return true;
for (var alias of (aliases: Array)) {
if (nodeType === alias) return true;
}
@@ -258,9 +260,9 @@ export function buildMatchMemberExpression(match:string, allowPartial?: boolean)
*/
export function removeComments(child: Object): Object {
each(COMMENT_KEYS, function (key) {
for (var key of (COMMENT_KEYS: Array)) {
delete child[key];
});
}
return child;
}
@@ -270,9 +272,9 @@ export function removeComments(child: Object): Object {
export function inheritsComments(child: Object, parent: Object): Object {
if (child && parent) {
each(COMMENT_KEYS, function (key) {
for (var key of (COMMENT_KEYS: Array)) {
child[key] = uniq(compact([].concat(child[key], parent[key])));
});
}
}
return child;
}

Some files were not shown because too many files have changed in this diff Show More