Skip to content

Commit 6025126

Browse files
sebmarkbageunstubbable
authored andcommitted
Block on debug info to resolve before resolving a chunk
1 parent 667696f commit 6025126

File tree

1 file changed

+74
-45
lines changed

1 file changed

+74
-45
lines changed

packages/react-client/src/ReactFlightClient.js

Lines changed: 74 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,17 @@ function initializeModelChunk<T>(chunk: ResolvedModelChunk<T>): void {
722722
initializingChunk = cyclicChunk;
723723
}
724724

725+
if (__DEV__) {
726+
const blockingDebugChunk = chunk._blockedDebugInfo;
727+
if (
728+
blockingDebugChunk != null &&
729+
(blockingDebugChunk.status === BLOCKED ||
730+
blockingDebugChunk.status === PENDING)
731+
) {
732+
waitForReference(blockingDebugChunk, {}, '', response, () => {}, ['']);
733+
}
734+
}
735+
725736
try {
726737
const value: T = parseModel(response, resolvedModel);
727738
// Invoke any listeners added while resolving this model. I.e. cyclic
@@ -2239,6 +2250,22 @@ function resolveStream<T: ReadableStream | $AsyncIterable<any, any, void>>(
22392250
chunks.set(id, createInitializedStreamChunk(response, stream, controller));
22402251
return;
22412252
}
2253+
if (__DEV__) {
2254+
const blockedDebugInfo = chunk._blockedDebugInfo;
2255+
if (blockedDebugInfo != null) {
2256+
// If we're blocked on debug info, wait until it has loaded before we resolve.
2257+
const unblock = resolveStream.bind(
2258+
null,
2259+
response,
2260+
id,
2261+
stream,
2262+
controller,
2263+
);
2264+
blockedDebugInfo.then(unblock, unblock);
2265+
return;
2266+
}
2267+
}
2268+
22422269
if (chunk.status !== PENDING) {
22432270
// We already resolved. We didn't expect to see this.
22442271
return;
@@ -2622,6 +2649,41 @@ function resolvePostponeDev(
26222649
}
26232650
}
26242651

2652+
function resolveErrorModel(
2653+
response: Response,
2654+
id: number,
2655+
row: UninitializedModel,
2656+
): void {
2657+
const chunks = response._chunks;
2658+
const chunk = chunks.get(id);
2659+
if (__DEV__ && chunk) {
2660+
if (__DEV__) {
2661+
const blockedDebugInfo = chunk._blockedDebugInfo;
2662+
if (blockedDebugInfo != null) {
2663+
// If we're blocked on debug info, wait until it has loaded before we resolve.
2664+
// TODO: Handle cycle if that model depends on this one.
2665+
const unblock = resolveErrorModel.bind(null, response, id, row);
2666+
blockedDebugInfo.then(unblock, unblock);
2667+
return;
2668+
}
2669+
}
2670+
}
2671+
const errorInfo = JSON.parse(row);
2672+
let error;
2673+
if (__DEV__) {
2674+
error = resolveErrorDev(response, errorInfo);
2675+
} else {
2676+
error = resolveErrorProd(response);
2677+
}
2678+
(error: any).digest = errorInfo.digest;
2679+
const errorWithDigest: ErrorWithDigest = (error: any);
2680+
if (!chunk) {
2681+
chunks.set(id, createErrorChunk(response, errorWithDigest));
2682+
} else {
2683+
triggerErrorOnChunk(chunk, errorWithDigest);
2684+
}
2685+
}
2686+
26252687
function resolveHint<Code: HintCode>(
26262688
response: Response,
26272689
code: Code,
@@ -3081,43 +3143,25 @@ function resolveDebugModel(
30813143
json: UninitializedModel,
30823144
): void {
30833145
const parentChunk = getChunk(response, id);
3084-
const blockedChunk = parentChunk._blockedDebugInfo;
3085-
if (blockedChunk == null) {
3086-
// If we're not blocked on any other chunks, we can try to eagerly initialize
3087-
// this as a fast-path to avoid awaiting them.
3088-
const chunk: ResolvedModelChunk<ReactDebugInfoEntry> =
3089-
createResolvedModelChunk(response, json);
3090-
initializeModelChunk(chunk);
3091-
const initializedChunk: SomeChunk<ReactDebugInfoEntry> = chunk;
3092-
if (initializedChunk.status === INITIALIZED) {
3093-
resolveDebugInfo(response, parentChunk, initializedChunk.value);
3094-
} else {
3095-
chunk.then(
3096-
v => resolveDebugInfo(response, parentChunk, v),
3097-
e => {
3098-
// Ignore debug info errors for now. Unnecessary noise.
3099-
},
3100-
);
3101-
parentChunk._blockedDebugInfo = chunk;
3102-
}
3146+
// If we're not blocked on any other chunks, we can try to eagerly initialize
3147+
// this as a fast-path to avoid awaiting them.
3148+
const chunk: ResolvedModelChunk<ReactDebugInfoEntry> =
3149+
createResolvedModelChunk(response, json);
3150+
// The previous blocked chunk is now blocking this one.
3151+
chunk._blockedDebugInfo = parentChunk._blockedDebugInfo;
3152+
initializeModelChunk(chunk);
3153+
const initializedChunk: SomeChunk<ReactDebugInfoEntry> = chunk;
3154+
if (initializedChunk.status === INITIALIZED) {
3155+
resolveDebugInfo(response, parentChunk, initializedChunk.value);
3156+
parentChunk._blockedDebugInfo = null;
31033157
} else {
3104-
// We're still waiting on a previous chunk so we can't enqueue quite yet.
3105-
const chunk: SomeChunk<ReactDebugInfoEntry> = createPendingChunk(response);
31063158
chunk.then(
31073159
v => resolveDebugInfo(response, parentChunk, v),
31083160
e => {
31093161
// Ignore debug info errors for now. Unnecessary noise.
31103162
},
31113163
);
31123164
parentChunk._blockedDebugInfo = chunk;
3113-
blockedChunk.then(function () {
3114-
if (parentChunk._blockedDebugInfo === chunk) {
3115-
// We were still the last chunk so we can now clear the queue and return
3116-
// to synchronous emitting.
3117-
parentChunk._blockedDebugInfo = null;
3118-
}
3119-
resolveModelChunk(response, chunk, json);
3120-
});
31213165
}
31223166
}
31233167

@@ -3753,22 +3797,7 @@ function processFullStringRow(
37533797
return;
37543798
}
37553799
case 69 /* "E" */: {
3756-
const errorInfo = JSON.parse(row);
3757-
let error;
3758-
if (__DEV__) {
3759-
error = resolveErrorDev(response, errorInfo);
3760-
} else {
3761-
error = resolveErrorProd(response);
3762-
}
3763-
(error: any).digest = errorInfo.digest;
3764-
const errorWithDigest: ErrorWithDigest = (error: any);
3765-
const chunks = response._chunks;
3766-
const chunk = chunks.get(id);
3767-
if (!chunk) {
3768-
chunks.set(id, createErrorChunk(response, errorWithDigest));
3769-
} else {
3770-
triggerErrorOnChunk(chunk, errorWithDigest);
3771-
}
3800+
resolveErrorModel(response, id, row);
37723801
return;
37733802
}
37743803
case 84 /* "T" */: {

0 commit comments

Comments
 (0)