implement Scope so we can keep track of references to avoid collisions when generating ids
This commit is contained in:
@@ -134,7 +134,19 @@ File.prototype.generate = function () {
|
||||
return result;
|
||||
};
|
||||
|
||||
File.prototype.generateUid = function (name) {
|
||||
File.prototype.generateUid = function (name, scope) {
|
||||
if (scope) {
|
||||
var uid;
|
||||
do {
|
||||
uid = this._generateUid(name);
|
||||
} while (scope.has(uid));
|
||||
return uid;
|
||||
} else {
|
||||
return this._generateUid(name);
|
||||
}
|
||||
};
|
||||
|
||||
File.prototype._generateUid = function (name) {
|
||||
// replace all non-valid identifiers with dashes
|
||||
name = name.replace(/[^a-zA-Z0-9]/g, "-");
|
||||
|
||||
|
||||
44
lib/6to5/scope.js
Normal file
44
lib/6to5/scope.js
Normal file
@@ -0,0 +1,44 @@
|
||||
module.exports = Scope;
|
||||
|
||||
var traverse = require("./traverse");
|
||||
var t = require("./types");
|
||||
var _ = require("lodash");
|
||||
|
||||
function Scope(parent, block) {
|
||||
this.parent = parent;
|
||||
|
||||
var ids = [];
|
||||
|
||||
if (t.isBlockStatement(block)) {
|
||||
_.each(block.body, function (node) {
|
||||
if (t.isVariableDeclaration(node)) {
|
||||
ids = ids.concat(t.getIds(node));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (t.isProgram(block) || t.isFunction(block)) {
|
||||
traverse(block, function (node) {
|
||||
if (t.isVariableDeclaration(node)) {
|
||||
ids = ids.concat(t.getIds(node));
|
||||
} else if (t.isFunction(node)) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (t.isFunction(block)) {
|
||||
_.each(block.params, function (param) {
|
||||
ids = ids.concat(t.getIds(param));
|
||||
});
|
||||
}
|
||||
|
||||
this.ids = ids;
|
||||
}
|
||||
|
||||
Scope.prototype.has = function (id) {
|
||||
if (!id) return false;
|
||||
if (_.contains(this.ids, id)) return true;
|
||||
if (this.parent) return this.parent.has(id);
|
||||
return false;
|
||||
};
|
||||
@@ -1,16 +1,16 @@
|
||||
var traverse = require("../traverse");
|
||||
var t = require("../types");
|
||||
|
||||
var go = function (getBody, node, file) {
|
||||
var go = function (getBody, node, file, scope) {
|
||||
var argumentsId;
|
||||
var thisId;
|
||||
|
||||
var getArgumentsId = function () {
|
||||
return argumentsId = argumentsId || t.identifier(file.generateUid("arguments"));
|
||||
return argumentsId = argumentsId || t.identifier(file.generateUid("arguments", scope));
|
||||
};
|
||||
|
||||
var getThisId = function () {
|
||||
return thisId = thisId || t.identifier(file.generateUid("this"));
|
||||
return thisId = thisId || t.identifier(file.generateUid("this", scope));
|
||||
};
|
||||
|
||||
// traverse the function and find all alias functions so we can alias
|
||||
@@ -70,16 +70,16 @@ var go = function (getBody, node, file) {
|
||||
}
|
||||
};
|
||||
|
||||
exports.Program = function (node, parent, file) {
|
||||
exports.Program = function (node, parent, file, scope) {
|
||||
go(function () {
|
||||
return node.body;
|
||||
}, node, file);
|
||||
}, node, file, scope);
|
||||
};
|
||||
|
||||
exports.FunctionDeclaration =
|
||||
exports.FunctionExpression = function (node, parent, file) {
|
||||
exports.FunctionExpression = function (node, parent, file, scope) {
|
||||
go(function () {
|
||||
t.ensureBlock(node);
|
||||
return node.body.body;
|
||||
}, node, file);
|
||||
}, node, file, scope);
|
||||
};
|
||||
|
||||
@@ -3,14 +3,14 @@ var util = require("../util");
|
||||
var t = require("../types");
|
||||
var _ = require("lodash");
|
||||
|
||||
exports.ClassDeclaration = function (node, parent, file) {
|
||||
exports.ClassDeclaration = function (node, parent, file, scope) {
|
||||
return t.variableDeclaration("var", [
|
||||
t.variableDeclarator(node.id, buildClass(node, file))
|
||||
t.variableDeclarator(node.id, buildClass(node, file, scope))
|
||||
]);
|
||||
};
|
||||
|
||||
exports.ClassExpression = function (node, parent, file) {
|
||||
return buildClass(node, file);
|
||||
exports.ClassExpression = function (node, parent, file, scope) {
|
||||
return buildClass(node, file, scope);
|
||||
};
|
||||
|
||||
var getMemberExpressionObject = function (node) {
|
||||
@@ -20,9 +20,9 @@ var getMemberExpressionObject = function (node) {
|
||||
return node;
|
||||
};
|
||||
|
||||
var buildClass = function (node, file) {
|
||||
var buildClass = function (node, file, scope) {
|
||||
var superName = node.superClass;
|
||||
var className = node.id || t.identifier(file.generateUid("class"));
|
||||
var className = node.id || t.identifier(file.generateUid("class", scope));
|
||||
|
||||
var superClassArgument = node.superClass;
|
||||
var superClassCallee = node.superClass;
|
||||
@@ -32,7 +32,7 @@ var buildClass = function (node, file) {
|
||||
superClassArgument = superClassCallee = getMemberExpressionObject(superName);
|
||||
} else if (!t.isIdentifier(superName)) {
|
||||
superClassArgument = superName;
|
||||
superClassCallee = superName = t.identifier(file.generateUid("ref"));
|
||||
superClassCallee = superName = t.identifier(file.generateUid("ref", scope));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ exports.ForStatement = function (node, parent, file) {
|
||||
_.each(node.body, function (child) {
|
||||
if (child && t.isVariableDeclaration(child) && child.kind === "const") {
|
||||
_.each(child.declarations, function (declar) {
|
||||
_.each(util.getIds(declar.id), function (name) {
|
||||
_.each(t.getIds(declar.id), function (name) {
|
||||
check(declar, name);
|
||||
constants.push(name);
|
||||
});
|
||||
|
||||
@@ -45,7 +45,7 @@ var pushArrayPattern = function (kind, nodes, pattern, parentId) {
|
||||
});
|
||||
};
|
||||
|
||||
var pushPattern = function (kind, nodes, pattern, parentId, file) {
|
||||
var pushPattern = function (kind, nodes, pattern, parentId, file, scope) {
|
||||
if (parentId.type !== "MemberExpression" && parentId.type !== "Identifier") {
|
||||
var key = t.identifier(file.generateUid("ref"));
|
||||
|
||||
@@ -60,14 +60,14 @@ var pushPattern = function (kind, nodes, pattern, parentId, file) {
|
||||
};
|
||||
|
||||
exports.ForInStatement =
|
||||
exports.ForOfStatement = function (node, parent, file) {
|
||||
exports.ForOfStatement = function (node, parent, file, scope) {
|
||||
var declar = node.left;
|
||||
if (declar.type !== "VariableDeclaration") return;
|
||||
|
||||
var pattern = declar.declarations[0].id;
|
||||
if (!t.isPattern(pattern)) return;
|
||||
|
||||
var key = t.identifier(file.generateUid("ref"));
|
||||
var key = t.identifier(file.generateUid("ref", scope));
|
||||
node.left = t.variableDeclaration(declar.kind, [
|
||||
t.variableDeclarator(key, null)
|
||||
]);
|
||||
@@ -82,7 +82,7 @@ exports.ForOfStatement = function (node, parent, file) {
|
||||
block.body = nodes.concat(block.body);
|
||||
};
|
||||
|
||||
exports.Function = function (node, parent, file) {
|
||||
exports.Function = function (node, parent, file, scope) {
|
||||
var nodes = [];
|
||||
|
||||
var hasDestructuring = false;
|
||||
@@ -91,8 +91,8 @@ exports.Function = function (node, parent, file) {
|
||||
if (!t.isPattern(pattern)) return pattern;
|
||||
|
||||
hasDestructuring = true;
|
||||
var parentId = t.identifier(file.generateUid("ref"));
|
||||
pushPattern("var", nodes, pattern, parentId, file);
|
||||
var parentId = t.identifier(file.generateUid("ref", scope));
|
||||
pushPattern("var", nodes, pattern, parentId, file, scope);
|
||||
return parentId;
|
||||
});
|
||||
|
||||
@@ -104,7 +104,7 @@ exports.Function = function (node, parent, file) {
|
||||
block.body = nodes.concat(block.body);
|
||||
};
|
||||
|
||||
exports.ExpressionStatement = function (node, parent, file) {
|
||||
exports.ExpressionStatement = function (node, parent, file, scope) {
|
||||
var expr = node.expression;
|
||||
if (expr.type !== "AssignmentExpression") return;
|
||||
|
||||
@@ -112,7 +112,7 @@ exports.ExpressionStatement = function (node, parent, file) {
|
||||
|
||||
var nodes = [];
|
||||
|
||||
var ref = t.identifier(file.generateUid("ref"));
|
||||
var ref = t.identifier(file.generateUid("ref", scope));
|
||||
nodes.push(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(ref, expr.right)
|
||||
]));
|
||||
@@ -122,7 +122,7 @@ exports.ExpressionStatement = function (node, parent, file) {
|
||||
return nodes;
|
||||
};
|
||||
|
||||
exports.VariableDeclaration = function (node, parent, file) {
|
||||
exports.VariableDeclaration = function (node, parent, file, scope) {
|
||||
if (t.isForInStatement(parent)) return;
|
||||
|
||||
var nodes = [];
|
||||
@@ -140,7 +140,7 @@ exports.VariableDeclaration = function (node, parent, file) {
|
||||
var patternId = declar.init;
|
||||
var pattern = declar.id;
|
||||
if (t.isPattern(pattern) && patternId) {
|
||||
pushPattern(node.kind, nodes, pattern, patternId, file);
|
||||
pushPattern(node.kind, nodes, pattern, patternId, file, scope);
|
||||
} else {
|
||||
nodes.push(buildVariableAssign(node.kind, declar.id, declar.init));
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
var util = require("../util");
|
||||
var t = require("../types");
|
||||
|
||||
exports.ForOfStatement = function (node, parent, file) {
|
||||
exports.ForOfStatement = function (node, parent, file, scope) {
|
||||
var left = node.left;
|
||||
var declar;
|
||||
|
||||
var stepKey = t.identifier(file.generateUid("step"));
|
||||
var stepKey = t.identifier(file.generateUid("step", scope));
|
||||
var stepValueId = t.memberExpression(stepKey, t.identifier("value"));
|
||||
|
||||
if (t.isIdentifier(left)) {
|
||||
@@ -19,7 +19,7 @@ exports.ForOfStatement = function (node, parent, file) {
|
||||
}
|
||||
|
||||
var node2 = util.template("for-of", {
|
||||
ITERATOR_KEY: file.generateUid("iterator"),
|
||||
ITERATOR_KEY: file.generateUid("iterator", scope),
|
||||
STEP_KEY: stepKey,
|
||||
OBJECT: node.right
|
||||
});
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
{
|
||||
"ArrowFunctionExpression": ["Function"],
|
||||
"FunctionDeclaration": ["Function"],
|
||||
"FunctionExpression": ["Function"],
|
||||
"ArrowFunctionExpression": ["Scope", "Function"],
|
||||
"FunctionDeclaration": ["Scope", "Function"],
|
||||
"FunctionExpression": ["Scope", "Function"],
|
||||
|
||||
"BlockStatement": ["Scope"],
|
||||
"Program": ["Scope"],
|
||||
|
||||
"LogicalExpression": ["Binary"],
|
||||
"BinaryExpression": ["Binary"],
|
||||
|
||||
Reference in New Issue
Block a user