dry up array comprehension and arrow functions by introducing an alias-functions transformer
This commit is contained in:
parent
a6ffde6e9b
commit
3d2c41bb5a
@ -31,15 +31,13 @@ transform.test = function (task, assert) {
|
|||||||
actualCode = recast.prettyPrint(actualAst).code;
|
actualCode = recast.prettyPrint(actualAst).code;
|
||||||
|
|
||||||
if (task.options.exec) {
|
if (task.options.exec) {
|
||||||
try {
|
|
||||||
var fn = new Function("assert", actualCode);
|
var fn = new Function("assert", actualCode);
|
||||||
fn(assert);
|
fn(assert);
|
||||||
} catch (err) {
|
|
||||||
console.log(actualCode);
|
|
||||||
throw err;
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
var expectCode = expect.code.trim();
|
var expectCode = expect.code.trim();
|
||||||
|
|
||||||
|
if (!task.options.exec || (task.options.exec && expectCode)) {
|
||||||
var expectAst = util.parse(expect, expectCode);
|
var expectAst = util.parse(expect, expectCode);
|
||||||
var expectResult = recast.prettyPrint(expectAst);
|
var expectResult = recast.prettyPrint(expectAst);
|
||||||
expectCode = expectResult.code;
|
expectCode = expectResult.code;
|
||||||
@ -64,7 +62,7 @@ transform.test = function (task, assert) {
|
|||||||
|
|
||||||
transform._ensureTransformerNames = function (type, keys) {
|
transform._ensureTransformerNames = function (type, keys) {
|
||||||
_.each(keys, function (key) {
|
_.each(keys, function (key) {
|
||||||
if (!transform.transformers[key]) {
|
if (key[0] === "_" || !transform.transformers[key]) {
|
||||||
throw new ReferenceError("unknown transformer " + key + " specified in " + type);
|
throw new ReferenceError("unknown transformer " + key + " specified in " + type);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -87,5 +85,7 @@ transform.transformers = {
|
|||||||
restParameters: require("./transformers/rest-parameters"),
|
restParameters: require("./transformers/rest-parameters"),
|
||||||
destructuring: require("./transformers/destructuring"),
|
destructuring: require("./transformers/destructuring"),
|
||||||
forOf: require("./transformers/for-of"),
|
forOf: require("./transformers/for-of"),
|
||||||
unicodeRegex: require("./transformers/unicode-regex")
|
unicodeRegex: require("./transformers/unicode-regex"),
|
||||||
|
|
||||||
|
_aliasFunctions: require("./transformers/_alias-functions")
|
||||||
};
|
};
|
||||||
|
|||||||
77
lib/6to5/transformers/_alias-functions.js
Normal file
77
lib/6to5/transformers/_alias-functions.js
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
var traverse = require("../traverse");
|
||||||
|
var util = require("../util");
|
||||||
|
var b = require("ast-types").builders;
|
||||||
|
|
||||||
|
var go = function (getBody, node, file) {
|
||||||
|
var argumentsId;
|
||||||
|
var thisId;
|
||||||
|
|
||||||
|
var getArgumentsId = function () {
|
||||||
|
return argumentsId = argumentsId || b.identifier(file.generateUid("arguments"));
|
||||||
|
};
|
||||||
|
|
||||||
|
var getThisId = function () {
|
||||||
|
return thisId = thisId || b.identifier(file.generateUid("this"));
|
||||||
|
};
|
||||||
|
|
||||||
|
// traverse the function and find all alias functions so we can alias
|
||||||
|
// arguments and this if neccesary
|
||||||
|
traverse(node, function (node) {
|
||||||
|
if (!node._aliasFunction) {
|
||||||
|
if (traverse.isFunction(node)) {
|
||||||
|
// stop traversal of this node as it'll be hit again by this transformer
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// traverse all child nodes of this function and find arguments and this
|
||||||
|
traverse(node, function (node, parent) {
|
||||||
|
var getId;
|
||||||
|
|
||||||
|
if (node.type === "Identifier" && node.name === "arguments") {
|
||||||
|
getId = getArgumentsId;
|
||||||
|
} else if (node.type === "ThisExpression") {
|
||||||
|
getId = getThisId;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (util.isReferenced(node, parent)) return getId();
|
||||||
|
}, node._aliasFunctionStopNonArrowFunctions && ["FunctionExpression", "FunctionDeclaration"]);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
var body;
|
||||||
|
|
||||||
|
var pushDeclaration = function (id, init) {
|
||||||
|
body = body || getBody();
|
||||||
|
body.unshift(b.variableDeclaration("var", [
|
||||||
|
b.variableDeclarator(id, init)
|
||||||
|
]));
|
||||||
|
};
|
||||||
|
|
||||||
|
if (argumentsId) {
|
||||||
|
pushDeclaration(argumentsId, b.identifier("arguments"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thisId) {
|
||||||
|
pushDeclaration(thisId, b.identifier("this"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Program = function (node, parent, file) {
|
||||||
|
go(function () {
|
||||||
|
return node.body;
|
||||||
|
}, node, file);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.FunctionDeclaration =
|
||||||
|
exports.FunctionExpression = function (node, parent, file) {
|
||||||
|
go(function () {
|
||||||
|
util.ensureBlock(node);
|
||||||
|
return node.body.body;
|
||||||
|
}, node, file);
|
||||||
|
};
|
||||||
@ -9,12 +9,14 @@ var single = function (node) {
|
|||||||
var templateName = "array-comprehension-map";
|
var templateName = "array-comprehension-map";
|
||||||
if (node.filter) templateName = "array-comprehension-filter";
|
if (node.filter) templateName = "array-comprehension-filter";
|
||||||
|
|
||||||
return util.template(templateName, {
|
var result = util.template(templateName, {
|
||||||
STATEMENT: node.body,
|
STATEMENT: node.body,
|
||||||
FILTER: node.filter,
|
FILTER: node.filter,
|
||||||
ARRAY: block.right,
|
ARRAY: block.right,
|
||||||
KEY: block.left
|
KEY: block.left
|
||||||
});
|
});
|
||||||
|
result._aliasFunction = true;
|
||||||
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
var multiple = function (node, file) {
|
var multiple = function (node, file) {
|
||||||
@ -23,6 +25,7 @@ var multiple = function (node, file) {
|
|||||||
var container = util.template("array-comprehension-container", {
|
var container = util.template("array-comprehension-container", {
|
||||||
KEY: uid
|
KEY: uid
|
||||||
});
|
});
|
||||||
|
container._aliasFunction = true;
|
||||||
|
|
||||||
var block = container.callee.body;
|
var block = container.callee.body;
|
||||||
var body = block.body;
|
var body = block.body;
|
||||||
@ -47,7 +50,10 @@ var multiple = function (node, file) {
|
|||||||
var filter = util.template("if", {
|
var filter = util.template("if", {
|
||||||
STATEMENT: node.filter
|
STATEMENT: node.filter
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// set if body
|
||||||
filter.consequent.body = [child];
|
filter.consequent.body = [child];
|
||||||
|
|
||||||
child = filter;
|
child = filter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,7 +62,10 @@ var multiple = function (node, file) {
|
|||||||
ARRAY: self.right,
|
ARRAY: self.right,
|
||||||
KEY: self.left
|
KEY: self.left
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
|
// set function body
|
||||||
container2.expression.arguments[0].body.body = [child];
|
container2.expression.arguments[0].body.body = [child];
|
||||||
|
|
||||||
return container2;
|
return container2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,58 +1,12 @@
|
|||||||
var traverse = require("../traverse");
|
|
||||||
var util = require("../util");
|
var util = require("../util");
|
||||||
var b = require("ast-types").builders;
|
|
||||||
|
|
||||||
exports.ArrowFunctionExpression = function (node, parent, file) {
|
exports.ArrowFunctionExpression = function (node) {
|
||||||
util.ensureBlock(node);
|
util.ensureBlock(node);
|
||||||
|
|
||||||
|
node._aliasFunction = true;
|
||||||
|
node._aliasFunctionStopNonArrowFunctions = true;
|
||||||
node.expression = false;
|
node.expression = false;
|
||||||
node.type = "FunctionExpression";
|
node.type = "FunctionExpression";
|
||||||
|
|
||||||
if (traverse.hasType(node, "ThisExpression")) {
|
|
||||||
return util.template("function-bind-this", {
|
|
||||||
FUNCTION: node
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return node;
|
return node;
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.FunctionDeclaration =
|
|
||||||
exports.FunctionExpression = function (node, parent, file) {
|
|
||||||
var argumentsId;
|
|
||||||
|
|
||||||
var isArgumentIdentifier = function (node) {
|
|
||||||
return node.type === "Identifier" && node.name === "arguments";
|
|
||||||
};
|
|
||||||
|
|
||||||
var getId = function () {
|
|
||||||
return argumentsId = argumentsId || b.identifier(file.generateUid("arguments"));
|
|
||||||
};
|
|
||||||
|
|
||||||
// traverse the function and find all arrow functions so we can alias
|
|
||||||
// arguments if neccesary
|
|
||||||
traverse(node, function (node) {
|
|
||||||
if (node.type !== "ArrowFunctionExpression") return;
|
|
||||||
|
|
||||||
// traverse all child nodes of this arrow function and find a sole arguments
|
|
||||||
// identifier
|
|
||||||
traverse(node, function (node, parent) {
|
|
||||||
if (isArgumentIdentifier(node) && parent.type !== "MemberExpression") {
|
|
||||||
return getId();
|
|
||||||
} else if (node.type === "MemberExpression" && isArgumentIdentifier(node.object)) {
|
|
||||||
node.object = getId();
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}, traverse.FUNCTION_TYPES);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}, ["FunctionDeclaration", "FunctionExpression"]);
|
|
||||||
|
|
||||||
if (argumentsId) {
|
|
||||||
util.ensureBlock(node);
|
|
||||||
node.body.body.unshift(b.variableDeclaration("var", [
|
|
||||||
b.variableDeclarator(argumentsId, b.identifier("arguments"))
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -23,19 +23,7 @@ exports.VariableDeclaration = function (node, parent, file) {
|
|||||||
var id = ids[node.name];
|
var id = ids[node.name];
|
||||||
if (!id) return;
|
if (!id) return;
|
||||||
|
|
||||||
// we're a property key
|
if (util.isReferenced(node, parent)) return id;
|
||||||
if (parent.type === "Property" && parent.key === node) return;
|
|
||||||
|
|
||||||
var isMemberExpression = parent.type === "MemberExpression";
|
|
||||||
|
|
||||||
// we're in a member expression and we're the computed property so we're referenced
|
|
||||||
var isComputedProperty = isMemberExpression && parent.property === node && parent.computed;
|
|
||||||
|
|
||||||
// we're in a member expression and we're the object so we're referenced
|
|
||||||
var isObject = isMemberExpression && parent.object === node;
|
|
||||||
|
|
||||||
// we are referenced
|
|
||||||
if (!isMemberExpression || isComputedProperty || isObject) return id;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var replace = function (node, parent) {
|
var replace = function (node, parent) {
|
||||||
@ -55,7 +43,7 @@ exports.VariableDeclaration = function (node, parent, file) {
|
|||||||
b.returnStatement(node)
|
b.returnStatement(node)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
), letReferences)
|
), letReferences);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
function add() {
|
function add() {
|
||||||
var _arguments = arguments;
|
var _arguments = arguments;
|
||||||
return [1, 2, 3].map(function () {
|
return [1, 2, 3].map(function (i) {
|
||||||
return i * _arguments[0];
|
return i * _arguments[0];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
function add() {
|
function add() {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
return [1, 2, 3].map(function () {
|
return [1, 2, 3].map(function (i) {
|
||||||
return i * _this.multiplier;
|
return i * _this.multiplier;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,3 +32,14 @@ function five(obj) {
|
|||||||
return fn();
|
return fn();
|
||||||
}
|
}
|
||||||
five({ arguments: ["foo"] });
|
five({ arguments: ["foo"] });
|
||||||
|
|
||||||
|
function six(obj) {
|
||||||
|
var fn = () => {
|
||||||
|
var fn2 = function () {
|
||||||
|
return arguments[0];
|
||||||
|
};
|
||||||
|
return fn2("foobar");
|
||||||
|
};
|
||||||
|
return fn();
|
||||||
|
}
|
||||||
|
six();
|
||||||
|
|||||||
@ -43,3 +43,14 @@ function five(obj) {
|
|||||||
return fn();
|
return fn();
|
||||||
}
|
}
|
||||||
five({ arguments: ["foo"] });
|
five({ arguments: ["foo"] });
|
||||||
|
|
||||||
|
function six(obj) {
|
||||||
|
var fn = function () {
|
||||||
|
var fn2 = function () {
|
||||||
|
return arguments[0];
|
||||||
|
};
|
||||||
|
return fn2("foobar");
|
||||||
|
};
|
||||||
|
return fn();
|
||||||
|
}
|
||||||
|
six();
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
var _this = this;
|
||||||
var t = function (x) {
|
var t = function (x) {
|
||||||
return this.x + x;
|
return _this.x + x;
|
||||||
}.bind(this);
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user