mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Add todo for for loops with context iterator variable
Detect the previous case — for loops where the iterator is a context variables — and throw a todo rather than hitting the invariant.
This commit is contained in:
+15
-1
@@ -967,6 +967,20 @@ function codegenForInit(
|
||||
init: ReactiveValue
|
||||
): t.Expression | t.VariableDeclaration | null {
|
||||
if (init.kind === "SequenceExpression") {
|
||||
for (const instr of init.instructions) {
|
||||
if (instr.value.kind === "DeclareContext") {
|
||||
CompilerError.throwTodo({
|
||||
reason: `Support for loops where the index variable is a context variable`,
|
||||
loc: instr.loc,
|
||||
description:
|
||||
instr.value.lvalue.place.identifier.name != null
|
||||
? `'${instr.value.lvalue.place.identifier.name.value}' is a context variable`
|
||||
: null,
|
||||
suggestions: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const body = codegenBlock(
|
||||
cx,
|
||||
init.instructions.map((instruction) => ({
|
||||
@@ -983,7 +997,7 @@ function codegenForInit(
|
||||
{
|
||||
reason: "Expected a variable declaration",
|
||||
loc: init.loc,
|
||||
description: null,
|
||||
description: `Got ${instr.type}`,
|
||||
suggestions: null,
|
||||
}
|
||||
);
|
||||
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
import { useHook } from "shared-runtime";
|
||||
|
||||
function Component(props) {
|
||||
const data = useHook();
|
||||
const items = [];
|
||||
// NOTE: `item` is a context variable because it's reassigned and also referenced
|
||||
// within a closure, the `onClick` handler of each item
|
||||
for (let key in props.data) {
|
||||
key = key ?? null; // no-op reassignment to force a context variable
|
||||
items.push(
|
||||
<div key={key} onClick={() => data.set(key)}>
|
||||
{key}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return <div>{items}</div>;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ data: { a: "a", b: true, c: "hello" } }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
6 | // NOTE: `item` is a context variable because it's reassigned and also referenced
|
||||
7 | // within a closure, the `onClick` handler of each item
|
||||
> 8 | for (let key in props.data) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 9 | key = key ?? null; // no-op reassignment to force a context variable
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 10 | items.push(
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 11 | <div key={key} onClick={() => data.set(key)}>
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 12 | {key}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 13 | </div>
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 14 | );
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 15 | }
|
||||
| ^^^^ [ReactForget] Todo: Support non-trivial ForOf inits (8:15)
|
||||
16 | return <div>{items}</div>;
|
||||
17 | }
|
||||
18 |
|
||||
```
|
||||
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
import { useHook } from "shared-runtime";
|
||||
|
||||
function Component(props) {
|
||||
const data = useHook();
|
||||
const items = [];
|
||||
// NOTE: `item` is a context variable because it's reassigned and also referenced
|
||||
// within a closure, the `onClick` handler of each item
|
||||
for (let key in props.data) {
|
||||
key = key ?? null; // no-op reassignment to force a context variable
|
||||
items.push(
|
||||
<div key={key} onClick={() => data.set(key)}>
|
||||
{key}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return <div>{items}</div>;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ data: { a: "a", b: true, c: "hello" } }],
|
||||
};
|
||||
+7
-11
@@ -19,17 +19,13 @@ function Component() {
|
||||
## Error
|
||||
|
||||
```
|
||||
4 | // NOTE: `i` is a context variable because it's reassigned and also referenced
|
||||
5 | // within a closure, the `onClick` handler of each item
|
||||
> 6 | for (let i = MIN; i <= MAX; i += INCREMENT) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 7 | items.push(<Stringify key={i} onClick={() => data.set(i)} />);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 8 | }
|
||||
| ^^^^ [ReactForget] Invariant: Expected a variable declaration (6:8)
|
||||
9 | return items;
|
||||
10 | }
|
||||
11 |
|
||||
4 | // NOTE: `i` is a context variable because it's reassigned and also referenced
|
||||
5 | // within a closure, the `onClick` handler of each item
|
||||
> 6 | for (let i = MIN; i <= MAX; i += INCREMENT) {
|
||||
| ^^^^^^^^^^^ [ReactForget] Todo: Support for loops where the index variable is a context variable. 'i' is a context variable (6:6)
|
||||
7 | items.push(<Stringify key={i} onClick={() => data.set(i)} />);
|
||||
8 | }
|
||||
9 | return items;
|
||||
```
|
||||
|
||||
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
import { useHook } from "shared-runtime";
|
||||
|
||||
function Component(props) {
|
||||
const data = useHook();
|
||||
const items = [];
|
||||
// NOTE: `item` is a context variable because it's reassigned and also referenced
|
||||
// within a closure, the `onClick` handler of each item
|
||||
for (let item of props.data) {
|
||||
item = item ?? {}; // reassignment to force a context variable
|
||||
items.push(
|
||||
<div key={item.id} onClick={() => data.set(item)}>
|
||||
{item.id}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return <div>{items}</div>;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ data: [{ id: "1" }, { id: "2" }] }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
6 | // NOTE: `item` is a context variable because it's reassigned and also referenced
|
||||
7 | // within a closure, the `onClick` handler of each item
|
||||
> 8 | for (let item of props.data) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 9 | item = item ?? {}; // reassignment to force a context variable
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 10 | items.push(
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 11 | <div key={item.id} onClick={() => data.set(item)}>
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 12 | {item.id}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 13 | </div>
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 14 | );
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 15 | }
|
||||
| ^^^^ [ReactForget] Todo: Support non-trivial ForOf inits (8:15)
|
||||
16 | return <div>{items}</div>;
|
||||
17 | }
|
||||
18 |
|
||||
```
|
||||
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
import { useHook } from "shared-runtime";
|
||||
|
||||
function Component(props) {
|
||||
const data = useHook();
|
||||
const items = [];
|
||||
// NOTE: `item` is a context variable because it's reassigned and also referenced
|
||||
// within a closure, the `onClick` handler of each item
|
||||
for (let item of props.data) {
|
||||
item = item ?? {}; // reassignment to force a context variable
|
||||
items.push(
|
||||
<div key={item.id} onClick={() => data.set(item)}>
|
||||
{item.id}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return <div>{items}</div>;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ data: [{ id: "1" }, { id: "2" }] }],
|
||||
};
|
||||
Reference in New Issue
Block a user