Skip to content

Commit 38ef655

Browse files
authored
[compiler][playground][tests] Standardize more pragmas (facebook#33146)
(Almost) all pragmas are now one of the following: - `@...TestOnly`: custom pragma for test fixtures - `@<configName>` | `@<configName>:true`: enables with either true or a default enabled value - `@<configName>:<json value>`
1 parent b629a86 commit 38ef655

File tree

182 files changed

+350
-454
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

182 files changed

+350
-454
lines changed

compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/compilationMode-all-output.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { c as _c } from "react/compiler-runtime"; // 
2-
        @compilationMode(all)
2+
        @compilationMode:"all"
33
function nonReactFn() {
44
  const $ = _c(1);
55
  let t0;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// @compilationMode(infer)
1+
// @compilationMode:"infer"
22
function nonReactFn() {
33
  return {};
44
}

compiler/apps/playground/__tests__/e2e/page.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ function useFoo(propVal: {+baz: number}) {
9292
},
9393
{
9494
name: 'compilationMode-infer',
95-
input: `// @compilationMode(infer)
95+
input: `// @compilationMode:"infer"
9696
function nonReactFn() {
9797
return {};
9898
}
@@ -101,7 +101,7 @@ function nonReactFn() {
101101
},
102102
{
103103
name: 'compilationMode-all',
104-
input: `// @compilationMode(all)
104+
input: `// @compilationMode:"all"
105105
function nonReactFn() {
106106
return {};
107107
}

compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Options.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,15 +98,15 @@ export type PluginOptions = {
9898
* provided rules will skip compilation. To disable this feature (never bailout of compilation
9999
* even if the default ESLint is suppressed), pass an empty array.
100100
*/
101-
eslintSuppressionRules?: Array<string> | null | undefined;
101+
eslintSuppressionRules: Array<string> | null | undefined;
102102

103103
flowSuppressions: boolean;
104104
/*
105105
* Ignore 'use no forget' annotations. Helpful during testing but should not be used in production.
106106
*/
107107
ignoreUseNoForget: boolean;
108108

109-
sources?: Array<string> | ((filename: string) => boolean) | null;
109+
sources: Array<string> | ((filename: string) => boolean) | null;
110110

111111
/**
112112
* The compiler has customized support for react-native-reanimated, intended as a temporary workaround.

compiler/packages/babel-plugin-react-compiler/src/Utils/TestUtils.ts

Lines changed: 71 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {CompilerError} from '../CompilerError';
1010
import {
1111
CompilationMode,
1212
defaultOptions,
13-
PanicThresholdOptions,
1413
parsePluginOptions,
1514
PluginOptions,
1615
} from '../Entrypoint';
@@ -19,14 +18,24 @@ import {
1918
EnvironmentConfigSchema,
2019
PartialEnvironmentConfig,
2120
} from '../HIR/Environment';
21+
import {Err, Ok, Result} from './Result';
22+
import {hasOwnProperty} from './utils';
23+
24+
function tryParseTestPragmaValue(val: string): Result<unknown, unknown> {
25+
try {
26+
let parsedVal: unknown;
27+
const stringMatch = /^"([^"]*)"$/.exec(val);
28+
if (stringMatch && stringMatch.length > 1) {
29+
parsedVal = stringMatch[1];
30+
} else {
31+
parsedVal = JSON.parse(val);
32+
}
33+
return Ok(parsedVal);
34+
} catch (e) {
35+
return Err(e);
36+
}
37+
}
2238

23-
/**
24-
* For test fixtures and playground only.
25-
*
26-
* Pragmas are straightforward to parse for boolean options (`:true` and
27-
* `:false`). These are 'enabled' config values for non-boolean configs (i.e.
28-
* what is used when parsing `:true`).
29-
*/
3039
const testComplexConfigDefaults: PartialEnvironmentConfig = {
3140
validateNoCapitalizedCalls: [],
3241
enableChangeDetectionForDebugging: {
@@ -84,34 +93,37 @@ const testComplexConfigDefaults: PartialEnvironmentConfig = {
8493
},
8594
],
8695
};
87-
8896
/**
8997
* For snap test fixtures and playground only.
9098
*/
9199
function parseConfigPragmaEnvironmentForTest(
92100
pragma: string,
93101
): EnvironmentConfig {
94-
const maybeConfig: any = {};
95-
// Get the defaults to programmatically check for boolean properties
96-
const defaultConfig = EnvironmentConfigSchema.parse({});
102+
const maybeConfig: Partial<Record<keyof EnvironmentConfig, unknown>> = {};
97103

98104
for (const token of pragma.split(' ')) {
99105
if (!token.startsWith('@')) {
100106
continue;
101107
}
102108
const keyVal = token.slice(1);
103-
let [key, val = undefined] = keyVal.split(':');
109+
const valIdx = keyVal.indexOf(':');
110+
const key = valIdx === -1 ? keyVal : keyVal.slice(0, valIdx);
111+
const val = valIdx === -1 ? undefined : keyVal.slice(valIdx + 1);
104112
const isSet = val === undefined || val === 'true';
105-
106-
if (isSet && key in testComplexConfigDefaults) {
107-
maybeConfig[key] =
108-
testComplexConfigDefaults[key as keyof PartialEnvironmentConfig];
113+
if (!hasOwnProperty(EnvironmentConfigSchema.shape, key)) {
109114
continue;
110115
}
111116

112-
if (key === 'customMacros' && val) {
113-
const valSplit = val.split('.');
114-
if (valSplit.length > 0) {
117+
if (isSet && key in testComplexConfigDefaults) {
118+
maybeConfig[key] = testComplexConfigDefaults[key];
119+
} else if (isSet) {
120+
maybeConfig[key] = true;
121+
} else if (val === 'false') {
122+
maybeConfig[key] = false;
123+
} else if (val) {
124+
const parsedVal = tryParseTestPragmaValue(val).unwrap();
125+
if (key === 'customMacros' && typeof parsedVal === 'string') {
126+
const valSplit = parsedVal.split('.');
115127
const props = [];
116128
for (const elt of valSplit.slice(1)) {
117129
if (elt === '*') {
@@ -121,21 +133,9 @@ function parseConfigPragmaEnvironmentForTest(
121133
}
122134
}
123135
maybeConfig[key] = [[valSplit[0], props]];
136+
continue;
124137
}
125-
continue;
126-
}
127-
128-
if (
129-
key !== 'enableResetCacheOnSourceFileChanges' &&
130-
typeof defaultConfig[key as keyof EnvironmentConfig] !== 'boolean'
131-
) {
132-
// skip parsing non-boolean properties
133-
continue;
134-
}
135-
if (val === undefined || val === 'true') {
136-
maybeConfig[key] = true;
137-
} else {
138-
maybeConfig[key] = false;
138+
maybeConfig[key] = parsedVal;
139139
}
140140
}
141141
const config = EnvironmentConfigSchema.safeParse(maybeConfig);
@@ -156,51 +156,55 @@ function parseConfigPragmaEnvironmentForTest(
156156
suggestions: null,
157157
});
158158
}
159+
160+
const testComplexPluginOptionDefaults: Partial<PluginOptions> = {
161+
gating: {
162+
source: 'ReactForgetFeatureFlag',
163+
importSpecifierName: 'isForgetEnabled_Fixtures',
164+
},
165+
};
159166
export function parseConfigPragmaForTests(
160167
pragma: string,
161168
defaults: {
162169
compilationMode: CompilationMode;
163170
},
164171
): PluginOptions {
165172
const environment = parseConfigPragmaEnvironmentForTest(pragma);
166-
let compilationMode: CompilationMode = defaults.compilationMode;
167-
let panicThreshold: PanicThresholdOptions = 'all_errors';
168-
let noEmit: boolean = defaultOptions.noEmit;
173+
const options: Record<keyof PluginOptions, unknown> = {
174+
...defaultOptions,
175+
panicThreshold: 'all_errors',
176+
compilationMode: defaults.compilationMode,
177+
environment,
178+
};
169179
for (const token of pragma.split(' ')) {
170180
if (!token.startsWith('@')) {
171181
continue;
172182
}
173-
switch (token) {
174-
case '@compilationMode(annotation)': {
175-
compilationMode = 'annotation';
176-
break;
177-
}
178-
case '@compilationMode(infer)': {
179-
compilationMode = 'infer';
180-
break;
181-
}
182-
case '@compilationMode(all)': {
183-
compilationMode = 'all';
184-
break;
185-
}
186-
case '@compilationMode(syntax)': {
187-
compilationMode = 'syntax';
188-
break;
189-
}
190-
case '@panicThreshold(none)': {
191-
panicThreshold = 'none';
192-
break;
193-
}
194-
case '@noEmit': {
195-
noEmit = true;
196-
break;
183+
const keyVal = token.slice(1);
184+
const idx = keyVal.indexOf(':');
185+
const key = idx === -1 ? keyVal : keyVal.slice(0, idx);
186+
const val = idx === -1 ? undefined : keyVal.slice(idx + 1);
187+
if (!hasOwnProperty(defaultOptions, key)) {
188+
continue;
189+
}
190+
const isSet = val === undefined || val === 'true';
191+
if (isSet && key in testComplexPluginOptionDefaults) {
192+
options[key] = testComplexPluginOptionDefaults[key];
193+
} else if (isSet) {
194+
options[key] = true;
195+
} else if (val === 'false') {
196+
options[key] = false;
197+
} else if (val != null) {
198+
const parsedVal = tryParseTestPragmaValue(val).unwrap();
199+
if (key === 'target' && parsedVal === 'donotuse_meta_internal') {
200+
options[key] = {
201+
kind: parsedVal,
202+
runtimeModule: 'react',
203+
};
204+
} else {
205+
options[key] = parsedVal;
197206
}
198207
}
199208
}
200-
return parsePluginOptions({
201-
environment,
202-
compilationMode,
203-
panicThreshold,
204-
noEmit,
205-
});
209+
return parsePluginOptions(options);
206210
}

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/arrow-function-with-implicit-return.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-
// @compilationMode(infer)
5+
// @compilationMode:"infer"
66
const Test = () => <div />;
77

88
export const FIXTURE_ENTRYPOINT = {
@@ -15,7 +15,7 @@ export const FIXTURE_ENTRYPOINT = {
1515
## Code
1616

1717
```javascript
18-
import { c as _c } from "react/compiler-runtime"; // @compilationMode(infer)
18+
import { c as _c } from "react/compiler-runtime"; // @compilationMode:"infer"
1919
const Test = () => {
2020
const $ = _c(1);
2121
let t0;

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/arrow-function-with-implicit-return.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// @compilationMode(infer)
1+
// @compilationMode:"infer"
22
const Test = () => <div />;
33

44
export const FIXTURE_ENTRYPOINT = {

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/class-component-with-render-helper.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-
// @compilationMode(infer)
5+
// @compilationMode:"infer"
66
class Component {
77
_renderMessage = () => {
88
const Message = () => {
@@ -22,7 +22,7 @@ class Component {
2222
## Code
2323

2424
```javascript
25-
// @compilationMode(infer)
25+
// @compilationMode:"infer"
2626
class Component {
2727
_renderMessage = () => {
2828
const Message = () => {

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/class-component-with-render-helper.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// @compilationMode(infer)
1+
// @compilationMode:"infer"
22
class Component {
33
_renderMessage = () => {
44
const Message = () => {

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-
// @enableEmitInstrumentForget @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 { shouldInstrument, useRenderCounter } from "react-compiler-runtime";
27-
import { c as _c } from "react/compiler-runtime"; // @enableEmitInstrumentForget @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-
// @enableEmitInstrumentForget @compilationMode(annotation)
1+
// @enableEmitInstrumentForget @compilationMode:"annotation"
22

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

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/component-declaration-basic.flow.expect.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
## Input
33

44
```javascript
5-
// @flow @compilationMode(infer)
5+
// @flow @compilationMode:"infer"
66
export default component Foo(bar: number) {
77
return <Bar bar={bar} />;
88
}

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/component-declaration-basic.flow.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// @flow @compilationMode(infer)
1+
// @flow @compilationMode:"infer"
22
export default component Foo(bar: number) {
33
return <Bar bar={bar} />;
44
}

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/conflict-codegen-instrument-forget.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-
// @enableEmitInstrumentForget @compilationMode(annotation)
5+
// @enableEmitInstrumentForget @compilationMode:"annotation"
66

77
import {identity} from 'shared-runtime';
88

@@ -35,7 +35,7 @@ import {
3535
shouldInstrument as _shouldInstrument3,
3636
useRenderCounter,
3737
} from "react-compiler-runtime";
38-
import { c as _c } from "react/compiler-runtime"; // @enableEmitInstrumentForget @compilationMode(annotation)
38+
import { c as _c } from "react/compiler-runtime"; // @enableEmitInstrumentForget @compilationMode:"annotation"
3939

4040
import { identity } from "shared-runtime";
4141

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

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

33
import {identity} from 'shared-runtime';
44

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bailout-on-suppression-of-custom-rule.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-
// @eslintSuppressionRules(my-app/react-rule)
5+
// @eslintSuppressionRules:["my-app","react-rule"]
66

77
/* eslint-disable my-app/react-rule */
88
function lowercasecomponent() {
@@ -19,7 +19,7 @@ function lowercasecomponent() {
1919
## Error
2020

2121
```
22-
1 | // @eslintSuppressionRules(my-app/react-rule)
22+
1 | // @eslintSuppressionRules:["my-app","react-rule"]
2323
2 |
2424
> 3 | /* eslint-disable my-app/react-rule */
2525
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior. eslint-disable my-app/react-rule (3:3)

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bailout-on-suppression-of-custom-rule.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// @eslintSuppressionRules(my-app/react-rule)
1+
// @eslintSuppressionRules:["my-app","react-rule"]
22

33
/* eslint-disable my-app/react-rule */
44
function lowercasecomponent() {

0 commit comments

Comments
 (0)