71 lines
1.8 KiB
JavaScript
71 lines
1.8 KiB
JavaScript
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");
|
|
}
|
|
|
|
if (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);
|
|
if (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 = [];
|
|
};
|