Skip to content

Commit e88b05e

Browse files
committed
[compiler][ez] Clean up pragma parsing for tests + playground
Move environment config parsing for `inlineJsxTransform`, `lowerContextAccess`, and some dev-only options out of snap (test fixture). These should now be available for playground via `@inlineJsxTransform` and `lowerContextAccess`. Other small change: Changed zod fields from `nullish()` -> `nullable().default(null)`. [`nullish`](https://zod.dev/?id=nullish) fields accept `null | undefined` and default to `undefined`. We don't distinguish between null and undefined for any of these options, so let's only accept null + default to null. This also makes EnvironmentConfig in the playground more accurate. Previously, some fields just didn't show up as `prettyFormat({field: undefined})` does not print `field`.
1 parent 33c7bd9 commit e88b05e

10 files changed

+88
-101
lines changed

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

Lines changed: 63 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ export const ExternalFunctionSchema = z.object({
6969
export const InstrumentationSchema = z
7070
.object({
7171
fn: ExternalFunctionSchema,
72-
gating: ExternalFunctionSchema.nullish(),
73-
globalGating: z.string().nullish(),
72+
gating: ExternalFunctionSchema.nullable(),
73+
globalGating: z.string().nullable(),
7474
})
7575
.refine(
7676
opts => opts.gating != null || opts.globalGating != null,
@@ -147,7 +147,7 @@ export type Hook = z.infer<typeof HookSchema>;
147147
*/
148148

149149
const EnvironmentConfigSchema = z.object({
150-
customHooks: z.map(z.string(), HookSchema).optional().default(new Map()),
150+
customHooks: z.map(z.string(), HookSchema).default(new Map()),
151151

152152
/**
153153
* A function that, given the name of a module, can optionally return a description
@@ -248,7 +248,7 @@ const EnvironmentConfigSchema = z.object({
248248
*
249249
* The symbol configuration is set for backwards compatability with pre-React 19 transforms
250250
*/
251-
inlineJsxTransform: ReactElementSymbolSchema.nullish(),
251+
inlineJsxTransform: ReactElementSymbolSchema.nullable().default(null),
252252

253253
/*
254254
* Enable validation of hooks to partially check that the component honors the rules of hooks.
@@ -339,9 +339,9 @@ const EnvironmentConfigSchema = z.object({
339339
* }
340340
* }
341341
*/
342-
enableEmitFreeze: ExternalFunctionSchema.nullish(),
342+
enableEmitFreeze: ExternalFunctionSchema.nullable().default(null),
343343

344-
enableEmitHookGuards: ExternalFunctionSchema.nullish(),
344+
enableEmitHookGuards: ExternalFunctionSchema.nullable().default(null),
345345

346346
/**
347347
* Enable instruction reordering. See InstructionReordering.ts for the details
@@ -425,7 +425,7 @@ const EnvironmentConfigSchema = z.object({
425425
* }
426426
*
427427
*/
428-
enableEmitInstrumentForget: InstrumentationSchema.nullish(),
428+
enableEmitInstrumentForget: InstrumentationSchema.nullable().default(null),
429429

430430
// Enable validation of mutable ranges
431431
assertValidMutableRanges: z.boolean().default(false),
@@ -464,8 +464,6 @@ const EnvironmentConfigSchema = z.object({
464464
*/
465465
throwUnknownException__testonly: z.boolean().default(false),
466466

467-
enableSharedRuntime__testonly: z.boolean().default(false),
468-
469467
/**
470468
* Enables deps of a function epxression to be treated as conditional. This
471469
* makes sure we don't load a dep when it's a property (to check if it has
@@ -503,7 +501,8 @@ const EnvironmentConfigSchema = z.object({
503501
* computed one. This detects cases where rules of react violations may cause the
504502
* compiled code to behave differently than the original.
505503
*/
506-
enableChangeDetectionForDebugging: ExternalFunctionSchema.nullish(),
504+
enableChangeDetectionForDebugging:
505+
ExternalFunctionSchema.nullable().default(null),
507506

508507
/**
509508
* The react native re-animated library uses custom Babel transforms that
@@ -543,7 +542,7 @@ const EnvironmentConfigSchema = z.object({
543542
*
544543
* Here the variables `ref` and `myRef` will be typed as Refs.
545544
*/
546-
enableTreatRefLikeIdentifiersAsRefs: z.boolean().nullable().default(false),
545+
enableTreatRefLikeIdentifiersAsRefs: z.boolean().default(false),
547546

548547
/*
549548
* If specified a value, the compiler lowers any calls to `useContext` to use
@@ -565,11 +564,56 @@ const EnvironmentConfigSchema = z.object({
565564
* const {foo, bar} = useCompiledContext(MyContext, (c) => [c.foo, c.bar]);
566565
* ```
567566
*/
568-
lowerContextAccess: ExternalFunctionSchema.nullish(),
567+
lowerContextAccess: ExternalFunctionSchema.nullable().default(null),
569568
});
570569

571570
export type EnvironmentConfig = z.infer<typeof EnvironmentConfigSchema>;
572571

572+
/**
573+
* For test fixtures and playground only.
574+
*
575+
* Pragmas are straightforward to parse for boolean options (`:true` and
576+
* `:false`). These are 'enabled' config values for non-boolean configs (i.e.
577+
* what is used when parsing `:true`).
578+
*/
579+
const testConfigValues: PartialEnvironmentConfig = {
580+
validateNoCapitalizedCalls: [],
581+
enableChangeDetectionForDebugging: {
582+
source: 'react-compiler-runtime',
583+
importSpecifierName: '$structuralCheck',
584+
},
585+
enableEmitFreeze: {
586+
source: 'react-compiler-runtime',
587+
importSpecifierName: 'makeReadOnly',
588+
},
589+
enableEmitInstrumentForget: {
590+
fn: {
591+
source: 'react-compiler-runtime',
592+
importSpecifierName: 'useRenderCounter',
593+
},
594+
gating: {
595+
source: 'react-compiler-runtime',
596+
importSpecifierName: 'shouldInstrument',
597+
},
598+
globalGating: '__DEV__',
599+
},
600+
enableEmitHookGuards: {
601+
source: 'react-compiler-runtime',
602+
importSpecifierName: '$dispatcherGuard',
603+
},
604+
inlineJsxTransform: {
605+
elementSymbol: 'react.transitional.element',
606+
globalDevVar: 'DEV',
607+
},
608+
lowerContextAccess: {
609+
source: 'react-compiler-runtime',
610+
importSpecifierName: 'useContext_withSelector',
611+
},
612+
};
613+
614+
/**
615+
* For snap test fixtures and playground only.
616+
*/
573617
export function parseConfigPragma(pragma: string): EnvironmentConfig {
574618
const maybeConfig: any = {};
575619
// Get the defaults to programmatically check for boolean properties
@@ -580,21 +624,12 @@ export function parseConfigPragma(pragma: string): EnvironmentConfig {
580624
continue;
581625
}
582626
const keyVal = token.slice(1);
583-
let [key, val]: any = keyVal.split(':');
584-
585-
if (key === 'validateNoCapitalizedCalls') {
586-
maybeConfig[key] = [];
587-
continue;
588-
}
627+
let [key, val = undefined] = keyVal.split(':');
628+
const isSet = val === undefined || val === 'true';
589629

590-
if (
591-
key === 'enableChangeDetectionForDebugging' &&
592-
(val === undefined || val === 'true')
593-
) {
594-
maybeConfig[key] = {
595-
source: 'react-compiler-runtime',
596-
importSpecifierName: '$structuralCheck',
597-
};
630+
if (isSet && key in testConfigValues) {
631+
maybeConfig[key] =
632+
testConfigValues[key as keyof PartialEnvironmentConfig];
598633
continue;
599634
}
600635

@@ -609,7 +644,6 @@ export function parseConfigPragma(pragma: string): EnvironmentConfig {
609644
props.push({type: 'name', name: elt});
610645
}
611646
}
612-
console.log([valSplit[0], props.map(x => x.name ?? '*').join('.')]);
613647
maybeConfig[key] = [[valSplit[0], props]];
614648
}
615649
continue;
@@ -620,11 +654,10 @@ export function parseConfigPragma(pragma: string): EnvironmentConfig {
620654
continue;
621655
}
622656
if (val === undefined || val === 'true') {
623-
val = true;
657+
maybeConfig[key] = true;
624658
} else {
625-
val = false;
659+
maybeConfig[key] = false;
626660
}
627-
maybeConfig[key] = val;
628661
}
629662

630663
const config = EnvironmentConfigSchema.safeParse(maybeConfig);

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/codegen-emit-imports-same-source.expect.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
## Input
33

44
```javascript
5-
// @enableEmitFreeze @instrumentForget
5+
// @enableEmitFreeze @enableEmitInstrumentForget
66

77
function useFoo(props) {
88
return foo(props.x);
@@ -18,7 +18,7 @@ import {
1818
shouldInstrument,
1919
makeReadOnly,
2020
} from "react-compiler-runtime";
21-
import { c as _c } from "react/compiler-runtime"; // @enableEmitFreeze @instrumentForget
21+
import { c as _c } from "react/compiler-runtime"; // @enableEmitFreeze @enableEmitInstrumentForget
2222

2323
function useFoo(props) {
2424
if (__DEV__ && shouldInstrument)

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/codegen-emit-imports-same-source.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// @enableEmitFreeze @instrumentForget
1+
// @enableEmitFreeze @enableEmitInstrumentForget
22

33
function useFoo(props) {
44
return foo(props.x);

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/codegen-instrument-forget-gating-test.expect.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
## Input
33

44
```javascript
5-
// @instrumentForget @compilationMode(annotation) @gating
5+
// @enableEmitInstrumentForget @compilationMode(annotation) @gating
66

77
function Bar(props) {
88
'use forget';
@@ -25,7 +25,7 @@ function Foo(props) {
2525
```javascript
2626
import { isForgetEnabled_Fixtures } from "ReactForgetFeatureFlag";
2727
import { useRenderCounter, shouldInstrument } from "react-compiler-runtime";
28-
import { c as _c } from "react/compiler-runtime"; // @instrumentForget @compilationMode(annotation) @gating
28+
import { c as _c } from "react/compiler-runtime"; // @enableEmitInstrumentForget @compilationMode(annotation) @gating
2929
const Bar = isForgetEnabled_Fixtures()
3030
? function Bar(props) {
3131
"use forget";

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/codegen-instrument-forget-gating-test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// @instrumentForget @compilationMode(annotation) @gating
1+
// @enableEmitInstrumentForget @compilationMode(annotation) @gating
22

33
function Bar(props) {
44
'use forget';

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/codegen-instrument-forget-test.expect.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
## Input
33

44
```javascript
5-
// @instrumentForget @compilationMode(annotation)
5+
// @enableEmitInstrumentForget @compilationMode(annotation)
66

77
function Bar(props) {
88
'use forget';
@@ -24,7 +24,7 @@ function Foo(props) {
2424

2525
```javascript
2626
import { useRenderCounter, shouldInstrument } from "react-compiler-runtime";
27-
import { c as _c } from "react/compiler-runtime"; // @instrumentForget @compilationMode(annotation)
27+
import { c as _c } from "react/compiler-runtime"; // @enableEmitInstrumentForget @compilationMode(annotation)
2828

2929
function Bar(props) {
3030
"use forget";

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/codegen-instrument-forget-test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// @instrumentForget @compilationMode(annotation)
1+
// @enableEmitInstrumentForget @compilationMode(annotation)
22

33
function Bar(props) {
44
'use forget';

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inline-jsx-transform.expect.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
## Input
33

44
```javascript
5-
// @enableInlineJsxTransform
5+
// @inlineJsxTransform
66

77
function Parent({children, a: _a, b: _b, c: _c, ref}) {
88
return <div ref={ref}>{children}</div>;
@@ -76,7 +76,7 @@ export const FIXTURE_ENTRYPOINT = {
7676
## Code
7777

7878
```javascript
79-
import { c as _c2 } from "react/compiler-runtime"; // @enableInlineJsxTransform
79+
import { c as _c2 } from "react/compiler-runtime"; // @inlineJsxTransform
8080

8181
function Parent(t0) {
8282
const $ = _c2(2);

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/inline-jsx-transform.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// @enableInlineJsxTransform
1+
// @inlineJsxTransform
22

33
function Parent({children, a: _a, b: _b, c: _c, ref}) {
44
return <div ref={ref}>{children}</div>;

0 commit comments

Comments
 (0)