diff --git a/lib/babel/transformation/templates/tail-call-body.js b/lib/babel/transformation/templates/tail-call-body.js index a8391779f8..57c3e5e018 100644 --- a/lib/babel/transformation/templates/tail-call-body.js +++ b/lib/babel/transformation/templates/tail-call-body.js @@ -1,3 +1,4 @@ { - FUNCTION_ID:while (true) BLOCK + var AGAIN_ID = true; + FUNCTION_ID: while (AGAIN_ID) BLOCK } diff --git a/lib/babel/transformation/templates/tail-call.js b/lib/babel/transformation/templates/tail-call.js deleted file mode 100644 index 86fd368be2..0000000000 --- a/lib/babel/transformation/templates/tail-call.js +++ /dev/null @@ -1,23 +0,0 @@ -(function () { - function Tail(func, args, context) { - this.func = func; - this.args = args; - this.context = context; - } - - Tail.prototype._isTailDescriptor = true; - - var isRunning = false; - - return function (func, args, context) { - var result = new Tail(func, args, context); - if (!isRunning) { - isRunning = true; - do { - result = result.func.apply(result.context, result.args); - } while (result instanceof Tail || (result && result._isTailDescriptor)); - isRunning = false; - } - return result; - }; -})() diff --git a/lib/babel/transformation/transformers/es6/tail-call.js b/lib/babel/transformation/transformers/es6/tail-call.js index d326d39c65..17e41d68a7 100644 --- a/lib/babel/transformation/transformers/es6/tail-call.js +++ b/lib/babel/transformation/transformers/es6/tail-call.js @@ -40,6 +40,10 @@ TailCallTransformer.prototype.getFunctionId = function () { return this.functionId = this.functionId || this.scope.generateUidIdentifier("function"); }; +TailCallTransformer.prototype.getAgainId = function () { + return this.againId = this.againId || this.scope.generateUidIdentifier("again"); +}; + TailCallTransformer.prototype.getParams = function () { var params = this.params; @@ -112,9 +116,12 @@ TailCallTransformer.prototype.run = function () { body.unshift(t.variableDeclaration("var", paramDecls)); } - body.push(t.returnStatement()); + body.unshift(t.expressionStatement( + t.assignmentExpression("=", this.getAgainId(), t.literal(false))) + ); node.body = util.template("tail-call-body", { + AGAIN_ID: this.getAgainId(), THIS_ID: this.thisId, ARGUMENTS_ID: this.argumentsId, FUNCTION_ID: this.getFunctionId(), @@ -288,6 +295,9 @@ TailCallTransformer.prototype.subTransformCallExpression = function (node) { } } + body.push(t.expressionStatement( + t.assignmentExpression("=", this.getAgainId(), t.literal(true)) + )); body.push(t.continueStatement(this.getFunctionId())); return body; 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 e4f1e2f6b3..c54d8457eb 100755 --- a/test/fixtures/transformation/es6-tail-call/call-apply/expected.js +++ b/test/fixtures/transformation/es6-tail-call/call-apply/expected.js @@ -4,7 +4,10 @@ var _this = this, _arguments = arguments; - _function: while (true) { + var _again = true; + + _function: while (_again) { + _again = false; var n = _x; if (n <= 0) { @@ -14,10 +17,12 @@ if (Math.random() > 0.5) { _arguments = [_x = n - 1]; + _again = true; continue _function; } else { _arguments = [_x = n - 1]; + _again = true; continue _function; - }return; + } } })(1000000) === "foo"; diff --git a/test/fixtures/transformation/es6-tail-call/expression-consequent/expected.js b/test/fixtures/transformation/es6-tail-call/expression-consequent/expected.js index 8645d2c4a7..fba01025e8 100644 --- a/test/fixtures/transformation/es6-tail-call/expression-consequent/expected.js +++ b/test/fixtures/transformation/es6-tail-call/expression-consequent/expected.js @@ -1,10 +1,14 @@ "use strict"; function f() { - _function: while (true) { + var _again = true; + + _function: while (_again) { + _again = false; + if (true) {} else { + _again = true; continue _function; } - return; } } diff --git a/test/fixtures/transformation/es6-tail-call/expressions/expected.js b/test/fixtures/transformation/es6-tail-call/expressions/expected.js index 1c86593dbf..785a0413cc 100755 --- a/test/fixtures/transformation/es6-tail-call/expressions/expected.js +++ b/test/fixtures/transformation/es6-tail-call/expressions/expected.js @@ -3,7 +3,10 @@ (function f(_x) { var _left; - _function: while (true) { + var _again = true; + + _function: while (_again) { + _again = false; var n = _x; if (n <= 0) { return "foo"; @@ -19,7 +22,8 @@ } _x = n - 1; + _again = true; continue _function; - }return; + } } -})(1000000, true) === "foo"; +})(1000000, true) === "foo"; \ No newline at end of file diff --git a/test/fixtures/transformation/es6-tail-call/factorial/expected.js b/test/fixtures/transformation/es6-tail-call/factorial/expected.js index 61ec9282e0..1450a96726 100644 --- a/test/fixtures/transformation/es6-tail-call/factorial/expected.js +++ b/test/fixtures/transformation/es6-tail-call/factorial/expected.js @@ -2,16 +2,19 @@ function fact(_x2) { var _arguments = arguments; + var _again = true; - _function: while (true) { + _function: while (_again) { + _again = false; var n = _x2; acc = undefined; var acc = _arguments[1] === undefined ? 1 : _arguments[1]; if (n > 1) { _arguments = [_x2 = n - 1, acc * n]; + _again = true; continue _function; } else { return acc; - }return; + } } -} +} \ No newline at end of file diff --git a/test/fixtures/transformation/es6-tail-call/recursion/expected.js b/test/fixtures/transformation/es6-tail-call/recursion/expected.js index 6a33e19173..74551bd894 100755 --- a/test/fixtures/transformation/es6-tail-call/recursion/expected.js +++ b/test/fixtures/transformation/es6-tail-call/recursion/expected.js @@ -2,10 +2,12 @@ (function f(_x2) { var _arguments = arguments; + var _again = true; - _function: while (true) { + _function: while (_again) { var g = function g() {}; + _again = false; var n = _x2; m = local1 = local2 = local3 = undefined; var m = _arguments[1] === undefined ? getDefaultValue() : _arguments[1]; @@ -21,7 +23,7 @@ // `g` should be function here on each pass g = 123; _arguments = [_x2 = n - 1]; + _again = true; continue _function; - return; } -})(1000000, true) === "foo"; +})(1000000, true) === "foo"; \ No newline at end of file diff --git a/test/fixtures/transformation/es6-tail-call/try-catch/expected.js b/test/fixtures/transformation/es6-tail-call/try-catch/expected.js index d911002438..5fbeb6cd4c 100755 --- a/test/fixtures/transformation/es6-tail-call/try-catch/expected.js +++ b/test/fixtures/transformation/es6-tail-call/try-catch/expected.js @@ -11,7 +11,10 @@ })(1000000) === "foo"; (function f(_x) { - _function: while (true) { + var _again = true; + + _function: while (_again) { + _again = false; var n = _x; if (n <= 0) { @@ -22,9 +25,9 @@ throw new Error(); } catch (e) { _x = n - 1; + _again = true; continue _function; } - return; } })(1000000) === "foo"; @@ -41,7 +44,10 @@ })(1000000) === "foo"; (function f(_x) { - _function: while (true) { + var _again = true; + + _function: while (_again) { + _again = false; var n = _x; if (n <= 0) { @@ -50,8 +56,8 @@ try {} finally { _x = n - 1; + _again = true; continue _function; } - return; } -})(1000000) === "foo"; +})(1000000) === "foo"; \ No newline at end of file