System Info
System:
OS: Windows 10 10.0.19045
CPU: (4) x64 Intel(R) Core(TM) i5-7500 CPU @ 3.40GHz
Memory: 13.06 GB / 31.88 GB
Binaries:
Node: 24.12.0 - C:\Program Files\nodejs\node.EXE
Yarn: 1.22.19 - C:\Users\WHAdmin\AppData\Roaming\npm\yarn.CMD
npm: 10.2.1 - C:\Users\WHAdmin\AppData\Roaming\npm\npm.CMD
pnpm: 11.21.0 - C:\Users\WHAdmin\AppData\Roaming\npm\pnpm.CMD
Browsers:
Chrome: 151.0.7922.137
Edge: Chromium (151.0.4129.93)
Internet Explorer: 11.0.19041.5794
Relevant package versions:
{
"react": "^19.2.8",
"react-dom": "^19.2.8",
"@rspack/core": "^2.1.10"
}
Details
When using React Compiler with Rspack, the following expression is incorrectly transformed.
Source code:
if (retainRef.current++ <= 0) {
// ...
}
The generated code becomes effectively:
retainRef.current = retainRef.current + 1;
if (retainRef.current <= 0) {
// ...
}
These two expressions are not semantically equivalent because x++ is a postfix increment expression: the comparison must use the value before the increment.
For example, if:
the original code behaves as follows:
if (retainRef.current++ <= 0) {
// This branch IS executed
}
// retainRef.current === 1
The comparison evaluates:
and only then increments retainRef.current to 1.
However, after the transformation:
retainRef.current = retainRef.current + 1;
if (retainRef.current <= 0) {
// This branch is NOT executed
}
the comparison becomes:
Therefore, this transformation changes the runtime behavior of the program.
Conceptually:
may be transformed into something equivalent to:
const previous = x;
x = x + 1;
previous <= 0;
but it must not be transformed into:
This issue can cause subtle runtime bugs because the generated code is still valid JavaScript and does not produce any compilation or runtime error. It simply executes different logic from the source code.
Reproduce link
No response
Reproduce Steps
A minimal example:
import { useCallback, useRef } from 'react';
export function App() {
const retainRef = useRef(0);
const test = useCallback(() => {
if (retainRef.current++ <= 0) {
console.log('condition matched');
}
console.log('current:', retainRef.current);
}, []);
return <button onClick={test}>Test</button>;
}
- Build/compile the code with Rspack and React Compiler enabled.
- Inspect the generated JavaScript.
- The original expression:
if (retainRef.current++ <= 0)
is transformed into code equivalent to:
retainRef.current = retainRef.current + 1;
if (retainRef.current <= 0)
- Run the code with
retainRef.current initially set to 0.
Expected output:
condition matched
current: 1
Actual output after the transformation:
The condition is no longer entered because the comparison incorrectly uses the incremented value.
System Info
Relevant package versions:
{ "react": "^19.2.8", "react-dom": "^19.2.8", "@rspack/core": "^2.1.10" }Details
When using React Compiler with Rspack, the following expression is incorrectly transformed.
Source code:
The generated code becomes effectively:
These two expressions are not semantically equivalent because
x++is a postfix increment expression: the comparison must use the value before the increment.For example, if:
the original code behaves as follows:
The comparison evaluates:
and only then increments
retainRef.currentto1.However, after the transformation:
the comparison becomes:
Therefore, this transformation changes the runtime behavior of the program.
Conceptually:
may be transformed into something equivalent to:
but it must not be transformed into:
This issue can cause subtle runtime bugs because the generated code is still valid JavaScript and does not produce any compilation or runtime error. It simply executes different logic from the source code.
Reproduce link
No response
Reproduce Steps
A minimal example:
is transformed into code equivalent to:
retainRef.currentinitially set to0.Expected output:
Actual output after the transformation:
The condition is no longer entered because the comparison incorrectly uses the incremented value.