@samitouri / QOS-React-2 / commits / a7450572fa

import runtime from "React.unstable_ForgetRuntime"

Imports the runtime from `React.unstable_ForgetRuntime` rather than from a separate module. The hope is that any code that gets transformed already has a dependency on React anyway, so we can avoid adding a new dependency that other systems don't know about. While here, i also cleaned up the `guardThrows` flag (we still parse it if present and warn, rather than throwing, to make it easier to adopt the latest version in various places).

Joseph Savona committed Oct 21, 2022 at 09:13 UTC a7450572faeca9c0d976c7620251475a48a13ed3
8 files changed +52 -64
compiler/forget/scripts/jest/e2e-forget.config.js
+4 -1
@@ -7,4 +7,7 @@
7
8 const makeE2EConfig = require("../jest/makeE2EConfig");
9
10 -module.exports = makeE2EConfig("e2e with forget", true);
10 +const config = makeE2EConfig("e2e with forget", true);
11 +config.setupFilesAfterEnv = ["<rootDir>/../scripts/jest/setupEnvE2E.js"];
12 +
13 +module.exports = config;
compiler/forget/scripts/jest/makeTransform.js
+4 -3
@@ -42,9 +42,10 @@ module.exports = (useForget) => {
42 if (path.node.callee.name === "require") {
43 const arg = path.node.arguments[0];
44 if (arg.type === "StringLiteral") {
45 - if (arg.value === "react-forget-runtime") {
46 - arg.value =
47 - "../../../packages/react-forget-runtime";
45 + // The compiler adds requires of "React", which is expected to be a wrapper
46 + // around the "react" package. For tests, we just rewrite the require.
47 + if (arg.value === "React") {
48 + arg.value = "react";
49 }
50 }
51 }
compiler/forget/scripts/jest/setupEnvE2E.js new
+11
@@ -0,0 +1,11 @@
1 +/**
2 + * Copyright (c) Meta Platforms, Inc. and affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + */
7 +
8 +const React = require("react");
9 +const ForgetRuntime = require("../../packages/react-forget-runtime");
10 +React.unstable_ForgetRuntime = ForgetRuntime;
11 +React.unstable_useMemoCache = ForgetRuntime.unstable_useMemoCache;
compiler/forget/src/BackEnd/JSGen.ts
+27 -43
@@ -52,17 +52,36 @@ export function run(lirProg: LIR.Prog, context: CompilerContext) {
52 if (context.opts.flags.addFreeze) {
53 utils.push("$makeReadOnly");
54 }
55 - if (context.opts.flags.guardThrows) {
56 - utils.push("$reset");
57 - }
55 if (utils.length > 0) {
56 prog.unshiftContainer(
57 "body",
61 - t.importDeclaration(
62 - utils.map((name) =>
63 - t.importSpecifier(t.identifier(name), t.identifier(name))
58 + t.variableDeclaration("const", [
59 + t.variableDeclarator(
60 + t.objectPattern(
61 + utils.map((util) =>
62 + t.objectProperty(
63 + t.identifier(util),
64 + t.identifier(util),
65 + false,
66 + true,
67 + null
68 + )
69 + )
70 + ),
71 + t.identifier("$ForgetRuntime")
72 ),
65 - t.stringLiteral("react-forget-runtime")
73 + ])
74 + );
75 + prog.unshiftContainer(
76 + "body",
77 + t.importDeclaration(
78 + [
79 + t.importSpecifier(
80 + t.identifier("$ForgetRuntime"),
81 + t.identifier("unstable_ForgetRuntime")
82 + ),
83 + ],
84 + t.stringLiteral("React")
85 )
86 );
87 }
@@ -155,42 +174,7 @@ export function runFunc(
174 const directives = funcBody.node.directives;
175
176 let code = jsFunc.code;
158 - if (context.opts.flags.guardThrows) {
159 - code = [
160 - jsFunc.useMemoCacheCall(lirFunc.memoCache.size),
161 - t.tryStatement(
162 - t.blockStatement(
163 - code.map((node) => {
164 - if (t.isStatement(node)) {
165 - return node;
166 - } else if (t.isExpression(node)) {
167 - return t.expressionStatement(node);
168 - } else {
169 - throw new Error(`unhandled node type: ${node.type}`);
170 - }
171 - })
172 - ),
173 - t.catchClause(
174 - t.identifier("e"),
175 - t.blockStatement([
176 - t.expressionStatement(
177 - t.callExpression(
178 - t.memberExpression(
179 - t.identifier("useMemoCache"),
180 - t.identifier("reset")
181 - ),
182 - [jsFunc.memoCache.id]
183 - )
184 - ),
185 - t.throwStatement(t.identifier("e")),
186 - ])
187 - ),
188 - null
189 - ),
190 - ];
191 - } else {
192 - code.unshift(jsFunc.useMemoCacheCall(lirFunc.memoCache.size));
193 - }
177 + code.unshift(jsFunc.useMemoCacheCall(lirFunc.memoCache.size));
178 funcBody.replaceWithMultiple(code);
179
180 // recover directives.
compiler/forget/src/CompilerFlags.ts
+6 -10
@@ -73,14 +73,6 @@ export type CompilerFlags = {
73 */
74 guardHooks: boolean;
75
76 - /**
77 - * Adds a guard around the whole function to ensure the memo cache is reset
78 - * on any throw.
79 - *
80 - * When https://github.com/facebook/react/pull/25143 lands on internally, we
81 - * can remove this flag.
82 - */
83 - guardThrows: boolean;
76 /**
77 * Experimental runtime logging to collect data
78 */
@@ -98,7 +90,6 @@ export function createCompilerFlags(): CompilerFlags {
90 condCache: false,
91 guardReads: false,
92 guardHooks: false,
101 - guardThrows: false,
93 addFreeze: false,
94 };
95 }
@@ -119,13 +110,18 @@ export function parseCompilerFlags(
110 case "condCache":
111 case "guardReads":
112 case "guardHooks":
122 - case "guardThrows":
113 case "addFreeze":
114 if (typeof value !== "boolean") {
115 throw `Expected boolean for flag '${key}': ${value}`;
116 }
117 res[key] = value;
118 break;
119 + case "guardThrows": {
120 + console.warn(
121 + `the 'guardThrows' flag is no longer supported, this feature is built into React now`
122 + );
123 + break;
124 + }
125 default:
126 if (!ignoreInvalidInput) {
127 throw `Unknown flag: ${key}`;
compiler/forget/src/__tests__/CompilerOptions-test.ts
-1
@@ -53,7 +53,6 @@ describe("CompilerOptions", () => {
53 condCache: true,
54 guardReads: true,
55 guardHooks: true,
56 - guardThrows: true,
56 localMutationThroughFreeVars: false,
57 bailOnMultipleReturns: true,
58 bailOnCapitalizedFunctionCalls: true,
compiler/forget/src/__tests__/e2e/hello.e2e.js
-3
@@ -9,9 +9,6 @@ import * as React from "react";
9 import { render } from "@testing-library/react";
10 import { expectLogsAndClear, log } from "./expectLogs";
11
12 -import { unstable_useMemoCache } from "react-forget-runtime";
13 -React.unstable_useMemoCache = unstable_useMemoCache;
14 -
12 function Hello({ name }) {
13 "use forget";
14 const items = [1, 2, 3].map((item) => <div key={item}>Item {item}</div>);
compiler/forget/src/__tests__/e2e/update-button.e2e.js
-3
@@ -8,9 +8,6 @@
8 import * as React from "react";
9 import { render } from "@testing-library/react";
10
11 -import { unstable_useMemoCache } from "react-forget-runtime";
12 -React.unstable_useMemoCache = unstable_useMemoCache;
13 -
11 function Button({ label }) {
12 const theme = useTheme();
13 const style = computeStyle(theme);