diff --git a/src/babel/transformation/transformers/es6/tail-call.js b/src/babel/transformation/transformers/es6/tail-call.js index 78eb809380..3168f8ce02 100644 --- a/src/babel/transformation/transformers/es6/tail-call.js +++ b/src/babel/transformation/transformers/es6/tail-call.js @@ -34,6 +34,12 @@ var visitor = { return state.subTransform(node.argument); }, + ExpressionStatement(node, parent, scope, state) { + if (this.isCompletionRecord(true)) { + return state.subTransform(node.expression); + } + }, + Function() { this.skip(); }, diff --git a/src/babel/traversal/path/verification.js b/src/babel/traversal/path/verification.js index 19b2e84c1b..5ef4caa171 100644 --- a/src/babel/traversal/path/verification.js +++ b/src/babel/traversal/path/verification.js @@ -121,17 +121,20 @@ export function isPreviousType(type: string): boolean { * Check whether the current path references a completion record */ -export function isCompletionRecord() { +export function isCompletionRecord(allowInsideFunction?) { var path = this; + var first = true; do { var container = path.container; // we're in a function so can't be a completion record - if (path.isFunctionDeclaration()) { - return false; + if (path.isFunction() && !first) { + return !!allowInsideFunction; } + first = false; + // check to see if we're the last item in the container and if we are // we're a completion record! if (Array.isArray(container) && path.key !== container.length - 1) { diff --git a/test/core/fixtures/transformation/es6.tail-call/shadow/expected.js b/test/core/fixtures/transformation/es6.tail-call/shadow/expected.js index 82f39882d9..c5f7327030 100644 --- a/test/core/fixtures/transformation/es6.tail-call/shadow/expected.js +++ b/test/core/fixtures/transformation/es6.tail-call/shadow/expected.js @@ -2,12 +2,19 @@ (function () { var _this = this, - _arguments = arguments; + _arguments2 = arguments; var foo = function foo() { - _this; - _arguments; - foo(); + var _again = true; + + _function: while (_again) { + _again = false; + + _this; + _arguments2; + _again = true; + continue _function; + } }; foo(); }); diff --git a/test/core/fixtures/transformation/es6.tail-call/void/actual.js b/test/core/fixtures/transformation/es6.tail-call/void/actual.js new file mode 100644 index 0000000000..7a4a757979 --- /dev/null +++ b/test/core/fixtures/transformation/es6.tail-call/void/actual.js @@ -0,0 +1,11 @@ +function skipWhile(cond) { + if (!hasNext() || cond(current, last)) return; + move(); + skipWhile(cond); +} + +var skipWhile2 = function (cond) { + if (!hasNext() || cond(current, last)) return; + move(); + skipWhile2(cond); +}; diff --git a/test/core/fixtures/transformation/es6.tail-call/void/expected.js b/test/core/fixtures/transformation/es6.tail-call/void/expected.js new file mode 100644 index 0000000000..36a4e6446d --- /dev/null +++ b/test/core/fixtures/transformation/es6.tail-call/void/expected.js @@ -0,0 +1,31 @@ +"use strict"; + +function skipWhile(_x) { + var _again = true; + + _function: while (_again) { + var cond = _x; + _again = false; + + if (!hasNext() || cond(current, last)) return; + move(); + _x = cond; + _again = true; + continue _function; + } +} + +var skipWhile2 = function skipWhile2(_x2) { + var _again2 = true; + + _function2: while (_again2) { + var cond = _x2; + _again2 = false; + + if (!hasNext() || cond(current, last)) return; + move(); + _x2 = cond; + _again2 = true; + continue _function2; + } +};