69 lines
1.8 KiB
JavaScript
69 lines
1.8 KiB
JavaScript
var traverse = require("../../traverse");
|
|
var t = require("../../types");
|
|
var _ = require("lodash");
|
|
|
|
exports.Program =
|
|
exports.BlockStatement =
|
|
exports.ForInStatement =
|
|
exports.ForOfStatement =
|
|
exports.ForStatement = function (node, parent, file) {
|
|
var constants = {};
|
|
|
|
/**
|
|
* 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");
|
|
});
|
|
};
|
|
|
|
var getIds = function (node) {
|
|
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) {
|
|
_.each(getIds(declar), function (nameNode, name) {
|
|
var names = {};
|
|
names[name] = nameNode;
|
|
check(parent, names);
|
|
|
|
constants[name] = parent;
|
|
});
|
|
|
|
declar._ignoreConstant = true;
|
|
});
|
|
|
|
child._ignoreConstant = true;
|
|
child.kind = "let";
|
|
}
|
|
});
|
|
|
|
if (_.isEmpty(constants)) return;
|
|
|
|
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), scope);
|
|
}
|
|
});
|
|
};
|