[Flight] Emit Infinite Promise as a Halted Row (#30746)
Stacked on #30731. When logging a Promise we emit it as an infinite promise instead of blocking the replay on it. This models that as a halted row instead. No need for this special case. I unflag the receiving side since now it's used to replace a feature that's already unflagged so it's used.
Sebastian Markbåge committed
Aug 19, 2024 at 15:02 UTC
52c9c43735d0d5ebb9cd5e2a47c174cb5a5a1713
3 files changed
+17
-15
packages/react-client/src/ReactFlightClient.js
+2
-9
@@ -46,7 +46,6 @@ import {
46
enableRefAsProp,
47
enableFlightReadableStream,
48
enableOwnerStacks,
49
- enableHalt,
49
} from 'shared/ReactFeatureFlags';
50
51
import {
@@ -1194,10 +1193,6 @@ function parseModelString(
1193
}
1194
case '@': {
1195
// Promise
1197
- if (value.length === 2) {
1198
- // Infinite promise that never resolves.
1199
- return new Promise(() => {});
1200
- }
1196
const id = parseInt(value.slice(2), 16);
1197
const chunk = getChunk(response, id);
1198
return chunk;
@@ -2638,10 +2633,8 @@ function processFullStringRow(
2633
}
2634
// Fallthrough
2635
case 35 /* "#" */: {
2641
- if (enableHalt) {
2642
- resolveBlocked(response, id);
2643
- return;
2644
- }
2636
+ resolveBlocked(response, id);
2637
+ return;
2638
}
2639
// Fallthrough
2640
default: /* """ "{" "[" "t" "f" "n" "0" - "9" */ {
packages/react-client/src/__tests__/ReactFlight-test.js
+11
-1
@@ -2952,8 +2952,14 @@ describe('ReactFlight', () => {
2952
function foo() {
2953
return 'hello';
2954
}
2955
+
2956
function ServerComponent() {
2956
- console.log('hi', {prop: 123, fn: foo, map: new Map([['foo', foo]])});
2957
+ console.log('hi', {
2958
+ prop: 123,
2959
+ fn: foo,
2960
+ map: new Map([['foo', foo]]),
2961
+ promise: new Promise(() => {}),
2962
+ });
2963
throw new Error('err');
2964
}
2965
@@ -3018,6 +3024,10 @@ describe('ReactFlight', () => {
3024
expect(loggedFn2).not.toBe(foo);
3025
expect(loggedFn2.toString()).toBe(foo.toString());
3026
3027
+ const promise = mockConsoleLog.mock.calls[0][1].promise;
3028
+ expect(promise).toBeInstanceOf(Promise);
3029
+ expect(promise.status).toBe('blocked');
3030
+
3031
expect(ownerStacks).toEqual(['\n in App (at **)']);
3032
});
3033
packages/react-server/src/ReactFlightServer.js
+4
-5
@@ -1817,10 +1817,6 @@ function serializeLazyID(id: number): string {
1817
return '$L' + id.toString(16);
1818
}
1819
1820
-function serializeInfinitePromise(): string {
1821
- return '$@';
1822
-}
1823
-
1820
function serializePromiseID(id: number): string {
1821
return '$@' + id.toString(16);
1822
}
@@ -3273,7 +3269,10 @@ function renderConsoleValue(
3269
}
3270
// If it hasn't already resolved (and been instrumented) we just encode an infinite
3271
// promise that will never resolve.
3276
- return serializeInfinitePromise();
3272
+ request.pendingChunks++;
3273
+ const blockedId = request.nextChunkId++;
3274
+ emitBlockedChunk(request, blockedId);
3275
+ return serializePromiseID(blockedId);
3276
}
3277
3278
if (existingReference !== undefined) {