babel/lib/6to5/transformers/let-scoping.js

61 lines
1.7 KiB
JavaScript

var traverse = require("../traverse");
var util = require("../util");
var t = require("../types");
var _ = require("lodash");
exports.VariableDeclaration = function (node, parent, file) {
if (node.kind !== "let") return;
node.kind = "var";
var ids = {};
_.each(node.declarations, function (declar) {
_.each(util.getIds(declar.id), function (id) {
ids[id] = t.identifier(file.generateUid(id));
});
});
var replaceId = function (node, parent) {
// not an identifier so we have no use for this node
if (node.type !== "Identifier") return;
// not a let reference
var id = ids[node.name];
if (!id) return;
if (t.isReferenced(node, parent)) return id;
};
var isProgram = t.isProgram(parent);
var replace = function (node, parent) {
if (!isProgram && _.contains(t.FUNCTION_TYPES, node.type)) {
var letReferences = [];
traverse(node, function (node, parent) {
var id = replaceId(node, parent);
if (id && !_.contains(letReferences, id)) letReferences.push(id);
return id;
});
if (letReferences.length) {
if (t.isFunctionDeclaration(node)) {
throw new Error("`FunctionDeclaration`s that use `let` and `constant` references aren't allowed outside of the root scope");
} else {
var func = t.functionExpression(null, letReferences, t.blockStatement([
t.returnStatement(node)
]));
func._aliasFunction = true;
return t.callExpression(func, letReferences);
}
} else {
return false;
}
}
return replaceId(node, parent);
};
traverse(parent, replace);
};