Skip to content

Commit 22ea72d

Browse files
committed
Allow global mutation within useEffect (#2646)
Summary: Currently Forget bails on mutations to globals within any callback function. However, callbacks passed to useEffect should not bail and are not subject to the rules of react in the same way. We allow this by instead of immediately raising errors when we see illegal writes, storing the error as part of the function. When the function is called, or passed to a position that could call it during rendering, we bail as before; but if it's passed to `useEffect`, we don't raise the errors.
1 parent f5d99ba commit 22ea72d

9 files changed

+349
-51
lines changed

compiler/packages/babel-plugin-react-forget/src/CompilerError.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,12 @@ export class CompilerError extends Error {
165165
throw errors;
166166
}
167167

168+
static throw(options: CompilerErrorDetailOptions): never {
169+
const errors = new CompilerError();
170+
errors.pushErrorDetail(new CompilerErrorDetail(options));
171+
throw errors;
172+
}
173+
168174
constructor(...args: any[]) {
169175
super(...args);
170176
this.name = "ReactForgetCompilerError";

compiler/packages/babel-plugin-react-forget/src/HIR/BuildHIR.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ export function lower(
216216
async: func.node.async === true,
217217
loc: func.node.loc ?? GeneratedSource,
218218
env,
219+
effects: null,
219220
});
220221
}
221222

compiler/packages/babel-plugin-react-forget/src/HIR/HIR.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*/
77

88
import * as t from "@babel/types";
9-
import { CompilerError } from "../CompilerError";
9+
import { CompilerError, CompilerErrorDetailOptions } from "../CompilerError";
1010
import { assertExhaustive } from "../Utils/utils";
1111
import { Environment } from "./Environment";
1212
import { HookKind } from "./ObjectShape";
@@ -244,11 +244,17 @@ export type HIRFunction = {
244244
params: Array<Place | SpreadPattern>;
245245
returnType: t.FlowType | t.TSType | null;
246246
context: Array<Place>;
247+
effects: Array<FunctionEffect> | null;
247248
body: HIR;
248249
generator: boolean;
249250
async: boolean;
250251
};
251252

253+
export type FunctionEffect = {
254+
kind: "GlobalMutation";
255+
error: CompilerErrorDetailOptions;
256+
};
257+
252258
/*
253259
* Each reactive scope may have its own control-flow, so the instructions form
254260
* a control-flow graph. The graph comprises a set of basic blocks which reference

0 commit comments

Comments
 (0)