@samitouri / QOS-React / commits / a437c99ff7

[Flight] Clarify that location field is a FunctionLocation not a CallSite (#33141)

Follow up to #33136. This clarifies in the types where the conversion happens from a CallSite which we use to simulate getting the enclosing line/col to a FunctionLocation which doesn't represent a CallSite but actually just the function which only has an enclosing line/col.

Sebastian Markbåge committed May 7, 2025 at 13:02 UTC a437c99ff7a45025367571363653c2ad5db482a7
4 files changed +23 -10
packages/react-client/src/ReactFlightClient.js
+2 -2
@@ -15,7 +15,7 @@ import type {
15 ReactAsyncInfo,
16 ReactTimeInfo,
17 ReactStackTrace,
18 - ReactCallSite,
18 + ReactFunctionLocation,
19 ReactErrorInfoDev,
20 } from 'shared/ReactTypes';
21 import type {LazyComponent} from 'react/src/ReactLazy';
@@ -1074,7 +1074,7 @@ function loadServerReference<A: Iterable<any>, T>(
1074 bound: null | Thenable<Array<any>>,
1075 name?: string, // DEV-only
1076 env?: string, // DEV-only
1077 - location?: ReactCallSite, // DEV-only
1077 + location?: ReactFunctionLocation, // DEV-only
1078 },
1079 parentObject: Object,
1080 key: string,
packages/react-client/src/ReactFlightReplyClient.js
+4 -4
@@ -13,7 +13,7 @@ import type {
13 FulfilledThenable,
14 RejectedThenable,
15 ReactCustomFormAction,
16 - ReactCallSite,
16 + ReactFunctionLocation,
17 } from 'shared/ReactTypes';
18 import type {LazyComponent} from 'react/src/ReactLazy';
19 import type {TemporaryReferenceSet} from './ReactFlightTemporaryReferences';
@@ -1248,7 +1248,7 @@ export function createBoundServerReference<A: Iterable<any>, T>(
1248 bound: null | Thenable<Array<any>>,
1249 name?: string, // DEV-only
1250 env?: string, // DEV-only
1251 - location?: ReactCallSite, // DEV-only
1251 + location?: ReactFunctionLocation, // DEV-only
1252 },
1253 callServer: CallServerCallback,
1254 encodeFormAction?: EncodeFormActionCallback,
@@ -1309,7 +1309,7 @@ const v8FrameRegExp =
1309 // filename:0:0
1310 const jscSpiderMonkeyFrameRegExp = /(?:(.*)@)?(.*):(\d+):(\d+)/;
1311
1312 -function parseStackLocation(error: Error): null | ReactCallSite {
1312 +function parseStackLocation(error: Error): null | ReactFunctionLocation {
1313 // This parsing is special in that we know that the calling function will always
1314 // be a module that initializes the server action. We also need this part to work
1315 // cross-browser so not worth a Config. It's DEV only so not super code size
@@ -1354,7 +1354,7 @@ function parseStackLocation(error: Error): null | ReactCallSite {
1354 const line = +(parsed[3] || parsed[6]);
1355 const col = +(parsed[4] || parsed[7]);
1356
1357 - return [name, filename, line, col, line, col];
1357 + return [name, filename, line, col];
1358 }
1359
1360 export function createServerReference<A: Iterable<any>, T>(
packages/react-server/src/ReactFlightServer.js
+10 -4
@@ -62,7 +62,7 @@ import type {
62 ReactAsyncInfo,
63 ReactTimeInfo,
64 ReactStackTrace,
65 - ReactCallSite,
65 + ReactFunctionLocation,
66 ReactErrorInfo,
67 ReactErrorInfoDev,
68 } from 'shared/ReactTypes';
@@ -2089,7 +2089,7 @@ function serializeServerReference(
2089 const bound = boundArgs === null ? null : Promise.resolve(boundArgs);
2090 const id = getServerReferenceId(request.bundlerConfig, serverReference);
2091
2092 - let location: null | ReactCallSite = null;
2092 + let location: null | ReactFunctionLocation = null;
2093 if (__DEV__) {
2094 const error = getServerReferenceLocation(
2095 request.bundlerConfig,
@@ -2098,7 +2098,13 @@ function serializeServerReference(
2098 if (error) {
2099 const frames = parseStackTrace(error, 1);
2100 if (frames.length > 0) {
2101 - location = frames[0];
2101 + const firstFrame = frames[0];
2102 + location = [
2103 + firstFrame[0],
2104 + firstFrame[1],
2105 + firstFrame[2], // The line and col of the callsite represents the
2106 + firstFrame[3], // enclosing line and col of the function.
2107 + ];
2108 }
2109 }
2110 }
@@ -2108,7 +2114,7 @@ function serializeServerReference(
2114 bound: null | Promise<Array<any>>,
2115 name?: string, // DEV-only
2116 env?: string, // DEV-only
2111 - location?: ReactCallSite, // DEV-only
2117 + location?: ReactFunctionLocation, // DEV-only
2118 } =
2119 __DEV__ && location !== null
2120 ? {
packages/shared/ReactTypes.js
+7
@@ -192,6 +192,13 @@ export type ReactCallSite = [
192
193 export type ReactStackTrace = Array<ReactCallSite>;
194
195 +export type ReactFunctionLocation = [
196 + string, // function name
197 + string, // file name TODO: model nested eval locations as nested arrays
198 + number, // enclosing line number
199 + number, // enclosing column number
200 +];
201 +
202 export type ReactComponentInfo = {
203 +name: string,
204 +env?: string,