babel-core
Version:
A compiler for writing next generation JavaScript
165 lines (125 loc) • 4.36 kB
JavaScript
;
exports.__esModule = true;
// istanbul ignore next
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj["default"] = obj; return newObj; } }
// istanbul ignore next
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
var _helpersCallDelegate = require("../../../helpers/call-delegate");
var _helpersCallDelegate2 = _interopRequireDefault(_helpersCallDelegate);
var _helpersGetFunctionArity = require("../../../helpers/get-function-arity");
var _helpersGetFunctionArity2 = _interopRequireDefault(_helpersGetFunctionArity);
var _util = require("../../../../util");
var util = _interopRequireWildcard(_util);
var _types = require("../../../../types");
var t = _interopRequireWildcard(_types);
/**
* [Please add a description.]
*/
var hasDefaults = function hasDefaults(node) {
for (var i = 0; i < node.params.length; i++) {
if (!t.isIdentifier(node.params[i])) return true;
}
return false;
};
/**
* [Please add a description.]
*/
var iifeVisitor = {
/**
* [Please add a description.]
*/
ReferencedIdentifier: function ReferencedIdentifier(node, parent, scope, state) {
if (node.name !== "eval") {
if (!state.scope.hasOwnBinding(node.name)) return;
if (state.scope.bindingIdentifierEquals(node.name, node)) return;
}
state.iife = true;
this.stop();
}
};
/**
* [Please add a description.]
*/
var visitor = {
/**
* [Please add a description.]
*/
Function: function Function(node, parent, scope, file) {
if (!hasDefaults(node)) return;
// ensure it's a block, useful for arrow functions
this.ensureBlock();
var state = {
iife: false,
scope: scope
};
var body = [];
//
var argsIdentifier = t.identifier("arguments");
argsIdentifier._shadowedFunctionLiteral = this;
// push a default parameter definition
function pushDefNode(left, right, i) {
var defNode;
if (exceedsLastNonDefault(i) || t.isPattern(left) || file.transformers["es6.spec.blockScoping"].canTransform()) {
defNode = util.template("default-parameter", {
VARIABLE_NAME: left,
DEFAULT_VALUE: right,
ARGUMENT_KEY: t.literal(i),
ARGUMENTS: argsIdentifier
}, true);
} else {
defNode = util.template("default-parameter-assign", {
VARIABLE_NAME: left,
DEFAULT_VALUE: right
}, true);
}
defNode._blockHoist = node.params.length - i;
body.push(defNode);
}
// check if an index exceeds the functions arity
function exceedsLastNonDefault(i) {
return i + 1 > lastNonDefaultParam;
}
//
var lastNonDefaultParam = _helpersGetFunctionArity2["default"](node);
//
var params = this.get("params");
for (var i = 0; i < params.length; i++) {
var param = params[i];
if (!param.isAssignmentPattern()) {
if (!param.isIdentifier()) {
param.traverse(iifeVisitor, state);
}
if (file.transformers["es6.spec.blockScoping"].canTransform() && param.isIdentifier()) {
pushDefNode(param.node, t.identifier("undefined"), i);
}
continue;
}
var left = param.get("left");
var right = param.get("right");
if (exceedsLastNonDefault(i) || left.isPattern()) {
var placeholder = scope.generateUidIdentifier("x");
placeholder._isDefaultPlaceholder = true;
node.params[i] = placeholder;
} else {
node.params[i] = left.node;
}
if (!state.iife) {
if (right.isIdentifier() && scope.hasOwnBinding(right.node.name)) {
state.iife = true;
} else {
right.traverse(iifeVisitor, state);
}
}
pushDefNode(left.node, right.node, i);
}
// we need to cut off all trailing default parameters
node.params = node.params.slice(0, lastNonDefaultParam);
if (state.iife) {
body.push(_helpersCallDelegate2["default"](node, scope));
node.body = t.blockStatement(body);
} else {
node.body.body = body.concat(node.body.body);
}
}
};
exports.visitor = visitor;