var traverse = require("../../traverse");
var util = require("../../util");
var t = require("../../types");
var _ = require("lodash");
exports.Function = function (node, parent, file, scope) {
if (!node.defaults || !node.defaults.length) return;
t.ensureBlock(node);
var ids = node.params.map(function (param) {
return t.getIds(param);
});
var closure = false;
_.each(node.defaults, function (def, i) {
if (!def) return;
var param = node.params[i];
// temporal dead zone check - here we prevent accessing of params that
// are to the right - ie. uninitialized parameters
_.each(ids.slice(i), function (ids) {
var check = function (node, parent) {
if (!t.isIdentifier(node) || !t.isReferenced(node, parent)) return;
if (_.contains(ids, node.name)) {
throw file.errorWithNode(node, "Temporal dead zone - accessing a variable before it's initialized");
}
Eif (scope.has(node.name)) {
closure = true;
}
};
check(def, node);
traverse(def, check);
});
// we're accessing a variable that's already defined within this function
var has = scope.get(param.name);
Iif (has && !_.contains(node.params, has)) {
closure = true;
}
});
var body = [];
_.each(node.defaults, function (def, i) {
if (!def) return;
body.push(util.template("if-undefined-set-to", {
VARIABLE: node.params[i],
DEFAULT: def
}, true));
});
if (closure) {
var container = t.functionExpression(null, [], node.body, node.generator);
container._aliasFunction = true;
body.push(t.returnStatement(t.callExpression(container, [])));
node.body = t.blockStatement(body);
} else {
node.body.body = body.concat(node.body.body);
}
node.defaults = [];
};
|