[rcr] Add target flag to compiler (#31143)
lauren committed
Oct 7, 2024 at 17:50 UTC
8dd4cda3808d83f2565c25f367fb8f16e7a2fc73
2 files changed
+59
-13
compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Options.ts
+50
-13
@@ -14,6 +14,7 @@ import {
14
parseEnvironmentConfig,
15
} from '../HIR/Environment';
16
import {hasOwnProperty} from '../Utils/utils';
17
+import {fromZodError} from 'zod-validation-error';
18
19
const PanicThresholdOptionsSchema = z.enum([
20
/*
@@ -121,8 +122,19 @@ export type PluginOptions = {
122
* Set this flag (on by default) to automatically check for this library and activate the support.
123
*/
124
enableReanimatedCheck: boolean;
125
+
126
+ /**
127
+ * The minimum major version of React that the compiler should emit code for. If the target is 19
128
+ * or higher, the compiler emits direct imports of React runtime APIs needed by the compiler. On
129
+ * versions prior to 19, an extra runtime package react-compiler-runtime is necessary to provide
130
+ * a userspace approximation of runtime APIs.
131
+ */
132
+ target: CompilerReactTarget;
133
};
134
135
+const CompilerReactTargetSchema = z.enum(['17', '18', '19']);
136
+export type CompilerReactTarget = z.infer<typeof CompilerReactTargetSchema>;
137
+
138
const CompilationModeSchema = z.enum([
139
/*
140
* Compiles functions annotated with "use forget" or component/hook-like functions.
@@ -210,6 +222,7 @@ export const defaultOptions: PluginOptions = {
222
return filename.indexOf('node_modules') === -1;
223
},
224
enableReanimatedCheck: true,
225
+ target: '19',
226
} as const;
227
228
export function parsePluginOptions(obj: unknown): PluginOptions {
@@ -222,25 +235,49 @@ export function parsePluginOptions(obj: unknown): PluginOptions {
235
// normalize string configs to be case insensitive
236
value = value.toLowerCase();
237
}
225
- if (key === 'environment') {
226
- const environmentResult = parseEnvironmentConfig(value);
227
- if (environmentResult.isErr()) {
228
- CompilerError.throwInvalidConfig({
229
- reason:
230
- 'Error in validating environment config. This is an advanced setting and not meant to be used directly',
231
- description: environmentResult.unwrapErr().toString(),
232
- suggestions: null,
233
- loc: null,
234
- });
238
+ if (isCompilerFlag(key)) {
239
+ switch (key) {
240
+ case 'environment': {
241
+ const environmentResult = parseEnvironmentConfig(value);
242
+ if (environmentResult.isErr()) {
243
+ CompilerError.throwInvalidConfig({
244
+ reason:
245
+ 'Error in validating environment config. This is an advanced setting and not meant to be used directly',
246
+ description: environmentResult.unwrapErr().toString(),
247
+ suggestions: null,
248
+ loc: null,
249
+ });
250
+ }
251
+ parsedOptions[key] = environmentResult.unwrap();
252
+ break;
253
+ }
254
+ case 'target': {
255
+ parsedOptions[key] = parseTargetConfig(value);
256
+ break;
257
+ }
258
+ default: {
259
+ parsedOptions[key] = value;
260
+ }
261
}
236
- parsedOptions[key] = environmentResult.unwrap();
237
- } else if (isCompilerFlag(key)) {
238
- parsedOptions[key] = value;
262
}
263
}
264
return {...defaultOptions, ...parsedOptions};
265
}
266
267
+export function parseTargetConfig(value: unknown): CompilerReactTarget {
268
+ const parsed = CompilerReactTargetSchema.safeParse(value);
269
+ if (parsed.success) {
270
+ return parsed.data;
271
+ } else {
272
+ CompilerError.throwInvalidConfig({
273
+ reason: 'Not a valid target',
274
+ description: `${fromZodError(parsed.error)}`,
275
+ suggestions: null,
276
+ loc: null,
277
+ });
278
+ }
279
+}
280
+
281
function isCompilerFlag(s: string): s is keyof PluginOptions {
282
return hasOwnProperty(defaultOptions, s);
283
}
compiler/packages/snap/src/compiler.ts
+9
@@ -56,6 +56,7 @@ function makePluginOptions(
56
let enableChangeDetectionForDebugging = null;
57
let customMacros: null | Array<Macro> = null;
58
let validateBlocklistedImports = null;
59
+ let target = '19' as const;
60
61
if (firstLine.indexOf('@compilationMode(annotation)') !== -1) {
62
assert(
@@ -107,6 +108,13 @@ function makePluginOptions(
108
if (runtimeModuleMatch) {
109
runtimeModule = runtimeModuleMatch[1];
110
}
111
+
112
+ const targetMatch = /@target="([^"]+)"/.exec(firstLine);
113
+ if (targetMatch) {
114
+ // @ts-ignore
115
+ target = targetMatch[1];
116
+ }
117
+
118
if (firstLine.includes('@panicThreshold(none)')) {
119
panicThreshold = 'none';
120
}
@@ -248,6 +256,7 @@ function makePluginOptions(
256
flowSuppressions,
257
ignoreUseNoForget,
258
enableReanimatedCheck: false,
259
+ target,
260
};
261
return [options, logs];
262
}