babel/lib/6to5/transformation/transformers/es6-default-parameters.js
Sebastian McKenzie 2fb6c7820c microoptimizations
2014-12-15 13:59:54 +11:00

74 lines
1.9 KiB
JavaScript

var traverse = require("../../traverse");
var Scope = require("../../traverse/scope");
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 iife = false;
for (var i in node.defaults) {
var def = node.defaults[i];
if (!def) continue;
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)) {
iife = 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)) {
iife = true;
}
}
var body = [];
for (var i in node.defaults) {
var def = node.defaults[i];
if (!def) continue;
body.push(util.template("if-undefined-set-to", {
VARIABLE: node.params[i],
DEFAULT: def
}, true));
}
if (iife) {
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 = [];
};