remove functions inside of loops

This commit is contained in:
Sebastian McKenzie 2015-01-13 22:18:58 +11:00
parent f560062d82
commit 70eae9f6ce
3 changed files with 25 additions and 94 deletions

View File

@ -1,7 +1,6 @@
var traverse = require("../../traverse");
var util = require("../../util");
var t = require("../../types");
var _ = require("lodash");
exports.Function = function (node, parent, file, scope) {
if (!node.defaults || !node.defaults.length) return;
@ -15,6 +14,23 @@ exports.Function = function (node, parent, file, scope) {
var i;
var def;
var checkTDZ = function (ids) {
var check = function (node, parent) {
if (!t.isIdentifier(node) || !t.isReferenced(node, parent)) return;
if (ids.indexOf(node.name) >= 0) {
throw file.errorWithNode(node, "Temporal dead zone - accessing a variable before it's initialized");
}
if (scope.has(node.name, true)) {
iife = true;
}
};
check(def, node);
traverse(def, { enter: check });
};
for (i in node.defaults) {
def = node.defaults[i];
if (!def) continue;
@ -23,22 +39,10 @@ exports.Function = function (node, parent, file, scope) {
// temporal dead zone check - here we prevent accessing of params that
// are to the right - ie. uninitialized parameters
_.each(ids.slice(i), function (ids) {
var check = function (node, parent) {
if (!t.isIdentifier(node) || !t.isReferenced(node, parent)) return;
if (ids.indexOf(node.name) >= 0) {
throw file.errorWithNode(node, "Temporal dead zone - accessing a variable before it's initialized");
}
if (scope.has(node.name, true)) {
iife = true;
}
};
check(def, node);
traverse(def, { enter: check });
});
var rightIds = ids.slice(i);
for (i in rightIds) {
checkTDZ(rightIds[i]);
}
// we're accessing a variable that's already defined within this function
var has = scope.get(param.name);

View File

@ -250,10 +250,11 @@ LetScoping.prototype.getInfo = function () {
declar = block.body[i];
if (!isLet(declar, block)) continue;
_.each(t.getIds(declar, true), function (id, key) {
duplicates(id, key);
var declars = t.getIds(declar, true);
for (var key in declars) {
duplicates(declars[key], key);
opts.keys.push(key);
});
}
}
return opts;

View File

@ -1,74 +0,0 @@
var traverse = require("../../traverse");
var util = require("../../util");
var t = require("../../types");
exports.optional = true;
exports.Class = function (node) {
var superClass = node.superClass || t.identifier("Function");
var hasConstructor = false;
var body = node.body.body;
for (var i in body) {
var methodNode = body[i];
hasConstructor = hasConstructor || methodNode.key.name === "constructor";
traverse(methodNode, {
enter: function (node, parent) {
if (t.isIdentifier(node, { name: "super" })) {
return superIdentifier(superClass, methodNode, node, parent);
} else if (t.isCallExpression(node)) {
var callee = node.callee;
if (!t.isMemberExpression(callee)) return;
if (callee.object.name !== "super") return;
// super.test(); -> ClassName.prototype.MethodName.call(this);
t.appendToMemberExpression(callee, t.identifier("call"));
node.arguments.unshift(t.thisExpression());
}
}
});
}
if (node.superClass && !hasConstructor) {
body.unshift(t.methodDefinition(
t.identifier("constructor"),
util.template("class-super-constructor-call-fast", {
SUPER_NAME: superClass
})
));
}
};
var superIdentifier = function (superClass, methodNode, id, parent) {
var methodName = methodNode.key;
if (parent.property === id) {
return;
} else if (t.isCallExpression(parent, { callee: id })) {
// super(); -> ClassName.prototype.MethodName.call(this);
parent.arguments.unshift(t.thisExpression());
if (methodName.name === "constructor") {
// constructor() { super(); }
return t.memberExpression(superClass, t.identifier("call"));
} else {
id = superClass;
// foo() { super(); }
if (!methodNode.static) {
id = t.memberExpression(id, t.identifier("prototype"));
}
id = t.memberExpression(id, methodName, methodNode.computed);
return t.memberExpression(id, t.identifier("call"));
}
} else if (t.isMemberExpression(parent) && !methodNode.static) {
// super.test -> ClassName.prototype.test
return t.memberExpression(superClass, t.identifier("prototype"));
} else {
return superClass;
}
};