The library for web and native user interfaces.
Don't plumb PartialEnvironmentConfig
Let's do validation at the API level and pass around the fully parsed config inside the plugin.
Sathya Gunasekaran committed
Nov 7, 2023 at 11:04 UTC
1c53385db59536165e7b7468652ab962c4cfe769
4 files changed
+30
-21
compiler/packages/babel-plugin-react-forget/scripts/jest/makeTransform.ts
+4
-3
@@ -7,14 +7,14 @@
7
8
import { jsx } from "@babel/plugin-syntax-jsx";
9
import babelJest from "babel-jest";
10
-import { compile } from "babel-plugin-react-forget";
10
+import { DEFAULT_ENVIRONMENT_CONFIG, compile } from "babel-plugin-react-forget";
11
import { execSync } from "child_process";
12
13
import type { NodePath, Visitor } from "@babel/traverse";
14
import type { CallExpression, FunctionDeclaration } from "@babel/types";
15
import * as t from "@babel/types";
16
-import type { PluginOptions } from "babel-plugin-react-forget";
16
import { basename } from "path";
17
+import { EnvironmentConfig } from "../../src/HIR/Environment";
18
19
/**
20
* -- IMPORTANT --
@@ -23,7 +23,8 @@ import { basename } from "path";
23
* as our script files are currently not used for babel cache breaking!!
24
*/
25
const e2eTransformerCacheKey = 1;
26
-const forgetOptions: Partial<PluginOptions["environment"]> = {
26
+const forgetOptions: EnvironmentConfig = {
27
+ ...DEFAULT_ENVIRONMENT_CONFIG,
28
enableAssumeHooksFollowRulesOfReact: true,
29
};
30
const debugMode = process.env["DEBUG_FORGET_COMPILER"] != null;
compiler/packages/babel-plugin-react-forget/src/Entrypoint/Pipeline.ts
+5
-5
@@ -18,7 +18,7 @@ import {
18
lower,
19
mergeConsecutiveBlocks,
20
} from "../HIR";
21
-import { Environment, PartialEnvironmentConfig } from "../HIR/Environment";
21
+import { Environment, EnvironmentConfig } from "../HIR/Environment";
22
import { findContextIdentifiers } from "../HIR/FindContextIdentifiers";
23
import {
24
analyseFunctions,
@@ -87,10 +87,10 @@ export function* run(
87
func: NodePath<
88
t.FunctionDeclaration | t.ArrowFunctionExpression | t.FunctionExpression
89
>,
90
- config?: PartialEnvironmentConfig | null
90
+ config: EnvironmentConfig
91
): Generator<CompilerPipelineValue, CodegenFunction> {
92
const contextIdentifiers = findContextIdentifiers(func);
93
- const env = new Environment(config ?? null, contextIdentifiers);
93
+ const env = new Environment(config, contextIdentifiers);
94
yield {
95
kind: "debug",
96
name: "EnvironmentConfig",
@@ -368,9 +368,9 @@ export function compileFn(
368
func: NodePath<
369
t.FunctionDeclaration | t.ArrowFunctionExpression | t.FunctionExpression
370
>,
371
- options?: Partial<PartialEnvironmentConfig> | null
371
+ config: EnvironmentConfig
372
): CodegenFunction {
373
- let generator = run(func, options);
373
+ let generator = run(func, config);
374
while (true) {
375
const next = generator.next();
376
if (next.done) {
compiler/packages/babel-plugin-react-forget/src/Entrypoint/Program.ts
+3
-1
@@ -13,6 +13,7 @@ import {
13
CompilerSuggestionOperation,
14
ErrorSeverity,
15
} from "../CompilerError";
16
+import { validateEnvironmentConfig } from "../HIR/Environment";
17
import { CodegenFunction } from "../ReactiveScopes";
18
import { isComponentDeclaration } from "../Utils/ComponentDeclaration";
19
import { assertExhaustive } from "../Utils/utils";
@@ -247,7 +248,8 @@ export function compileProgram(
248
249
let compiledFn: CodegenFunction;
250
try {
250
- compiledFn = compileFn(fn, pass.opts.environment);
251
+ const config = validateEnvironmentConfig(pass.opts.environment);
252
+ compiledFn = compileFn(fn, config);
253
pass.opts.logger?.logEvent(pass.filename, {
254
kind: "CompileSuccess",
255
fnLoc: fn.node.loc ?? null,
compiler/packages/babel-plugin-react-forget/src/HIR/Environment.ts
+18
-12
@@ -328,21 +328,10 @@ export class Environment {
328
#hoistedIdentifiers: Set<t.Identifier>;
329
330
constructor(
331
- partialConfig: PartialEnvironmentConfig | null,
331
+ config: EnvironmentConfig,
332
contextIdentifiers: Set<t.Identifier>
333
) {
334
this.#shapes = new Map(DEFAULT_SHAPES);
335
- const config: EnvironmentConfig = { ...DEFAULT_ENVIRONMENT_CONFIG };
336
- if (partialConfig != null) {
337
- for (const key of Object.keys(DEFAULT_ENVIRONMENT_CONFIG)) {
338
- if (!isEnvironmentConfigKey(key)) {
339
- continue;
340
- }
341
- if (Object.prototype.hasOwnProperty.call(partialConfig, key)) {
342
- config[key] = partialConfig[key] as any; // we know the key is present from hasOwnProperty
343
- }
344
- }
345
- }
335
this.config = config;
336
337
if (this.config.customHooks != null && this.config.customHooks.size > 0) {
@@ -473,3 +462,20 @@ function isHookName(name: string): boolean {
462
// }
463
return /^use[A-Z0-9]/.test(name);
464
}
465
+
466
+export function validateEnvironmentConfig(
467
+ partialConfig: PartialEnvironmentConfig | null
468
+): EnvironmentConfig {
469
+ const config: EnvironmentConfig = { ...DEFAULT_ENVIRONMENT_CONFIG };
470
+ if (partialConfig != null) {
471
+ for (const key of Object.keys(DEFAULT_ENVIRONMENT_CONFIG)) {
472
+ if (!isEnvironmentConfigKey(key)) {
473
+ continue;
474
+ }
475
+ if (Object.prototype.hasOwnProperty.call(partialConfig, key)) {
476
+ config[key] = partialConfig[key] as any; // we know the key is present from hasOwnProperty
477
+ }
478
+ }
479
+ }
480
+ return config;
481
+}