Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
75be876f2a | ||
|
|
7d696dc3b8 |
@@ -114,6 +114,99 @@ const TYPED_GLOBALS: Array<[string, BuiltInType]> = [
|
|||||||
returnValueKind: ValueKind.Mutable,
|
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(
|
const effects = typeConfig.effects.map(
|
||||||
(effect: AliasingEffectConfig): AliasingEffect => {
|
(effect: AliasingEffectConfig): AliasingEffect => {
|
||||||
switch (effect.kind) {
|
switch (effect.kind) {
|
||||||
|
case 'ImmutableCapture':
|
||||||
case 'CreateFrom':
|
case 'CreateFrom':
|
||||||
case 'Capture':
|
case 'Capture':
|
||||||
case 'Alias':
|
case 'Alias':
|
||||||
|
|||||||
@@ -111,6 +111,19 @@ export const AliasEffectSchema: z.ZodType<AliasEffectConfig> = z.object({
|
|||||||
into: LifetimeIdSchema,
|
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 = {
|
export type CaptureEffectConfig = {
|
||||||
kind: 'Capture';
|
kind: 'Capture';
|
||||||
from: string;
|
from: string;
|
||||||
@@ -187,6 +200,7 @@ export type AliasingEffectConfig =
|
|||||||
| AssignEffectConfig
|
| AssignEffectConfig
|
||||||
| AliasEffectConfig
|
| AliasEffectConfig
|
||||||
| CaptureEffectConfig
|
| CaptureEffectConfig
|
||||||
|
| ImmutableCaptureEffectConfig
|
||||||
| ImpureEffectConfig
|
| ImpureEffectConfig
|
||||||
| MutateEffectConfig
|
| MutateEffectConfig
|
||||||
| MutateTransitiveConditionallyConfig
|
| MutateTransitiveConditionallyConfig
|
||||||
@@ -199,6 +213,7 @@ export const AliasingEffectSchema: z.ZodType<AliasingEffectConfig> = z.union([
|
|||||||
AssignEffectSchema,
|
AssignEffectSchema,
|
||||||
AliasEffectSchema,
|
AliasEffectSchema,
|
||||||
CaptureEffectSchema,
|
CaptureEffectSchema,
|
||||||
|
ImmutableCaptureEffectSchema,
|
||||||
ImpureEffectSchema,
|
ImpureEffectSchema,
|
||||||
MutateEffectSchema,
|
MutateEffectSchema,
|
||||||
MutateTransitiveConditionallySchema,
|
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
|
// Don't emit errors on Flow suppressions--Flow already gave a signal
|
||||||
flowSuppressions: false,
|
flowSuppressions: false,
|
||||||
environment: validateEnvironmentConfig({
|
environment: validateEnvironmentConfig({
|
||||||
validateRefAccessDuringRender: false,
|
validateRefAccessDuringRender: true,
|
||||||
validateNoSetStateInRender: true,
|
validateNoSetStateInRender: true,
|
||||||
validateNoSetStateInEffects: true,
|
validateNoSetStateInEffects: true,
|
||||||
validateNoJSXInTryStatements: true,
|
validateNoJSXInTryStatements: true,
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ const COMPILER_OPTIONS: Partial<PluginOptions> = {
|
|||||||
// Don't emit errors on Flow suppressions--Flow already gave a signal
|
// Don't emit errors on Flow suppressions--Flow already gave a signal
|
||||||
flowSuppressions: false,
|
flowSuppressions: false,
|
||||||
environment: validateEnvironmentConfig({
|
environment: validateEnvironmentConfig({
|
||||||
validateRefAccessDuringRender: false,
|
validateRefAccessDuringRender: true,
|
||||||
validateNoSetStateInRender: true,
|
validateNoSetStateInRender: true,
|
||||||
validateNoSetStateInEffects: true,
|
validateNoSetStateInEffects: true,
|
||||||
validateNoJSXInTryStatements: true,
|
validateNoJSXInTryStatements: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user