Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2596,11 +2596,17 @@ function lowerExpression(

// Store the previous value to a temporary
const previousValuePlace = lowerValueToTemporary(builder, value);
const capturedPreviousValue = lowerValueToTemporary(builder, {
kind: 'LoadLocal',
place: {...previousValuePlace},
loc: exprLoc,
});

// Store the new value to a temporary
const updatedValue = lowerValueToTemporary(builder, {
kind: 'BinaryExpression',
operator: binaryOperator,
left: {...previousValuePlace},
left: {...capturedPreviousValue},
right: lowerValueToTemporary(builder, {
kind: 'Primitive',
value: 1,
Expand Down Expand Up @@ -2633,7 +2639,7 @@ function lowerExpression(
kind: 'LoadLocal',
place: expr.node.prefix
? {...newValuePlace}
: {...previousValuePlace},
: {...capturedPreviousValue},
loc: exprLoc,
};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@

## Input

```javascript
// @enableNewMutationAliasingModel:false
/**
* Bug repro:
* Found differences in evaluator results
* Non-forget (expected):
* (kind: ok) {"count":3,"res":[0,1,2]}
* Forget:
* (kind: ok) {"count":3,"res":[1,2,3]}
*
* The post-increment operator `agg.count++` should return the value
* BEFORE incrementing, but the compiler's optimization incorrectly
* causes the incremented value to be used.
*/
function Component(props) {
const items = [0, 1, 2];
return items.reduce((agg, item) => {
const current = agg.count++;
agg.res.push(current);
return agg;
}, {count: 0, res: []});
}

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

```

## Code

```javascript
import { c as _c } from "react/compiler-runtime"; // @enableNewMutationAliasingModel:false
/**
* Bug repro:
* Found differences in evaluator results
* Non-forget (expected):
* (kind: ok) {"count":3,"res":[0,1,2]}
* Forget:
* (kind: ok) {"count":3,"res":[1,2,3]}
*
* The post-increment operator `agg.count++` should return the value
* BEFORE incrementing, but the compiler's optimization incorrectly
* causes the incremented value to be used.
*/
function Component(props) {
const $ = _c(1);
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
const items = [0, 1, 2];
t0 = items.reduce(
_temp,

{ count: 0, res: [] },
);
$[0] = t0;
} else {
t0 = $[0];
}
return t0;
}
function _temp(agg, item) {
agg.count = agg.count + 1;
const current = agg.count;
Comment on lines +67 to +68
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: Expected output still shows incorrect behavior: const current = agg.count assigns the incremented value (1, 2, 3) instead of pre-increment values (0, 1, 2). Expectation file may need regeneration after fix is verified.

Suggested change
agg.count = agg.count + 1;
const current = agg.count;
const current = agg.count - 1;
agg.count = agg.count + 1;
Prompt To Fix With AI
This is a comment left during a code review.
Path: compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/bug-post-increment-assignment.expect.md
Line: 67:68

Comment:
**logic:** Expected output still shows incorrect behavior: `const current = agg.count` assigns the incremented value (1, 2, 3) instead of pre-increment values (0, 1, 2). Expectation file may need regeneration after fix is verified.

```suggestion
  const current = agg.count - 1;
  agg.count = agg.count + 1;
```

How can I resolve this? If you propose a fix, please make it concise.

agg.res.push(current);
return agg;
}

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

```

Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// @enableNewMutationAliasingModel:false
/**
* Bug repro:
* Found differences in evaluator results
* Non-forget (expected):
* (kind: ok) {"count":3,"res":[0,1,2]}
* Forget:
* (kind: ok) {"count":3,"res":[1,2,3]}
*
* The post-increment operator `agg.count++` should return the value
* BEFORE incrementing, but the compiler's optimization incorrectly
* causes the incremented value to be used.
*/
function Component(props) {
const items = [0, 1, 2];
return items.reduce((agg, item) => {
const current = agg.count++;
agg.res.push(current);
return agg;
}, {count: 0, res: []});
}

export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{}],
};
1 change: 1 addition & 0 deletions compiler/packages/snap/src/SproutTodoFilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,7 @@ const skipFilter = new Set([
'fbt/bug-fbt-plural-multiple-function-calls',
'fbt/bug-fbt-plural-multiple-mixed-call-tag',
'bug-invalid-phi-as-dependency',
'bug-post-increment-assignment',
'bug-ref-prefix-postfix-operator',

// 'react-compiler-runtime' not yet supported
Expand Down
Loading