Skip to content

Commit

Permalink
[compiler] Support for member expression inc/decrement
Browse files Browse the repository at this point in the history
Test Plan:
Builds support for a.x++ and friends. Similar to a.x += y, emits it as an assignment expression.

ghstack-source-id: 8f3979913aad561cdba70464c3cc5f0ee95887b5
Pull Request resolved: #30697
  • Loading branch information
mvitousek committed Aug 15, 2024
1 parent bb6acc2 commit 50d2197
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 4 deletions.
51 changes: 51 additions & 0 deletions compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2385,6 +2385,57 @@ function lowerExpression(
case 'UpdateExpression': {
let expr = exprPath as NodePath<t.UpdateExpression>;
const argument = expr.get('argument');
if (argument.isMemberExpression()) {
const binaryOperator = expr.node.operator === '++' ? '+' : '-';
const leftExpr = argument as NodePath<t.MemberExpression>;
const {object, property, value} = lowerMemberExpression(
builder,
leftExpr,
);

// Store the previous value to a temporary
const previousValuePlace = lowerValueToTemporary(builder, value);
// Store the new value to a temporary
const updatedValue = lowerValueToTemporary(builder, {
kind: 'BinaryExpression',
operator: binaryOperator,
left: {...previousValuePlace},
right: lowerValueToTemporary(builder, {
kind: 'Primitive',
value: 1,
loc: GeneratedSource,
}),
loc: leftExpr.node.loc ?? GeneratedSource,
});

// Save the result back to the property
let newValuePlace;
if (typeof property === 'string') {
newValuePlace = lowerValueToTemporary(builder, {
kind: 'PropertyStore',
object: {...object},
property,
value: {...updatedValue},
loc: leftExpr.node.loc ?? GeneratedSource,
});
} else {
newValuePlace = lowerValueToTemporary(builder, {
kind: 'ComputedStore',
object: {...object},
property: {...property},
value: {...updatedValue},
loc: leftExpr.node.loc ?? GeneratedSource,
});
}

return {
kind: 'LoadLocal',
place: expr.node.prefix
? {...newValuePlace}
: {...previousValuePlace},
loc: exprLoc,
};
}
if (!argument.isIdentifier()) {
builder.errors.push({
reason: `(BuildHIR::lowerExpression) Handle UpdateExpression with ${argument.type} argument`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,6 @@ Todo: (BuildHIR::lowerStatement) Handle ArrayPattern inits in ForOfStatement (38
Todo: (BuildHIR::lowerStatement) Handle ObjectPattern inits in ForOfStatement (40:40)
Todo: (BuildHIR::lowerExpression) Handle UpdateExpression with MemberExpression argument (49:49)
Todo: (BuildHIR::lowerExpression) Handle UpdateExpression with MemberExpression argument (50:50)
Todo: (BuildHIR::node.lowerReorderableExpression) Expression type `MemberExpression` cannot be safely reordered (57:57)
Todo: (BuildHIR::node.lowerReorderableExpression) Expression type `BinaryExpression` cannot be safely reordered (53:53)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@

## Input

```javascript
//@flow

component Foo() {
let x = {a: 1};
x.a++;
x.a--;
console.log(++x.a);
console.log(x.a++);

console.log(x.a);
let y = x.a++;
console.log(y);
console.log(x.a);

console.log((++x.a).toString(), (x.a++).toString(), x.a);
}

export const FIXTURE_ENTRYPOINT = {
fn: Foo,
params: [],
};

```

## Code

```javascript
function Foo() {
const x = { a: 1 };
x.a = x.a + 1;
x.a = x.a - 1;
console.log((x.a = x.a + 1));
const t0 = x.a;
x.a = t0 + 1;
console.log(t0);

console.log(x.a);
const t1 = x.a;
x.a = t1 + 1;
const y = t1;
console.log(y);
console.log(x.a);

const t2 = (x.a = x.a + 1).toString();
const t3 = x.a;
x.a = t3 + 1;
console.log(t2, t3.toString(), x.a);
}

export const FIXTURE_ENTRYPOINT = {
fn: Foo,
params: [],
};

```
### Eval output
(kind: ok)
logs: [2,2,3,3,4,'5','5',6]
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//@flow

component Foo() {
let x = {a: 1};
x.a++;
x.a--;
console.log(++x.a);
console.log(x.a++);

console.log(x.a);
let y = x.a++;
console.log(y);
console.log(x.a);

console.log((++x.a).toString(), (x.a++).toString(), x.a);
}

export const FIXTURE_ENTRYPOINT = {
fn: Foo,
params: [],
};

0 comments on commit 50d2197

Please sign in to comment.