Skip to content

Commit 87178ee

Browse files
committed
[Flight] Schedule work in a microtask
Flight pings much more often than Fizz because async function components will always take at least a microtask to resolve . Rather than scheduling this work as a new macrotask Flight now schedules pings in a microtask. This allows more microta sks to ping before actually doing a work flush but doesn't force the vm to sping up a new task which is quite common give n the nature of Server Components
1 parent f55d172 commit 87178ee

12 files changed

+64
-2
lines changed

packages/react-dom-bindings/src/server/ReactDOMLegacyServerStreamConfig.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ export opaque type PrecomputedChunk = string;
1616
export opaque type Chunk = string;
1717
export opaque type BinaryChunk = string;
1818

19+
export function scheduleMicrotask(callback: () => void) {
20+
throw new Error(
21+
'Legacy React Server builds should not be using scheduleMicrotask. This is a bug in React.',
22+
);
23+
}
24+
1925
export function scheduleWork(callback: () => void) {
2026
callback();
2127
}

packages/react-noop-renderer/src/ReactNoopFlightServer.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ type Destination = Array<Uint8Array>;
2525
const textEncoder = new TextEncoder();
2626

2727
const ReactNoopFlightServer = ReactFlightServer({
28+
scheduleMicrotask(callback: () => void) {
29+
callback();
30+
},
2831
scheduleWork(callback: () => void) {
2932
callback();
3033
},

packages/react-noop-renderer/src/ReactNoopServer.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ function write(destination: Destination, buffer: Uint8Array): void {
7474
}
7575

7676
const ReactNoopServer = ReactFizzServer({
77+
scheduleMicrotask(callback: () => void) {
78+
callback();
79+
},
7780
scheduleWork(callback: () => void) {
7881
callback();
7982
},

packages/react-server/src/ReactFlightServer.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {enableFlightReadableStream} from 'shared/ReactFeatureFlags';
2626

2727
import {
2828
scheduleWork,
29+
scheduleMicrotask,
2930
flushBuffered,
3031
beginWriting,
3132
writeChunkAndReturn,
@@ -1517,7 +1518,7 @@ function pingTask(request: Request, task: Task): void {
15171518
pingedTasks.push(task);
15181519
if (pingedTasks.length === 1) {
15191520
request.flushScheduled = request.destination !== null;
1520-
scheduleWork(() => performWork(request));
1521+
scheduleMicrotask(() => performWork(request));
15211522
}
15221523
}
15231524

packages/react-server/src/ReactServerStreamConfigBrowser.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,19 @@ export type PrecomputedChunk = Uint8Array;
1313
export opaque type Chunk = Uint8Array;
1414
export type BinaryChunk = Uint8Array;
1515

16+
function handleErrorInNextTick(error: any) {
17+
setTimeout(() => {
18+
throw error;
19+
});
20+
}
21+
22+
export const scheduleMicrotask: (callback: () => void) => void =
23+
typeof queueMicrotask === 'function'
24+
? queueMicrotask
25+
: callback => {
26+
Promise.resolve(null).then(callback).catch(handleErrorInNextTick);
27+
};
28+
1629
export function scheduleWork(callback: () => void) {
1730
callback();
1831
}

packages/react-server/src/ReactServerStreamConfigBun.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ export type PrecomputedChunk = string;
2121
export opaque type Chunk = string;
2222
export type BinaryChunk = $ArrayBufferView;
2323

24+
export const scheduleMicrotask = queueMicrotask;
25+
2426
export function scheduleWork(callback: () => void) {
2527
callback();
2628
}

packages/react-server/src/ReactServerStreamConfigEdge.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,19 @@ export type PrecomputedChunk = Uint8Array;
1313
export opaque type Chunk = Uint8Array;
1414
export type BinaryChunk = Uint8Array;
1515

16+
function handleErrorInNextTick(error: any) {
17+
setTimeout(() => {
18+
throw error;
19+
});
20+
}
21+
22+
export const scheduleMicrotask: (callback: () => void) => void =
23+
typeof queueMicrotask === 'function'
24+
? queueMicrotask
25+
: callback => {
26+
Promise.resolve(null).then(callback).catch(handleErrorInNextTick);
27+
};
28+
1629
export function scheduleWork(callback: () => void) {
1730
setTimeout(callback, 0);
1831
}

packages/react-server/src/ReactServerStreamConfigNode.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ export type PrecomputedChunk = Uint8Array;
2222
export opaque type Chunk = string;
2323
export type BinaryChunk = Uint8Array;
2424

25+
export const scheduleMicrotask = queueMicrotask;
26+
2527
export function scheduleWork(callback: () => void) {
2628
setImmediate(callback);
2729
}

packages/react-server/src/forks/ReactServerStreamConfig.custom.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export opaque type PrecomputedChunk = mixed; // eslint-disable-line no-undef
3030
export opaque type Chunk = mixed; // eslint-disable-line no-undef
3131
export opaque type BinaryChunk = mixed; // eslint-disable-line no-undef
3232

33+
export const scheduleMicrotask = $$$config.scheduleMicrotask;
3334
export const scheduleWork = $$$config.scheduleWork;
3435
export const beginWriting = $$$config.beginWriting;
3536
export const writeChunk = $$$config.writeChunk;

packages/react-server/src/forks/ReactServerStreamConfig.dom-fb-experimental.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,19 @@ export interface Destination {
4242
onError(error: mixed): void;
4343
}
4444

45+
function handleErrorInNextTick(error: any) {
46+
setTimeout(() => {
47+
throw error;
48+
});
49+
}
50+
51+
export const scheduleMicrotask: (callback: () => void) => void =
52+
typeof queueMicrotask === 'function'
53+
? queueMicrotask
54+
: callback => {
55+
Promise.resolve(null).then(callback).catch(handleErrorInNextTick);
56+
};
57+
4558
export function scheduleWork(callback: () => void) {
4659
callback();
4760
}

0 commit comments

Comments
 (0)