@samitouri / QOS-React / commits / 52c9c43735

[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) {