diff --git a/lib/6to5/transformation/transformers/es6/tail-call.js b/lib/6to5/transformation/transformers/es6/tail-call.js index b5ff8e71b2..5ad846c8cc 100644 --- a/lib/6to5/transformation/transformers/es6/tail-call.js +++ b/lib/6to5/transformation/transformers/es6/tail-call.js @@ -12,51 +12,21 @@ function transformExpression(node, scope, state) { return (function subTransform(node) { switch (node.type) { case "ConditionalExpression": - var callConsequent = subTransform(node.consequent); - var callAlternate = subTransform(node.alternate); - if (!callConsequent && !callAlternate) { - return; - } - - // if ternary operator had tail recursion in value, convert to optimized if-statement - node.type = "IfStatement"; - node.consequent = callConsequent ? t.toBlock(callConsequent) : returnBlock(node.consequent); - if (callAlternate) { - node.alternate = t.isIfStatement(callAlternate) ? callAlternate : t.toBlock(callAlternate); - } else { - node.alternate = returnBlock(node.alternate); - } - return [node]; + // any value of ternary operator can be final one + subTransform(node.consequent); + subTransform(node.alternate); + break; case "LogicalExpression": - // only call in right-value of can be optimized - var callRight = subTransform(node.right); - if (!callRight) { - return; - } - - var test = state.wrapSideEffect(node.left); - if (node.operator === "&&") { - test.expr = t.unaryExpression("!", test.expr); - } - return [t.ifStatement(test.expr, returnBlock(test.ref))].concat(callRight); + // only right expression can be final and so optimized + subTransform(node.right); + break; case "SequenceExpression": + // only last element of sequence can be optimized var seq = node.expressions; - - // only last element can be optimized - var lastCall = subTransform(seq[seq.length - 1]); - if (!lastCall) { - return; - } - - // remove converted expression from sequence - // and convert to regular expression if needed - if (--seq.length === 1) { - node = seq[0]; - } - - return [t.expressionStatement(node)].concat(lastCall); + subTransform(seq[seq.length - 1]); + break; case "CallExpression": var callee = node.callee, thisBinding; @@ -77,10 +47,9 @@ function transformExpression(node, scope, state) { args.push(thisBinding); } - return [t.returnStatement(t.callExpression( - state.getHelperRef(), - args - ))]; + node.callee = state.getHelperRef(); + node.arguments = args; + break; } })(node); } @@ -92,7 +61,8 @@ var functionChildrenVisitor = { this.skip(); // transform return argument into statement if // it contains tail recursion - return transformExpression(node.argument, scope, state); + transformExpression(node.argument, scope, state); + return; } else if (t.isFunction(node)) { return this.skip(); } else if (t.isTryStatement(parent)) { diff --git a/test/fixtures/transformation/es6-tail-call/call-apply/expected.js b/test/fixtures/transformation/es6-tail-call/call-apply/expected.js index 9224827414..5e763b2f23 100644 --- a/test/fixtures/transformation/es6-tail-call/call-apply/expected.js +++ b/test/fixtures/transformation/es6-tail-call/call-apply/expected.js @@ -5,9 +5,5 @@ console.log(this, arguments); return "foo"; } - if (Math.random() > 0.5) { - return to5Runtime.tailCall(f.call, [this, n - 1], f); - } else { - return to5Runtime.tailCall(f.apply, [this, [n - 1]], f); - } + return Math.random() > 0.5 ? to5Runtime.tailCall(f.call, [this, n - 1], f) : to5Runtime.tailCall(f.apply, [this, [n - 1]], f); })(1000000) === "foo"; diff --git a/test/fixtures/transformation/es6-tail-call/cross-function/actual.js b/test/fixtures/transformation/es6-tail-call/cross-function/actual.js index 289cfe3893..173a50bb62 100644 --- a/test/fixtures/transformation/es6-tail-call/cross-function/actual.js +++ b/test/fixtures/transformation/es6-tail-call/cross-function/actual.js @@ -1,7 +1,7 @@ function f(n) { - return n <= 0 ? "foo" : g(n - 1); + return n <= 0 ? "foo" : g(n - 1); } function g(n) { - return n <= 0 ? "goo" : f(n - 1); + return n <= 0 ? "goo" : f(n - 1); } diff --git a/test/fixtures/transformation/es6-tail-call/cross-function/expected.js b/test/fixtures/transformation/es6-tail-call/cross-function/expected.js index 6c4743fba4..9f3c8cbd66 100644 --- a/test/fixtures/transformation/es6-tail-call/cross-function/expected.js +++ b/test/fixtures/transformation/es6-tail-call/cross-function/expected.js @@ -1,17 +1,9 @@ "use strict"; function f(n) { - if (n <= 0) { - return "foo"; - } else { - return to5Runtime.tailCall(g, [n - 1]); - } + return n <= 0 ? "foo" : to5Runtime.tailCall(g, [n - 1]); } function g(n) { - if (n <= 0) { - return "goo"; - } else { - return to5Runtime.tailCall(f, [n - 1]); - } + return n <= 0 ? "goo" : to5Runtime.tailCall(f, [n - 1]); } diff --git a/test/fixtures/transformation/es6-tail-call/expressions/expected.js b/test/fixtures/transformation/es6-tail-call/expressions/expected.js index 4d778083a9..466a76628f 100644 --- a/test/fixtures/transformation/es6-tail-call/expressions/expected.js +++ b/test/fixtures/transformation/es6-tail-call/expressions/expected.js @@ -1,18 +1,5 @@ "use strict"; (function f(n) { - var _temp; - if (n <= 0) { - return "foo"; - } else { - doSmth(); - - if (!(_temp = getTrueValue())) { - return _temp; - } - if (_temp = getFalseValue()) { - return _temp; - } - return to5Runtime.tailCall(f, [n - 1]); - } + return n <= 0 ? "foo" : (doSmth(), getTrueValue() && (getFalseValue() || to5Runtime.tailCall(f, [n - 1]))); })(1000000, true) === "foo"; diff --git a/test/fixtures/transformation/es6-tail-call/side-effect/actual.js b/test/fixtures/transformation/es6-tail-call/side-effect/actual.js index 249d520be4..3bcab98c40 100644 --- a/test/fixtures/transformation/es6-tail-call/side-effect/actual.js +++ b/test/fixtures/transformation/es6-tail-call/side-effect/actual.js @@ -1,5 +1,5 @@ function f() { - return getObj().method(); + return getObj().method(); } function g() { diff --git a/test/fixtures/transformation/es6-tail-call/side-effect/expected.js b/test/fixtures/transformation/es6-tail-call/side-effect/expected.js index bd18748164..f7598aa5b8 100644 --- a/test/fixtures/transformation/es6-tail-call/side-effect/expected.js +++ b/test/fixtures/transformation/es6-tail-call/side-effect/expected.js @@ -6,9 +6,5 @@ function f() { } function g() { - var _temp; - if (_temp = getFalseValue()) { - return _temp; - } - return to5Runtime.tailCall(getValue); + return getFalseValue() || to5Runtime.tailCall(getValue); }