Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fdda013d07 | ||
|
|
64477d934d | ||
|
|
45c507056a | ||
|
|
730b96c195 | ||
|
|
a185f91433 | ||
|
|
d053622802 | ||
|
|
74d6b61973 | ||
|
|
97784c8cca | ||
|
|
812d93553a | ||
|
|
d251b4cb56 | ||
|
|
caf38e1962 | ||
|
|
4ccbee4639 | ||
|
|
84196a3a07 | ||
|
|
29361c055a | ||
|
|
4277265591 | ||
|
|
812a2b315d | ||
|
|
0a1724fc3f | ||
|
|
bcc9e016b1 | ||
|
|
4ea0175ca7 | ||
|
|
799445c745 | ||
|
|
481ea12999 | ||
|
|
de6b608dda | ||
|
|
606f813822 | ||
|
|
e06c8cd106 | ||
|
|
9e3c67a8a2 | ||
|
|
91362f80b1 | ||
|
|
cde988f99f | ||
|
|
9ec0854659 |
18
CHANGELOG.md
18
CHANGELOG.md
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
13
lib/6to5/transformation/templates/tail-call-body.js
Normal file
13
lib/6to5/transformation/templates/tail-call-body.js
Normal 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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
116
lib/6to5/transformation/transformers/es6/.tail-call.js
Normal file
116
lib/6to5/transformation/transformers/es6/.tail-call.js
Normal 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)
|
||||
]));
|
||||
}
|
||||
};
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -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")
|
||||
};
|
||||
|
||||
5
lib/6to5/transformation/transformers/internal/cleanup.js
Normal file
5
lib/6to5/transformation/transformers/internal/cleanup.js
Normal file
@@ -0,0 +1,5 @@
|
||||
exports.SequenceExpression = function (node) {
|
||||
if (node.expressions.length === 1) {
|
||||
return node.expressions[0];
|
||||
}
|
||||
};
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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>"
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
7
test/fixtures/transformation/.es6-tail-call/call-apply/actual.js
vendored
Normal file
7
test/fixtures/transformation/.es6-tail-call/call-apply/actual.js
vendored
Normal 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";
|
||||
9
test/fixtures/transformation/.es6-tail-call/call-apply/expected.js
vendored
Normal file
9
test/fixtures/transformation/.es6-tail-call/call-apply/expected.js
vendored
Normal 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";
|
||||
7
test/fixtures/transformation/.es6-tail-call/cross-function/actual.js
vendored
Normal file
7
test/fixtures/transformation/.es6-tail-call/cross-function/actual.js
vendored
Normal 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);
|
||||
}
|
||||
9
test/fixtures/transformation/.es6-tail-call/cross-function/expected.js
vendored
Normal file
9
test/fixtures/transformation/.es6-tail-call/cross-function/expected.js
vendored
Normal 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]);
|
||||
}
|
||||
3
test/fixtures/transformation/.es6-tail-call/expressions/actual.js
vendored
Normal file
3
test/fixtures/transformation/.es6-tail-call/expressions/actual.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
(function f(n) {
|
||||
return n <= 0 ? "foo" : (doSmth(), getTrueValue() && (getFalseValue() || f(n - 1)));
|
||||
})(1e6, true) === "foo";
|
||||
5
test/fixtures/transformation/.es6-tail-call/expressions/expected.js
vendored
Normal file
5
test/fixtures/transformation/.es6-tail-call/expressions/expected.js
vendored
Normal 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";
|
||||
8
test/fixtures/transformation/.es6-tail-call/recursion/actual.js
vendored
Normal file
8
test/fixtures/transformation/.es6-tail-call/recursion/actual.js
vendored
Normal 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";
|
||||
11
test/fixtures/transformation/.es6-tail-call/recursion/expected.js
vendored
Normal file
11
test/fixtures/transformation/.es6-tail-call/recursion/expected.js
vendored
Normal 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";
|
||||
@@ -1,5 +1,5 @@
|
||||
function f() {
|
||||
return getObj().method();
|
||||
return getObj().method();
|
||||
}
|
||||
|
||||
function g() {
|
||||
@@ -6,9 +6,5 @@ function f() {
|
||||
}
|
||||
|
||||
function g() {
|
||||
var _temp;
|
||||
if (_temp = getFalseValue()) {
|
||||
return _temp;
|
||||
}
|
||||
return to5Runtime.tailCall(getValue);
|
||||
return getFalseValue() || to5Runtime.tailCall(getValue);
|
||||
}
|
||||
39
test/fixtures/transformation/.es6-tail-call/try-catch/actual.js
vendored
Normal file
39
test/fixtures/transformation/.es6-tail-call/try-catch/actual.js
vendored
Normal 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";
|
||||
41
test/fixtures/transformation/.es6-tail-call/try-catch/expected.js
vendored
Normal file
41
test/fixtures/transformation/.es6-tail-call/try-catch/expected.js
vendored
Normal 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";
|
||||
@@ -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;
|
||||
@@ -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
0
test/fixtures/transformation/es6-tail-call/call-apply/actual.js
vendored
Normal file → Executable file
32
test/fixtures/transformation/es6-tail-call/call-apply/expected.js
vendored
Normal file → Executable file
32
test/fixtures/transformation/es6-tail-call/call-apply/expected.js
vendored
Normal file → Executable 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";
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
function f(n) {
|
||||
return n <= 0 ? "foo" : g(n - 1);
|
||||
}
|
||||
|
||||
function g(n) {
|
||||
return n <= 0 ? "goo" : f(n - 1);
|
||||
}
|
||||
@@ -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
0
test/fixtures/transformation/es6-tail-call/expressions/actual.js
vendored
Normal file → Executable file
38
test/fixtures/transformation/es6-tail-call/expressions/expected.js
vendored
Normal file → Executable file
38
test/fixtures/transformation/es6-tail-call/expressions/expected.js
vendored
Normal file → Executable 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
0
test/fixtures/transformation/es6-tail-call/recursion/actual.js
vendored
Normal file → Executable file
26
test/fixtures/transformation/es6-tail-call/recursion/expected.js
vendored
Normal file → Executable file
26
test/fixtures/transformation/es6-tail-call/recursion/expected.js
vendored
Normal file → Executable 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
0
test/fixtures/transformation/es6-tail-call/try-catch/actual.js
vendored
Normal file → Executable file
52
test/fixtures/transformation/es6-tail-call/try-catch/expected.js
vendored
Normal file → Executable file
52
test/fixtures/transformation/es6-tail-call/try-catch/expected.js
vendored
Normal file → Executable 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";
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user