@samitouri / QOS-React / commits / cd108cd430

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