mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Record todo bailouts in CodegenReactiveFunction
Went over this pass and converted any todos to bailouts, otherwise we continue to throw an invariant if there's an internal error
This commit is contained in:
@@ -13,7 +13,7 @@ export enum ErrorSeverity {
|
||||
export type CompilerErrorOptions = {
|
||||
reason: string;
|
||||
severity: ErrorSeverity;
|
||||
nodePath: AnyNodePath;
|
||||
nodePath: AnyNodePath | null;
|
||||
};
|
||||
type AnyNodePath = NodePath<Node | null | undefined>;
|
||||
type CompilerErrorKind = typeof InvalidInputError | typeof TodoError;
|
||||
|
||||
@@ -46,11 +46,7 @@ export type CompilerPipelineValue =
|
||||
export function* run(
|
||||
func: NodePath<t.FunctionDeclaration>
|
||||
): Generator<CompilerPipelineValue, t.Function> {
|
||||
const lowering = lower(func).orElse((error) => {
|
||||
throw error;
|
||||
});
|
||||
|
||||
const hir = lowering.unwrap();
|
||||
const hir = lower(func).unwrap();
|
||||
yield log({ kind: "hir", name: "HIR", value: hir });
|
||||
|
||||
mergeConsecutiveBlocks(hir);
|
||||
@@ -153,7 +149,7 @@ export function* run(
|
||||
value: reactiveFunction,
|
||||
});
|
||||
|
||||
const ast = codegenReactiveFunction(reactiveFunction);
|
||||
const ast = codegenReactiveFunction(reactiveFunction).unwrap();
|
||||
yield log({ kind: "ast", name: "Codegen", value: ast });
|
||||
|
||||
return ast;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
import * as t from "@babel/types";
|
||||
import invariant from "invariant";
|
||||
import { CompilerError, ErrorSeverity } from "../CompilerError";
|
||||
import {
|
||||
BlockId,
|
||||
GeneratedSource,
|
||||
@@ -24,12 +25,12 @@ import {
|
||||
ReactiveValue,
|
||||
SourceLocation,
|
||||
} from "../HIR/HIR";
|
||||
import { todoInvariant } from "../Utils/todo";
|
||||
import { Err, Ok, Result } from "../Utils/Result";
|
||||
import { assertExhaustive } from "../Utils/utils";
|
||||
|
||||
export function codegenReactiveFunction(
|
||||
fn: ReactiveFunction
|
||||
): t.FunctionDeclaration {
|
||||
): Result<t.FunctionDeclaration, CompilerError> {
|
||||
const cx = new Context();
|
||||
const params = fn.params.map((param) => convertIdentifier(param.identifier));
|
||||
const body = codegenBlock(cx, fn.body);
|
||||
@@ -56,13 +57,20 @@ export function codegenReactiveFunction(
|
||||
])
|
||||
);
|
||||
}
|
||||
return createFunctionDeclaration(
|
||||
fn.loc,
|
||||
fn.id !== null ? convertIdentifier(fn.id) : null,
|
||||
params,
|
||||
body,
|
||||
fn.generator,
|
||||
fn.async
|
||||
|
||||
if (cx.errors.hasErrors()) {
|
||||
return Err(cx.errors);
|
||||
}
|
||||
|
||||
return Ok(
|
||||
createFunctionDeclaration(
|
||||
fn.loc,
|
||||
fn.id !== null ? convertIdentifier(fn.id) : null,
|
||||
params,
|
||||
body,
|
||||
fn.generator,
|
||||
fn.async
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -70,6 +78,7 @@ class Context {
|
||||
#nextCacheIndex: number = 0;
|
||||
#identifiers: Set<Identifier> = new Set();
|
||||
temp: Temporaries = new Map();
|
||||
errors: CompilerError = new CompilerError();
|
||||
|
||||
get nextCacheIndex(): number {
|
||||
return this.#nextCacheIndex++;
|
||||
@@ -711,17 +720,22 @@ function codegenInstructionValue(
|
||||
} else {
|
||||
if (t.isVariableDeclaration(stmt)) {
|
||||
const declarator = stmt.declarations[0];
|
||||
todoInvariant(
|
||||
false,
|
||||
`Cannot declare variables in a value block, tried to declare '${
|
||||
cx.errors.push({
|
||||
reason: `(CodegenReactiveFunction::codegenInstructionValue) Cannot declare variables in a value block, tried to declare '${
|
||||
(declarator.id as t.Identifier).name
|
||||
}'`
|
||||
);
|
||||
}'`,
|
||||
severity: ErrorSeverity.Todo,
|
||||
nodePath: null,
|
||||
});
|
||||
return t.stringLiteral(`TODO handle ${declarator.id}`);
|
||||
} else {
|
||||
cx.errors.push({
|
||||
reason: `(CodegenReactiveFunction::codegenInstructionValue) Handle conversion of ${stmt.type} to expression`,
|
||||
severity: ErrorSeverity.Todo,
|
||||
nodePath: null,
|
||||
});
|
||||
return t.stringLiteral(`TODO handle ${stmt.type}`);
|
||||
}
|
||||
todoInvariant(
|
||||
false,
|
||||
`Handle conversion of ${stmt.type} to expression`
|
||||
);
|
||||
}
|
||||
});
|
||||
if (expressions.length === 0) {
|
||||
@@ -788,7 +802,6 @@ function codegenValue(
|
||||
}
|
||||
|
||||
function codegenPlace(cx: Context, place: Place): t.Expression {
|
||||
todoInvariant(place.kind === "Identifier", "support scope values");
|
||||
let tmp = cx.temp.get(place.identifier.id);
|
||||
if (tmp != null) {
|
||||
return tmp;
|
||||
|
||||
@@ -167,6 +167,9 @@ class OkImpl<T> implements Result<T, never> {
|
||||
}
|
||||
|
||||
unwrapErr(): never {
|
||||
if (this.val instanceof Error) {
|
||||
throw this.val;
|
||||
}
|
||||
throw new Error(`Can't unwrap \`Ok\` to \`Err\`: ${this.val}`);
|
||||
}
|
||||
}
|
||||
@@ -227,6 +230,9 @@ class ErrImpl<E> implements Result<never, E> {
|
||||
}
|
||||
|
||||
unwrap(): never {
|
||||
if (this.val instanceof Error) {
|
||||
throw this.val;
|
||||
}
|
||||
throw new Error(`Can't unwrap \`Err\` to \`Ok\`: ${this.val}`);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { CompilerError } from "../CompilerError";
|
||||
import { Err, Ok, Result } from "../Utils/Result";
|
||||
|
||||
function addMax10(a: number, b: number): Result<number, string> {
|
||||
@@ -9,6 +10,8 @@ function onlyFoo(foo: string): Result<string, string> {
|
||||
return foo === "foo" ? Ok(foo) : Err(foo);
|
||||
}
|
||||
|
||||
class CustomDummyError extends Error {}
|
||||
|
||||
describe("Result", () => {
|
||||
test(".map", () => {
|
||||
expect(addMax10(1, 1).map((n) => n * 2)).toEqual(Ok(4));
|
||||
@@ -107,6 +110,9 @@ describe("Result", () => {
|
||||
}).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Can't unwrap \`Err\` to \`Ok\`: 20 is too high"`
|
||||
);
|
||||
expect(() => {
|
||||
Err(new CustomDummyError("oops")).unwrap();
|
||||
}).toThrowErrorMatchingInlineSnapshot(`"oops"`);
|
||||
});
|
||||
|
||||
test(".unwrapOr", () => {
|
||||
@@ -126,5 +132,8 @@ describe("Result", () => {
|
||||
`"Can't unwrap \`Ok\` to \`Err\`: 2"`
|
||||
);
|
||||
expect(addMax10(10, 10).unwrapErr()).toEqual("20 is too high");
|
||||
expect(() => {
|
||||
Ok(new CustomDummyError("oops")).unwrapErr();
|
||||
}).toThrowErrorMatchingInlineSnapshot(`"oops"`);
|
||||
});
|
||||
});
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ function f(reader) {
|
||||
## Error
|
||||
|
||||
```
|
||||
TODO: Cannot declare variables in a value block, tried to declare 'value$0'
|
||||
[ReactForget] Todo: (CodegenReactiveFunction::codegenInstructionValue) Cannot declare variables in a value block, tried to declare 'value$0'
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user