From 6f664ca64e9e76683fa52c97e0148d8e857933ae Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Thu, 7 May 2015 15:53:22 +0100 Subject: [PATCH] merge internal transformers into single traversal pass --- src/babel/transformation/file/index.js | 76 ++++++++++--------- ...-binary-assignment-operator-transformer.js | 4 - .../helpers/build-react-transformer.js | 6 -- src/babel/transformation/index.js | 7 ++ src/babel/transformation/transformer-pass.js | 19 ++--- src/babel/transformation/transformer.js | 13 ---- .../transformers/es5/properties.mutators.js | 42 +++++----- .../transformers/es6/arrow-functions.js | 2 - .../transformers/es6/block-scoping.js | 4 - .../transformers/es6/classes.js | 10 +-- .../transformers/es6/constants.js | 4 - .../transformers/es6/destructuring.js | 5 -- .../transformation/transformers/es6/for-of.js | 2 - .../transformers/es6/modules.js | 2 - .../transformers/es6/object-super.js | 2 - .../transformers/es6/parameters.default.js | 6 -- .../transformers/es6/parameters.rest.js | 4 - .../transformers/es6/properties.computed.js | 70 +++++++++-------- .../transformers/es6/properties.shorthand.js | 4 - .../transformers/es6/regex.sticky.js | 4 - .../transformers/es6/regex.unicode.js | 4 - .../transformation/transformers/es6/spread.js | 2 - .../transformers/es6/template-literals.js | 4 - .../transformers/es7/async-functions.js | 4 - .../transformers/es7/class-properties.js | 4 - .../transformers/es7/decorators.js | 4 - .../transformers/es7/do-expressions.js | 2 - .../transformers/es7/export-extensions.js | 4 - .../es7/trailing-function-commas.js | 4 - .../transformation/transformers/index.js | 66 +--------------- .../transformers/internal/hoist-directives.js | 16 ++++ .../transformers/internal/module-formatter.js | 2 - .../transformers/internal/modules.js | 4 - .../transformers/internal/shadow-functions.js | 29 +++---- .../transformers/internal/strict.js | 19 ----- .../transformers/internal/validation.js | 17 ----- .../transformers/optimisation/flow.for-of.js | 1 - .../transformation/transformers/other/flow.js | 4 - .../transformers/other/regenerator.js | 8 +- .../transformers/other/strict.js | 35 ++++++--- .../spec/block-scoped-functions.js | 15 ---- .../transformers/validation/react.js | 8 -- .../validation/undeclared-variable-check.js | 3 +- src/babel/traversal/index.js | 9 ++- src/babel/traversal/path/index.js | 67 +++++++++------- src/babel/traversal/visitors.js | 23 ++++-- .../es6.arrow-functions/arguments/expected.js | 10 +-- .../assignment-expression/expected.js | 6 +- 48 files changed, 243 insertions(+), 417 deletions(-) create mode 100644 src/babel/transformation/transformers/internal/hoist-directives.js delete mode 100644 src/babel/transformation/transformers/internal/strict.js diff --git a/src/babel/transformation/file/index.js b/src/babel/transformation/file/index.js index bec58c718a..bb2d3697db 100644 --- a/src/babel/transformation/file/index.js +++ b/src/babel/transformation/file/index.js @@ -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"; @@ -26,19 +27,6 @@ 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.dynamicImportTypes = {}; @@ -234,7 +222,46 @@ export default class File { stack = beforePlugins.concat(stack, afterPlugins); // register - this.transformerStack = stack.concat(secondaryStack); + this.transformerStack = this.mergeStack(stack.concat(secondaryStack)); + + + } + + mergeStack(_stack) { + var stack = []; + var ignore = []; + + for (let pass of (_stack: Array)) { + // been merged + if (ignore.indexOf(pass) >= 0) continue; + + var category = pass.transformer.metadata.category; + + // can't merge + if (!pass.canTransform() || !category) { + stack.push(pass); + continue; + } + + var mergeStack = []; + for (let pass of (_stack: Array)) { + if (pass.transformer.metadata.category === category) { + 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(category, visitor); + //console.log(mergeTransformer); + stack.push(mergeTransformer.buildPass(this)); + } + + return stack; } set(key: string, val): any { @@ -357,23 +384,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 +471,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()) { 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 45a6d812c5..04ffc4c1b3 100644 --- a/src/babel/transformation/helpers/build-binary-assignment-operator-transformer.js +++ b/src/babel/transformation/helpers/build-binary-assignment-operator-transformer.js @@ -10,10 +10,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; diff --git a/src/babel/transformation/helpers/build-react-transformer.js b/src/babel/transformation/helpers/build-react-transformer.js index 46a9bdfef7..c63bd60882 100644 --- a/src/babel/transformation/helpers/build-react-transformer.js +++ b/src/babel/transformation/helpers/build-react-transformer.js @@ -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(); diff --git a/src/babel/transformation/index.js b/src/babel/transformation/index.js index 442ed37849..3f71068bc2 100644 --- a/src/babel/transformation/index.js +++ b/src/babel/transformation/index.js @@ -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.category = metadata.category || "builtin"; +} + pipeline.addTransformers(transformers); // diff --git a/src/babel/transformation/transformer-pass.js b/src/babel/transformation/transformer-pass.js index 38c3e8ef8c..715ba6de2e 100644 --- a/src/babel/transformation/transformer-pass.js +++ b/src/babel/transformation/transformer-pass.js @@ -8,27 +8,18 @@ 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.skipKey = transformer.skipKey; + this.file = file; + this.ran = false; } 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); - } - 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 3e12abcf1d..a5fac03bf9 100644 --- a/src/babel/transformation/transformer.js +++ b/src/babel/transformation/transformer.js @@ -25,7 +25,6 @@ export default class Transformer { }; this.manipulateOptions = take("manipulateOptions"); - this.shouldVisit = take("shouldVisit"); this.metadata = take("metadata") || {}; this.parser = take("parser"); this.post = take("post"); @@ -41,18 +40,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 { diff --git a/src/babel/transformation/transformers/es5/properties.mutators.js b/src/babel/transformation/transformers/es5/properties.mutators.js index 9b1deb2870..7fe77c7f41 100644 --- a/src/babel/transformation/transformers/es5/properties.mutators.js +++ b/src/babel/transformation/transformers/es5/properties.mutators.js @@ -1,28 +1,26 @@ 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 var ObjectExpression = { + exit(node, parent, scope, file) { + var mutatorMap = {}; + var hasAny = false; -export function ObjectExpression(node, parent, scope, file) { - var mutatorMap = {}; - var hasAny = false; + node.properties = node.properties.filter(function (prop) { + if (prop.kind === "get" || prop.kind === "set") { + hasAny = true; + defineMap.push(mutatorMap, prop, prop.kind, file); + return false; + } else { + return true; + } + }); - node.properties = node.properties.filter(function (prop) { - if (prop.kind === "get" || prop.kind === "set") { - hasAny = true; - defineMap.push(mutatorMap, prop, prop.kind, file); - return false; - } else { - return true; - } - }); + if (!hasAny) return; - if (!hasAny) return; - - return t.callExpression( - t.memberExpression(t.identifier("Object"), t.identifier("defineProperties")), - [node, defineMap.toDefineObject(mutatorMap)] - ); -} + return t.callExpression( + t.memberExpression(t.identifier("Object"), t.identifier("defineProperties")), + [node, defineMap.toDefineObject(mutatorMap)] + ); + } +}; diff --git a/src/babel/transformation/transformers/es6/arrow-functions.js b/src/babel/transformation/transformers/es6/arrow-functions.js index d40d436727..39d93f829a 100644 --- a/src/babel/transformation/transformers/es6/arrow-functions.js +++ b/src/babel/transformation/transformers/es6/arrow-functions.js @@ -1,7 +1,5 @@ import * as t from "../../../types"; -export var shouldVisit = t.isArrowFunctionExpression; - export function ArrowFunctionExpression(node) { t.ensureBlock(node); diff --git a/src/babel/transformation/transformers/es6/block-scoping.js b/src/babel/transformation/transformers/es6/block-scoping.js index 1b81d95232..850dca35f0 100644 --- a/src/babel/transformation/transformers/es6/block-scoping.js +++ b/src/babel/transformation/transformers/es6/block-scoping.js @@ -37,10 +37,6 @@ function standardizeLets(declars) { } } -export function shouldVisit(node) { - return t.isVariableDeclaration(node) && (node.kind === "let" || node.kind === "const"); -} - export function VariableDeclaration(node, parent, scope, file) { if (!isLet(node, parent)) return; diff --git a/src/babel/transformation/transformers/es6/classes.js b/src/babel/transformation/transformers/es6/classes.js index 670a18b5fb..e1bb106659 100644 --- a/src/babel/transformation/transformers/es6/classes.js +++ b/src/babel/transformation/transformers/es6/classes.js @@ -11,17 +11,17 @@ 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)) ]); } -export function ClassExpression(node, parent, scope, file) { - return new ClassTransformer(this, file).run(); -} +export var ClassExpression = { + exit(node, parent, scope, file) { + return new ClassTransformer(this, file).run(); + } +}; var collectPropertyReferencesVisitor = { Identifier: { diff --git a/src/babel/transformation/transformers/es6/constants.js b/src/babel/transformation/transformers/es6/constants.js index b8df344bfb..4125b68d10 100644 --- a/src/babel/transformation/transformers/es6/constants.js +++ b/src/babel/transformation/transformers/es6/constants.js @@ -1,10 +1,6 @@ import * as messages from "../../../messages"; import * as t from "../../../types"; -export function shouldVisit(node) { - return t.isVariableDeclaration(node, { kind: "const" }) || t.isImportDeclaration(node); -} - var visitor = { enter(node, parent, scope, state) { if (this.isAssignmentExpression() || this.isUpdateExpression()) { diff --git a/src/babel/transformation/transformers/es6/destructuring.js b/src/babel/transformation/transformers/es6/destructuring.js index 5dd84da762..5fb2df518b 100644 --- a/src/babel/transformation/transformers/es6/destructuring.js +++ b/src/babel/transformation/transformers/es6/destructuring.js @@ -1,8 +1,6 @@ import * as messages from "../../../messages"; import * as t from "../../../types"; -export var shouldVisit = t.isPattern; - export function ForOfStatement(node, parent, scope, file) { var left = node.left; @@ -83,7 +81,6 @@ 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) { @@ -104,8 +101,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) { diff --git a/src/babel/transformation/transformers/es6/for-of.js b/src/babel/transformation/transformers/es6/for-of.js index 7d007d6465..b986492da9 100644 --- a/src/babel/transformation/transformers/es6/for-of.js +++ b/src/babel/transformation/transformers/es6/for-of.js @@ -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); diff --git a/src/babel/transformation/transformers/es6/modules.js b/src/babel/transformation/transformers/es6/modules.js index 5abf2b1af4..6141ab9217 100644 --- a/src/babel/transformation/transformers/es6/modules.js +++ b/src/babel/transformation/transformers/es6/modules.js @@ -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++) { diff --git a/src/babel/transformation/transformers/es6/object-super.js b/src/babel/transformation/transformers/es6/object-super.js index b261520da2..10d01e09f8 100644 --- a/src/babel/transformation/transformers/es6/object-super.js +++ b/src/babel/transformation/transformers/es6/object-super.js @@ -1,8 +1,6 @@ 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; diff --git a/src/babel/transformation/transformers/es6/parameters.default.js b/src/babel/transformation/transformers/es6/parameters.default.js index 56345ee839..165c177844 100644 --- a/src/babel/transformation/transformers/es6/parameters.default.js +++ b/src/babel/transformation/transformers/es6/parameters.default.js @@ -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; @@ -96,6 +92,4 @@ exports.Function = function (node, parent, scope, file) { } else { node.body.body = body.concat(node.body.body); } - - this.checkSelf(); }; diff --git a/src/babel/transformation/transformers/es6/parameters.rest.js b/src/babel/transformation/transformers/es6/parameters.rest.js index 631701a766..6b57c156a3 100644 --- a/src/babel/transformation/transformers/es6/parameters.rest.js +++ b/src/babel/transformation/transformers/es6/parameters.rest.js @@ -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 @@ -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(); }; diff --git a/src/babel/transformation/transformers/es6/properties.computed.js b/src/babel/transformation/transformers/es6/properties.computed.js index e846e4d2a6..d944844ca0 100644 --- a/src/babel/transformation/transformers/es6/properties.computed.js +++ b/src/babel/transformation/transformers/es6/properties.computed.js @@ -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 i = 0; i < node.properties.length; i++) { + hasComputed = t.isProperty(node.properties[i], { 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; -} +}; diff --git a/src/babel/transformation/transformers/es6/properties.shorthand.js b/src/babel/transformation/transformers/es6/properties.shorthand.js index 5f6830cfb7..b5140ac364 100644 --- a/src/babel/transformation/transformers/es6/properties.shorthand.js +++ b/src/babel/transformation/transformers/es6/properties.shorthand.js @@ -1,9 +1,5 @@ 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; diff --git a/src/babel/transformation/transformers/es6/regex.sticky.js b/src/babel/transformation/transformers/es6/regex.sticky.js index 3227c59635..e298e0501b 100644 --- a/src/babel/transformation/transformers/es6/regex.sticky.js +++ b/src/babel/transformation/transformers/es6/regex.sticky.js @@ -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"), [ diff --git a/src/babel/transformation/transformers/es6/regex.unicode.js b/src/babel/transformation/transformers/es6/regex.unicode.js index 58471da84a..a914f2b529 100644 --- a/src/babel/transformation/transformers/es6/regex.unicode.js +++ b/src/babel/transformation/transformers/es6/regex.unicode.js @@ -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); diff --git a/src/babel/transformation/transformers/es6/spread.js b/src/babel/transformation/transformers/es6/spread.js index a856453ed0..e7c403588a 100644 --- a/src/babel/transformation/transformers/es6/spread.js +++ b/src/babel/transformation/transformers/es6/spread.js @@ -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; diff --git a/src/babel/transformation/transformers/es6/template-literals.js b/src/babel/transformation/transformers/es6/template-literals.js index 10128abaf7..912fcdbbdf 100644 --- a/src/babel/transformation/transformers/es6/template-literals.js +++ b/src/babel/transformation/transformers/es6/template-literals.js @@ -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 = []; diff --git a/src/babel/transformation/transformers/es7/async-functions.js b/src/babel/transformation/transformers/es7/async-functions.js index df6bc46bd4..5059fdd666 100644 --- a/src/babel/transformation/transformers/es7/async-functions.js +++ b/src/babel/transformation/transformers/es7/async-functions.js @@ -1,7 +1,3 @@ export var metadata = { stage: 1 }; - -export function shouldVisit() { - return false; -} diff --git a/src/babel/transformation/transformers/es7/class-properties.js b/src/babel/transformation/transformers/es7/class-properties.js index 9c08f42ae1..871398b386 100644 --- a/src/babel/transformation/transformers/es7/class-properties.js +++ b/src/babel/transformation/transformers/es7/class-properties.js @@ -1,7 +1,3 @@ export var metadata = { stage: 0 }; - -export function shouldVisit() { - return false; -} diff --git a/src/babel/transformation/transformers/es7/decorators.js b/src/babel/transformation/transformers/es7/decorators.js index a67843cf3d..af98294cf8 100644 --- a/src/babel/transformation/transformers/es7/decorators.js +++ b/src/babel/transformation/transformers/es7/decorators.js @@ -7,10 +7,6 @@ export var metadata = { 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++) { diff --git a/src/babel/transformation/transformers/es7/do-expressions.js b/src/babel/transformation/transformers/es7/do-expressions.js index 8f1e18875f..efefe06ba2 100644 --- a/src/babel/transformation/transformers/es7/do-expressions.js +++ b/src/babel/transformation/transformers/es7/do-expressions.js @@ -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) { diff --git a/src/babel/transformation/transformers/es7/export-extensions.js b/src/babel/transformation/transformers/es7/export-extensions.js index 80a11c34ab..77880f3a10 100644 --- a/src/babel/transformation/transformers/es7/export-extensions.js +++ b/src/babel/transformation/transformers/es7/export-extensions.js @@ -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; diff --git a/src/babel/transformation/transformers/es7/trailing-function-commas.js b/src/babel/transformation/transformers/es7/trailing-function-commas.js index df6bc46bd4..5059fdd666 100644 --- a/src/babel/transformation/transformers/es7/trailing-function-commas.js +++ b/src/babel/transformation/transformers/es7/trailing-function-commas.js @@ -1,7 +1,3 @@ export var metadata = { stage: 1 }; - -export function shouldVisit() { - return false; -} diff --git a/src/babel/transformation/transformers/index.js b/src/babel/transformation/transformers/index.js index 05f7c47c41..0c3ea89b1d 100644 --- a/src/babel/transformation/transformers/index.js +++ b/src/babel/transformation/transformers/index.js @@ -1,124 +1,66 @@ export default { "utility.removeDebugger": require("./utility/remove-debugger"), "utility.removeConsole": require("./utility/remove-console"), - "utility.inlineEnvironmentVariables": require("./utility/inline-environment-variables"), "utility.inlineExpressions": require("./utility/inline-expressions"), - "minification.deadCodeElimination": require("./minification/dead-code-elimination"), - _modules: require("./internal/modules"), - "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"), - - // needs to be before `es6.blockScoping` as let variables may be produced "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"), - 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 + runtime: require("./other/runtime"), "es7.exportExtensions": require("./es7/export-extensions"), "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"), - "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") + flow: require("./other/flow"), + _hoistDirectives: require("./internal/hoist-directives"), + _blockHoist: require("./internal/block-hoist") }; diff --git a/src/babel/transformation/transformers/internal/hoist-directives.js b/src/babel/transformation/transformers/internal/hoist-directives.js new file mode 100644 index 0000000000..8c0c1280cf --- /dev/null +++ b/src/babel/transformation/transformers/internal/hoist-directives.js @@ -0,0 +1,16 @@ +import * as t from "../../../types"; + +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 }; diff --git a/src/babel/transformation/transformers/internal/module-formatter.js b/src/babel/transformation/transformers/internal/module-formatter.js index 92ef7baab2..400f27e28a 100644 --- a/src/babel/transformation/transformers/internal/module-formatter.js +++ b/src/babel/transformation/transformers/internal/module-formatter.js @@ -1,8 +1,6 @@ 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/internal/modules.js b/src/babel/transformation/transformers/internal/modules.js index 5953072c27..6d3dfe83c8 100644 --- a/src/babel/transformation/transformers/internal/modules.js +++ b/src/babel/transformation/transformers/internal/modules.js @@ -6,10 +6,6 @@ import * as t from "../../../types"; -export function shouldVisit(node) { - return t.isImportDeclaration(node) || t.isExportDeclaration(node); -} - export function ImportDeclaration(node, parent, scope, file) { if (node.source) { node.source.value = file.resolveModuleSource(node.source.value); diff --git a/src/babel/transformation/transformers/internal/shadow-functions.js b/src/babel/transformation/transformers/internal/shadow-functions.js index 4eb4e5e375..30925d8a8f 100644 --- a/src/babel/transformation/transformers/internal/shadow-functions.js +++ b/src/babel/transformation/transformers/internal/shadow-functions.js @@ -82,21 +82,24 @@ function aliasFunction(getBody, path, scope) { } }; -export function shouldVisit(node) { - return true; -} +// todo: on all `this` and `arguments`, walk UP the tree instead of +// crawling the entire function tree -export function Program(node, parent, scope) { - aliasFunction(function () { - return node.body; - }, this, scope); +export var Program = { + exit(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 var FunctionDeclaration = { + exit(node, parent, scope) { + aliasFunction(function () { + t.ensureBlock(node); + return node.body.body; + }, this, scope); + } +}; export { FunctionDeclaration as FunctionExpression }; diff --git a/src/babel/transformation/transformers/internal/strict.js b/src/babel/transformation/transformers/internal/strict.js deleted file mode 100644 index afc820c665..0000000000 --- a/src/babel/transformation/transformers/internal/strict.js +++ /dev/null @@ -1,19 +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]); - } - this.stop(); -} diff --git a/src/babel/transformation/transformers/internal/validation.js b/src/babel/transformation/transformers/internal/validation.js index 8fab413fdd..da830eabef 100644 --- a/src/babel/transformation/transformers/internal/validation.js +++ b/src/babel/transformation/transformers/internal/validation.js @@ -1,10 +1,6 @@ import * as messages from "../../../messages"; import * as t from "../../../types"; -export var metadata = { - readOnly: true -}; - export function ForOfStatement(node, parent, scope, file) { var left = node.left; if (t.isVariableDeclaration(left)) { @@ -43,16 +39,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 }; diff --git a/src/babel/transformation/transformers/optimisation/flow.for-of.js b/src/babel/transformation/transformers/optimisation/flow.for-of.js index f69525e307..0f031a9b51 100644 --- a/src/babel/transformation/transformers/optimisation/flow.for-of.js +++ b/src/babel/transformation/transformers/optimisation/flow.for-of.js @@ -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 }; diff --git a/src/babel/transformation/transformers/other/flow.js b/src/babel/transformation/transformers/other/flow.js index b3a963e3cc..bb6bf4c393 100644 --- a/src/babel/transformation/transformers/other/flow.js +++ b/src/babel/transformation/transformers/other/flow.js @@ -1,9 +1,5 @@ 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/other/regenerator.js b/src/babel/transformation/transformers/other/regenerator.js index 7c109a92a5..2897527cd1 100644 --- a/src/babel/transformation/transformers/other/regenerator.js +++ b/src/babel/transformation/transformers/other/regenerator.js @@ -1,14 +1,8 @@ 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) { + exit(ast) { regenerator.transform(ast); - this.stop(); - this.checkSelf(); } }; diff --git a/src/babel/transformation/transformers/other/strict.js b/src/babel/transformation/transformers/other/strict.js index 1c8acc2651..1889800b11 100644 --- a/src/babel/transformation/transformers/other/strict.js +++ b/src/babel/transformation/transformers/other/strict.js @@ -1,22 +1,33 @@ 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"); + if (!this.findParent(function (node) { + return !node.shadow && THIS_BREAK_KEYS.indexOf(node.type) >= 0; + })) { + return t.identifier("undefined"); + } } export function CallExpression(node, parent, scope, file) { diff --git a/src/babel/transformation/transformers/spec/block-scoped-functions.js b/src/babel/transformation/transformers/spec/block-scoped-functions.js index b5327d8c0f..ae16f05fcb 100644 --- a/src/babel/transformation/transformers/spec/block-scoped-functions.js +++ b/src/babel/transformation/transformers/spec/block-scoped-functions.js @@ -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; diff --git a/src/babel/transformation/transformers/validation/react.js b/src/babel/transformation/transformers/validation/react.js index 5666f8c299..536aff1768 100644 --- a/src/babel/transformation/transformers/validation/react.js +++ b/src/babel/transformation/transformers/validation/react.js @@ -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)) { diff --git a/src/babel/transformation/transformers/validation/undeclared-variable-check.js b/src/babel/transformation/transformers/validation/undeclared-variable-check.js index 01f1f4a86c..f8d3b25a78 100644 --- a/src/babel/transformation/transformers/validation/undeclared-variable-check.js +++ b/src/babel/transformation/transformers/validation/undeclared-variable-check.js @@ -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) { diff --git a/src/babel/traversal/index.js b/src/babel/traversal/index.js index 1f2ccccf12..80cb1f0c93 100644 --- a/src/babel/traversal/index.js +++ b/src/babel/traversal/index.js @@ -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,7 @@ export default function traverse(parent, opts, scope, state, parentPath) { } if (!opts) opts = {}; - verify(opts); + visitors.verify(opts); // array of nodes if (Array.isArray(parent)) { @@ -26,8 +26,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]; diff --git a/src/babel/traversal/path/index.js b/src/babel/traversal/path/index.js index 14b801de53..23b971a900 100644 --- a/src/babel/traversal/path/index.js +++ b/src/babel/traversal/path/index.js @@ -107,12 +107,43 @@ 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 + */ + + findParent(callback) { + var path = this; + while (path) { + if (callback(path.node)) return path.node; + path = path.parentPath; + } + return null; + } + /** * Description */ queueNode(path) { - if (this.context) { + if (this.context && this.context.queue) { this.context.queue.push(path); } } @@ -136,7 +167,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 +193,6 @@ export default class TraversalPath { paths.push(TraversalPath.get(this, null, node, this.container, to)); } } - - this.checkPaths(paths); } _containerInsertBefore(nodes) { @@ -234,7 +262,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?"); } @@ -528,7 +555,7 @@ export default class TraversalPath { } if (this.node === replacement) { - return this.checkSelf(); + return; } // normalise inserting an entire AST @@ -572,26 +599,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); } /** @@ -691,9 +698,13 @@ export default class TraversalPath { // 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); + if (replacement) { + this.replaceWith(replacement, true); + this.queueNode(this); + break; + } - if (this.shouldStop) break; + if (this.shouldStop || this.removed) break; } } diff --git a/src/babel/traversal/visitors.js b/src/babel/traversal/visitors.js index 8e994c1ccb..f922351d1f 100644 --- a/src/babel/traversal/visitors.js +++ b/src/babel/traversal/visitors.js @@ -36,12 +36,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 +61,7 @@ export function explode(visitor, mergeConflicts) { var existing = visitor[alias]; if (existing) { if (mergeConflicts) { - merge(existing, fns); + mergePair(existing, fns); } } else { visitor[alias] = fns; @@ -105,6 +105,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 +148,7 @@ function addSelector(visitor, selector, fns) { }; } - merge(visitor, fns); + mergePair(visitor, fns); } function wrapCheck(wrapper, fn) { @@ -159,7 +172,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]); } diff --git a/test/core/fixtures/transformation/es6.arrow-functions/arguments/expected.js b/test/core/fixtures/transformation/es6.arrow-functions/arguments/expected.js index b8104fab4d..2972f6b9b1 100644 --- a/test/core/fixtures/transformation/es6.arrow-functions/arguments/expected.js +++ b/test/core/fixtures/transformation/es6.arrow-functions/arguments/expected.js @@ -11,17 +11,17 @@ function one() { one(1, 2); function two() { - var _arguments2 = arguments; + var _arguments3 = arguments; var inner = function inner() { - return _arguments2; + return _arguments3; }; var another = function another() { - var _arguments3 = arguments; + var _arguments2 = arguments; var inner2 = function inner2() { - return _arguments3; + return _arguments2; }; }; @@ -66,4 +66,4 @@ function six(obj) { }; return fn(); } -six(); \ No newline at end of file +six(); diff --git a/test/core/fixtures/transformation/spec.proto-to-assign/assignment-expression/expected.js b/test/core/fixtures/transformation/spec.proto-to-assign/assignment-expression/expected.js index 1a55265b4c..0980420528 100644 --- a/test/core/fixtures/transformation/spec.proto-to-assign/assignment-expression/expected.js +++ b/test/core/fixtures/transformation/spec.proto-to-assign/assignment-expression/expected.js @@ -1,11 +1,11 @@ "use strict"; -function _defaults(obj, defaults) { var keys = Object.getOwnPropertyNames(defaults); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var value = Object.getOwnPropertyDescriptor(defaults, key); if (value && value.configurable && obj[key] === undefined) { Object.defineProperty(obj, key, value); } } return obj; } - var _foo, _foo$bar, _foo$bar2; +function _defaults(obj, defaults) { var keys = Object.getOwnPropertyNames(defaults); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var value = Object.getOwnPropertyDescriptor(defaults, key); if (value && value.configurable && obj[key] === undefined) { Object.defineProperty(obj, key, value); } } return obj; } + console.log((_foo = foo, _defaults(_foo, bar), _foo)); console.log((_foo$bar = foo[bar], _defaults(_foo$bar, bar), _foo$bar)); -console.log((_foo$bar2 = foo[bar()], _defaults(_foo$bar2, bar), _foo$bar2)); \ No newline at end of file +console.log((_foo$bar2 = foo[bar()], _defaults(_foo$bar2, bar), _foo$bar2));