mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[hir-rewrite] Remove breaks to HIR ScopeTerminal after converting to reactiveFunction IR
ghstack-source-id: 67e979e1533b23ced762973e239a4290111e2242 Pull Request resolved: https://github.com/facebook/react-forget/pull/2911
This commit is contained in:
@@ -46,6 +46,7 @@ import {
|
||||
alignObjectMethodScopes,
|
||||
alignReactiveScopesToBlockScopes,
|
||||
assertScopeInstructionsWithinScopes,
|
||||
assertWellFormedBreakTargets,
|
||||
buildReactiveBlocks,
|
||||
buildReactiveFunction,
|
||||
codegenFunction,
|
||||
@@ -279,6 +280,8 @@ function* runWithEnvironment(
|
||||
value: reactiveFunction,
|
||||
});
|
||||
|
||||
assertWellFormedBreakTargets(reactiveFunction);
|
||||
|
||||
pruneUnusedLabels(reactiveFunction);
|
||||
yield log({
|
||||
kind: "reactive",
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import { CompilerError } from "..";
|
||||
import { BlockId, ReactiveFunction, ReactiveTerminalStatement } from "../HIR";
|
||||
import { ReactiveFunctionVisitor, visitReactiveFunction } from "./visitors";
|
||||
|
||||
/**
|
||||
* Assert that all break/continue targets reference existent labels.
|
||||
*/
|
||||
export function assertWellFormedBreakTargets(fn: ReactiveFunction): void {
|
||||
visitReactiveFunction(fn, new Visitor(), new Set());
|
||||
}
|
||||
|
||||
class Visitor extends ReactiveFunctionVisitor<Set<BlockId>> {
|
||||
override visitTerminal(
|
||||
stmt: ReactiveTerminalStatement,
|
||||
seenLabels: Set<BlockId>
|
||||
): void {
|
||||
if (stmt.label != null) {
|
||||
seenLabels.add(stmt.label.id);
|
||||
}
|
||||
const terminal = stmt.terminal;
|
||||
if (terminal.kind === "break" || terminal.kind === "continue") {
|
||||
CompilerError.invariant(seenLabels.has(terminal.target), {
|
||||
reason: "Unexpected break to invalid label",
|
||||
loc: stmt.terminal.loc,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
+21
-5
@@ -813,6 +813,7 @@ class Driver {
|
||||
if (fallthroughId !== null) {
|
||||
const scheduleId = this.cx.schedule(fallthroughId, "if");
|
||||
scheduleIds.push(scheduleId);
|
||||
this.cx.scopeFallthroughs.add(fallthroughId);
|
||||
}
|
||||
|
||||
let block: ReactiveBlock;
|
||||
@@ -1169,7 +1170,7 @@ class Driver {
|
||||
block: BlockId,
|
||||
id: InstructionId,
|
||||
loc: SourceLocation
|
||||
): ReactiveTerminalStatement<ReactiveBreakTerminal> {
|
||||
): ReactiveTerminalStatement<ReactiveBreakTerminal> | null {
|
||||
const target = this.cx.getBreakTarget(block);
|
||||
if (target === null) {
|
||||
CompilerError.invariant(false, {
|
||||
@@ -1179,6 +1180,13 @@ class Driver {
|
||||
suggestions: null,
|
||||
});
|
||||
}
|
||||
if (this.cx.scopeFallthroughs.has(target.block)) {
|
||||
CompilerError.invariant(target.type === "implicit", {
|
||||
reason: "Expected reactive scope to implicitly break to fallthrough",
|
||||
loc,
|
||||
});
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
kind: "terminal",
|
||||
terminal: {
|
||||
@@ -1231,6 +1239,7 @@ class Context {
|
||||
*/
|
||||
emitted: Set<BlockId> = new Set();
|
||||
|
||||
scopeFallthroughs: Set<BlockId> = new Set();
|
||||
/*
|
||||
* A set of blocks that are already scheduled to be emitted by eg a parent.
|
||||
* This allows child nodes to avoid re-emitting the same block and emit eg
|
||||
@@ -1361,9 +1370,10 @@ class Context {
|
||||
*
|
||||
* The returned 'block' value should be used as the label if necessary.
|
||||
*/
|
||||
getBreakTarget(
|
||||
block: BlockId
|
||||
): { block: BlockId; type: ReactiveTerminalTargetKind } | null {
|
||||
getBreakTarget(block: BlockId): {
|
||||
block: BlockId;
|
||||
type: ReactiveTerminalTargetKind;
|
||||
} {
|
||||
let hasPrecedingLoop = false;
|
||||
for (let i = this.#controlFlowStack.length - 1; i >= 0; i--) {
|
||||
const target = this.#controlFlowStack[i]!;
|
||||
@@ -1392,7 +1402,13 @@ class Context {
|
||||
}
|
||||
hasPrecedingLoop ||= target.type === "loop";
|
||||
}
|
||||
return null;
|
||||
|
||||
CompilerError.invariant(false, {
|
||||
reason: "Expected a break target",
|
||||
description: null,
|
||||
loc: null,
|
||||
suggestions: null,
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
export { alignObjectMethodScopes } from "./AlignObjectMethodScopes";
|
||||
export { alignReactiveScopesToBlockScopes } from "./AlignReactiveScopesToBlockScopes";
|
||||
export { assertScopeInstructionsWithinScopes } from "./AssertScopeInstructionsWithinScope";
|
||||
export { assertWellFormedBreakTargets } from "./AssertWellFormedBreakTargets";
|
||||
export { buildReactiveBlocks } from "./BuildReactiveBlocks";
|
||||
export { buildReactiveFunction } from "./BuildReactiveFunction";
|
||||
export {
|
||||
|
||||
Reference in New Issue
Block a user