2nd try: Add loose option for es2015-parameters transformation (#5943)
* Import changes to parameters package from previous branch * Refactor plugin option access via state
This commit is contained in:
parent
a0f0411abf
commit
b83e0ec7b0
@ -72,3 +72,23 @@ require("babel-core").transform("code", {
|
|||||||
plugins: ["transform-es2015-parameters"]
|
plugins: ["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
|
||||||
|
```
|
||||||
|
|||||||
@ -11,6 +11,16 @@ const buildDefaultParam = template(`
|
|||||||
DEFAULT_VALUE;
|
DEFAULT_VALUE;
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
const buildLooseDefaultParam = template(`
|
||||||
|
if (ASSIGMENT_IDENTIFIER === UNDEFINED) {
|
||||||
|
ASSIGMENT_IDENTIFIER = DEFAULT_VALUE;
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
const buildLooseDestructuredDefaultParam = template(`
|
||||||
|
let ASSIGMENT_IDENTIFIER = PARAMETER_NAME === UNDEFINED ? DEFAULT_VALUE : PARAMETER_NAME ;
|
||||||
|
`);
|
||||||
|
|
||||||
const buildCutOff = template(`
|
const buildCutOff = template(`
|
||||||
let $0 = $1[$2];
|
let $0 = $1[$2];
|
||||||
`);
|
`);
|
||||||
@ -51,6 +61,45 @@ export const visitor = {
|
|||||||
// ensure it's a block, useful for arrow functions
|
// ensure it's a block, useful for arrow functions
|
||||||
path.ensureBlock();
|
path.ensureBlock();
|
||||||
|
|
||||||
|
const params = path.get("params");
|
||||||
|
|
||||||
|
if (this.opts.loose) {
|
||||||
|
const body = [];
|
||||||
|
for (let i = 0; i < params.length; ++i) {
|
||||||
|
const param = params[i];
|
||||||
|
if (param.isAssignmentPattern()) {
|
||||||
|
const left = param.get("left");
|
||||||
|
const right = param.get("right");
|
||||||
|
|
||||||
|
const 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()) {
|
||||||
|
const 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;
|
||||||
|
}
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
iife: false,
|
iife: false,
|
||||||
scope: scope,
|
scope: scope,
|
||||||
@ -77,7 +126,6 @@ export const visitor = {
|
|||||||
const lastNonDefaultParam = getFunctionArity(node);
|
const lastNonDefaultParam = getFunctionArity(node);
|
||||||
|
|
||||||
//
|
//
|
||||||
const params = path.get("params");
|
|
||||||
for (let i = 0; i < params.length; i++) {
|
for (let i = 0; i < params.length; i++) {
|
||||||
const param = params[i];
|
const param = params[i];
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,3 @@
|
|||||||
|
function f(a, b = a, c = b) { return c; }
|
||||||
|
|
||||||
|
assert.equal(3, f(3));
|
||||||
@ -0,0 +1 @@
|
|||||||
|
function test({a: b} = {}) {}
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
function test(_temp) {
|
||||||
|
var _ref = _temp === void 0 ? {} : _temp,
|
||||||
|
b = _ref.a;
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
function t([,,a] = [1,2,3]) { return a }
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
function t([,,a] = [1,2,3]) { return a }
|
||||||
|
|
||||||
|
assert.equal(t(), 3);
|
||||||
|
assert.equal(t([4,5,6]), 6);
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
function t(_temp) {
|
||||||
|
var _ref = _temp === void 0 ? [1, 2, 3] : _temp,
|
||||||
|
_ref2 = babelHelpers.slicedToArray(_ref, 3),
|
||||||
|
a = _ref2[2];
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
function f(a, b = a, c = b) { return c; }
|
||||||
|
|
||||||
|
assert.equal(3, f(3));
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
const bar = true;
|
||||||
|
|
||||||
|
function foo(a = bar, ...b) {
|
||||||
|
const bar = false;
|
||||||
|
assert.equal(b[0], 2);
|
||||||
|
assert.equal(b[1], 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
foo(1, 2, 3);
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
class Ref {
|
||||||
|
static nextId = 0
|
||||||
|
constructor(id = ++Ref.nextId, n = id) {
|
||||||
|
this.id = n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.equal(1, new Ref().id)
|
||||||
|
assert.equal(2, new Ref().id)
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
class Ref {
|
||||||
|
constructor(ref = Ref) {
|
||||||
|
this.ref = ref
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.equal(Ref, new Ref().ref)
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
var t = function (e = "foo", f = 5) {
|
||||||
|
return e + " bar " + f;
|
||||||
|
};
|
||||||
|
|
||||||
|
var a = function (e, f = 5) {
|
||||||
|
return e + " bar " + f;
|
||||||
|
};
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
var t = function (e, f) {
|
||||||
|
if (e === void 0) {
|
||||||
|
e = "foo";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f === void 0) {
|
||||||
|
f = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
return e + " bar " + f;
|
||||||
|
};
|
||||||
|
|
||||||
|
var a = function (e, f) {
|
||||||
|
if (f === void 0) {
|
||||||
|
f = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
return e + " bar " + f;
|
||||||
|
};
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
function required(msg) {
|
||||||
|
throw new Error(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
function sum(
|
||||||
|
{ arr = required('arr is required') } = { arr: arr = [] },
|
||||||
|
length = arr.length
|
||||||
|
) {
|
||||||
|
let i = 0;
|
||||||
|
let acc = 0;
|
||||||
|
for (let item of arr) {
|
||||||
|
if (i >= length) return acc;
|
||||||
|
acc += item;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.equal(sum({arr:[1,2]}), 3);
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
const a = 1;
|
||||||
|
function rest(b = a, ...a) {
|
||||||
|
assert.equal(b, 1);
|
||||||
|
}
|
||||||
|
rest(undefined, 2)
|
||||||
|
|
||||||
|
function rest2(b = a, ...a) {
|
||||||
|
assert.equal(a[0], 2);
|
||||||
|
}
|
||||||
|
rest2(undefined, 2)
|
||||||
|
|
||||||
|
function rest3(b = a, ...a) {
|
||||||
|
assert.equal(a.length, 1);
|
||||||
|
}
|
||||||
|
rest3(undefined, 2)
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
var t = function (f = "foo") {
|
||||||
|
return f + " bar";
|
||||||
|
};
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
var t = function (f) {
|
||||||
|
if (f === void 0) {
|
||||||
|
f = "foo";
|
||||||
|
}
|
||||||
|
|
||||||
|
return f + " bar";
|
||||||
|
};
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["transform-class-properties", "external-helpers", "syntax-flow", ["transform-es2015-parameters", { "loose": true } ], "transform-es2015-block-scoping", "transform-es2015-spread", "transform-es2015-classes", "transform-es2015-destructuring", "transform-es2015-arrow-functions", "syntax-async-functions", "transform-es2015-for-of"]
|
||||||
|
}
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
function t(undefined = 17, a = 3) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.equal(t(), 3);
|
||||||
Loading…
x
Reference in New Issue
Block a user