Compare commits

...

28 Commits

Author SHA1 Message Date
Sebastian McKenzie
fdda013d07 v3.5.3 2015-02-08 22:17:05 +11:00
Sebastian McKenzie
64477d934d add 3.5.3 changelog 2015-02-08 22:10:00 +11:00
Sebastian McKenzie
45c507056a add back old tail call implementation 2015-02-08 22:09:41 +11:00
Sebastian McKenzie
730b96c195 3.5.2 2015-02-08 21:23:55 +11:00
Sebastian McKenzie
a185f91433 v3.5.2 2015-02-08 21:23:24 +11:00
Sebastian McKenzie
d053622802 add 3.5.2 changelog 2015-02-08 21:21:38 +11:00
Sebastian McKenzie
74d6b61973 disable es6 tail call tests 2015-02-08 21:21:32 +11:00
Sebastian McKenzie
97784c8cca comment out tailCall transformer 2015-02-08 21:19:01 +11:00
Sebastian McKenzie
812d93553a temporairly disable tailCall transformer 2015-02-08 21:17:21 +11:00
Sebastian McKenzie
d251b4cb56 3.5.1 2015-02-08 21:16:34 +11:00
Sebastian McKenzie
caf38e1962 v3.5.1 2015-02-08 21:04:05 +11:00
Sebastian McKenzie
4ccbee4639 fix linting errors 2015-02-08 20:59:48 +11:00
Sebastian McKenzie
84196a3a07 add 3.5.1 changelog 2015-02-08 20:57:58 +11:00
Ingvar Stepanyan
29361c055a Fix #718. 2015-02-08 11:56:39 +02:00
Sebastian McKenzie
4277265591 Merge branch 'master' of github.com:6to5/6to5 2015-02-08 20:40:47 +11:00
Sebastian McKenzie
812a2b315d bump acorn-6to5 2015-02-08 20:40:30 +11:00
Ingvar Stepanyan
0a1724fc3f Remove no more needed returnBlock helper. 2015-02-08 11:31:19 +02:00
Sebastian McKenzie
bcc9e016b1 only evaluate object destructuring pattern once 2015-02-08 20:23:22 +11:00
Sebastian McKenzie
4ea0175ca7 simplify set template 2015-02-08 20:23:22 +11:00
Sebastian McKenzie
799445c745 add property method assignment wrapper generator template 2015-02-08 20:23:22 +11:00
Sebastian McKenzie
481ea12999 add cleanup internal transformer 2015-02-08 20:23:22 +11:00
Sebastian McKenzie
de6b608dda add _declarations and _scopeInfo to t.inherits 2015-02-08 20:23:21 +11:00
Sebastian McKenzie
606f813822 enable traceur test suite by default 2015-02-08 20:23:21 +11:00
Sebastian McKenzie
e06c8cd106 support generators in nameMethod helper 2015-02-08 20:23:21 +11:00
Ingvar Stepanyan
9e3c67a8a2 Clean up functionChildrenVisitor a bit. 2015-02-08 10:53:09 +02:00
Ingvar Stepanyan
91362f80b1 Clean up transformations after #714.
Since now we have runtime helper, we don't need
expression -> statement conversions anymore.
2015-02-08 10:40:03 +02:00
Sebastian McKenzie
cde988f99f update 3.5.0 changelog 2015-02-08 16:53:33 +11:00
Sebastian McKenzie
9ec0854659 3.5.0 2015-02-08 16:37:13 +11:00
42 changed files with 560 additions and 145 deletions

View File

@@ -11,6 +11,21 @@
_Note: Gaps between patch versions are faulty/broken releases._
## 3.5.3
* Enable `es6.tailCall` transformer with the first implementation that only works with self referencing calls until we can implement nested tail calls elegantly.
## 3.5.2
* Disable `es6.tailCall` temporairly after reports of it breaking.
## 3.5.1
* **Polish**
* Allow tail calls to work across files without the runtime.
* **Internal**
* Upgrade `acorn-6to5`.
## 3.5.0
* **Bug Fix**
@@ -18,6 +33,9 @@ _Note: Gaps between patch versions are faulty/broken releases._
* **Polish**
* Make default parameter IIFE invocation smarter.
* Make `__esModule` flag non-enumerable. Thanks [@daliwali](https://github.com/daliwali)!
* **Internal**
* More performance improvements.
* Parsing is now ~30% faster thanks to [marijnh/acorn@7264bc0178e7e6af7cfe02e9e0c6b26ee0e6007f](https://github.com/marijnh/acorn/commit/7264bc0178e7e6af7cfe02e9e0c6b26ee0e6007f).
* **New Feature**
* Optional `es6.blockScopingTDZ` is now completely functional and handles all edgecases.
* `super` in object literals.

View File

@@ -36,15 +36,18 @@ exports.property = function (node, file, scope) {
scope.traverse(node, visitor, state);
var method = node.value;
if (state.selfReference) {
// todo: support generators
node.value = util.template("property-method-assignment-wrapper", {
FUNCTION: node.value,
var templateName = "property-method-assignment-wrapper";
if (method.generator) templateName += "-generator";
node.value = util.template(templateName, {
FUNCTION: method,
FUNCTION_ID: key,
FUNCTION_KEY: scope.generateUidIdentifier(id),
WRAPPER_KEY: scope.generateUidIdentifier(id + "Wrapper")
});
} else {
node.value.id = key;
method.id = key;
}
};

View File

@@ -0,0 +1,11 @@
(function (FUNCTION_KEY) {
var WRAPPER_KEY = function* FUNCTION_ID() {
return yield* FUNCTION_KEY.apply(this, arguments);
};
WRAPPER_KEY.toString = function () {
return FUNCTION_KEY.toString();
};
return WRAPPER_KEY;
})(FUNCTION)

View File

@@ -4,21 +4,16 @@
if (desc === undefined) {
var parent = Object.getPrototypeOf(object);
if (parent === null) {
return;
} else {
if (parent !== null) {
return set(parent, property, value, receiver);
}
} else if ("value" in desc && desc.writable) {
desc.value = value;
return;
return desc.value = value;
} else {
var setter = desc.set;
if (setter === undefined) {
return;
if (setter !== undefined) {
return setter.call(receiver, value);
}
return setter.call(receiver, value);
}
});

View File

@@ -0,0 +1,13 @@
{
var ARGUMENTS_ID = arguments,
THIS_ID = this,
SHOULD_CONTINUE_ID,
RESULT_ID;
do {
SHOULD_CONTINUE_ID = false;
RESULT_ID = FUNCTION.apply(THIS_ID, ARGUMENTS_ID);
} while(SHOULD_CONTINUE_ID);
return RESULT_ID;
}

View File

@@ -5,6 +5,8 @@
this.context = context;
}
Tail.prototype._isTailDescriptor = true;
var isRunning = false;
return function (func, args, context) {
@@ -13,7 +15,7 @@
isRunning = true;
do {
result = result.func.apply(result.context, result.args);
} while (result instanceof Tail);
} while (result instanceof Tail || (result && result._isTailDescriptor));
isRunning = false;
}
return result;

View File

@@ -0,0 +1,116 @@
"use strict";
var t = require("../../../types");
function transformExpression(node, scope, state) {
if (!node) return;
return (function subTransform(node) {
switch (node.type) {
case "ConditionalExpression":
// any value of ternary operator can be final one
subTransform(node.consequent);
subTransform(node.alternate);
break;
case "LogicalExpression":
// 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;
subTransform(seq[seq.length - 1]);
break;
case "CallExpression":
var callee = node.callee, thisBinding;
var args = [callee];
// bind `this` to object in member expressions
if (t.isMemberExpression(callee)) {
var object = state.wrapSideEffect(callee.object);
callee.object = object.expr;
thisBinding = object.ref;
}
if (node.arguments.length > 0 || thisBinding) {
args.push(t.arrayExpression(node.arguments));
}
if (thisBinding) {
args.push(thisBinding);
}
node.callee = state.getHelperRef();
node.arguments = args;
break;
}
})(node);
}
var functionChildrenVisitor = {
enter: function (node, parent, scope, state) {
if (t.isReturnStatement(node)) {
// prevent entrance by current visitor
this.skip();
// transform return argument into statement if
// it contains tail recursion
transformExpression(node.argument, scope, state);
} else if (t.isFunction(node)) {
// inner function's bodies are irrelevant
this.skip();
} else if (t.isTryStatement(parent)) {
if (node === parent.block) {
// `try`-blocks can't be optimized
this.skip();
} else if (parent.finalizer && node !== parent.finalizer) {
// `catch` clause followed by `finally` can't be optimized
this.skip();
}
}
}
};
var functionVisitor = {
enter: function (node, parent, scope, state) {
// traverse all child nodes of this function and find `arguments` and `this`
scope.traverse(node, functionChildrenVisitor, state);
return this.skip();
}
};
exports.FunctionDeclaration =
exports.FunctionExpression = function (node, parent, scope, file) {
var tempId, helperRef;
var state = {
ownerId: node.id,
getHelperRef: function () {
return helperRef = helperRef || file.addHelper("tail-call");
},
wrapSideEffect: function (node) {
if (t.isIdentifier(node) || t.isLiteral(node)) {
return {expr: node, ref: node};
}
tempId = tempId || scope.generateUidIdentifier("temp");
return {
expr: t.assignmentExpression("=", tempId, node),
ref: tempId
};
}
};
// traverse the function and look for tail recursion
scope.traverse(node, functionVisitor, state);
if (tempId) {
t.ensureBlock(node).body.unshift(t.variableDeclaration("var", [
t.variableDeclarator(tempId)
]));
}
};

View File

@@ -112,6 +112,12 @@ Destructuring.prototype.pushObjectPattern = function (pattern, parentId) {
));
}
if (pattern.properties.length > 1 && t.isMemberExpression(parentId)) {
var temp = this.scope.generateUidBasedOnNode(parentId, this.file);
this.nodes.push(this.buildVariableDeclaration(temp, parentId));
parentId = temp;
}
for (var i = 0; i < pattern.properties.length; i++) {
var prop = pattern.properties[i];
if (t.isSpreadProperty(prop)) {

View File

@@ -27,7 +27,8 @@ exports.ForOfStatement = function (node, parent, scope, file) {
// push the rest of the original loop body onto our new body
block.body = block.body.concat(node.body.body);
block._declarations = node.body._declarations;
t.inherits(loop, node);
// todo: find out why this is necessary? #538
loop._scopeInfo = node._scopeInfo;

View File

@@ -1,5 +1,6 @@
"use strict";
var util = require("../../../util");
var t = require("../../../types");
function returnBlock(expr) {
@@ -26,7 +27,7 @@ function transformExpression(node, scope, state) {
} else {
node.alternate = returnBlock(node.alternate);
}
return [node];
return node;
case "LogicalExpression":
// only call in right-value of can be optimized
@@ -35,11 +36,17 @@ function transformExpression(node, scope, state) {
return;
}
var test = state.wrapSideEffect(node.left);
// cache left value as it might have side-effects
var leftId = state.getLeftId();
var testExpr = t.assignmentExpression(
"=",
leftId,
node.left
);
if (node.operator === "&&") {
test.expr = t.unaryExpression("!", test.expr);
testExpr = t.unaryExpression("!", testExpr);
}
return [t.ifStatement(test.expr, returnBlock(test.ref))].concat(callRight);
return [t.ifStatement(testExpr, returnBlock(leftId))].concat(callRight);
case "SequenceExpression":
var seq = node.expressions;
@@ -59,28 +66,53 @@ function transformExpression(node, scope, state) {
return [t.expressionStatement(node)].concat(lastCall);
case "CallExpression":
var callee = node.callee, thisBinding;
var args = [callee];
var callee = node.callee, prop, thisBinding, args;
// bind `this` to object in member expressions
if (t.isMemberExpression(callee)) {
var object = state.wrapSideEffect(callee.object);
callee.object = object.expr;
thisBinding = object.ref;
if (t.isMemberExpression(callee, { computed: false }) &&
t.isIdentifier(prop = callee.property)) {
switch (prop.name) {
case "call":
args = t.arrayExpression(node.arguments.slice(1));
break;
case "apply":
args = node.arguments[1] || t.identifier("undefined");
break;
default:
return;
}
thisBinding = node.arguments[0];
callee = callee.object;
}
if (node.arguments.length > 0 || thisBinding) {
args.push(t.arrayExpression(node.arguments));
// only tail recursion can be optimized as for now
if (!t.isIdentifier(callee) || !scope.bindingEquals(callee.name, state.ownerId)) {
return;
}
if (thisBinding) {
args.push(thisBinding);
}
state.hasTailRecursion = true;
return [t.returnStatement(t.callExpression(
state.getHelperRef(),
args
))];
return [
t.expressionStatement(t.assignmentExpression(
"=",
state.getArgumentsId(),
args || t.arrayExpression(node.arguments)
)),
t.expressionStatement(t.assignmentExpression(
"=",
state.getThisId(),
thisBinding || t.identifier("undefined")
)),
t.returnStatement(t.assignmentExpression(
"=",
state.getShouldContinueId(),
t.literal(true)
))
];
}
})(node);
}
@@ -120,34 +152,56 @@ var functionVisitor = {
};
exports.FunctionDeclaration =
exports.FunctionExpression = function (node, parent, scope, file) {
var tempId, helperRef;
exports.FunctionExpression = function (node, parent, scope) {
// only tail recursion can be optimized as for now,
// so we can skip anonymous functions entirely
var ownerId = node.id;
if (!ownerId) return;
var argumentsId, thisId, shouldContinueId, leftId;
var state = {
ownerId: node.id,
hasTailRecursion: false,
ownerId: ownerId,
getHelperRef: function () {
return helperRef = helperRef || file.addHelper("tail-call");
getArgumentsId: function () {
return argumentsId = argumentsId || scope.generateUidIdentifier("arguments");
},
wrapSideEffect: function (node) {
if (t.isIdentifier(node) || t.isLiteral(node)) {
return {expr: node, ref: node};
}
tempId = tempId || scope.generateUidIdentifier("temp");
return {
expr: t.assignmentExpression("=", tempId, node),
ref: tempId
};
getThisId: function () {
return thisId = thisId || scope.generateUidIdentifier("this");
},
getShouldContinueId: function () {
return shouldContinueId = shouldContinueId || scope.generateUidIdentifier("shouldContinue");
},
getLeftId: function () {
return leftId = leftId || scope.generateUidIdentifier("left");
}
};
// traverse the function and look for tail recursion
scope.traverse(node, functionVisitor, state);
if (tempId) {
t.ensureBlock(node).body.unshift(t.variableDeclaration("var", [
t.variableDeclarator(tempId)
if (!state.hasTailRecursion) return;
var block = t.ensureBlock(node);
if (leftId) {
block.body.unshift(t.variableDeclaration("var", [
t.variableDeclarator(leftId)
]));
}
var resultId = scope.generateUidIdentifier("result");
state.getShouldContinueId();
node.body = util.template("tail-call-body", {
SHOULD_CONTINUE_ID: shouldContinueId,
ARGUMENTS_ID: argumentsId,
RESULT_ID: resultId,
FUNCTION: t.functionExpression(null, node.params, block),
THIS_ID: thisId,
});
};

View File

@@ -92,5 +92,7 @@ module.exports = {
"minification.removeDebugger": require("./minification/remove-debugger"),
"minification.removeConsoleCalls": require("./minification/remove-console-calls"),
"minification.deadCodeElimination": require("./minification/dead-code-elimination"),
"minification.renameLocalVariables": require("./minification/rename-local-variables")
"minification.renameLocalVariables": require("./minification/rename-local-variables"),
_cleanUp: require("./internal/cleanup")
};

View File

@@ -0,0 +1,5 @@
exports.SequenceExpression = function (node) {
if (node.expressions.length === 1) {
return node.expressions[0];
}
};

View File

@@ -690,10 +690,12 @@ t.inheritsComments = function (child, parent) {
*/
t.inherits = function (child, parent) {
child.range = parent.range;
child.start = parent.start;
child.loc = parent.loc;
child.end = parent.end;
child._declarations = parent._declarations;
child._scopeInfo = parent._scopeInfo;
child.range = parent.range;
child.start = parent.start;
child.loc = parent.loc;
child.end = parent.end;
t.inheritsComments(child, parent);
return child;
};

View File

@@ -1,7 +1,7 @@
{
"name": "6to5",
"description": "Turn ES6 code into readable vanilla ES5 with source maps",
"version": "3.5.0",
"version": "3.5.3",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://6to5.org/",
"repository": "6to5/6to5",
@@ -33,7 +33,7 @@
"test": "make test"
},
"dependencies": {
"acorn-6to5": "0.11.1-27",
"acorn-6to5": "0.11.1-28",
"ast-types": "~0.6.1",
"chalk": "^0.5.1",
"chokidar": "0.12.6",

View File

@@ -1,7 +1,7 @@
{
"name": "6to5-runtime",
"description": "6to5 selfContained runtime",
"version": "3.4.1",
"version": "3.5.2",
"repository": "6to5/6to5",
"author": "Sebastian McKenzie <sebmck@gmail.com>"
}

View File

@@ -37,6 +37,8 @@ chai.assert.throw = function (fn, msg) {
msg = "Generator is already running";
} else if (msg === "Sent value to newborn generator") {
msg = /^attempt to send (.*?) to newborn generator$/;
} else if (msg === "super prototype must be an Object or null") {
msg = "Object prototype may only be an Object or null";
}
return chai.assert._throw(fn, msg);

View File

@@ -0,0 +1,7 @@
(function f(n) {
if (n <= 0) {
console.log(this, arguments);
return "foo";
}
return Math.random() > 0.5 ? f.call(this, n - 1) : f.apply(this, [n - 1]);
})(1e6) === "foo";

View File

@@ -0,0 +1,9 @@
"use strict";
(function f(n) {
if (n <= 0) {
console.log(this, arguments);
return "foo";
}
return Math.random() > 0.5 ? to5Runtime.tailCall(f.call, [this, n - 1], f) : to5Runtime.tailCall(f.apply, [this, [n - 1]], f);
})(1000000) === "foo";

View File

@@ -0,0 +1,7 @@
function f(n) {
return n <= 0 ? "foo" : g(n - 1);
}
function g(n) {
return n <= 0 ? "goo" : f(n - 1);
}

View File

@@ -0,0 +1,9 @@
"use strict";
function f(n) {
return n <= 0 ? "foo" : to5Runtime.tailCall(g, [n - 1]);
}
function g(n) {
return n <= 0 ? "goo" : to5Runtime.tailCall(f, [n - 1]);
}

View File

@@ -0,0 +1,3 @@
(function f(n) {
return n <= 0 ? "foo" : (doSmth(), getTrueValue() && (getFalseValue() || f(n - 1)));
})(1e6, true) === "foo";

View File

@@ -0,0 +1,5 @@
"use strict";
(function f(n) {
return n <= 0 ? "foo" : (doSmth(), getTrueValue() && (getFalseValue() || to5Runtime.tailCall(f, [n - 1])));
})(1000000, true) === "foo";

View File

@@ -0,0 +1,8 @@
(function f(n = getDefaultValue(), /* should be undefined after first pass */ m) {
if (n <= 0) {
return "foo";
}
// Should be clean (undefined) on each pass
var local;
return f(n - 1);
})(1e6, true) === "foo";

View File

@@ -0,0 +1,11 @@
"use strict";
(function f(_x, /* should be undefined after first pass */m) {
var n = arguments[0] === undefined ? getDefaultValue() : arguments[0];
if (n <= 0) {
return "foo";
}
// Should be clean (undefined) on each pass
var local;
return to5Runtime.tailCall(f, [n - 1]);
})(1000000, true) === "foo";

View File

@@ -1,5 +1,5 @@
function f() {
return getObj().method();
return getObj().method();
}
function g() {

View File

@@ -6,9 +6,5 @@ function f() {
}
function g() {
var _temp;
if (_temp = getFalseValue()) {
return _temp;
}
return to5Runtime.tailCall(getValue);
return getFalseValue() || to5Runtime.tailCall(getValue);
}

View File

@@ -0,0 +1,39 @@
(function f(n) {
if (n <= 0) {
return "foo";
}
try {
return f(n - 1);
} catch (e) {}
})(1e6) === "foo";
(function f(n) {
if (n <= 0) {
return "foo";
}
try {
throw new Error();
} catch (e) {
return f(n - 1);
}
})(1e6) === "foo";
(function f(n) {
if (n <= 0) {
return "foo";
}
try {
throw new Error();
} catch (e) {
return f(n - 1);
} finally {}
})(1e6) === "foo";
(function f(n) {
if (n <= 0) {
return "foo";
}
try {} finally {
return f(n - 1);
}
})(1e6) === "foo";

View File

@@ -0,0 +1,41 @@
"use strict";
(function f(n) {
if (n <= 0) {
return "foo";
}
try {
return f(n - 1);
} catch (e) {}
})(1000000) === "foo";
(function f(n) {
if (n <= 0) {
return "foo";
}
try {
throw new Error();
} catch (e) {
return to5Runtime.tailCall(f, [n - 1]);
}
})(1000000) === "foo";
(function f(n) {
if (n <= 0) {
return "foo";
}
try {
throw new Error();
} catch (e) {
return f(n - 1);
} finally {}
})(1000000) === "foo";
(function f(n) {
if (n <= 0) {
return "foo";
}
try {} finally {
return to5Runtime.tailCall(f, [n - 1]);
}
})(1000000) === "foo";

View File

@@ -1,6 +1,8 @@
"use strict";
var x1 = rect.topLeft.x;
var y1 = rect.topLeft.y;
var x2 = rect.bottomRight.x;
var y2 = rect.bottomRight.y;
var _rect$topLeft = rect.topLeft;
var x1 = _rect$topLeft.x;
var y1 = _rect$topLeft.y;
var _rect$bottomRight = rect.bottomRight;
var x2 = _rect$bottomRight.x;
var y2 = _rect$bottomRight.y;

View File

@@ -3,10 +3,12 @@
var _slicedToArray = function (arr, i) { if (Array.isArray(arr)) { return arr; } else { var _arr = []; for (var _iterator = arr[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) { _arr.push(_step.value); if (i && _arr.length === i) break; } return _arr; } };
function somethingAdvanced(_ref) {
var x1 = _ref.topLeft.x;
var y1 = _ref.topLeft.y;
var x2 = _ref.bottomRight.x;
var y2 = _ref.bottomRight.y;
var _ref$topLeft = _ref.topLeft;
var x1 = _ref$topLeft.x;
var y1 = _ref$topLeft.y;
var _ref$bottomRight = _ref.bottomRight;
var x2 = _ref$bottomRight.x;
var y2 = _ref$bottomRight.y;
}
function unpackObject(_ref) {

0
test/fixtures/transformation/es6-tail-call/call-apply/actual.js vendored Normal file → Executable file
View File

32
test/fixtures/transformation/es6-tail-call/call-apply/expected.js vendored Normal file → Executable file
View File

@@ -1,13 +1,27 @@
"use strict";
(function f(n) {
if (n <= 0) {
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);
}
var _arguments = arguments,
_this = this,
_shouldContinue,
_result;
do {
_shouldContinue = false;
_result = (function (n) {
if (n <= 0) {
console.log(this, arguments);
return "foo";
}
if (Math.random() > 0.5) {
_arguments = [n - 1];
_this = this;
return _shouldContinue = true;
} else {
_arguments = [n - 1];
_this = this;
return _shouldContinue = true;
}
}).apply(_this, _arguments);
} while (_shouldContinue);
return _result;
})(1000000) === "foo";

View File

@@ -1,7 +0,0 @@
function f(n) {
return n <= 0 ? "foo" : g(n - 1);
}
function g(n) {
return n <= 0 ? "goo" : f(n - 1);
}

View File

@@ -1,17 +0,0 @@
"use strict";
function f(n) {
if (n <= 0) {
return "foo";
} else {
return to5Runtime.tailCall(g, [n - 1]);
}
}
function g(n) {
if (n <= 0) {
return "goo";
} else {
return to5Runtime.tailCall(f, [n - 1]);
}
}

0
test/fixtures/transformation/es6-tail-call/expressions/actual.js vendored Normal file → Executable file
View File

38
test/fixtures/transformation/es6-tail-call/expressions/expected.js vendored Normal file → Executable file
View File

@@ -1,18 +1,30 @@
"use strict";
(function f(n) {
var _temp;
if (n <= 0) {
return "foo";
} else {
doSmth();
var _arguments = arguments,
_this = this,
_shouldContinue,
_result;
do {
_shouldContinue = false;
_result = (function (n) {
var _left;
if (n <= 0) {
return "foo";
} else {
doSmth();
if (!(_temp = getTrueValue())) {
return _temp;
}
if (_temp = getFalseValue()) {
return _temp;
}
return to5Runtime.tailCall(f, [n - 1]);
}
if (!(_left = getTrueValue())) {
return _left;
}
if (_left = getFalseValue()) {
return _left;
}
_arguments = [n - 1];
_this = undefined;
return _shouldContinue = true;
}
}).apply(_this, _arguments);
} while (_shouldContinue);
return _result;
})(1000000, true) === "foo";

0
test/fixtures/transformation/es6-tail-call/recursion/actual.js vendored Normal file → Executable file
View File

26
test/fixtures/transformation/es6-tail-call/recursion/expected.js vendored Normal file → Executable file
View File

@@ -1,11 +1,23 @@
"use strict";
(function f(_x, /* should be undefined after first pass */m) {
var n = arguments[0] === undefined ? getDefaultValue() : arguments[0];
if (n <= 0) {
return "foo";
}
// Should be clean (undefined) on each pass
var local;
return to5Runtime.tailCall(f, [n - 1]);
var _arguments = arguments,
_this = this,
_shouldContinue,
_result;
do {
_shouldContinue = false;
_result = (function (_x, m) {
var n = arguments[0] === undefined ? getDefaultValue() : arguments[0];
if (n <= 0) {
return "foo";
}
// Should be clean (undefined) on each pass
var local;
_arguments = [n - 1];
_this = undefined;
return _shouldContinue = true;
}).apply(_this, _arguments);
} while (_shouldContinue);
return _result;
})(1000000, true) === "foo";

0
test/fixtures/transformation/es6-tail-call/try-catch/actual.js vendored Normal file → Executable file
View File

52
test/fixtures/transformation/es6-tail-call/try-catch/expected.js vendored Normal file → Executable file
View File

@@ -10,14 +10,26 @@
})(1000000) === "foo";
(function f(n) {
if (n <= 0) {
return "foo";
}
try {
throw new Error();
} catch (e) {
return to5Runtime.tailCall(f, [n - 1]);
}
var _arguments = arguments,
_this = this,
_shouldContinue,
_result;
do {
_shouldContinue = false;
_result = (function (n) {
if (n <= 0) {
return "foo";
}
try {
throw new Error();
} catch (e) {
_arguments = [n - 1];
_this = undefined;
return _shouldContinue = true;
}
}).apply(_this, _arguments);
} while (_shouldContinue);
return _result;
})(1000000) === "foo";
(function f(n) {
@@ -32,10 +44,22 @@
})(1000000) === "foo";
(function f(n) {
if (n <= 0) {
return "foo";
}
try {} finally {
return to5Runtime.tailCall(f, [n - 1]);
}
var _arguments = arguments,
_this = this,
_shouldContinue,
_result;
do {
_shouldContinue = false;
_result = (function (n) {
if (n <= 0) {
return "foo";
}
try {} finally {
_arguments = [n - 1];
_this = undefined;
return _shouldContinue = true;
}
}).apply(_this, _arguments);
} while (_shouldContinue);
return _result;
})(1000000) === "foo";

View File

@@ -1,5 +1,3 @@
if (!process.env.ALL_6TO5_TESTS) return;
require("./_helper").assertVendor("traceur");
var fs = require("fs");
@@ -10,8 +8,8 @@ require("./_transformation-helper")({
loc: __dirname + "/../vendor/traceur/test/feature",
ignoreSuites: [
// weird environmental issue make these hard to test
"Modules",
"Classes",
// these are the responsibility of regenerator
"AsyncFunctions",
@@ -36,6 +34,16 @@ require("./_transformation-helper")({
],
ignoreTasks: [
// TODO: #426
"Classes/SuperUnary",
"Classes/SuperPostfix",
// TODO: investigate
"Classes/SuperSet",
"Classes/PrototypeDescriptor",
"Classes/ExtendStrange",
"Classes/ClassNameBinding",
// these are the responsibility of core-js
"Symbol/GetOwnPropertySymbols",
"Spread/Type",
@@ -59,7 +67,7 @@ require("./_transformation-helper")({
// they have no names
"PropertyMethodAssignment/PropertyMethodAssignment",
// 6to5 assumes that all code transformed is a module
// 6to5 assumes that all code transformed is a module so this isn't necessary
"Strict",
"Syntax/UseStrictEscapeSequence",
"Syntax/UseStrictLineContinuation",