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;
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