mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Support AssignmentPattern (default values in destructuring)
"Supports" default values in destructuring (AssignmentPattern) by lowering to a
ternary, even in the output. Examples:
```javascript
// Input:
const [x = 'default'] = y;
// Output:
const [t0] = y;
const x = t0 === undefined ? 'default' : t0;
```
```javascript
// Input 2
const [{x} = makeObject()] = y;
// Output 2
const [t0] = y;
const {x} = t0 === undefined ? makeObject() : t0;
```
Note that this is how Babel lowers AssignmentPattern, so it isn't too bad. This
should help avoid the need to update product code, even if the output isn't
perfectly ideal.
This commit is contained in:
@@ -2446,6 +2446,106 @@ function lowerAssignment(
|
||||
}
|
||||
return { kind: "LoadLocal", place: temporary, loc: value.loc };
|
||||
}
|
||||
case "AssignmentPattern": {
|
||||
const lvalue = lvaluePath as NodePath<t.AssignmentPattern>;
|
||||
const loc = lvalue.node.loc ?? GeneratedSource;
|
||||
const temp = buildTemporaryPlace(builder, loc);
|
||||
|
||||
const testBlock = builder.reserve("value");
|
||||
const continuationBlock = builder.reserve(builder.currentBlockKind());
|
||||
|
||||
const consequent = builder.enter("value", () => {
|
||||
const defaultValue = lowerExpressionToTemporary(
|
||||
builder,
|
||||
lvalue.get("right")
|
||||
);
|
||||
builder.push({
|
||||
id: makeInstructionId(0),
|
||||
lvalue: buildTemporaryPlace(builder, loc),
|
||||
value: {
|
||||
kind: "StoreLocal",
|
||||
lvalue: { kind: InstructionKind.Const, place: { ...temp } },
|
||||
value: { ...defaultValue },
|
||||
loc,
|
||||
},
|
||||
loc,
|
||||
});
|
||||
return {
|
||||
kind: "goto",
|
||||
variant: GotoVariant.Break,
|
||||
block: continuationBlock.id,
|
||||
id: makeInstructionId(0),
|
||||
loc,
|
||||
};
|
||||
});
|
||||
|
||||
const alternate = builder.enter("value", () => {
|
||||
builder.push({
|
||||
id: makeInstructionId(0),
|
||||
lvalue: buildTemporaryPlace(builder, loc),
|
||||
value: {
|
||||
kind: "StoreLocal",
|
||||
lvalue: { kind: InstructionKind.Const, place: { ...temp } },
|
||||
value: { ...value },
|
||||
loc,
|
||||
},
|
||||
loc,
|
||||
});
|
||||
return {
|
||||
kind: "goto",
|
||||
variant: GotoVariant.Break,
|
||||
block: continuationBlock.id,
|
||||
id: makeInstructionId(0),
|
||||
loc,
|
||||
};
|
||||
});
|
||||
builder.terminateWithContinuation(
|
||||
{
|
||||
kind: "ternary",
|
||||
test: testBlock.id,
|
||||
fallthrough: continuationBlock.id,
|
||||
id: makeInstructionId(0),
|
||||
loc,
|
||||
},
|
||||
testBlock
|
||||
);
|
||||
const undef = buildTemporaryPlace(builder, loc);
|
||||
builder.push({
|
||||
id: makeInstructionId(0),
|
||||
lvalue: { ...undef },
|
||||
value: {
|
||||
kind: "Primitive",
|
||||
value: undefined,
|
||||
loc,
|
||||
},
|
||||
loc,
|
||||
});
|
||||
const test = buildTemporaryPlace(builder, loc);
|
||||
builder.push({
|
||||
id: makeInstructionId(0),
|
||||
lvalue: { ...test },
|
||||
value: {
|
||||
kind: "BinaryExpression",
|
||||
left: { ...value },
|
||||
operator: "===",
|
||||
right: { ...undef },
|
||||
loc,
|
||||
},
|
||||
loc,
|
||||
});
|
||||
builder.terminateWithContinuation(
|
||||
{
|
||||
kind: "branch",
|
||||
test: { ...test },
|
||||
consequent,
|
||||
alternate,
|
||||
id: makeInstructionId(0),
|
||||
},
|
||||
continuationBlock
|
||||
);
|
||||
|
||||
return lowerAssignment(builder, loc, kind, lvalue.get("left"), temp);
|
||||
}
|
||||
default: {
|
||||
builder.errors.push({
|
||||
reason: `(BuildHIR::lowerAssignment) Handle ${lvaluePath.type} assignments`,
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const [[x] = [foo()]] = props.y;
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
const [t0] = props.y;
|
||||
const c_0 = $[0] !== t0;
|
||||
let t1;
|
||||
if (c_0) {
|
||||
t1 = t0 === undefined ? [foo()] : t0;
|
||||
$[0] = t0;
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[1];
|
||||
}
|
||||
const [x] = t1;
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
function Component(props) {
|
||||
const [[x] = [foo()]] = props.y;
|
||||
return x;
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
let x;
|
||||
if (props.cond) {
|
||||
[[x] = [foo()]] = props.y;
|
||||
} else {
|
||||
x = props.fallback;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
let x = undefined;
|
||||
if (props.cond) {
|
||||
const [t0] = props.y;
|
||||
const c_0 = $[0] !== t0;
|
||||
let t1;
|
||||
if (c_0) {
|
||||
t1 = t0 === undefined ? [foo()] : t0;
|
||||
$[0] = t0;
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[1];
|
||||
}
|
||||
[x] = t1;
|
||||
} else {
|
||||
x = props.fallback;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
function Component(props) {
|
||||
let x;
|
||||
if (props.cond) {
|
||||
[[x] = [foo()]] = props.y;
|
||||
} else {
|
||||
x = props.fallback;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const { x: { y } = { y: "default" } } = props.y;
|
||||
return y;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
const { x: t0 } = props.y;
|
||||
const c_0 = $[0] !== t0;
|
||||
let t1;
|
||||
if (c_0) {
|
||||
t1 = t0 === undefined ? { y: "default" } : t0;
|
||||
$[0] = t0;
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[1];
|
||||
}
|
||||
const { y } = t1;
|
||||
return y;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
function Component(props) {
|
||||
const { x: { y } = { y: "default" } } = props.y;
|
||||
return y;
|
||||
}
|
||||
@@ -79,13 +79,6 @@ let moduleLocal = false;
|
||||
## Error
|
||||
|
||||
```
|
||||
[ReactForget] TodoError: (BuildHIR::lowerAssignment) Handle AssignmentPattern assignments
|
||||
> 1 | function foo([a, b], { c, d, e = "e" }, f = "f", ...args) {
|
||||
| ^^^^^^^
|
||||
2 | let i = 0;
|
||||
3 | var x = [];
|
||||
4 |
|
||||
|
||||
[ReactForget] TodoError: (BuildHIR::lower) Handle AssignmentPattern params
|
||||
> 1 | function foo([a, b], { c, d, e = "e" }, f = "f", ...args) {
|
||||
| ^^^^^^^
|
||||
@@ -127,15 +120,6 @@ let moduleLocal = false;
|
||||
14 |
|
||||
15 | <Button haha={1}></Button>;
|
||||
|
||||
[ReactForget] TodoError: (BuildHIR::lowerAssignment) Handle AssignmentPattern assignments
|
||||
11 |
|
||||
12 | const g = { b() {}, c: () => {} };
|
||||
> 13 | const { z, aa = "aa" } = useCustom();
|
||||
| ^^^^^^^^^
|
||||
14 |
|
||||
15 | <Button haha={1}></Button>;
|
||||
16 | <Button>{/** empty */}</Button>;
|
||||
|
||||
[ReactForget] TodoError: (BuildHIR::lowerJsxElement) Handle JSXEmptyExpression expressions
|
||||
14 |
|
||||
15 | <Button haha={1}></Button>;
|
||||
|
||||
Reference in New Issue
Block a user