Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
75be876f2a | ||
|
|
7d696dc3b8 |
@@ -114,6 +114,99 @@ const TYPED_GLOBALS: Array<[string, BuiltInType]> = [
|
||||
returnValueKind: ValueKind.Mutable,
|
||||
}),
|
||||
],
|
||||
[
|
||||
'entries',
|
||||
addFunction(DEFAULT_SHAPES, [], {
|
||||
positionalParams: [Effect.Capture],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Object', shapeId: BuiltInArrayId},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Mutable,
|
||||
aliasing: {
|
||||
receiver: '@receiver',
|
||||
params: ['@object'],
|
||||
rest: null,
|
||||
returns: '@returns',
|
||||
temporaries: [],
|
||||
effects: [
|
||||
{
|
||||
kind: 'Create',
|
||||
into: '@returns',
|
||||
reason: ValueReason.KnownReturnSignature,
|
||||
value: ValueKind.Mutable,
|
||||
},
|
||||
// Object values are captured into the return
|
||||
{
|
||||
kind: 'Capture',
|
||||
from: '@object',
|
||||
into: '@returns',
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
],
|
||||
[
|
||||
'keys',
|
||||
addFunction(DEFAULT_SHAPES, [], {
|
||||
positionalParams: [Effect.Read],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Object', shapeId: BuiltInArrayId},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Mutable,
|
||||
aliasing: {
|
||||
receiver: '@receiver',
|
||||
params: ['@object'],
|
||||
rest: null,
|
||||
returns: '@returns',
|
||||
temporaries: [],
|
||||
effects: [
|
||||
{
|
||||
kind: 'Create',
|
||||
into: '@returns',
|
||||
reason: ValueReason.KnownReturnSignature,
|
||||
value: ValueKind.Mutable,
|
||||
},
|
||||
// Only keys are captured, and keys are immutable
|
||||
{
|
||||
kind: 'ImmutableCapture',
|
||||
from: '@object',
|
||||
into: '@returns',
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
],
|
||||
[
|
||||
'values',
|
||||
addFunction(DEFAULT_SHAPES, [], {
|
||||
positionalParams: [Effect.Capture],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Object', shapeId: BuiltInArrayId},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Mutable,
|
||||
aliasing: {
|
||||
receiver: '@receiver',
|
||||
params: ['@object'],
|
||||
rest: null,
|
||||
returns: '@returns',
|
||||
temporaries: [],
|
||||
effects: [
|
||||
{
|
||||
kind: 'Create',
|
||||
into: '@returns',
|
||||
reason: ValueReason.KnownReturnSignature,
|
||||
value: ValueKind.Mutable,
|
||||
},
|
||||
// Object values are captured into the return
|
||||
{
|
||||
kind: 'Capture',
|
||||
from: '@object',
|
||||
into: '@returns',
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
],
|
||||
]),
|
||||
],
|
||||
[
|
||||
|
||||
@@ -142,6 +142,7 @@ function parseAliasingSignatureConfig(
|
||||
const effects = typeConfig.effects.map(
|
||||
(effect: AliasingEffectConfig): AliasingEffect => {
|
||||
switch (effect.kind) {
|
||||
case 'ImmutableCapture':
|
||||
case 'CreateFrom':
|
||||
case 'Capture':
|
||||
case 'Alias':
|
||||
|
||||
@@ -111,6 +111,19 @@ export const AliasEffectSchema: z.ZodType<AliasEffectConfig> = z.object({
|
||||
into: LifetimeIdSchema,
|
||||
});
|
||||
|
||||
export type ImmutableCaptureEffectConfig = {
|
||||
kind: 'ImmutableCapture';
|
||||
from: string;
|
||||
into: string;
|
||||
};
|
||||
|
||||
export const ImmutableCaptureEffectSchema: z.ZodType<ImmutableCaptureEffectConfig> =
|
||||
z.object({
|
||||
kind: z.literal('ImmutableCapture'),
|
||||
from: LifetimeIdSchema,
|
||||
into: LifetimeIdSchema,
|
||||
});
|
||||
|
||||
export type CaptureEffectConfig = {
|
||||
kind: 'Capture';
|
||||
from: string;
|
||||
@@ -187,6 +200,7 @@ export type AliasingEffectConfig =
|
||||
| AssignEffectConfig
|
||||
| AliasEffectConfig
|
||||
| CaptureEffectConfig
|
||||
| ImmutableCaptureEffectConfig
|
||||
| ImpureEffectConfig
|
||||
| MutateEffectConfig
|
||||
| MutateTransitiveConditionallyConfig
|
||||
@@ -199,6 +213,7 @@ export const AliasingEffectSchema: z.ZodType<AliasingEffectConfig> = z.union([
|
||||
AssignEffectSchema,
|
||||
AliasEffectSchema,
|
||||
CaptureEffectSchema,
|
||||
ImmutableCaptureEffectSchema,
|
||||
ImpureEffectSchema,
|
||||
MutateEffectSchema,
|
||||
MutateTransitiveConditionallySchema,
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @validatePreserveExistingMemoizationGuarantees
|
||||
import {makeObject_Primitives, Stringify} from 'shared-runtime';
|
||||
|
||||
function Component(props) {
|
||||
const object = {object: props.object};
|
||||
const entries = useMemo(() => Object.entries(object), [object]);
|
||||
entries.map(([, value]) => {
|
||||
value.updated = true;
|
||||
});
|
||||
return <Stringify entries={entries} />;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{object: {key: makeObject_Primitives()}}],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
Found 2 errors:
|
||||
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly.
|
||||
|
||||
error.validate-object-entries-mutation.ts:6:57
|
||||
4 | function Component(props) {
|
||||
5 | const object = {object: props.object};
|
||||
> 6 | const entries = useMemo(() => Object.entries(object), [object]);
|
||||
| ^^^^^^ This dependency may be modified later
|
||||
7 | entries.map(([, value]) => {
|
||||
8 | value.updated = true;
|
||||
9 | });
|
||||
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output.
|
||||
|
||||
error.validate-object-entries-mutation.ts:6:18
|
||||
4 | function Component(props) {
|
||||
5 | const object = {object: props.object};
|
||||
> 6 | const entries = useMemo(() => Object.entries(object), [object]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Could not preserve existing memoization
|
||||
7 | entries.map(([, value]) => {
|
||||
8 | value.updated = true;
|
||||
9 | });
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// @validatePreserveExistingMemoizationGuarantees
|
||||
import {makeObject_Primitives, Stringify} from 'shared-runtime';
|
||||
|
||||
function Component(props) {
|
||||
const object = {object: props.object};
|
||||
const entries = useMemo(() => Object.entries(object), [object]);
|
||||
entries.map(([, value]) => {
|
||||
value.updated = true;
|
||||
});
|
||||
return <Stringify entries={entries} />;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{object: {key: makeObject_Primitives()}}],
|
||||
};
|
||||
@@ -0,0 +1,57 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @validatePreserveExistingMemoizationGuarantees
|
||||
import {makeObject_Primitives, Stringify} from 'shared-runtime';
|
||||
|
||||
function Component(props) {
|
||||
const object = {object: props.object};
|
||||
const values = useMemo(() => Object.values(object), [object]);
|
||||
values.map(value => {
|
||||
value.updated = true;
|
||||
});
|
||||
return <Stringify values={values} />;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{object: {key: makeObject_Primitives()}}],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
Found 2 errors:
|
||||
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly.
|
||||
|
||||
error.validate-object-values-mutation.ts:6:55
|
||||
4 | function Component(props) {
|
||||
5 | const object = {object: props.object};
|
||||
> 6 | const values = useMemo(() => Object.values(object), [object]);
|
||||
| ^^^^^^ This dependency may be modified later
|
||||
7 | values.map(value => {
|
||||
8 | value.updated = true;
|
||||
9 | });
|
||||
|
||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
||||
|
||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output.
|
||||
|
||||
error.validate-object-values-mutation.ts:6:17
|
||||
4 | function Component(props) {
|
||||
5 | const object = {object: props.object};
|
||||
> 6 | const values = useMemo(() => Object.values(object), [object]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Could not preserve existing memoization
|
||||
7 | values.map(value => {
|
||||
8 | value.updated = true;
|
||||
9 | });
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// @validatePreserveExistingMemoizationGuarantees
|
||||
import {makeObject_Primitives, Stringify} from 'shared-runtime';
|
||||
|
||||
function Component(props) {
|
||||
const object = {object: props.object};
|
||||
const values = useMemo(() => Object.values(object), [object]);
|
||||
values.map(value => {
|
||||
value.updated = true;
|
||||
});
|
||||
return <Stringify values={values} />;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{object: {key: makeObject_Primitives()}}],
|
||||
};
|
||||
@@ -0,0 +1,57 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
import {makeObject_Primitives, Stringify} from 'shared-runtime';
|
||||
|
||||
function Component(props) {
|
||||
const object = {object: props.object};
|
||||
const entries = Object.entries(object);
|
||||
entries.map(([, value]) => {
|
||||
value.updated = true;
|
||||
});
|
||||
return <Stringify entries={entries} />;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{object: {key: makeObject_Primitives()}}],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import { makeObject_Primitives, Stringify } from "shared-runtime";
|
||||
|
||||
function Component(props) {
|
||||
const $ = _c(2);
|
||||
let t0;
|
||||
if ($[0] !== props.object) {
|
||||
const object = { object: props.object };
|
||||
const entries = Object.entries(object);
|
||||
entries.map(_temp);
|
||||
t0 = <Stringify entries={entries} />;
|
||||
$[0] = props.object;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
return t0;
|
||||
}
|
||||
function _temp(t0) {
|
||||
const [, value] = t0;
|
||||
value.updated = true;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ object: { key: makeObject_Primitives() } }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: ok) <div>{"entries":[["object",{"key":{"a":0,"b":"value1","c":true},"updated":true}]]}</div>
|
||||
@@ -0,0 +1,15 @@
|
||||
import {makeObject_Primitives, Stringify} from 'shared-runtime';
|
||||
|
||||
function Component(props) {
|
||||
const object = {object: props.object};
|
||||
const entries = Object.entries(object);
|
||||
entries.map(([, value]) => {
|
||||
value.updated = true;
|
||||
});
|
||||
return <Stringify entries={entries} />;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{object: {key: makeObject_Primitives()}}],
|
||||
};
|
||||
@@ -0,0 +1,108 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @validatePreserveExistingMemoizationGuarantees
|
||||
import {useMemo} from 'react';
|
||||
import {Stringify} from 'shared-runtime';
|
||||
|
||||
// derived from https://github.com/facebook/react/issues/32261
|
||||
function Component({items}) {
|
||||
const record = useMemo(
|
||||
() =>
|
||||
Object.fromEntries(
|
||||
items.map(item => [item.id, ref => <Stringify ref={ref} {...item} />])
|
||||
),
|
||||
[items]
|
||||
);
|
||||
|
||||
// Without a declaration for Object.entries(), this would be assumed to mutate
|
||||
// `record`, meaning existing memoization couldn't be preserved
|
||||
return (
|
||||
<div>
|
||||
{Object.keys(record).map(id => (
|
||||
<Stringify key={id} render={record[id]} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [
|
||||
{
|
||||
items: [
|
||||
{id: '0', name: 'Hello'},
|
||||
{id: '1', name: 'World!'},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime"; // @validatePreserveExistingMemoizationGuarantees
|
||||
import { useMemo } from "react";
|
||||
import { Stringify } from "shared-runtime";
|
||||
|
||||
// derived from https://github.com/facebook/react/issues/32261
|
||||
function Component(t0) {
|
||||
const $ = _c(7);
|
||||
const { items } = t0;
|
||||
let t1;
|
||||
if ($[0] !== items) {
|
||||
t1 = Object.fromEntries(items.map(_temp));
|
||||
$[0] = items;
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[1];
|
||||
}
|
||||
const record = t1;
|
||||
let t2;
|
||||
if ($[2] !== record) {
|
||||
t2 = Object.keys(record);
|
||||
$[2] = record;
|
||||
$[3] = t2;
|
||||
} else {
|
||||
t2 = $[3];
|
||||
}
|
||||
let t3;
|
||||
if ($[4] !== record || $[5] !== t2) {
|
||||
t3 = (
|
||||
<div>
|
||||
{t2.map((id) => (
|
||||
<Stringify key={id} render={record[id]} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
$[4] = record;
|
||||
$[5] = t2;
|
||||
$[6] = t3;
|
||||
} else {
|
||||
t3 = $[6];
|
||||
}
|
||||
return t3;
|
||||
}
|
||||
function _temp(item) {
|
||||
return [item.id, (ref) => <Stringify ref={ref} {...item} />];
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [
|
||||
{
|
||||
items: [
|
||||
{ id: "0", name: "Hello" },
|
||||
{ id: "1", name: "World!" },
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: ok) <div><div>{"render":"[[ function params=1 ]]"}</div><div>{"render":"[[ function params=1 ]]"}</div></div>
|
||||
@@ -0,0 +1,36 @@
|
||||
// @validatePreserveExistingMemoizationGuarantees
|
||||
import {useMemo} from 'react';
|
||||
import {Stringify} from 'shared-runtime';
|
||||
|
||||
// derived from https://github.com/facebook/react/issues/32261
|
||||
function Component({items}) {
|
||||
const record = useMemo(
|
||||
() =>
|
||||
Object.fromEntries(
|
||||
items.map(item => [item.id, ref => <Stringify ref={ref} {...item} />])
|
||||
),
|
||||
[items]
|
||||
);
|
||||
|
||||
// Without a declaration for Object.entries(), this would be assumed to mutate
|
||||
// `record`, meaning existing memoization couldn't be preserved
|
||||
return (
|
||||
<div>
|
||||
{Object.keys(record).map(id => (
|
||||
<Stringify key={id} render={record[id]} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [
|
||||
{
|
||||
items: [
|
||||
{id: '0', name: 'Hello'},
|
||||
{id: '1', name: 'World!'},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,57 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
import {makeObject_Primitives, Stringify} from 'shared-runtime';
|
||||
|
||||
function Component(props) {
|
||||
const object = {object: props.object};
|
||||
const entries = Object.entries(object);
|
||||
entries.map(([, value]) => {
|
||||
value.updated = true;
|
||||
});
|
||||
return <Stringify entries={entries} />;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{object: {key: makeObject_Primitives()}}],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import { makeObject_Primitives, Stringify } from "shared-runtime";
|
||||
|
||||
function Component(props) {
|
||||
const $ = _c(2);
|
||||
let t0;
|
||||
if ($[0] !== props.object) {
|
||||
const object = { object: props.object };
|
||||
const entries = Object.entries(object);
|
||||
entries.map(_temp);
|
||||
t0 = <Stringify entries={entries} />;
|
||||
$[0] = props.object;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
return t0;
|
||||
}
|
||||
function _temp(t0) {
|
||||
const [, value] = t0;
|
||||
value.updated = true;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ object: { key: makeObject_Primitives() } }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: ok) <div>{"entries":[["object",{"key":{"a":0,"b":"value1","c":true},"updated":true}]]}</div>
|
||||
@@ -0,0 +1,15 @@
|
||||
import {makeObject_Primitives, Stringify} from 'shared-runtime';
|
||||
|
||||
function Component(props) {
|
||||
const object = {object: props.object};
|
||||
const entries = Object.entries(object);
|
||||
entries.map(([, value]) => {
|
||||
value.updated = true;
|
||||
});
|
||||
return <Stringify entries={entries} />;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{object: {key: makeObject_Primitives()}}],
|
||||
};
|
||||
@@ -0,0 +1,103 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @validatePreserveExistingMemoizationGuarantees
|
||||
import {useMemo} from 'react';
|
||||
import {Stringify} from 'shared-runtime';
|
||||
|
||||
// derived from https://github.com/facebook/react/issues/32261
|
||||
function Component({items}) {
|
||||
const record = useMemo(
|
||||
() =>
|
||||
Object.fromEntries(
|
||||
items.map(item => [
|
||||
item.id,
|
||||
{id: item.id, render: ref => <Stringify ref={ref} {...item} />},
|
||||
])
|
||||
),
|
||||
[items]
|
||||
);
|
||||
|
||||
// Without a declaration for Object.entries(), this would be assumed to mutate
|
||||
// `record`, meaning existing memoization couldn't be preserved
|
||||
return (
|
||||
<div>
|
||||
{Object.values(record).map(({id, render}) => (
|
||||
<Stringify key={id} render={render} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [
|
||||
{
|
||||
items: [
|
||||
{id: '0', name: 'Hello'},
|
||||
{id: '1', name: 'World!'},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime"; // @validatePreserveExistingMemoizationGuarantees
|
||||
import { useMemo } from "react";
|
||||
import { Stringify } from "shared-runtime";
|
||||
|
||||
// derived from https://github.com/facebook/react/issues/32261
|
||||
function Component(t0) {
|
||||
const $ = _c(4);
|
||||
const { items } = t0;
|
||||
let t1;
|
||||
if ($[0] !== items) {
|
||||
t1 = Object.fromEntries(items.map(_temp));
|
||||
$[0] = items;
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[1];
|
||||
}
|
||||
const record = t1;
|
||||
let t2;
|
||||
if ($[2] !== record) {
|
||||
t2 = <div>{Object.values(record).map(_temp2)}</div>;
|
||||
$[2] = record;
|
||||
$[3] = t2;
|
||||
} else {
|
||||
t2 = $[3];
|
||||
}
|
||||
return t2;
|
||||
}
|
||||
function _temp2(t0) {
|
||||
const { id, render } = t0;
|
||||
return <Stringify key={id} render={render} />;
|
||||
}
|
||||
function _temp(item) {
|
||||
return [
|
||||
item.id,
|
||||
{ id: item.id, render: (ref) => <Stringify ref={ref} {...item} /> },
|
||||
];
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [
|
||||
{
|
||||
items: [
|
||||
{ id: "0", name: "Hello" },
|
||||
{ id: "1", name: "World!" },
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: ok) <div><div>{"render":"[[ function params=1 ]]"}</div><div>{"render":"[[ function params=1 ]]"}</div></div>
|
||||
@@ -0,0 +1,39 @@
|
||||
// @validatePreserveExistingMemoizationGuarantees
|
||||
import {useMemo} from 'react';
|
||||
import {Stringify} from 'shared-runtime';
|
||||
|
||||
// derived from https://github.com/facebook/react/issues/32261
|
||||
function Component({items}) {
|
||||
const record = useMemo(
|
||||
() =>
|
||||
Object.fromEntries(
|
||||
items.map(item => [
|
||||
item.id,
|
||||
{id: item.id, render: ref => <Stringify ref={ref} {...item} />},
|
||||
])
|
||||
),
|
||||
[items]
|
||||
);
|
||||
|
||||
// Without a declaration for Object.entries(), this would be assumed to mutate
|
||||
// `record`, meaning existing memoization couldn't be preserved
|
||||
return (
|
||||
<div>
|
||||
{Object.values(record).map(({id, render}) => (
|
||||
<Stringify key={id} render={render} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [
|
||||
{
|
||||
items: [
|
||||
{id: '0', name: 'Hello'},
|
||||
{id: '1', name: 'World!'},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,97 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @validatePreserveExistingMemoizationGuarantees
|
||||
import {useMemo} from 'react';
|
||||
import {Stringify} from 'shared-runtime';
|
||||
|
||||
// derived from https://github.com/facebook/react/issues/32261
|
||||
function Component({items}) {
|
||||
const record = useMemo(
|
||||
() =>
|
||||
Object.fromEntries(
|
||||
items.map(item => [item.id, ref => <Stringify ref={ref} {...item} />])
|
||||
),
|
||||
[items]
|
||||
);
|
||||
|
||||
// Without a declaration for Object.entries(), this would be assumed to mutate
|
||||
// `record`, meaning existing memoization couldn't be preserved
|
||||
return (
|
||||
<div>
|
||||
{Object.entries(record).map(([id, render]) => (
|
||||
<Stringify key={id} render={render} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [
|
||||
{
|
||||
items: [
|
||||
{id: '0', name: 'Hello'},
|
||||
{id: '1', name: 'World!'},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime"; // @validatePreserveExistingMemoizationGuarantees
|
||||
import { useMemo } from "react";
|
||||
import { Stringify } from "shared-runtime";
|
||||
|
||||
// derived from https://github.com/facebook/react/issues/32261
|
||||
function Component(t0) {
|
||||
const $ = _c(4);
|
||||
const { items } = t0;
|
||||
let t1;
|
||||
if ($[0] !== items) {
|
||||
t1 = Object.fromEntries(items.map(_temp));
|
||||
$[0] = items;
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[1];
|
||||
}
|
||||
const record = t1;
|
||||
let t2;
|
||||
if ($[2] !== record) {
|
||||
t2 = <div>{Object.entries(record).map(_temp2)}</div>;
|
||||
$[2] = record;
|
||||
$[3] = t2;
|
||||
} else {
|
||||
t2 = $[3];
|
||||
}
|
||||
return t2;
|
||||
}
|
||||
function _temp2(t0) {
|
||||
const [id, render] = t0;
|
||||
return <Stringify key={id} render={render} />;
|
||||
}
|
||||
function _temp(item) {
|
||||
return [item.id, (ref) => <Stringify ref={ref} {...item} />];
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [
|
||||
{
|
||||
items: [
|
||||
{ id: "0", name: "Hello" },
|
||||
{ id: "1", name: "World!" },
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: ok) <div><div>{"render":"[[ function params=1 ]]"}</div><div>{"render":"[[ function params=1 ]]"}</div></div>
|
||||
@@ -0,0 +1,36 @@
|
||||
// @validatePreserveExistingMemoizationGuarantees
|
||||
import {useMemo} from 'react';
|
||||
import {Stringify} from 'shared-runtime';
|
||||
|
||||
// derived from https://github.com/facebook/react/issues/32261
|
||||
function Component({items}) {
|
||||
const record = useMemo(
|
||||
() =>
|
||||
Object.fromEntries(
|
||||
items.map(item => [item.id, ref => <Stringify ref={ref} {...item} />])
|
||||
),
|
||||
[items]
|
||||
);
|
||||
|
||||
// Without a declaration for Object.entries(), this would be assumed to mutate
|
||||
// `record`, meaning existing memoization couldn't be preserved
|
||||
return (
|
||||
<div>
|
||||
{Object.entries(record).map(([id, render]) => (
|
||||
<Stringify key={id} render={render} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [
|
||||
{
|
||||
items: [
|
||||
{id: '0', name: 'Hello'},
|
||||
{id: '1', name: 'World!'},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -101,7 +101,7 @@ const COMPILER_OPTIONS: Partial<PluginOptions> = {
|
||||
// Don't emit errors on Flow suppressions--Flow already gave a signal
|
||||
flowSuppressions: false,
|
||||
environment: validateEnvironmentConfig({
|
||||
validateRefAccessDuringRender: false,
|
||||
validateRefAccessDuringRender: true,
|
||||
validateNoSetStateInRender: true,
|
||||
validateNoSetStateInEffects: true,
|
||||
validateNoJSXInTryStatements: true,
|
||||
|
||||
@@ -103,7 +103,7 @@ const COMPILER_OPTIONS: Partial<PluginOptions> = {
|
||||
// Don't emit errors on Flow suppressions--Flow already gave a signal
|
||||
flowSuppressions: false,
|
||||
environment: validateEnvironmentConfig({
|
||||
validateRefAccessDuringRender: false,
|
||||
validateRefAccessDuringRender: true,
|
||||
validateNoSetStateInRender: true,
|
||||
validateNoSetStateInEffects: true,
|
||||
validateNoJSXInTryStatements: true,
|
||||
|
||||
Reference in New Issue
Block a user