Add enableOnlyOnUseForgetDirective flag
When this flag is enabled, Forget will only compile function declarations opted in via the `'use forget'` directive. By default this is false. Tested internally, see related diffs
Lauren Tan committed
Feb 6, 2023 at 16:47 UTC
cd108cd430fecda79b2d75abacbe9e5c7ac4eee8
2 files changed
+47
-3
compiler/forget/src/Babel/BabelPlugin.ts
+15
-1
@@ -9,6 +9,7 @@
9
10
import type * as BabelCore from "@babel/core";
11
import jsx from "@babel/plugin-syntax-jsx";
12
+import { parseCompilerFlags } from "../CompilerFlags";
13
import { compile } from "../CompilerPipeline";
14
15
/**
@@ -24,7 +25,20 @@ export default function ReactForgetBabelPlugin(
25
inherits: jsx,
26
visitor: {
27
FunctionDeclaration: {
27
- enter(fn, _pass) {
28
+ enter(fn, pass) {
29
+ const flags = parseCompilerFlags(pass.opts);
30
+ if (flags.enableOnlyOnUseForgetDirective) {
31
+ let hasUseForgetDirective = false;
32
+ for (const directive of fn.node.body.directives) {
33
+ if (directive.value.value === "use forget") {
34
+ hasUseForgetDirective = true;
35
+ break;
36
+ }
37
+ }
38
+ if (!hasUseForgetDirective) {
39
+ return;
40
+ }
41
+ }
42
if (fn.scope.getProgramParent() !== fn.scope.parent) {
43
return;
44
}
compiler/forget/src/CompilerFlags.ts
+32
-2
@@ -5,6 +5,36 @@
5
* LICENSE file in the root directory of this source tree.
6
*/
7
8
-type Flags = {};
8
+export type CompilerFlags = {
9
+ /**
10
+ * Enable to make Forget only compile functions containing the 'use forget' directive.
11
+ */
12
+ enableOnlyOnUseForgetDirective: boolean;
13
+};
14
10
-export const flags: Flags = {};
15
+export const defaultFlags: CompilerFlags = {
16
+ enableOnlyOnUseForgetDirective: false,
17
+} as const;
18
+
19
+export function parseCompilerFlags(obj: unknown): CompilerFlags {
20
+ if (obj == null || typeof obj !== "object") {
21
+ return defaultFlags;
22
+ }
23
+ const invalidFlags: Array<string> = [];
24
+ let parsedFlags: Partial<CompilerFlags> = Object.create(null);
25
+ for (const [key, value] of Object.entries(obj)) {
26
+ if (isCompilerFlag(key)) {
27
+ parsedFlags[key] = value;
28
+ } else {
29
+ invalidFlags.push(key);
30
+ }
31
+ }
32
+ if (invalidFlags.length > 0) {
33
+ throw new Error(`Unexpected React Forget compiler flags: ${invalidFlags}`);
34
+ }
35
+ return { ...defaultFlags, ...parsedFlags };
36
+}
37
+
38
+function isCompilerFlag(s: string): s is keyof typeof defaultFlags {
39
+ return Object.prototype.hasOwnProperty.call(defaultFlags, s);
40
+}