mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Capturing a frozen value is a Read
If a value is known to be frozen (or potentially frozen), then it doesn't need to be considered 'captured' since no mutation can occur via aliasing.
This commit is contained in:
@@ -308,7 +308,14 @@ class Environment {
|
||||
break;
|
||||
}
|
||||
case Effect.Capture: {
|
||||
effect = Effect.Capture;
|
||||
if (
|
||||
valueKind === ValueKind.Frozen ||
|
||||
valueKind === ValueKind.MaybeFrozen
|
||||
) {
|
||||
effect = Effect.Read;
|
||||
} else {
|
||||
effect = Effect.Capture;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Effect.Read: {
|
||||
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// note: comments are for the ideal scopes, not what is currently
|
||||
// emitted
|
||||
function foo(props) {
|
||||
// scope 0: deps=[props.a] decl=[x] reassign=none
|
||||
let x = [];
|
||||
x.push(props.a);
|
||||
|
||||
// scope 1: deps=[x] decl=[header] reassign=none
|
||||
const header = props.showHeader ? <div>{x}</div> : null;
|
||||
|
||||
// scope 2:
|
||||
// deps=[x, props.b, props.c]
|
||||
// decl=none
|
||||
// reassign=[x]
|
||||
const y = [x]; // y depends on the earlier x
|
||||
x = []; // x reassigned
|
||||
y.push(props.b); // interleaved mutation of x/y
|
||||
x.push(props.c); // interleaved mutation
|
||||
|
||||
// scope 3 ...
|
||||
const content = (
|
||||
<div>
|
||||
{x}
|
||||
{y}
|
||||
</div>
|
||||
);
|
||||
|
||||
// scope 4 ...
|
||||
return (
|
||||
<>
|
||||
{header}
|
||||
{content}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
// note: comments are for the ideal scopes, not what is currently
|
||||
// emitted
|
||||
function foo(props) {
|
||||
const $ = React.unstable_useMemoCache();
|
||||
const c_0 = $[0] !== props.a;
|
||||
let x;
|
||||
if (c_0) {
|
||||
x = [];
|
||||
x.push(props.a);
|
||||
$[0] = props.a;
|
||||
$[1] = x;
|
||||
} else {
|
||||
x = $[1];
|
||||
}
|
||||
const c_2 = $[2] !== props;
|
||||
const c_3 = $[3] !== x;
|
||||
let t0;
|
||||
if (c_2 || c_3) {
|
||||
t0 = props.showHeader ? <div>{x}</div> : null;
|
||||
$[2] = props;
|
||||
$[3] = x;
|
||||
$[4] = t0;
|
||||
} else {
|
||||
t0 = $[4];
|
||||
}
|
||||
const header = t0;
|
||||
const c_5 = $[5] !== x;
|
||||
const c_6 = $[6] !== props.b;
|
||||
const c_7 = $[7] !== props.c;
|
||||
let x$0;
|
||||
let y;
|
||||
if (c_5 || c_6 || c_7) {
|
||||
y = [x];
|
||||
x$0 = [];
|
||||
y.push(props.b);
|
||||
x$0.push(props.c);
|
||||
$[5] = x;
|
||||
$[6] = props.b;
|
||||
$[7] = props.c;
|
||||
$[8] = x$0;
|
||||
$[9] = y;
|
||||
} else {
|
||||
x$0 = $[8];
|
||||
y = $[9];
|
||||
}
|
||||
const c_10 = $[10] !== x$0;
|
||||
const c_11 = $[11] !== y;
|
||||
let content;
|
||||
if (c_10 || c_11) {
|
||||
content = (
|
||||
<div>
|
||||
{x$0}
|
||||
{y}
|
||||
</div>
|
||||
);
|
||||
$[10] = x$0;
|
||||
$[11] = y;
|
||||
$[12] = content;
|
||||
} else {
|
||||
content = $[12];
|
||||
}
|
||||
const c_13 = $[13] !== header;
|
||||
const c_14 = $[14] !== content;
|
||||
let t1;
|
||||
if (c_13 || c_14) {
|
||||
t1 = (
|
||||
<>
|
||||
{header}
|
||||
{content}
|
||||
</>
|
||||
);
|
||||
$[13] = header;
|
||||
$[14] = content;
|
||||
$[15] = t1;
|
||||
} else {
|
||||
t1 = $[15];
|
||||
}
|
||||
return t1;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
// note: comments are for the ideal scopes, not what is currently
|
||||
// emitted
|
||||
function foo(props) {
|
||||
// scope 0: deps=[props.a] decl=[x] reassign=none
|
||||
let x = [];
|
||||
x.push(props.a);
|
||||
|
||||
// scope 1: deps=[x] decl=[header] reassign=none
|
||||
const header = props.showHeader ? <div>{x}</div> : null;
|
||||
|
||||
// scope 2:
|
||||
// deps=[x, props.b, props.c]
|
||||
// decl=none
|
||||
// reassign=[x]
|
||||
const y = [x]; // y depends on the earlier x
|
||||
x = []; // x reassigned
|
||||
y.push(props.b); // interleaved mutation of x/y
|
||||
x.push(props.c); // interleaved mutation
|
||||
|
||||
// scope 3 ...
|
||||
const content = (
|
||||
<div>
|
||||
{x}
|
||||
{y}
|
||||
</div>
|
||||
);
|
||||
|
||||
// scope 4 ...
|
||||
return (
|
||||
<>
|
||||
{header}
|
||||
{content}
|
||||
</>
|
||||
);
|
||||
}
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// note: comments are for the ideal scopes, not what is currently
|
||||
// emitted
|
||||
function foo(props) {
|
||||
// scope 0: deps=[props.a] decl=[x] reassign=none
|
||||
let x = [];
|
||||
x.push(props.a);
|
||||
|
||||
// scope 1: deps=[x] decl=[header] reassign=none
|
||||
const header = <div>{x}</div>;
|
||||
|
||||
// scope 2:
|
||||
// deps=[x, props.b, props.c]
|
||||
// decl=none
|
||||
// reassign=[x]
|
||||
const y = [x]; // y depends on the earlier x
|
||||
x = []; // x reassigned
|
||||
y.push(props.b); // interleaved mutation of x/y
|
||||
x.push(props.c); // interleaved mutation
|
||||
|
||||
// scope 3 ...
|
||||
const content = (
|
||||
<div>
|
||||
{x}
|
||||
{y}
|
||||
</div>
|
||||
);
|
||||
|
||||
// scope 4 ...
|
||||
return (
|
||||
<>
|
||||
{header}
|
||||
{content}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
// note: comments are for the ideal scopes, not what is currently
|
||||
// emitted
|
||||
function foo(props) {
|
||||
const $ = React.unstable_useMemoCache();
|
||||
const c_0 = $[0] !== props.a;
|
||||
let x;
|
||||
if (c_0) {
|
||||
x = [];
|
||||
x.push(props.a);
|
||||
$[0] = props.a;
|
||||
$[1] = x;
|
||||
} else {
|
||||
x = $[1];
|
||||
}
|
||||
const c_2 = $[2] !== x;
|
||||
let header;
|
||||
if (c_2) {
|
||||
header = <div>{x}</div>;
|
||||
$[2] = x;
|
||||
$[3] = header;
|
||||
} else {
|
||||
header = $[3];
|
||||
}
|
||||
const c_4 = $[4] !== x;
|
||||
const c_5 = $[5] !== props.b;
|
||||
const c_6 = $[6] !== props.c;
|
||||
let x$0;
|
||||
let y;
|
||||
if (c_4 || c_5 || c_6) {
|
||||
y = [x];
|
||||
x$0 = [];
|
||||
y.push(props.b);
|
||||
x$0.push(props.c);
|
||||
$[4] = x;
|
||||
$[5] = props.b;
|
||||
$[6] = props.c;
|
||||
$[7] = x$0;
|
||||
$[8] = y;
|
||||
} else {
|
||||
x$0 = $[7];
|
||||
y = $[8];
|
||||
}
|
||||
const c_9 = $[9] !== x$0;
|
||||
const c_10 = $[10] !== y;
|
||||
let content;
|
||||
if (c_9 || c_10) {
|
||||
content = (
|
||||
<div>
|
||||
{x$0}
|
||||
{y}
|
||||
</div>
|
||||
);
|
||||
$[9] = x$0;
|
||||
$[10] = y;
|
||||
$[11] = content;
|
||||
} else {
|
||||
content = $[11];
|
||||
}
|
||||
const c_12 = $[12] !== header;
|
||||
const c_13 = $[13] !== content;
|
||||
let t0;
|
||||
if (c_12 || c_13) {
|
||||
t0 = (
|
||||
<>
|
||||
{header}
|
||||
{content}
|
||||
</>
|
||||
);
|
||||
$[12] = header;
|
||||
$[13] = content;
|
||||
$[14] = t0;
|
||||
} else {
|
||||
t0 = $[14];
|
||||
}
|
||||
return t0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
// note: comments are for the ideal scopes, not what is currently
|
||||
// emitted
|
||||
function foo(props) {
|
||||
// scope 0: deps=[props.a] decl=[x] reassign=none
|
||||
let x = [];
|
||||
x.push(props.a);
|
||||
|
||||
// scope 1: deps=[x] decl=[header] reassign=none
|
||||
const header = <div>{x}</div>;
|
||||
|
||||
// scope 2:
|
||||
// deps=[x, props.b, props.c]
|
||||
// decl=none
|
||||
// reassign=[x]
|
||||
const y = [x]; // y depends on the earlier x
|
||||
x = []; // x reassigned
|
||||
y.push(props.b); // interleaved mutation of x/y
|
||||
x.push(props.c); // interleaved mutation
|
||||
|
||||
// scope 3 ...
|
||||
const content = (
|
||||
<div>
|
||||
{x}
|
||||
{y}
|
||||
</div>
|
||||
);
|
||||
|
||||
// scope 4 ...
|
||||
return (
|
||||
<>
|
||||
{header}
|
||||
{content}
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user