mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[repro] Repro for control flow bug in PropagateScopeDependency
--- Thanks to @josephsavona for finding this bug. This is another example of why we really want hir-everywhere. Forget output currently nullthrows because we believe `obj.a` is run unconditionally in source (missing the break/returns out of this scope)
This commit is contained in:
+63
@@ -0,0 +1,63 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function useFoo({ obj, objIsNull }) {
|
||||
const x = [];
|
||||
b0: {
|
||||
if (objIsNull) {
|
||||
break b0;
|
||||
}
|
||||
x.push(obj.a);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [{ obj: null, objIsNull: true }],
|
||||
sequentialRenders: [
|
||||
{ obj: null, objIsNull: true },
|
||||
{ obj: { a: 2 }, objIsNull: false },
|
||||
],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { unstable_useMemoCache as useMemoCache } from "react";
|
||||
function useFoo(t0) {
|
||||
const $ = useMemoCache(3);
|
||||
const { obj, objIsNull } = t0;
|
||||
let x;
|
||||
if ($[0] !== objIsNull || $[1] !== obj.a) {
|
||||
x = [];
|
||||
bb1: {
|
||||
if (objIsNull) {
|
||||
break bb1;
|
||||
}
|
||||
|
||||
x.push(obj.a);
|
||||
}
|
||||
$[0] = objIsNull;
|
||||
$[1] = obj.a;
|
||||
$[2] = x;
|
||||
} else {
|
||||
x = $[2];
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [{ obj: null, objIsNull: true }],
|
||||
sequentialRenders: [
|
||||
{ obj: null, objIsNull: true },
|
||||
{ obj: { a: 2 }, objIsNull: false },
|
||||
],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
function useFoo({ obj, objIsNull }) {
|
||||
const x = [];
|
||||
b0: {
|
||||
if (objIsNull) {
|
||||
break b0;
|
||||
}
|
||||
x.push(obj.a);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [{ obj: null, objIsNull: true }],
|
||||
sequentialRenders: [
|
||||
{ obj: null, objIsNull: true },
|
||||
{ obj: { a: 2 }, objIsNull: false },
|
||||
],
|
||||
};
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function useFoo({ obj, objIsNull }) {
|
||||
const x = [];
|
||||
if (objIsNull) {
|
||||
return;
|
||||
}
|
||||
x.push(obj.b);
|
||||
return x;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [{ obj: null, objIsNull: true }],
|
||||
sequentialRenders: [
|
||||
{ obj: null, objIsNull: true },
|
||||
{ obj: { a: 2 }, objIsNull: false },
|
||||
],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { unstable_useMemoCache as useMemoCache } from "react";
|
||||
function useFoo(t0) {
|
||||
const $ = useMemoCache(4);
|
||||
const { obj, objIsNull } = t0;
|
||||
let x;
|
||||
let t1;
|
||||
if ($[0] !== objIsNull || $[1] !== obj.b) {
|
||||
t1 = Symbol.for("react.early_return_sentinel");
|
||||
bb7: {
|
||||
x = [];
|
||||
if (objIsNull) {
|
||||
t1 = undefined;
|
||||
break bb7;
|
||||
}
|
||||
|
||||
x.push(obj.b);
|
||||
}
|
||||
$[0] = objIsNull;
|
||||
$[1] = obj.b;
|
||||
$[2] = x;
|
||||
$[3] = t1;
|
||||
} else {
|
||||
x = $[2];
|
||||
t1 = $[3];
|
||||
}
|
||||
if (t1 !== Symbol.for("react.early_return_sentinel")) {
|
||||
return t1;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [{ obj: null, objIsNull: true }],
|
||||
sequentialRenders: [
|
||||
{ obj: null, objIsNull: true },
|
||||
{ obj: { a: 2 }, objIsNull: false },
|
||||
],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
function useFoo({ obj, objIsNull }) {
|
||||
const x = [];
|
||||
if (objIsNull) {
|
||||
return;
|
||||
}
|
||||
x.push(obj.b);
|
||||
return x;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [{ obj: null, objIsNull: true }],
|
||||
sequentialRenders: [
|
||||
{ obj: null, objIsNull: true },
|
||||
{ obj: { a: 2 }, objIsNull: false },
|
||||
],
|
||||
};
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function useFoo({ obj, objIsNull }) {
|
||||
const x = [];
|
||||
b0: {
|
||||
if (objIsNull) {
|
||||
break b0;
|
||||
} else {
|
||||
x.push(obj.a);
|
||||
}
|
||||
x.push(obj.b);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [{ obj: null, objIsNull: true }],
|
||||
sequentialRenders: [
|
||||
{ obj: null, objIsNull: true },
|
||||
{ obj: { a: 2 }, objIsNull: false },
|
||||
],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { unstable_useMemoCache as useMemoCache } from "react";
|
||||
function useFoo(t0) {
|
||||
const $ = useMemoCache(3);
|
||||
const { obj, objIsNull } = t0;
|
||||
let x;
|
||||
if ($[0] !== objIsNull || $[1] !== obj) {
|
||||
x = [];
|
||||
bb1: {
|
||||
if (objIsNull) {
|
||||
break bb1;
|
||||
} else {
|
||||
x.push(obj.a);
|
||||
}
|
||||
|
||||
x.push(obj.b);
|
||||
}
|
||||
$[0] = objIsNull;
|
||||
$[1] = obj;
|
||||
$[2] = x;
|
||||
} else {
|
||||
x = $[2];
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [{ obj: null, objIsNull: true }],
|
||||
sequentialRenders: [
|
||||
{ obj: null, objIsNull: true },
|
||||
{ obj: { a: 2 }, objIsNull: false },
|
||||
],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: ok) []
|
||||
[2,null]
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
function useFoo({ obj, objIsNull }) {
|
||||
const x = [];
|
||||
b0: {
|
||||
if (objIsNull) {
|
||||
break b0;
|
||||
} else {
|
||||
x.push(obj.a);
|
||||
}
|
||||
x.push(obj.b);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [{ obj: null, objIsNull: true }],
|
||||
sequentialRenders: [
|
||||
{ obj: null, objIsNull: true },
|
||||
{ obj: { a: 2 }, objIsNull: false },
|
||||
],
|
||||
};
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function useFoo({ obj, objIsNull }) {
|
||||
const x = [];
|
||||
if (objIsNull) {
|
||||
return;
|
||||
} else {
|
||||
x.push(obj.a);
|
||||
}
|
||||
x.push(obj.b);
|
||||
return x;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [{ obj: null, objIsNull: true }],
|
||||
sequentialRenders: [
|
||||
{ obj: null, objIsNull: true },
|
||||
{ obj: { a: 2 }, objIsNull: false },
|
||||
],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { unstable_useMemoCache as useMemoCache } from "react";
|
||||
function useFoo(t0) {
|
||||
const $ = useMemoCache(4);
|
||||
const { obj, objIsNull } = t0;
|
||||
let x;
|
||||
let t1;
|
||||
if ($[0] !== objIsNull || $[1] !== obj) {
|
||||
t1 = Symbol.for("react.early_return_sentinel");
|
||||
bb8: {
|
||||
x = [];
|
||||
if (objIsNull) {
|
||||
t1 = undefined;
|
||||
break bb8;
|
||||
} else {
|
||||
x.push(obj.a);
|
||||
}
|
||||
|
||||
x.push(obj.b);
|
||||
}
|
||||
$[0] = objIsNull;
|
||||
$[1] = obj;
|
||||
$[2] = x;
|
||||
$[3] = t1;
|
||||
} else {
|
||||
x = $[2];
|
||||
t1 = $[3];
|
||||
}
|
||||
if (t1 !== Symbol.for("react.early_return_sentinel")) {
|
||||
return t1;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [{ obj: null, objIsNull: true }],
|
||||
sequentialRenders: [
|
||||
{ obj: null, objIsNull: true },
|
||||
{ obj: { a: 2 }, objIsNull: false },
|
||||
],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: ok)
|
||||
[2,null]
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
function useFoo({ obj, objIsNull }) {
|
||||
const x = [];
|
||||
if (objIsNull) {
|
||||
return;
|
||||
} else {
|
||||
x.push(obj.a);
|
||||
}
|
||||
x.push(obj.b);
|
||||
return x;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [{ obj: null, objIsNull: true }],
|
||||
sequentialRenders: [
|
||||
{ obj: null, objIsNull: true },
|
||||
{ obj: { a: 2 }, objIsNull: false },
|
||||
],
|
||||
};
|
||||
@@ -531,10 +531,9 @@ const skipFilter = new Set([
|
||||
"rules-of-hooks/rules-of-hooks-93dc5d5e538a",
|
||||
"rules-of-hooks/rules-of-hooks-69521d94fa03",
|
||||
|
||||
// bug
|
||||
"bug-jsx-memberexpr-tag-in-lambda",
|
||||
"bug-invalid-code-when-bailout",
|
||||
"component-syntax-ref-gating.flow",
|
||||
// bugs
|
||||
"bug-reduce-reactive-deps-return-in-scope",
|
||||
"bug-reduce-reactive-deps-break-in-scope",
|
||||
|
||||
// 'react-forget-runtime' not yet supported
|
||||
"flag-enable-emit-hook-guards",
|
||||
|
||||
Reference in New Issue
Block a user