mirror of
https://github.com/hanzoai/react.git
synced 2026-09-24 17:02:27 +00:00
[compiler] PruneNonEscapingScopes understands terminal operands
We weren't treating terminal operands as eligible for memoization in PruneNonEscapingScopes, which meant that they could end up un-memoized. Terminal operands can also be compound ReactiveValues like SequenceExpressions, so part of the fix is to make sure we don't just recurse into compound values but record the full aliasing information we would for top-level instructions. Still WIP, this needs to handle terminals other than for..of. ghstack-source-id: 09a29230514e3bc95d1833cd4392de238fabbeda Pull Request resolved: https://github.com/facebook/react/pull/33062
This commit is contained in:
+6
@@ -255,6 +255,12 @@ function writeReactiveValue(writer: Writer, value: ReactiveValue): void {
|
||||
}
|
||||
}
|
||||
|
||||
export function printReactiveTerminal(terminal: ReactiveTerminal): string {
|
||||
const writer = new Writer();
|
||||
writeTerminal(writer, terminal);
|
||||
return writer.complete();
|
||||
}
|
||||
|
||||
function writeTerminal(writer: Writer, terminal: ReactiveTerminal): void {
|
||||
switch (terminal.kind) {
|
||||
case 'break': {
|
||||
|
||||
+519
-468
File diff suppressed because it is too large
Load Diff
+67
@@ -0,0 +1,67 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function useHook(nodeID, condition) {
|
||||
const graph = useContext(GraphContext);
|
||||
const node = nodeID != null ? graph[nodeID] : null;
|
||||
|
||||
for (const key of Object.keys(node?.fields ?? {})) {
|
||||
if (condition) {
|
||||
return new Class(node.fields?.[field]);
|
||||
}
|
||||
}
|
||||
return new Class();
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
function useHook(nodeID, condition) {
|
||||
const $ = _c(7);
|
||||
const graph = useContext(GraphContext);
|
||||
const node = nodeID != null ? graph[nodeID] : null;
|
||||
let t0;
|
||||
if ($[0] !== node?.fields) {
|
||||
t0 = Object.keys(node?.fields ?? {});
|
||||
$[0] = node?.fields;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
let t1;
|
||||
if ($[2] !== condition || $[3] !== node || $[4] !== t0) {
|
||||
t1 = Symbol.for("react.early_return_sentinel");
|
||||
bb0: for (const key of t0) {
|
||||
if (condition) {
|
||||
t1 = new Class(node.fields?.[field]);
|
||||
break bb0;
|
||||
}
|
||||
}
|
||||
$[2] = condition;
|
||||
$[3] = node;
|
||||
$[4] = t0;
|
||||
$[5] = t1;
|
||||
} else {
|
||||
t1 = $[5];
|
||||
}
|
||||
if (t1 !== Symbol.for("react.early_return_sentinel")) {
|
||||
return t1;
|
||||
}
|
||||
let t2;
|
||||
if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t2 = new Class();
|
||||
$[6] = t2;
|
||||
} else {
|
||||
t2 = $[6];
|
||||
}
|
||||
return t2;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: exception) Fixture not implemented
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
function useHook(nodeID, condition) {
|
||||
const graph = useContext(GraphContext);
|
||||
const node = nodeID != null ? graph[nodeID] : null;
|
||||
|
||||
for (const key of Object.keys(node?.fields ?? {})) {
|
||||
if (condition) {
|
||||
return new Class(node.fields?.[field]);
|
||||
}
|
||||
}
|
||||
return new Class();
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function useHook(nodeID, condition) {
|
||||
const graph = useContext(GraphContext);
|
||||
const node = nodeID != null ? graph[nodeID] : null;
|
||||
|
||||
// (2) Instead we can create a scope around the loop since the loop produces an escaping value
|
||||
let value;
|
||||
for (const key of Object.keys(node?.fields ?? {})) {
|
||||
if (condition) {
|
||||
// (1) We currently create a scope just for this instruction, then later prune the scope because
|
||||
// it's inside a loop
|
||||
value = new Class(node.fields?.[field]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
function useHook(nodeID, condition) {
|
||||
const $ = _c(6);
|
||||
const graph = useContext(GraphContext);
|
||||
const node = nodeID != null ? graph[nodeID] : null;
|
||||
|
||||
let value;
|
||||
let t0;
|
||||
if ($[0] !== node?.fields) {
|
||||
t0 = Object.keys(node?.fields ?? {});
|
||||
$[0] = node?.fields;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
if ($[2] !== condition || $[3] !== node || $[4] !== t0) {
|
||||
for (const key of t0) {
|
||||
if (condition) {
|
||||
value = new Class(node.fields?.[field]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
$[2] = condition;
|
||||
$[3] = node;
|
||||
$[4] = t0;
|
||||
$[5] = value;
|
||||
} else {
|
||||
value = $[5];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: exception) Fixture not implemented
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
function useHook(nodeID, condition) {
|
||||
const graph = useContext(GraphContext);
|
||||
const node = nodeID != null ? graph[nodeID] : null;
|
||||
|
||||
// (2) Instead we can create a scope around the loop since the loop produces an escaping value
|
||||
let value;
|
||||
for (const key of Object.keys(node?.fields ?? {})) {
|
||||
if (condition) {
|
||||
// (1) We currently create a scope just for this instruction, then later prune the scope because
|
||||
// it's inside a loop
|
||||
value = new Class(node.fields?.[field]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
Reference in New Issue
Block a user