babel-plugin-transform-es2015-parameters
Advanced tools
Comparing version 7.0.0-alpha.15 to 7.0.0-alpha.16
@@ -27,22 +27,14 @@ "use strict"; | ||
var buildDefaultParam = (0, _babelTemplate2.default)("\n let VARIABLE_NAME =\n ARGUMENTS.length > ARGUMENT_KEY && ARGUMENTS[ARGUMENT_KEY] !== undefined ?\n ARGUMENTS[ARGUMENT_KEY]\n :\n DEFAULT_VALUE;\n"); | ||
var buildLooseDefaultParam = (0, _babelTemplate2.default)("\n if (ASSIGMENT_IDENTIFIER === UNDEFINED) {\n ASSIGMENT_IDENTIFIER = DEFAULT_VALUE;\n }\n"); | ||
var buildLooseDestructuredDefaultParam = (0, _babelTemplate2.default)("\n let ASSIGMENT_IDENTIFIER = PARAMETER_NAME === UNDEFINED ? DEFAULT_VALUE : PARAMETER_NAME ;\n"); | ||
var buildCutOff = (0, _babelTemplate2.default)("\n let $0 = $1[$2];\n"); | ||
function hasDefaults(node) { | ||
for (var _iterator = node.params, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | ||
var _ref; | ||
var _arr = node.params; | ||
if (_isArray) { | ||
if (_i >= _iterator.length) break; | ||
_ref = _iterator[_i++]; | ||
} else { | ||
_i = _iterator.next(); | ||
if (_i.done) break; | ||
_ref = _i.value; | ||
} | ||
var param = _ref; | ||
for (var _i = 0; _i < _arr.length; _i++) { | ||
var param = _arr[_i]; | ||
if (!t.isIdentifier(param)) return true; | ||
} | ||
return false; | ||
@@ -74,3 +66,2 @@ } | ||
}; | ||
var visitor = exports.visitor = { | ||
@@ -80,7 +71,44 @@ Function: function Function(path) { | ||
scope = path.scope; | ||
if (!hasDefaults(node)) return; | ||
path.ensureBlock(); | ||
var params = path.get("params"); | ||
if (this.opts.loose) { | ||
var _body = []; | ||
for (var i = 0; i < params.length; ++i) { | ||
var param = params[i]; | ||
if (param.isAssignmentPattern()) { | ||
var left = param.get("left"); | ||
var right = param.get("right"); | ||
var undefinedNode = scope.buildUndefinedNode(); | ||
if (left.isIdentifier()) { | ||
_body.push(buildLooseDefaultParam({ | ||
ASSIGMENT_IDENTIFIER: left.node, | ||
DEFAULT_VALUE: right.node, | ||
UNDEFINED: undefinedNode | ||
})); | ||
param.replaceWith(left.node); | ||
} else if (left.isObjectPattern() || left.isArrayPattern()) { | ||
var paramName = scope.generateUidIdentifier(); | ||
_body.push(buildLooseDestructuredDefaultParam({ | ||
ASSIGMENT_IDENTIFIER: left.node, | ||
DEFAULT_VALUE: right.node, | ||
PARAMETER_NAME: paramName, | ||
UNDEFINED: undefinedNode | ||
})); | ||
param.replaceWith(paramName); | ||
} | ||
} | ||
} | ||
path.get("body").unshiftContainer("body", _body); | ||
return; | ||
} | ||
var state = { | ||
@@ -90,5 +118,3 @@ iife: false, | ||
}; | ||
var body = []; | ||
var argsIdentifier = t.identifier("arguments"); | ||
@@ -109,9 +135,8 @@ | ||
var params = path.get("params"); | ||
for (var i = 0; i < params.length; i++) { | ||
var param = params[i]; | ||
for (var _i2 = 0; _i2 < params.length; _i2++) { | ||
var _param = params[_i2]; | ||
if (!param.isAssignmentPattern()) { | ||
if (!state.iife && !param.isIdentifier()) { | ||
param.traverse(iifeVisitor, state); | ||
if (!_param.isAssignmentPattern()) { | ||
if (!state.iife && !_param.isIdentifier()) { | ||
_param.traverse(iifeVisitor, state); | ||
} | ||
@@ -122,30 +147,30 @@ | ||
var left = param.get("left"); | ||
var right = param.get("right"); | ||
var _left = _param.get("left"); | ||
if (i >= lastNonDefaultParam || left.isPattern()) { | ||
var _right = _param.get("right"); | ||
if (_i2 >= lastNonDefaultParam || _left.isPattern()) { | ||
var placeholder = scope.generateUidIdentifier("x"); | ||
placeholder._isDefaultPlaceholder = true; | ||
node.params[i] = placeholder; | ||
node.params[_i2] = placeholder; | ||
} else { | ||
node.params[i] = left.node; | ||
node.params[_i2] = _left.node; | ||
} | ||
if (!state.iife) { | ||
if (right.isIdentifier() && !isSafeBinding(scope, right.node)) { | ||
if (_right.isIdentifier() && !isSafeBinding(scope, _right.node)) { | ||
state.iife = true; | ||
} else { | ||
right.traverse(iifeVisitor, state); | ||
_right.traverse(iifeVisitor, state); | ||
} | ||
} | ||
pushDefNode(left.node, right.node, i); | ||
pushDefNode(_left.node, _right.node, _i2); | ||
} | ||
for (var _i2 = lastNonDefaultParam + 1; _i2 < node.params.length; _i2++) { | ||
var _param = node.params[_i2]; | ||
if (_param._isDefaultPlaceholder) continue; | ||
var declar = buildCutOff(_param, argsIdentifier, t.numericLiteral(_i2)); | ||
declar._blockHoist = node.params.length - _i2; | ||
for (var _i3 = lastNonDefaultParam + 1; _i3 < node.params.length; _i3++) { | ||
var _param2 = node.params[_i3]; | ||
if (_param2._isDefaultPlaceholder) continue; | ||
var declar = buildCutOff(_param2, argsIdentifier, t.numericLiteral(_i3)); | ||
declar._blockHoist = node.params.length - _i3; | ||
body.push(declar); | ||
@@ -152,0 +177,0 @@ } |
@@ -15,3 +15,2 @@ "use strict"; | ||
var params = path.get("params"); | ||
var hoistTweak = t.isRestElement(params[params.length - 1]) ? 1 : 0; | ||
@@ -22,11 +21,9 @@ var outputParamsLength = params.length - hoistTweak; | ||
var param = params[i]; | ||
if (param.isArrayPattern() || param.isObjectPattern()) { | ||
var uid = path.scope.generateUidIdentifier("ref"); | ||
var declar = t.variableDeclaration("let", [t.variableDeclarator(param.node, uid)]); | ||
declar._blockHoist = outputParamsLength - i; | ||
path.ensureBlock(); | ||
path.get("body").unshiftContainer("body", declar); | ||
param.replaceWith(uid); | ||
@@ -33,0 +30,0 @@ } |
@@ -10,4 +10,4 @@ "use strict"; | ||
if (!path.isArrowFunctionExpression()) return; | ||
var params = path.get("params"); | ||
var params = path.get("params"); | ||
for (var _iterator = params, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | ||
@@ -14,0 +14,0 @@ var _ref; |
@@ -19,7 +19,4 @@ "use strict"; | ||
var buildRest = (0, _babelTemplate2.default)("\n for (var LEN = ARGUMENTS.length,\n ARRAY = Array(ARRAY_LEN),\n KEY = START;\n KEY < LEN;\n KEY++) {\n ARRAY[ARRAY_KEY] = ARGUMENTS[KEY];\n }\n"); | ||
var restIndex = (0, _babelTemplate2.default)("\n (INDEX < OFFSET || ARGUMENTS.length <= INDEX) ? undefined : ARGUMENTS[INDEX]\n"); | ||
var restIndexImpure = (0, _babelTemplate2.default)("\n REF = INDEX, (REF < OFFSET || ARGUMENTS.length <= REF) ? undefined : ARGUMENTS[REF]\n"); | ||
var restLength = (0, _babelTemplate2.default)("\n ARGUMENTS.length <= OFFSET ? 0 : ARGUMENTS.length - OFFSET\n"); | ||
@@ -43,7 +40,4 @@ | ||
if (path.isTypeCastExpression()) return; | ||
path.skip(); | ||
}, | ||
"Function|ClassProperty": function FunctionClassProperty(path, state) { | ||
@@ -54,6 +48,4 @@ var oldNoOptimise = state.noOptimise; | ||
state.noOptimise = oldNoOptimise; | ||
path.skip(); | ||
}, | ||
ReferencedIdentifier: function ReferencedIdentifier(path, state) { | ||
@@ -77,15 +69,24 @@ var node = path.node; | ||
if (parentPath.isMemberExpression({ object: node })) { | ||
if (parentPath.isMemberExpression({ | ||
object: node | ||
})) { | ||
var grandparentPath = parentPath.parentPath; | ||
var argsOptEligible = !state.deopted && !(grandparentPath.isAssignmentExpression() && parentPath.node === grandparentPath.node.left || grandparentPath.isLVal() || grandparentPath.isForXStatement() || grandparentPath.isUpdateExpression() || grandparentPath.isUnaryExpression({ | ||
operator: "delete" | ||
}) || (grandparentPath.isCallExpression() || grandparentPath.isNewExpression()) && parentPath.node === grandparentPath.node.callee); | ||
var argsOptEligible = !state.deopted && !(grandparentPath.isAssignmentExpression() && parentPath.node === grandparentPath.node.left || grandparentPath.isLVal() || grandparentPath.isForXStatement() || grandparentPath.isUpdateExpression() || grandparentPath.isUnaryExpression({ operator: "delete" }) || (grandparentPath.isCallExpression() || grandparentPath.isNewExpression()) && parentPath.node === grandparentPath.node.callee); | ||
if (argsOptEligible) { | ||
if (parentPath.node.computed) { | ||
if (parentPath.get("property").isBaseType("number")) { | ||
state.candidates.push({ cause: "indexGetter", path: path }); | ||
state.candidates.push({ | ||
cause: "indexGetter", | ||
path: path | ||
}); | ||
return; | ||
} | ||
} else if (parentPath.node.property.name === "length") { | ||
state.candidates.push({ cause: "lengthGetter", path: path }); | ||
state.candidates.push({ | ||
cause: "lengthGetter", | ||
path: path | ||
}); | ||
return; | ||
@@ -98,4 +99,8 @@ } | ||
var call = parentPath.parentPath; | ||
if (call.isCallExpression() && call.node.arguments.length === 1) { | ||
state.candidates.push({ cause: "argSpread", path: path }); | ||
state.candidates.push({ | ||
cause: "argSpread", | ||
path: path | ||
}); | ||
return; | ||
@@ -114,2 +119,3 @@ } | ||
}; | ||
function hasRest(node) { | ||
@@ -135,3 +141,6 @@ return t.isRestElement(node.params[node.params.length - 1]); | ||
var temp = scope.generateUidIdentifierBasedOnNode(index); | ||
scope.push({ id: temp, kind: "var" }); | ||
scope.push({ | ||
id: temp, | ||
kind: "var" | ||
}); | ||
path.parentPath.replaceWith(restIndexImpure({ | ||
@@ -150,5 +159,5 @@ ARGUMENTS: argsId, | ||
})); | ||
var offsetTestPath = parentPath.get("test").get("left"); | ||
var valRes = offsetTestPath.evaluate(); | ||
if (valRes.confident) { | ||
@@ -179,39 +188,21 @@ if (valRes.value === true) { | ||
scope = path.scope; | ||
if (!hasRest(node)) return; | ||
var rest = node.params.pop().argument; | ||
var argsId = t.identifier("arguments"); | ||
var state = { | ||
references: [], | ||
offset: node.params.length, | ||
argumentsNode: argsId, | ||
outerBinding: scope.getBindingIdentifier(rest.name), | ||
candidates: [], | ||
name: rest.name, | ||
deopted: false | ||
}; | ||
path.traverse(memberExpressionOptimisationVisitor, state); | ||
if (!state.deopted && !state.references.length) { | ||
for (var _iterator = state.candidates, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | ||
var _ref2; | ||
var _arr = state.candidates; | ||
if (_isArray) { | ||
if (_i >= _iterator.length) break; | ||
_ref2 = _iterator[_i++]; | ||
} else { | ||
_i = _iterator.next(); | ||
if (_i.done) break; | ||
_ref2 = _i.value; | ||
} | ||
var _ref = _ref2; | ||
for (var _i = 0; _i < _arr.length; _i++) { | ||
var _ref = _arr[_i]; | ||
var _path = _ref.path, | ||
@@ -224,26 +215,28 @@ cause = _ref.cause; | ||
break; | ||
case "lengthGetter": | ||
optimiseLengthGetter(_path, argsId, state.offset); | ||
break; | ||
default: | ||
_path.replaceWith(argsId); | ||
} | ||
} | ||
return; | ||
} | ||
state.references = state.references.concat(state.candidates.map(function (_ref3) { | ||
var path = _ref3.path; | ||
state.references = state.references.concat(state.candidates.map(function (_ref2) { | ||
var path = _ref2.path; | ||
return path; | ||
})); | ||
var start = t.numericLiteral(node.params.length); | ||
var key = scope.generateUidIdentifier("key"); | ||
var len = scope.generateUidIdentifier("len"); | ||
var arrKey = key; | ||
var arrLen = len; | ||
if (node.params.length) { | ||
arrKey = t.binaryExpression("-", key, start); | ||
arrLen = t.conditionalExpression(t.binaryExpression(">", len, start), t.binaryExpression("-", len, start), t.numericLiteral(0)); | ||
@@ -267,5 +260,3 @@ } | ||
loop._blockHoist = 1; | ||
var target = path.getEarliestCommonAncestorFrom(state.references).getStatementParent(); | ||
target.findParent(function (path) { | ||
@@ -278,3 +269,2 @@ if (path.isLoop()) { | ||
}); | ||
target.insertBefore(loop); | ||
@@ -281,0 +271,0 @@ } |
{ | ||
"name": "babel-plugin-transform-es2015-parameters", | ||
"version": "7.0.0-alpha.15", | ||
"version": "7.0.0-alpha.16", | ||
"description": "Compile ES2015 default and rest parameters to ES5", | ||
@@ -9,7 +9,7 @@ "repository": "https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-es2015-parameters", | ||
"dependencies": { | ||
"babel-helper-call-delegate": "7.0.0-alpha.15", | ||
"babel-helper-get-function-arity": "7.0.0-alpha.15", | ||
"babel-template": "7.0.0-alpha.15", | ||
"babel-traverse": "7.0.0-alpha.15", | ||
"babel-types": "7.0.0-alpha.15" | ||
"babel-helper-call-delegate": "7.0.0-alpha.16", | ||
"babel-helper-get-function-arity": "7.0.0-alpha.16", | ||
"babel-template": "7.0.0-alpha.16", | ||
"babel-traverse": "7.0.0-alpha.16", | ||
"babel-types": "7.0.0-alpha.16" | ||
}, | ||
@@ -20,4 +20,4 @@ "keywords": [ | ||
"devDependencies": { | ||
"babel-helper-plugin-test-runner": "7.0.0-alpha.15" | ||
"babel-helper-plugin-test-runner": "7.0.0-alpha.16" | ||
} | ||
} |
@@ -75,1 +75,21 @@ # babel-plugin-transform-es2015-parameters | ||
``` | ||
## Options | ||
### `loose` | ||
`boolean`, defaults to `false`. | ||
In loose mode, parameters with default values will be counted into the arity of the function. This is not spec behavior where these parameters do not add to function arity. | ||
The `loose` implementation is a more performant solution as JavaScript engines will fully optimize a function that doesn't reference `arguments`. Please do your own benchmarking and determine if this option is the right fit for your application. | ||
```javascript | ||
// Spec behavior | ||
function bar1 (arg1 = 1) {} | ||
bar1.length // 0 | ||
// Loose mode | ||
function bar1 (arg1 = 1) {} | ||
bar1.length // 1 | ||
``` |
19132
419
95
+ Addedansi-styles@3.2.1(transitive)
+ Addedbabel-code-frame@7.0.0-alpha.16(transitive)
+ Addedbabel-helper-call-delegate@7.0.0-alpha.16(transitive)
+ Addedbabel-helper-function-name@7.0.0-alpha.16(transitive)
+ Addedbabel-helper-get-function-arity@7.0.0-alpha.16(transitive)
+ Addedbabel-helper-hoist-variables@7.0.0-alpha.16(transitive)
+ Addedbabel-messages@7.0.0-alpha.16(transitive)
+ Addedbabel-template@7.0.0-alpha.16(transitive)
+ Addedbabel-traverse@7.0.0-alpha.16(transitive)
+ Addedbabel-types@7.0.0-alpha.16(transitive)
+ Addedbabylon@7.0.0-beta.17(transitive)
+ Addedchalk@2.4.2(transitive)
+ Addedcolor-convert@1.9.3(transitive)
+ Addedcolor-name@1.1.3(transitive)
+ Addedglobals@10.4.0(transitive)
+ Addedhas-flag@3.0.0(transitive)
+ Addedsupports-color@5.5.0(transitive)
+ Addedto-fast-properties@2.0.0(transitive)
- Removedansi-regex@2.1.1(transitive)
- Removedansi-styles@2.2.1(transitive)
- Removedbabel-code-frame@7.0.0-alpha.15(transitive)
- Removedbabel-helper-call-delegate@7.0.0-alpha.15(transitive)
- Removedbabel-helper-function-name@7.0.0-alpha.15(transitive)
- Removedbabel-helper-get-function-arity@7.0.0-alpha.15(transitive)
- Removedbabel-helper-hoist-variables@7.0.0-alpha.15(transitive)
- Removedbabel-messages@7.0.0-alpha.15(transitive)
- Removedbabel-template@7.0.0-alpha.15(transitive)
- Removedbabel-traverse@7.0.0-alpha.15(transitive)
- Removedbabel-types@7.0.0-alpha.15(transitive)
- Removedbabylon@7.0.0-beta.13(transitive)
- Removedchalk@1.1.3(transitive)
- Removedglobals@9.18.0(transitive)
- Removedhas-ansi@2.0.0(transitive)
- Removedstrip-ansi@3.0.1(transitive)
- Removedsupports-color@2.0.0(transitive)
- Removedto-fast-properties@1.0.3(transitive)
Updatedbabel-types@7.0.0-alpha.16