mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[compiler][repro] Postfix operator is incorrectly compiled
This bug was reported via our wg and appears to only affect values created as a ref. Currently, postfix operators used in a callback gets compiled to: ```js modalId.current = modalId.current + 1; // 1 const id = modalId.current; // 1 return id; ``` which is semantically incorrect. The postfix increment operator should return the value before incrementing. In other words something like this should have been compiled instead: ```js const id = modalId.current; // 0 modalId.current = modalId.current + 1; // 1 return id; ``` This bug does not trigger when the incremented value is a plain primitive, instead there is a TODO bailout.
This commit is contained in:
+91
@@ -0,0 +1,91 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
import {useRef} from 'react';
|
||||
|
||||
/**
|
||||
* The postfix increment operator should return the value before incrementing.
|
||||
* ```js
|
||||
* const id = modalId.current; // 0
|
||||
* modalId.current = modalId.current + 1; // 1
|
||||
* return id;
|
||||
* ```
|
||||
* Currently we increment before the expression is evaluated, which is incorrect.
|
||||
* This bug does not trigger when the incremented value is a plain primitive.
|
||||
*/
|
||||
function useFoo() {
|
||||
const modalId = useRef(0);
|
||||
const showModal = () => {
|
||||
const id = modalId.current++;
|
||||
return id;
|
||||
};
|
||||
const showModal2 = () => {
|
||||
const id = ++modalId.current;
|
||||
return id;
|
||||
};
|
||||
return {modalId, showModal, showModal2};
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import { useRef } from "react";
|
||||
|
||||
/**
|
||||
* The postfix increment operator should return the value before incrementing.
|
||||
* ```js
|
||||
* const id = modalId.current; // 0
|
||||
* modalId.current = modalId.current + 1; // 1
|
||||
* return id;
|
||||
* ```
|
||||
* The bug is that
|
||||
* This bug does not trigger when the incremented value is a plain primitive.
|
||||
*/
|
||||
function useFoo() {
|
||||
const $ = _c(2);
|
||||
const modalId = useRef(0);
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = () => {
|
||||
modalId.current = modalId.current + 1;
|
||||
const id = modalId.current;
|
||||
return id;
|
||||
};
|
||||
$[0] = t0;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
const showModal = t0;
|
||||
let t1;
|
||||
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
const showModal2 = () => {
|
||||
const id_0 = (modalId.current = modalId.current + 1);
|
||||
return id_0;
|
||||
};
|
||||
|
||||
t1 = { modalId, showModal, showModal2 };
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[1];
|
||||
}
|
||||
return t1;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: ok) {"modalId":{"current":0},"showModal":"[[ function params=0 ]]","showModal2":"[[ function params=0 ]]"}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
import {useRef} from 'react';
|
||||
|
||||
/**
|
||||
* The postfix increment operator should return the value before incrementing.
|
||||
* ```js
|
||||
* const id = modalId.current; // 0
|
||||
* modalId.current = modalId.current + 1; // 1
|
||||
* return id;
|
||||
* ```
|
||||
* The bug is that
|
||||
* This bug does not trigger when the incremented value is a plain primitive.
|
||||
*/
|
||||
function useFoo() {
|
||||
const modalId = useRef(0);
|
||||
const showModal = () => {
|
||||
const id = modalId.current++;
|
||||
return id;
|
||||
};
|
||||
const showModal2 = () => {
|
||||
const id = ++modalId.current;
|
||||
return id;
|
||||
};
|
||||
return {modalId, showModal, showModal2};
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [],
|
||||
};
|
||||
Reference in New Issue
Block a user