Skip to content

Commit b51f8db

Browse files
committed
[compiler] Support for member expression inc/decrement
Test Plan: Builds support for a.x++ and friends. Similar to a.x += y, emits it as an assignment expression. ghstack-source-id: 8f39799 Pull Request resolved: #30697
1 parent c39da3e commit b51f8db

File tree

4 files changed

+135
-4
lines changed

4 files changed

+135
-4
lines changed

compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2396,6 +2396,57 @@ function lowerExpression(
23962396
case 'UpdateExpression': {
23972397
let expr = exprPath as NodePath<t.UpdateExpression>;
23982398
const argument = expr.get('argument');
2399+
if (argument.isMemberExpression()) {
2400+
const binaryOperator = expr.node.operator === '++' ? '+' : '-';
2401+
const leftExpr = argument as NodePath<t.MemberExpression>;
2402+
const {object, property, value} = lowerMemberExpression(
2403+
builder,
2404+
leftExpr,
2405+
);
2406+
2407+
// Store the previous value to a temporary
2408+
const previousValuePlace = lowerValueToTemporary(builder, value);
2409+
// Store the new value to a temporary
2410+
const updatedValue = lowerValueToTemporary(builder, {
2411+
kind: 'BinaryExpression',
2412+
operator: binaryOperator,
2413+
left: {...previousValuePlace},
2414+
right: lowerValueToTemporary(builder, {
2415+
kind: 'Primitive',
2416+
value: 1,
2417+
loc: GeneratedSource,
2418+
}),
2419+
loc: leftExpr.node.loc ?? GeneratedSource,
2420+
});
2421+
2422+
// Save the result back to the property
2423+
let newValuePlace;
2424+
if (typeof property === 'string') {
2425+
newValuePlace = lowerValueToTemporary(builder, {
2426+
kind: 'PropertyStore',
2427+
object: {...object},
2428+
property,
2429+
value: {...updatedValue},
2430+
loc: leftExpr.node.loc ?? GeneratedSource,
2431+
});
2432+
} else {
2433+
newValuePlace = lowerValueToTemporary(builder, {
2434+
kind: 'ComputedStore',
2435+
object: {...object},
2436+
property: {...property},
2437+
value: {...updatedValue},
2438+
loc: leftExpr.node.loc ?? GeneratedSource,
2439+
});
2440+
}
2441+
2442+
return {
2443+
kind: 'LoadLocal',
2444+
place: expr.node.prefix
2445+
? {...newValuePlace}
2446+
: {...previousValuePlace},
2447+
loc: exprLoc,
2448+
};
2449+
}
23992450
if (!argument.isIdentifier()) {
24002451
builder.errors.push({
24012452
reason: `(BuildHIR::lowerExpression) Handle UpdateExpression with ${argument.type} argument`,

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-kitchensink.expect.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,6 @@ Todo: (BuildHIR::lowerStatement) Handle ArrayPattern inits in ForOfStatement (38
104104
105105
Todo: (BuildHIR::lowerStatement) Handle ObjectPattern inits in ForOfStatement (40:40)
106106
107-
Todo: (BuildHIR::lowerExpression) Handle UpdateExpression with MemberExpression argument (49:49)
108-
109-
Todo: (BuildHIR::lowerExpression) Handle UpdateExpression with MemberExpression argument (50:50)
110-
111107
Todo: (BuildHIR::node.lowerReorderableExpression) Expression type `MemberExpression` cannot be safely reordered (57:57)
112108
113109
Todo: (BuildHIR::node.lowerReorderableExpression) Expression type `BinaryExpression` cannot be safely reordered (53:53)
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
2+
## Input
3+
4+
```javascript
5+
//@flow
6+
7+
component Foo() {
8+
let x = {a: 1};
9+
x.a++;
10+
x.a--;
11+
console.log(++x.a);
12+
console.log(x.a++);
13+
14+
console.log(x.a);
15+
let y = x.a++;
16+
console.log(y);
17+
console.log(x.a);
18+
19+
console.log((++x.a).toString(), (x.a++).toString(), x.a);
20+
}
21+
22+
export const FIXTURE_ENTRYPOINT = {
23+
fn: Foo,
24+
params: [],
25+
};
26+
27+
```
28+
29+
## Code
30+
31+
```javascript
32+
function Foo() {
33+
const x = { a: 1 };
34+
x.a = x.a + 1;
35+
x.a = x.a - 1;
36+
console.log((x.a = x.a + 1));
37+
const t0 = x.a;
38+
x.a = t0 + 1;
39+
console.log(t0);
40+
41+
console.log(x.a);
42+
const t1 = x.a;
43+
x.a = t1 + 1;
44+
const y = t1;
45+
console.log(y);
46+
console.log(x.a);
47+
48+
const t2 = (x.a = x.a + 1).toString();
49+
const t3 = x.a;
50+
x.a = t3 + 1;
51+
console.log(t2, t3.toString(), x.a);
52+
}
53+
54+
export const FIXTURE_ENTRYPOINT = {
55+
fn: Foo,
56+
params: [],
57+
};
58+
59+
```
60+
61+
### Eval output
62+
(kind: ok)
63+
logs: [2,2,3,3,4,'5','5',6]
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//@flow
2+
3+
component Foo() {
4+
let x = {a: 1};
5+
x.a++;
6+
x.a--;
7+
console.log(++x.a);
8+
console.log(x.a++);
9+
10+
console.log(x.a);
11+
let y = x.a++;
12+
console.log(y);
13+
console.log(x.a);
14+
15+
console.log((++x.a).toString(), (x.a++).toString(), x.a);
16+
}
17+
18+
export const FIXTURE_ENTRYPOINT = {
19+
fn: Foo,
20+
params: [],
21+
};

0 commit comments

Comments
 (0)