mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Scaffolding for early return from reactive scopes
Adds a new `earlyReturnValue` property on ReactiveScope which will be set if the scope had one or more early returns, with information about the temporary identifier that the early return value will be assigned to, as well as the label to be used for breaking (to simulate the early-return). The next PR shows the intended codegen.
This commit is contained in:
@@ -1053,10 +1053,35 @@ export function isMutableEffect(
|
||||
export type ReactiveScope = {
|
||||
id: ScopeId;
|
||||
range: MutableRange;
|
||||
|
||||
/**
|
||||
* The inputs to this reactive scope
|
||||
*/
|
||||
dependencies: ReactiveScopeDependencies;
|
||||
|
||||
/**
|
||||
* The set of values produced by this scope. This may be empty
|
||||
* for scopes that produce reassignments only.
|
||||
*/
|
||||
declarations: Map<IdentifierId, ReactiveScopeDeclaration>;
|
||||
|
||||
/**
|
||||
* A mutable range may sometimes include a reassignment of some variable.
|
||||
* This is the set of identifiers which are reassigned by this scope.
|
||||
*/
|
||||
reassignments: Set<Identifier>;
|
||||
|
||||
/**
|
||||
* Reactive scopes may contain a return statement, which needs to be replayed
|
||||
* whenever the inputs to the scope have not changed since the previous execution.
|
||||
* If the reactive scope has an early return, this variable stores the temporary
|
||||
* identifier to which the return value will be assigned. See PropagateEarlyReturns
|
||||
* for more about how early returns in reactive scopes are compiled and represented.
|
||||
*
|
||||
* This value is null for scopes that do not contain early returns.
|
||||
*/
|
||||
earlyReturnValue: { value: IdentifierId; loc: SourceLocation } | null;
|
||||
|
||||
/*
|
||||
* Some passes may merge scopes together. The merged set contains the
|
||||
* ids of scopes that were merged into this one, for passes that need
|
||||
|
||||
+14
-5
@@ -451,11 +451,20 @@ function codegenReactiveScope(
|
||||
const computationBlock = codegenBlock(cx, block);
|
||||
computationBlock.body.push(...cacheStoreStatements);
|
||||
const memoBlock = t.blockStatement(cacheLoadStatements);
|
||||
const memoStatement = t.ifStatement(
|
||||
testCondition,
|
||||
computationBlock,
|
||||
memoBlock
|
||||
);
|
||||
|
||||
let memoStatement;
|
||||
if (scope.earlyReturnValue !== null) {
|
||||
// Has early return
|
||||
CompilerError.throwTodo({
|
||||
reason: `Codegen support for reactive scopes with early return`,
|
||||
loc: scope.earlyReturnValue.loc,
|
||||
description: null,
|
||||
suggestions: null,
|
||||
});
|
||||
} else {
|
||||
memoStatement = t.ifStatement(testCondition, computationBlock, memoBlock);
|
||||
}
|
||||
|
||||
if (cx.env.config.enableMemoizationComments) {
|
||||
if (changeExpressionComments.length) {
|
||||
t.addComment(
|
||||
|
||||
+1
@@ -199,6 +199,7 @@ export function inferReactiveScopeVariables(fn: HIRFunction): void {
|
||||
dependencies: new Set(),
|
||||
declarations: new Map(),
|
||||
reassignments: new Set(),
|
||||
earlyReturnValue: null,
|
||||
merged: new Set(),
|
||||
};
|
||||
scopes.set(groupIdentifier, scope);
|
||||
|
||||
+26
-11
@@ -42,17 +42,32 @@ export function printReactiveFunction(fn: ReactiveFunction): string {
|
||||
}
|
||||
|
||||
export function printReactiveScopeSummary(scope: ReactiveScope): string {
|
||||
return `scope @${scope.id} [${scope.range.start}:${
|
||||
scope.range.end
|
||||
}] dependencies=[${Array.from(scope.dependencies)
|
||||
.map((dep) => printDependency(dep))
|
||||
.join(", ")}] declarations=[${Array.from(scope.declarations)
|
||||
.map(([, decl]) =>
|
||||
printIdentifier({ ...decl.identifier, scope: decl.scope })
|
||||
)
|
||||
.join(", ")}] reassignments=[${Array.from(scope.reassignments).map(
|
||||
(reassign) => printIdentifier(reassign)
|
||||
)}]`;
|
||||
const items = [];
|
||||
// If the scope has a return value it needs a label
|
||||
items.push("scope");
|
||||
items.push(`@${scope.id}`);
|
||||
items.push(`[${scope.range.start}:${scope.range.end}]`);
|
||||
items.push(
|
||||
`dependencies=[${Array.from(scope.dependencies)
|
||||
.map((dep) => printDependency(dep))
|
||||
.join(", ")}]`
|
||||
);
|
||||
items.push(
|
||||
`declarations=[${Array.from(scope.declarations)
|
||||
.map(([, decl]) =>
|
||||
printIdentifier({ ...decl.identifier, scope: decl.scope })
|
||||
)
|
||||
.join(", ")}]`
|
||||
);
|
||||
items.push(
|
||||
`reassignments=[${Array.from(scope.reassignments).map((reassign) =>
|
||||
printIdentifier(reassign)
|
||||
)}]`
|
||||
);
|
||||
if (scope.earlyReturnValue !== null) {
|
||||
items.push(`earlyReturn=${scope.earlyReturnValue.value}`);
|
||||
}
|
||||
return items.join(" ");
|
||||
}
|
||||
|
||||
export function writeReactiveBlock(
|
||||
|
||||
Reference in New Issue
Block a user