Skip to content

Commit

Permalink
Allow global mutation within useEffect (#2646)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
mvitousek committed Mar 5, 2024
1 parent f5d99ba commit 22ea72d
Show file tree
Hide file tree
Showing 9 changed files with 349 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,12 @@ export class CompilerError extends Error {
throw errors;
}

static throw(options: CompilerErrorDetailOptions): never {
const errors = new CompilerError();
errors.pushErrorDetail(new CompilerErrorDetail(options));
throw errors;
}

constructor(...args: any[]) {
super(...args);
this.name = "ReactForgetCompilerError";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ export function lower(
async: func.node.async === true,
loc: func.node.loc ?? GeneratedSource,
env,
effects: null,
});
}

Expand Down
8 changes: 7 additions & 1 deletion compiler/packages/babel-plugin-react-forget/src/HIR/HIR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import * as t from "@babel/types";
import { CompilerError } from "../CompilerError";
import { CompilerError, CompilerErrorDetailOptions } from "../CompilerError";
import { assertExhaustive } from "../Utils/utils";
import { Environment } from "./Environment";
import { HookKind } from "./ObjectShape";
Expand Down Expand Up @@ -244,11 +244,17 @@ export type HIRFunction = {
params: Array<Place | SpreadPattern>;
returnType: t.FlowType | t.TSType | null;
context: Array<Place>;
effects: Array<FunctionEffect> | null;
body: HIR;
generator: boolean;
async: boolean;
};

export type FunctionEffect = {
kind: "GlobalMutation";
error: CompilerErrorDetailOptions;
};

/*
* Each reactive scope may have its own control-flow, so the instructions form
* a control-flow graph. The graph comprises a set of basic blocks which reference
Expand Down
Loading

0 comments on commit 22ea72d

Please sign in to comment.