Skip to content

Commit faff8ac

Browse files
committed
[compiler] Type provider infra for tests
ghstack-source-id: d206061 Pull Request resolved: #30776
1 parent 8ece668 commit faff8ac

File tree

14 files changed

+543
-39
lines changed

14 files changed

+543
-39
lines changed

compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,6 @@ const HookSchema = z.object({
126126

127127
export type Hook = z.infer<typeof HookSchema>;
128128

129-
export const ModuleTypeResolver = z
130-
.function()
131-
.args(z.string())
132-
.returns(z.nullable(TypeSchema));
133-
134129
/*
135130
* TODO(mofeiZ): User defined global types (with corresponding shapes).
136131
* User defined global types should have inline ObjectShapes instead of directly
@@ -148,7 +143,7 @@ const EnvironmentConfigSchema = z.object({
148143
* A function that, given the name of a module, can optionally return a description
149144
* of that module's type signature.
150145
*/
151-
resolveModuleTypeSchema: z.nullable(ModuleTypeResolver).default(null),
146+
moduleTypeProvider: z.nullable(z.function().args(z.string())).default(null),
152147

153148
/**
154149
* A list of functions which the application compiles as macros, where
@@ -713,20 +708,30 @@ export class Environment {
713708
}
714709

715710
#resolveModuleType(moduleName: string): Global | null {
716-
if (this.config.resolveModuleTypeSchema == null) {
711+
if (this.config.moduleTypeProvider == null) {
717712
return null;
718713
}
719714
let moduleType = this.#moduleTypes.get(moduleName);
720715
if (moduleType === undefined) {
721-
const moduleConfig = this.config.resolveModuleTypeSchema(moduleName);
722-
if (moduleConfig != null) {
723-
const moduleTypes = TypeSchema.parse(moduleConfig);
724-
moduleType = installTypeConfig(
725-
this.#globals,
726-
this.#shapes,
727-
moduleTypes,
728-
);
729-
} else {
716+
try {
717+
const unparsedModuleConfig = this.config.moduleTypeProvider(moduleName);
718+
if (unparsedModuleConfig != null) {
719+
const parsedModuleConfig = TypeSchema.safeParse(unparsedModuleConfig);
720+
if (!parsedModuleConfig.success) {
721+
console.error(parsedModuleConfig.error.toString());
722+
process.exit(1);
723+
}
724+
const moduleConfig = parsedModuleConfig.data;
725+
moduleType = installTypeConfig(
726+
this.#globals,
727+
this.#shapes,
728+
moduleConfig,
729+
);
730+
} else {
731+
moduleType = null;
732+
}
733+
} catch (e) {
734+
console.error((e as Error).stack);
730735
moduleType = null;
731736
}
732737
this.#moduleTypes.set(moduleName, moduleType);
@@ -819,9 +824,7 @@ export class Environment {
819824
#isKnownReactModule(moduleName: string): boolean {
820825
return (
821826
moduleName.toLowerCase() === 'react' ||
822-
moduleName.toLowerCase() === 'react-dom' ||
823-
(this.config.enableSharedRuntime__testonly &&
824-
moduleName === 'shared-runtime')
827+
moduleName.toLowerCase() === 'react-dom'
825828
);
826829
}
827830

compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1361,6 +1361,15 @@ export enum ValueKind {
13611361
Context = 'context',
13621362
}
13631363

1364+
export const ValueKindSchema = z.enum([
1365+
ValueKind.MaybeFrozen,
1366+
ValueKind.Frozen,
1367+
ValueKind.Primitive,
1368+
ValueKind.Global,
1369+
ValueKind.Mutable,
1370+
ValueKind.Context,
1371+
]);
1372+
13641373
// The effect with which a value is modified.
13651374
export enum Effect {
13661375
// Default value: not allowed after lifetime inference

compiler/packages/babel-plugin-react-compiler/src/HIR/TypeSchema.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import {isValidIdentifier} from '@babel/types';
99
import {z} from 'zod';
1010
import {Effect, ValueKind} from '..';
11-
import {EffectSchema} from './HIR';
11+
import {EffectSchema, ValueKindSchema} from './HIR';
1212

1313
export type ObjectPropertiesConfig = {[key: string]: TypeConfig};
1414
export const ObjectPropertiesSchema: z.ZodType<ObjectPropertiesConfig> = z
@@ -45,7 +45,7 @@ export const FunctionTypeSchema: z.ZodType<FunctionTypeConfig> = z.object({
4545
restParam: EffectSchema.nullable(),
4646
calleeEffect: EffectSchema,
4747
returnType: z.lazy(() => TypeSchema),
48-
returnValueKind: z.nativeEnum(ValueKind),
48+
returnValueKind: ValueKindSchema,
4949
});
5050

5151
export type BuiltInTypeConfig = 'Ref' | 'Array' | 'Primitive' | 'MixedReadonly';

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hook-noAlias.expect.md

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import { c as _c } from "react/compiler-runtime";
2727
import { useNoAlias } from "shared-runtime";
2828

2929
function Component(props) {
30-
const $ = _c(5);
30+
const $ = _c(9);
3131
let t0;
3232
if ($[0] !== props.a) {
3333
t0 = { a: props.a };
@@ -37,19 +37,35 @@ function Component(props) {
3737
t0 = $[1];
3838
}
3939
const item = t0;
40-
const x = useNoAlias(item, () => {
41-
console.log(props);
42-
}, [props.a]);
4340
let t1;
44-
if ($[2] !== x || $[3] !== item) {
45-
t1 = [x, item];
46-
$[2] = x;
47-
$[3] = item;
48-
$[4] = t1;
41+
if ($[2] !== props) {
42+
t1 = () => {
43+
console.log(props);
44+
};
45+
$[2] = props;
46+
$[3] = t1;
47+
} else {
48+
t1 = $[3];
49+
}
50+
let t2;
51+
if ($[4] !== props.a) {
52+
t2 = [props.a];
53+
$[4] = props.a;
54+
$[5] = t2;
55+
} else {
56+
t2 = $[5];
57+
}
58+
const x = useNoAlias(item, t1, t2);
59+
let t3;
60+
if ($[6] !== x || $[7] !== item) {
61+
t3 = [x, item];
62+
$[6] = x;
63+
$[7] = item;
64+
$[8] = t3;
4965
} else {
50-
t1 = $[4];
66+
t3 = $[8];
5167
}
52-
return t1;
68+
return t3;
5369
}
5470

5571
export const FIXTURE_ENTRYPOINT = {

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/original-reactive-scopes-fork/allocating-logical-expression-instruction-scope.expect.md

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,23 @@ import { c as _c } from "react/compiler-runtime"; // @enableReactiveScopesInHIR:
3636
import { useFragment } from "shared-runtime";
3737

3838
function Foo() {
39-
const $ = _c(2);
39+
const $ = _c(4);
4040
const data = useFragment();
41-
const t0 = data?.toString() || "";
41+
let t0;
42+
if ($[0] !== data) {
43+
t0 = data?.toString() || "";
44+
$[0] = data;
45+
$[1] = t0;
46+
} else {
47+
t0 = $[1];
48+
}
4249
let t1;
43-
if ($[0] !== t0) {
50+
if ($[2] !== t0) {
4451
t1 = [t0];
45-
$[0] = t0;
46-
$[1] = t1;
52+
$[2] = t0;
53+
$[3] = t1;
4754
} else {
48-
t1 = $[1];
55+
t1 = $[3];
4956
}
5057
return t1;
5158
}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
2+
## Input
3+
4+
```javascript
5+
import {useMemo} from 'react';
6+
import {typedLog, ValidateMemoization} from 'shared-runtime';
7+
8+
export function Component({a, b}) {
9+
const item1 = useMemo(() => ({a}), [a]);
10+
const item2 = useMemo(() => ({b}), [b]);
11+
typedLog(item1, item2);
12+
13+
return (
14+
<>
15+
<ValidateMemoization inputs={[a]} output={item1} />
16+
<ValidateMemoization inputs={[b]} output={item2} />
17+
</>
18+
);
19+
}
20+
21+
export const FIXTURE_ENTRYPOINT = {
22+
fn: Component,
23+
params: [{a: 0, b: 0}],
24+
sequentialRenders: [
25+
{a: 0, b: 0},
26+
{a: 1, b: 0},
27+
{a: 1, b: 1},
28+
{a: 1, b: 2},
29+
{a: 2, b: 2},
30+
{a: 3, b: 2},
31+
{a: 0, b: 0},
32+
],
33+
};
34+
35+
```
36+
37+
## Code
38+
39+
```javascript
40+
import { c as _c } from "react/compiler-runtime";
41+
import { useMemo } from "react";
42+
import { typedLog, ValidateMemoization } from "shared-runtime";
43+
44+
export function Component(t0) {
45+
const $ = _c(17);
46+
const { a, b } = t0;
47+
let t1;
48+
let t2;
49+
if ($[0] !== a) {
50+
t2 = { a };
51+
$[0] = a;
52+
$[1] = t2;
53+
} else {
54+
t2 = $[1];
55+
}
56+
t1 = t2;
57+
const item1 = t1;
58+
let t3;
59+
let t4;
60+
if ($[2] !== b) {
61+
t4 = { b };
62+
$[2] = b;
63+
$[3] = t4;
64+
} else {
65+
t4 = $[3];
66+
}
67+
t3 = t4;
68+
const item2 = t3;
69+
typedLog(item1, item2);
70+
let t5;
71+
if ($[4] !== a) {
72+
t5 = [a];
73+
$[4] = a;
74+
$[5] = t5;
75+
} else {
76+
t5 = $[5];
77+
}
78+
let t6;
79+
if ($[6] !== t5 || $[7] !== item1) {
80+
t6 = <ValidateMemoization inputs={t5} output={item1} />;
81+
$[6] = t5;
82+
$[7] = item1;
83+
$[8] = t6;
84+
} else {
85+
t6 = $[8];
86+
}
87+
let t7;
88+
if ($[9] !== b) {
89+
t7 = [b];
90+
$[9] = b;
91+
$[10] = t7;
92+
} else {
93+
t7 = $[10];
94+
}
95+
let t8;
96+
if ($[11] !== t7 || $[12] !== item2) {
97+
t8 = <ValidateMemoization inputs={t7} output={item2} />;
98+
$[11] = t7;
99+
$[12] = item2;
100+
$[13] = t8;
101+
} else {
102+
t8 = $[13];
103+
}
104+
let t9;
105+
if ($[14] !== t6 || $[15] !== t8) {
106+
t9 = (
107+
<>
108+
{t6}
109+
{t8}
110+
</>
111+
);
112+
$[14] = t6;
113+
$[15] = t8;
114+
$[16] = t9;
115+
} else {
116+
t9 = $[16];
117+
}
118+
return t9;
119+
}
120+
121+
export const FIXTURE_ENTRYPOINT = {
122+
fn: Component,
123+
params: [{ a: 0, b: 0 }],
124+
sequentialRenders: [
125+
{ a: 0, b: 0 },
126+
{ a: 1, b: 0 },
127+
{ a: 1, b: 1 },
128+
{ a: 1, b: 2 },
129+
{ a: 2, b: 2 },
130+
{ a: 3, b: 2 },
131+
{ a: 0, b: 0 },
132+
],
133+
};
134+
135+
```
136+
137+
### Eval output
138+
(kind: ok) <div>{"inputs":[0],"output":{"a":0}}</div><div>{"inputs":[0],"output":{"b":0}}</div>
139+
<div>{"inputs":[1],"output":{"a":1}}</div><div>{"inputs":[0],"output":{"b":0}}</div>
140+
<div>{"inputs":[1],"output":{"a":1}}</div><div>{"inputs":[1],"output":{"b":1}}</div>
141+
<div>{"inputs":[1],"output":{"a":1}}</div><div>{"inputs":[2],"output":{"b":2}}</div>
142+
<div>{"inputs":[2],"output":{"a":2}}</div><div>{"inputs":[2],"output":{"b":2}}</div>
143+
<div>{"inputs":[3],"output":{"a":3}}</div><div>{"inputs":[2],"output":{"b":2}}</div>
144+
<div>{"inputs":[0],"output":{"a":0}}</div><div>{"inputs":[0],"output":{"b":0}}</div>
145+
logs: [{ a: 0 },{ b: 0 },{ a: 1 },{ b: 0 },{ a: 1 },{ b: 1 },{ a: 1 },{ b: 2 },{ a: 2 },{ b: 2 },{ a: 3 },{ b: 2 },{ a: 0 },{ b: 0 }]
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import {useMemo} from 'react';
2+
import {typedLog, ValidateMemoization} from 'shared-runtime';
3+
4+
export function Component({a, b}) {
5+
const item1 = useMemo(() => ({a}), [a]);
6+
const item2 = useMemo(() => ({b}), [b]);
7+
typedLog(item1, item2);
8+
9+
return (
10+
<>
11+
<ValidateMemoization inputs={[a]} output={item1} />
12+
<ValidateMemoization inputs={[b]} output={item2} />
13+
</>
14+
);
15+
}
16+
17+
export const FIXTURE_ENTRYPOINT = {
18+
fn: Component,
19+
params: [{a: 0, b: 0}],
20+
sequentialRenders: [
21+
{a: 0, b: 0},
22+
{a: 1, b: 0},
23+
{a: 1, b: 1},
24+
{a: 1, b: 2},
25+
{a: 2, b: 2},
26+
{a: 3, b: 2},
27+
{a: 0, b: 0},
28+
],
29+
};

0 commit comments

Comments
 (0)