[Flight] Allow passing DEV only startTime as an option (#34912)
When you use the `createFromFetch` API we assume that the start time of the request is the same time as when you call `createFromFetch` but in principle you could use it with a Promise that starts earlier and just happens to resolve to a `Response`. When you use `createFromReadableStream` that is almost definitely the case. E.g. you might have started it way earlier and you don't call `createFromReadableStream` until you get the headers back (the fetch promise resolves). This adds an option to pass in the start time for debug purposes if you started the request before starting to parse it.
Sebastian Markbåge committed
Oct 19, 2025 at 13:38 UTC
2cfb221937eac48209d01d5dda5664de473b1953
13 files changed
+52
-1
packages/react-client/src/ReactFlightClient.js
+5
-1
@@ -2561,6 +2561,7 @@ function ResponseInstance(
2561
findSourceMapURL: void | FindSourceMapURLCallback, // DEV-only
2562
replayConsole: boolean, // DEV-only
2563
environmentName: void | string, // DEV-only
2564
+ debugStartTime: void | number, // DEV-only
2565
debugChannel: void | DebugChannel, // DEV-only
2566
) {
2567
const chunks: Map<number, SomeChunk<any>> = new Map();
@@ -2621,7 +2622,8 @@ function ResponseInstance(
2622
// Note: createFromFetch allows this to be marked at the start of the fetch
2623
// where as if you use createFromReadableStream from the body of the fetch
2624
// then the start time is when the headers resolved.
2624
- this._debugStartTime = performance.now();
2625
+ this._debugStartTime =
2626
+ debugStartTime == null ? performance.now() : debugStartTime;
2627
this._debugIOStarted = false;
2628
// We consider everything before the first setTimeout task to be cached data
2629
// and is not considered I/O required to load the stream.
@@ -2669,6 +2671,7 @@ export function createResponse(
2671
findSourceMapURL: void | FindSourceMapURLCallback, // DEV-only
2672
replayConsole: boolean, // DEV-only
2673
environmentName: void | string, // DEV-only
2674
+ debugStartTime: void | number, // DEV-only
2675
debugChannel: void | DebugChannel, // DEV-only
2676
): WeakResponse {
2677
return getWeakResponse(
@@ -2684,6 +2687,7 @@ export function createResponse(
2687
findSourceMapURL,
2688
replayConsole,
2689
environmentName,
2690
+ debugStartTime,
2691
debugChannel,
2692
),
2693
);
packages/react-markup/src/ReactMarkupServer.js
+3
@@ -91,6 +91,9 @@ export function experimental_renderToHTML(
91
undefined,
92
undefined,
93
false,
94
+ undefined,
95
+ undefined,
96
+ undefined,
97
);
98
const streamState = createFlightStreamState(flightResponse, null);
99
const flightDestination = {
packages/react-server-dom-esm/src/client/ReactFlightDOMClientBrowser.js
+4
@@ -52,6 +52,7 @@ export type Options = {
52
findSourceMapURL?: FindSourceMapURLCallback,
53
replayConsoleLogs?: boolean,
54
environmentName?: string,
55
+ startTime?: number,
56
};
57
58
function createDebugCallbackFromWritableStream(
@@ -103,6 +104,9 @@ function createResponseFromOptions(options: void | Options) {
104
__DEV__ && options && options.environmentName
105
? options.environmentName
106
: undefined,
107
+ __DEV__ && options && options.startTime != null
108
+ ? options.startTime
109
+ : undefined,
110
debugChannel,
111
);
112
}
packages/react-server-dom-esm/src/client/ReactFlightDOMClientNode.js
+4
@@ -57,6 +57,7 @@ export type Options = {
57
findSourceMapURL?: FindSourceMapURLCallback,
58
replayConsoleLogs?: boolean,
59
environmentName?: string,
60
+ startTime?: number,
61
// For the Node.js client we only support a single-direction debug channel.
62
debugChannel?: Readable,
63
};
@@ -112,6 +113,9 @@ function createFromNodeStream<T>(
113
__DEV__ && options && options.environmentName
114
? options.environmentName
115
: undefined,
116
+ __DEV__ && options && options.startTime != null
117
+ ? options.startTime
118
+ : undefined,
119
debugChannel,
120
);
121
packages/react-server-dom-parcel/src/client/ReactFlightDOMClientBrowser.js
+4
@@ -129,6 +129,9 @@ function createResponseFromOptions(options: void | Options) {
129
__DEV__ && options && options.environmentName
130
? options.environmentName
131
: undefined,
132
+ __DEV__ && options && options.startTime != null
133
+ ? options.startTime
134
+ : undefined,
135
debugChannel,
136
);
137
}
@@ -205,6 +208,7 @@ export type Options = {
208
temporaryReferences?: TemporaryReferenceSet,
209
replayConsoleLogs?: boolean,
210
environmentName?: string,
211
+ startTime?: number,
212
};
213
214
export function createFromReadableStream<T>(
packages/react-server-dom-parcel/src/client/ReactFlightDOMClientEdge.js
+4
@@ -79,6 +79,7 @@ export type Options = {
79
temporaryReferences?: TemporaryReferenceSet,
80
replayConsoleLogs?: boolean,
81
environmentName?: string,
82
+ startTime?: number,
83
// For the Edge client we only support a single-direction debug channel.
84
debugChannel?: {readable?: ReadableStream, ...},
85
};
@@ -107,6 +108,9 @@ function createResponseFromOptions(options?: Options) {
108
__DEV__ && options && options.environmentName
109
? options.environmentName
110
: undefined,
111
+ __DEV__ && options && options.startTime != null
112
+ ? options.startTime
113
+ : undefined,
114
debugChannel,
115
);
116
}
packages/react-server-dom-parcel/src/client/ReactFlightDOMClientNode.js
+4
@@ -52,6 +52,7 @@ export type Options = {
52
encodeFormAction?: EncodeFormActionCallback,
53
replayConsoleLogs?: boolean,
54
environmentName?: string,
55
+ startTime?: number,
56
// For the Node.js client we only support a single-direction debug channel.
57
debugChannel?: Readable,
58
};
@@ -103,6 +104,9 @@ export function createFromNodeStream<T>(
104
__DEV__ && options && options.environmentName
105
? options.environmentName
106
: undefined,
107
+ __DEV__ && options && options.startTime != null
108
+ ? options.startTime
109
+ : undefined,
110
debugChannel,
111
);
112
packages/react-server-dom-turbopack/src/client/ReactFlightDOMClientBrowser.js
+4
@@ -51,6 +51,7 @@ export type Options = {
51
findSourceMapURL?: FindSourceMapURLCallback,
52
replayConsoleLogs?: boolean,
53
environmentName?: string,
54
+ startTime?: number,
55
};
56
57
function createDebugCallbackFromWritableStream(
@@ -102,6 +103,9 @@ function createResponseFromOptions(options: void | Options) {
103
__DEV__ && options && options.environmentName
104
? options.environmentName
105
: undefined,
106
+ __DEV__ && options && options.startTime != null
107
+ ? options.startTime
108
+ : undefined,
109
debugChannel,
110
);
111
}
packages/react-server-dom-turbopack/src/client/ReactFlightDOMClientEdge.js
+4
@@ -79,6 +79,7 @@ export type Options = {
79
findSourceMapURL?: FindSourceMapURLCallback,
80
replayConsoleLogs?: boolean,
81
environmentName?: string,
82
+ startTime?: number,
83
// For the Edge client we only support a single-direction debug channel.
84
debugChannel?: {readable?: ReadableStream, ...},
85
};
@@ -109,6 +110,9 @@ function createResponseFromOptions(options: Options) {
110
__DEV__ && options && options.environmentName
111
? options.environmentName
112
: undefined,
113
+ __DEV__ && options && options.startTime != null
114
+ ? options.startTime
115
+ : undefined,
116
debugChannel,
117
);
118
}
packages/react-server-dom-turbopack/src/client/ReactFlightDOMClientNode.js
+4
@@ -60,6 +60,7 @@ export type Options = {
60
findSourceMapURL?: FindSourceMapURLCallback,
61
replayConsoleLogs?: boolean,
62
environmentName?: string,
63
+ startTime?: number,
64
// For the Node.js client we only support a single-direction debug channel.
65
debugChannel?: Readable,
66
};
@@ -114,6 +115,9 @@ function createFromNodeStream<T>(
115
__DEV__ && options && options.environmentName
116
? options.environmentName
117
: undefined,
118
+ __DEV__ && options && options.startTime != null
119
+ ? options.startTime
120
+ : undefined,
121
debugChannel,
122
);
123
packages/react-server-dom-webpack/src/client/ReactFlightDOMClientBrowser.js
+4
@@ -51,6 +51,7 @@ export type Options = {
51
findSourceMapURL?: FindSourceMapURLCallback,
52
replayConsoleLogs?: boolean,
53
environmentName?: string,
54
+ startTime?: number,
55
};
56
57
function createDebugCallbackFromWritableStream(
@@ -102,6 +103,9 @@ function createResponseFromOptions(options: void | Options) {
103
__DEV__ && options && options.environmentName
104
? options.environmentName
105
: undefined,
106
+ __DEV__ && options && options.startTime != null
107
+ ? options.startTime
108
+ : undefined,
109
debugChannel,
110
);
111
}
packages/react-server-dom-webpack/src/client/ReactFlightDOMClientEdge.js
+4
@@ -79,6 +79,7 @@ export type Options = {
79
findSourceMapURL?: FindSourceMapURLCallback,
80
replayConsoleLogs?: boolean,
81
environmentName?: string,
82
+ startTime?: number,
83
// For the Edge client we only support a single-direction debug channel.
84
debugChannel?: {readable?: ReadableStream, ...},
85
};
@@ -109,6 +110,9 @@ function createResponseFromOptions(options: Options) {
110
__DEV__ && options && options.environmentName
111
? options.environmentName
112
: undefined,
113
+ __DEV__ && options && options.startTime != null
114
+ ? options.startTime
115
+ : undefined,
116
debugChannel,
117
);
118
}
packages/react-server-dom-webpack/src/client/ReactFlightDOMClientNode.js
+4
@@ -60,6 +60,7 @@ export type Options = {
60
findSourceMapURL?: FindSourceMapURLCallback,
61
replayConsoleLogs?: boolean,
62
environmentName?: string,
63
+ startTime?: number,
64
// For the Node.js client we only support a single-direction debug channel.
65
debugChannel?: Readable,
66
};
@@ -114,6 +115,9 @@ function createFromNodeStream<T>(
115
__DEV__ && options && options.environmentName
116
? options.environmentName
117
: undefined,
118
+ __DEV__ && options && options.startTime != null
119
+ ? options.startTime
120
+ : undefined,
121
debugChannel,
122
);
123