diff --git a/src/babel/transformation/file/index.js b/src/babel/transformation/file/index.js index 75e844f61a..84dd7d66d5 100644 --- a/src/babel/transformation/file/index.js +++ b/src/babel/transformation/file/index.js @@ -508,7 +508,7 @@ export default class File { this.log.debug("End set AST"); this.log.debug("Start prepass"); - //this.checkPath(this.path); + this.checkPath(this.path); this.log.debug("End prepass"); this.log.debug("Start module formatter init"); diff --git a/src/babel/transformation/helpers/build-binary-assignment-operator-transformer.js b/src/babel/transformation/helpers/build-binary-assignment-operator-transformer.js index 04ffc4c1b3..45a6d812c5 100644 --- a/src/babel/transformation/helpers/build-binary-assignment-operator-transformer.js +++ b/src/babel/transformation/helpers/build-binary-assignment-operator-transformer.js @@ -10,6 +10,10 @@ 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; diff --git a/src/babel/transformation/helpers/memoise-decorators.js b/src/babel/transformation/helpers/memoise-decorators.js index 9e012bdf72..25d1032b1d 100644 --- a/src/babel/transformation/helpers/memoise-decorators.js +++ b/src/babel/transformation/helpers/memoise-decorators.js @@ -26,7 +26,11 @@ export default function (decorators, scope) { [ref] )); - decorator.expression = t.sequenceExpression(nodes); + if (nodes.length === 1) { + decorator.expression = nodes[0]; + } else { + decorator.expression = t.sequenceExpression(nodes); + } } return decorators; diff --git a/src/babel/transformation/helpers/name-method.js b/src/babel/transformation/helpers/name-method.js index 0dc3628a9d..6e2845a274 100644 --- a/src/babel/transformation/helpers/name-method.js +++ b/src/babel/transformation/helpers/name-method.js @@ -39,7 +39,6 @@ var wrap = function (state, method, id, scope) { return template; } else { method.id = id; - return method; } }; @@ -96,7 +95,7 @@ export function custom(node, id, scope) { export function property(node, file, scope) { var key = t.toComputedKey(node, node.key); - if (!t.isLiteral(key)) return node; // we can't set a function id with this + if (!t.isLiteral(key)) return; // we can't set a function id with this var name = t.toIdentifier(key.value); if (name === "eval" || name === "arguments") name = "_" + name; @@ -109,7 +108,7 @@ export function property(node, file, scope) { export function bare(node, parent, scope) { // has an `id` so we don't need to infer one - if (node.id) return node; + if (node.id) return; var id; if (t.isProperty(parent) && parent.kind === "init" && (!parent.computed || t.isLiteral(parent.key))) { @@ -119,7 +118,7 @@ export function bare(node, parent, scope) { // var foo = function () {}; id = parent.id; } else { - return node; + return; } var name; @@ -128,7 +127,7 @@ export function bare(node, parent, scope) { } else if (t.isIdentifier(id)) { name = id.name; } else { - return node; + return; } name = t.toIdentifier(name); diff --git a/src/babel/transformation/transformer-pass.js b/src/babel/transformation/transformer-pass.js index c6ce71f05a..81e03eda28 100644 --- a/src/babel/transformation/transformer-pass.js +++ b/src/babel/transformation/transformer-pass.js @@ -8,11 +8,12 @@ import traverse from "../traversal"; export default class TransformerPass { constructor(file: File, transformer: Transformer) { - this.transformer = transformer; - this.handlers = transformer.handlers; - this.skipKey = transformer.skipKey; - this.file = file; - this.ran = false; + this.shouldTransform = !transformer.shouldVisit; + this.transformer = transformer; + this.handlers = transformer.handlers; + this.skipKey = transformer.skipKey; + this.file = file; + this.ran = false; } canTransform(): boolean { @@ -43,12 +44,14 @@ export default class TransformerPass { } checkPath(path: TraversalPath): boolean { - var shouldVisit = this.transformer.shouldVisit; - if (!shouldVisit) return; + if (this.shouldTransform || this.ran) return; + this.shouldTransform = this.transformer.shouldVisit(path.node); } transform() { + if (!this.shouldTransform) return; + var file = this.file; file.log.debug(`Start transformer ${this.transformer.key}`); diff --git a/src/babel/transformation/transformer.js b/src/babel/transformation/transformer.js index 71b27a3986..361a329078 100644 --- a/src/babel/transformation/transformer.js +++ b/src/babel/transformation/transformer.js @@ -26,7 +26,6 @@ export default class Transformer { this.manipulateOptions = take("manipulateOptions"); this.shouldVisit = take("shouldVisit"); this.metadata = take("metadata") || {}; - this.skipKey = `transformer:${transformerKey}:skip`; this.parser = take("parser"); this.post = take("post"); this.pre = take("pre"); @@ -48,7 +47,10 @@ export default class Transformer { if (!this.shouldVisit) { var types = Object.keys(this.handlers); this.shouldVisit = function (node) { - return types.indexOf(node.type) >= 0; + for (var i = 0; i < types.length; i++) { + if (node.type === types[i]) return true; + } + return false; }; } } @@ -79,10 +81,6 @@ export default class Transformer { transformer[type] = fns; }); - transformer.shouldSkip = (path) => { - return path.getData(this.skipKey) === true; - }; - return transformer; } diff --git a/src/babel/transformation/transformers/es6/classes.js b/src/babel/transformation/transformers/es6/classes.js index 12fb1765fe..4dedf33981 100644 --- a/src/babel/transformation/transformers/es6/classes.js +++ b/src/babel/transformation/transformers/es6/classes.js @@ -245,7 +245,7 @@ class ClassTransformer { if (body.length === 1) return t.toExpression(body[0]); } else { // infer class name if this is a nameless class expression - constructor = nameMethod.bare(constructor, this.parent, this.scope); + constructor = nameMethod.bare(constructor, this.parent, this.scope) || constructor; body.unshift(t.variableDeclaration("var", [ t.variableDeclarator(classRef, constructor) diff --git a/src/babel/transformation/transformers/index.js b/src/babel/transformation/transformers/index.js index 1ec845d14a..a6153cd1ba 100644 --- a/src/babel/transformation/transformers/index.js +++ b/src/babel/transformation/transformers/index.js @@ -115,6 +115,5 @@ export default { "utility.inlineExpressions": require("./utility/inline-expressions"), "utility.deadCodeElimination": require("./utility/dead-code-elimination"), - flow: require("./other/flow"), - _cleanUp: require("./internal/cleanup") + flow: require("./other/flow") }; diff --git a/src/babel/transformation/transformers/internal/cleanup.js b/src/babel/transformation/transformers/internal/cleanup.js deleted file mode 100644 index c9f7ca4f97..0000000000 --- a/src/babel/transformation/transformers/internal/cleanup.js +++ /dev/null @@ -1,30 +0,0 @@ -export var SequenceExpression = { - exit(node) { - if (node.expressions.length === 1) { - return node.expressions[0]; - } else if (!node.expressions.length) { - this.remove(); - } - } -}; - -export var ExpressionStatement = { - exit(node) { - if (!node.expression) this.remove(); - } -}; - -export var Binary = { - exit(node) { - var right = node.right; - var left = node.left; - - if (!left && !right) { - this.remove(); - } else if (!left) { - return right; - } else if (!right) { - return left; - } - } -}; diff --git a/src/babel/transformation/transformers/internal/module-formatter.js b/src/babel/transformation/transformers/internal/module-formatter.js index 400f27e28a..92ef7baab2 100644 --- a/src/babel/transformation/transformers/internal/module-formatter.js +++ b/src/babel/transformation/transformers/internal/module-formatter.js @@ -1,6 +1,8 @@ import * as strict from "../../helpers/strict"; export function Program(program, parent, scope, file) { + this.stop(); + strict.wrap(program, function () { program.body = file.dynamicImports.concat(program.body); }); diff --git a/src/babel/transformation/transformers/other/flow.js b/src/babel/transformation/transformers/other/flow.js index bb6bf4c393..b3a963e3cc 100644 --- a/src/babel/transformation/transformers/other/flow.js +++ b/src/babel/transformation/transformers/other/flow.js @@ -1,5 +1,9 @@ import * as t from "../../../types"; +export function shouldVisit(node) { + return node.isType || node.optional || node.implements || node.typeAnnotation || t.isFlow(node); +} + export function Flow(node) { this.remove(); } diff --git a/src/babel/transformation/transformers/spec/block-scoped-functions.js b/src/babel/transformation/transformers/spec/block-scoped-functions.js index ae16f05fcb..a1b17960f0 100644 --- a/src/babel/transformation/transformers/spec/block-scoped-functions.js +++ b/src/babel/transformation/transformers/spec/block-scoped-functions.js @@ -23,6 +23,16 @@ function statementList(key, path, file) { } } +export function shouldVisit(node) { + if (node.type !== "BlockStatement") return false; + + for (var i = 0; i < node.body.length; i++) { + if (node.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; diff --git a/src/babel/traversal/path/index.js b/src/babel/traversal/path/index.js index 267dbbd507..b7d6ffc201 100644 --- a/src/babel/traversal/path/index.js +++ b/src/babel/traversal/path/index.js @@ -253,15 +253,32 @@ export default class TraversalPath { } remove() { - var removeParent = false; - if (this.parentPath) { - removeParent ||= this.parentPath.isExpressionStatement(); - removeParent ||= this.parentPath.isSequenceExpression() && this.parent.expressions.length === 1; - if (removeParent) return this.parentPath.remove(); - } - this._remove(); this.removed = true; + + var parentPath = this.parentPath; + var parent = this.parent; + if (!parentPath) return; + + // we're the child of an expression statement so we should remove the parent + if (parentPath.isExpressionStatement()) { + return parentPath.remove(); + } + + // we've just removed the second element of a sequence expression so let's turn that sequence + // expression into a regular expression + if (parentPath.isSequenceExpression() && parent.expressions.length === 1) { + parentPath.replaceWith(parent.expressions[0]); + } + + // we're in a binary expression, better remove it and replace it with the last expression + if (parentPath.isBinary()) { + if (this.key === "left") { + parentPath.replaceWith(parent.right); + } else { // key === "right" + parentPath.replaceWith(parent.left); + } + } } skip() { diff --git a/src/babel/types/index.js b/src/babel/types/index.js index 312916c0fc..e731f40ade 100644 --- a/src/babel/types/index.js +++ b/src/babel/types/index.js @@ -78,7 +78,11 @@ export function isType(nodeType, targetType) { if (nodeType === targetType) return true; var aliases = t.FLIPPED_ALIAS_KEYS[targetType]; - if (aliases) return aliases.indexOf(nodeType) > -1; + if (aliases) { + for (var i = 0; i < aliases.length; i++) { + if (nodeType === aliases[i]) return true; + } + } return false; }