[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.
This commit is contained in:
Sebastian Markbåge 2025-05-07 13:02:41 -04:00 committed by GitHub
parent 4206fe4982
commit a437c99ff7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 23 additions and 10 deletions

View File

@ -15,7 +15,7 @@ import type {
ReactAsyncInfo, ReactAsyncInfo,
ReactTimeInfo, ReactTimeInfo,
ReactStackTrace, ReactStackTrace,
ReactCallSite, ReactFunctionLocation,
ReactErrorInfoDev, ReactErrorInfoDev,
} from 'shared/ReactTypes'; } from 'shared/ReactTypes';
import type {LazyComponent} from 'react/src/ReactLazy'; import type {LazyComponent} from 'react/src/ReactLazy';
@ -1074,7 +1074,7 @@ function loadServerReference<A: Iterable<any>, T>(
bound: null | Thenable<Array<any>>, bound: null | Thenable<Array<any>>,
name?: string, // DEV-only name?: string, // DEV-only
env?: string, // DEV-only env?: string, // DEV-only
location?: ReactCallSite, // DEV-only location?: ReactFunctionLocation, // DEV-only
}, },
parentObject: Object, parentObject: Object,
key: string, key: string,

View File

@ -13,7 +13,7 @@ import type {
FulfilledThenable, FulfilledThenable,
RejectedThenable, RejectedThenable,
ReactCustomFormAction, ReactCustomFormAction,
ReactCallSite, ReactFunctionLocation,
} from 'shared/ReactTypes'; } from 'shared/ReactTypes';
import type {LazyComponent} from 'react/src/ReactLazy'; import type {LazyComponent} from 'react/src/ReactLazy';
import type {TemporaryReferenceSet} from './ReactFlightTemporaryReferences'; import type {TemporaryReferenceSet} from './ReactFlightTemporaryReferences';
@ -1248,7 +1248,7 @@ export function createBoundServerReference<A: Iterable<any>, T>(
bound: null | Thenable<Array<any>>, bound: null | Thenable<Array<any>>,
name?: string, // DEV-only name?: string, // DEV-only
env?: string, // DEV-only env?: string, // DEV-only
location?: ReactCallSite, // DEV-only location?: ReactFunctionLocation, // DEV-only
}, },
callServer: CallServerCallback, callServer: CallServerCallback,
encodeFormAction?: EncodeFormActionCallback, encodeFormAction?: EncodeFormActionCallback,
@ -1309,7 +1309,7 @@ const v8FrameRegExp =
// filename:0:0 // filename:0:0
const jscSpiderMonkeyFrameRegExp = /(?:(.*)@)?(.*):(\d+):(\d+)/; const jscSpiderMonkeyFrameRegExp = /(?:(.*)@)?(.*):(\d+):(\d+)/;
function parseStackLocation(error: Error): null | ReactCallSite { function parseStackLocation(error: Error): null | ReactFunctionLocation {
// This parsing is special in that we know that the calling function will always // This parsing is special in that we know that the calling function will always
// be a module that initializes the server action. We also need this part to work // be a module that initializes the server action. We also need this part to work
// cross-browser so not worth a Config. It's DEV only so not super code size // 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 {
const line = +(parsed[3] || parsed[6]); const line = +(parsed[3] || parsed[6]);
const col = +(parsed[4] || parsed[7]); const col = +(parsed[4] || parsed[7]);
return [name, filename, line, col, line, col]; return [name, filename, line, col];
} }
export function createServerReference<A: Iterable<any>, T>( export function createServerReference<A: Iterable<any>, T>(

View File

@ -62,7 +62,7 @@ import type {
ReactAsyncInfo, ReactAsyncInfo,
ReactTimeInfo, ReactTimeInfo,
ReactStackTrace, ReactStackTrace,
ReactCallSite, ReactFunctionLocation,
ReactErrorInfo, ReactErrorInfo,
ReactErrorInfoDev, ReactErrorInfoDev,
} from 'shared/ReactTypes'; } from 'shared/ReactTypes';
@ -2089,7 +2089,7 @@ function serializeServerReference(
const bound = boundArgs === null ? null : Promise.resolve(boundArgs); const bound = boundArgs === null ? null : Promise.resolve(boundArgs);
const id = getServerReferenceId(request.bundlerConfig, serverReference); const id = getServerReferenceId(request.bundlerConfig, serverReference);
let location: null | ReactCallSite = null; let location: null | ReactFunctionLocation = null;
if (__DEV__) { if (__DEV__) {
const error = getServerReferenceLocation( const error = getServerReferenceLocation(
request.bundlerConfig, request.bundlerConfig,
@ -2098,7 +2098,13 @@ function serializeServerReference(
if (error) { if (error) {
const frames = parseStackTrace(error, 1); const frames = parseStackTrace(error, 1);
if (frames.length > 0) { if (frames.length > 0) {
location = frames[0]; const firstFrame = frames[0];
location = [
firstFrame[0],
firstFrame[1],
firstFrame[2], // The line and col of the callsite represents the
firstFrame[3], // enclosing line and col of the function.
];
} }
} }
} }
@ -2108,7 +2114,7 @@ function serializeServerReference(
bound: null | Promise<Array<any>>, bound: null | Promise<Array<any>>,
name?: string, // DEV-only name?: string, // DEV-only
env?: string, // DEV-only env?: string, // DEV-only
location?: ReactCallSite, // DEV-only location?: ReactFunctionLocation, // DEV-only
} = } =
__DEV__ && location !== null __DEV__ && location !== null
? { ? {

View File

@ -192,6 +192,13 @@ export type ReactCallSite = [
export type ReactStackTrace = Array<ReactCallSite>; export type ReactStackTrace = Array<ReactCallSite>;
export type ReactFunctionLocation = [
string, // function name
string, // file name TODO: model nested eval locations as nested arrays
number, // enclosing line number
number, // enclosing column number
];
export type ReactComponentInfo = { export type ReactComponentInfo = {
+name: string, +name: string,
+env?: string, +env?: string,