block scope constants
This commit is contained in:
@@ -9,11 +9,21 @@ exports.ForOfStatement =
|
||||
exports.ForStatement = function (node, parent, file) {
|
||||
var constants = {};
|
||||
|
||||
var check = function (parent, names) {
|
||||
/**
|
||||
* Check the results of `util.getIds` as `names` generated from a
|
||||
* node against it's parent.
|
||||
*/
|
||||
|
||||
var check = function (parent, names, scope) {
|
||||
_.each(names, function (nameNode, name) {
|
||||
if (!_.has(constants, name)) return;
|
||||
if (parent && t.isBlockStatement(parent) && parent !== constants[name]) return;
|
||||
|
||||
if (scope) {
|
||||
var defined = scope.get(name);
|
||||
if (defined && defined === nameNode) return;
|
||||
}
|
||||
|
||||
throw file.errorWithNode(nameNode, name + " is read-only");
|
||||
});
|
||||
};
|
||||
@@ -22,6 +32,10 @@ exports.ForStatement = function (node, parent, file) {
|
||||
return t.getIds(node, true, ["MemberExpression"]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Collect all constants in this scope.
|
||||
*/
|
||||
|
||||
_.each(node.body, function (child, parent) {
|
||||
if (child && t.isVariableDeclaration(child, { kind: "const" })) {
|
||||
_.each(child.declarations, function (declar) {
|
||||
@@ -43,12 +57,12 @@ exports.ForStatement = function (node, parent, file) {
|
||||
|
||||
if (_.isEmpty(constants)) return;
|
||||
|
||||
traverse(node, function (child, parent) {
|
||||
traverse(node, function (child, parent, scope) {
|
||||
if (child._ignoreConstant) return;
|
||||
if (t.isVariableDeclaration(child)) return;
|
||||
|
||||
if (t.isVariableDeclarator(child) || t.isDeclaration(child) || t.isAssignmentExpression(child)) {
|
||||
check(parent, getIds(child));
|
||||
check(parent, getIds(child), scope);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -27,12 +27,12 @@ Scope.add = function (node, references) {
|
||||
};
|
||||
|
||||
Scope.prototype.generateTemp = function (file, name) {
|
||||
var id = file.generateUidIdentifier(name || "temp", this);
|
||||
this.push({
|
||||
key: id.name,
|
||||
id: id
|
||||
});
|
||||
return id;
|
||||
var id = file.generateUidIdentifier(name || "temp", this);
|
||||
this.push({
|
||||
key: id.name,
|
||||
id: id
|
||||
});
|
||||
return id;
|
||||
};
|
||||
|
||||
Scope.prototype.getReferences = function () {
|
||||
@@ -86,12 +86,15 @@ Scope.prototype.getReferences = function () {
|
||||
// declared within are accessible
|
||||
if (t.isFunction(node)) return false;
|
||||
|
||||
// function identifier doesn't belong to this scope
|
||||
if (block.id && node === block.id) return;
|
||||
|
||||
if (t.isIdentifier(node) && t.isReferenced(node, parent) && !scope.has(node.name)) {
|
||||
add(node);
|
||||
}
|
||||
|
||||
// we've ran into a declaration!
|
||||
// we'll let the BlockStatement scope deal with `let` declarations
|
||||
// we'll let the BlockStatement scope deal with `let` declarations unless
|
||||
if (t.isDeclaration(node) && !t.isLet(node)) {
|
||||
add(node);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user