Skip to content

Commit a65fbef

Browse files
committed
Update on "[compiler] Option to always take the non-memo branch"
Summary: This adds a debugging mode to the compiler that simply adds a `|| true` to the guard on all memoization blocks, which results in the generated code never using memoized values and always recomputing them. This is designed as a validation tool for the compiler's correctness--every program *should* behave exactly the same with this option enabled as it would with it disabled, and so any difference in behavior should be investigated as either a compiler bug or a pipeline issue. (We add `|| true` rather than dropping the conditional block entirely because we still want to exercise the guard tests, in case the guards themselves are the source of an error, like reading a property from undefined in a guard.) [ghstack-poisoned]
2 parents 94dd84d + 4328d55 commit a65fbef

File tree

2 files changed

+35
-6
lines changed

2 files changed

+35
-6
lines changed

.github/ISSUE_TEMPLATE/config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
blank_issues_enabled: false
12
contact_links:
23
- name: 📃 Documentation Issue
34
url: https://github.com/reactjs/react.dev/issues/new/choose

packages/react-client/src/ReactFlightClient.js

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ export type Response = {
254254
_rowLength: number, // remaining bytes in the row. 0 indicates that we're looking for a newline.
255255
_buffer: Array<Uint8Array>, // chunks received so far as part of this row
256256
_tempRefs: void | TemporaryReferenceSet, // the set temporary references can be resolved from
257+
_debugRootTask?: null | ConsoleTask, // DEV-only
257258
};
258259

259260
function readChunk<T>(chunk: SomeChunk<T>): T {
@@ -614,6 +615,7 @@ function getTaskName(type: mixed): string {
614615
}
615616

616617
function createElement(
618+
response: Response,
617619
type: mixed,
618620
key: mixed,
619621
props: mixed,
@@ -697,9 +699,15 @@ function createElement(
697699
const callStack = buildFakeCallStack(stack, createTaskFn);
698700
// This owner should ideally have already been initialized to avoid getting
699701
// user stack frames on the stack.
700-
const ownerTask = owner === null ? null : initializeFakeTask(owner);
702+
const ownerTask =
703+
owner === null ? null : initializeFakeTask(response, owner);
701704
if (ownerTask === null) {
702-
task = callStack();
705+
const rootTask = response._debugRootTask;
706+
if (rootTask != null) {
707+
task = rootTask.run(callStack);
708+
} else {
709+
task = callStack();
710+
}
703711
} else {
704712
task = ownerTask.run(callStack);
705713
}
@@ -1106,6 +1114,7 @@ function parseModelTuple(
11061114
// TODO: Consider having React just directly accept these arrays as elements.
11071115
// Or even change the ReactElement type to be an array.
11081116
return createElement(
1117+
response,
11091118
tuple[1],
11101119
tuple[2],
11111120
tuple[3],
@@ -1149,6 +1158,14 @@ export function createResponse(
11491158
_buffer: [],
11501159
_tempRefs: temporaryReferences,
11511160
};
1161+
if (supportsCreateTask) {
1162+
// Any stacks that appear on the server need to be rooted somehow on the client
1163+
// so we create a root Task for this response which will be the root owner for any
1164+
// elements created by the server. We use the "use server" string to indicate that
1165+
// this is where we enter the server from the client.
1166+
// TODO: Make this string configurable.
1167+
response._debugRootTask = (console: any).createTask('"use server"');
1168+
}
11521169
// Don't inline this call because it causes closure to outline the call above.
11531170
response._fromJSON = createFromJSONCallback(response);
11541171
return response;
@@ -1730,6 +1747,7 @@ function buildFakeCallStack<T>(stack: string, innerCall: () => T): () => T {
17301747
}
17311748

17321749
function initializeFakeTask(
1750+
response: Response,
17331751
debugInfo: ReactComponentInfo | ReactAsyncInfo,
17341752
): null | ConsoleTask {
17351753
if (taskCache === null || typeof debugInfo.stack !== 'string') {
@@ -1745,7 +1763,7 @@ function initializeFakeTask(
17451763
const ownerTask =
17461764
componentInfo.owner == null
17471765
? null
1748-
: initializeFakeTask(componentInfo.owner);
1766+
: initializeFakeTask(response, componentInfo.owner);
17491767

17501768
// eslint-disable-next-line react-internal/no-production-logging
17511769
const createTaskFn = (console: any).createTask.bind(
@@ -1755,7 +1773,12 @@ function initializeFakeTask(
17551773
const callStack = buildFakeCallStack(stack, createTaskFn);
17561774

17571775
if (ownerTask === null) {
1758-
return callStack();
1776+
const rootTask = response._debugRootTask;
1777+
if (rootTask != null) {
1778+
return rootTask.run(callStack);
1779+
} else {
1780+
return callStack();
1781+
}
17591782
} else {
17601783
return ownerTask.run(callStack);
17611784
}
@@ -1776,7 +1799,7 @@ function resolveDebugInfo(
17761799
// We eagerly initialize the fake task because this resolving happens outside any
17771800
// render phase so we're not inside a user space stack at this point. If we waited
17781801
// to initialize it when we need it, we might be inside user code.
1779-
initializeFakeTask(debugInfo);
1802+
initializeFakeTask(response, debugInfo);
17801803
const chunk = getChunk(response, id);
17811804
const chunkDebugInfo: ReactDebugInfo =
17821805
chunk._debugInfo || (chunk._debugInfo = []);
@@ -1813,12 +1836,17 @@ function resolveConsoleEntry(
18131836
printToConsole.bind(null, methodName, args, env),
18141837
);
18151838
if (owner != null) {
1816-
const task = initializeFakeTask(owner);
1839+
const task = initializeFakeTask(response, owner);
18171840
if (task !== null) {
18181841
task.run(callStack);
18191842
return;
18201843
}
18211844
}
1845+
const rootTask = response._debugRootTask;
1846+
if (rootTask != null) {
1847+
rootTask.run(callStack);
1848+
return;
1849+
}
18221850
callStack();
18231851
}
18241852

0 commit comments

Comments
 (0)