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
+}