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 hasConstants = false;
var constants = {};
/**
* Check the results of `util.getIds` as `names` generated from a
* node against it's parent.
*/
var check = function (parent, names, scope) {
for (var name in names) {
var nameNode = names[name];
if (!_.has(constants, name)) continue;
Iif (parent && t.isBlockStatement(parent) && parent !== constants[name]) continue;
if (scope) {
var defined = scope.get(name);
if (defined && defined === nameNode) continue;
}
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) {
Iif (t.isExportDeclaration(child)) {
child = child.declaration;
}
if (t.isVariableDeclaration(child, { kind: "const" })) {
for (var i in child.declarations) {
var declar = child.declarations[i];
var ids = getIds(declar);
for (var name in ids) {
var nameNode = ids[name];
var names = {};
names[name] = nameNode;
check(parent, names);
constants[name] = parent;
hasConstants = true;
}
declar._ignoreConstant = true;
}
child._ignoreConstant = true;
child.kind = "let";
}
});
if (!hasConstants) return;
traverse(node, {
enter: 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);
}
}
});
};
|