[Flight] Pass line/column to filterStackFrame (#33707)

This commit is contained in:
Sebastian "Sebbie" Silbermann 2025-07-07 13:51:53 +02:00 committed by GitHub
parent 9a645e1d10
commit bb402876f7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 27 additions and 6 deletions

View File

@ -1309,6 +1309,8 @@ describe('ReactFlight', () => {
// third-party RSC frame
// Ideally this would be a real frame produced by React not a mocked one.
' at ThirdParty (rsc://React/ThirdParty/file:///code/%5Broot%2520of%2520the%2520server%5D.js?42:1:1)',
// We'll later filter this out based on line/column in `filterStackFrame`.
' at ThirdPartyModule (file:///file-with-index-source-map.js:52656:16374)',
// host component in parent stack
' at div (<anonymous>)',
...originalStackLines.slice(2),
@ -1357,7 +1359,10 @@ describe('ReactFlight', () => {
}
return `digest(${String(x)})`;
},
filterStackFrame(filename, functionName) {
filterStackFrame(filename, functionName, lineNumber, columnNumber) {
if (lineNumber === 52656 && columnNumber === 16374) {
return false;
}
if (!filename) {
// Allow anonymous
return functionName === 'div';
@ -3682,7 +3687,7 @@ describe('ReactFlight', () => {
onError(x) {
return `digest("${x.message}")`;
},
filterStackFrame(url, functionName) {
filterStackFrame(url, functionName, lineNumber, columnNumber) {
return functionName !== 'intermediate';
},
},

View File

@ -204,11 +204,13 @@ function findCalledFunctionNameFromStackTrace(
const callsite = stack[i];
const functionName = callsite[0];
const url = devirtualizeURL(callsite[1]);
const lineNumber = callsite[2];
const columnNumber = callsite[3];
if (functionName === 'new Promise') {
// Ignore Promise constructors.
} else if (url === 'node:internal/async_hooks') {
// Ignore the stack frames from the async hooks themselves.
} else if (filterStackFrame(url, functionName)) {
} else if (filterStackFrame(url, functionName, lineNumber, columnNumber)) {
if (bestMatch === '') {
// If we had no good stack frames for internal calls, just use the last
// first party function name.
@ -236,7 +238,9 @@ function filterStackTrace(
const callsite = stack[i];
const functionName = callsite[0];
const url = devirtualizeURL(callsite[1]);
if (filterStackFrame(url, functionName)) {
const lineNumber = callsite[2];
const columnNumber = callsite[3];
if (filterStackFrame(url, functionName, lineNumber, columnNumber)) {
// Use a clone because the Flight protocol isn't yet resilient to deduping
// objects in the debug info. TODO: Support deduping stacks.
const clone: ReactCallSite = (callsite.slice(0): any);
@ -466,7 +470,12 @@ export type Request = {
// DEV-only
completedDebugChunks: Array<Chunk | BinaryChunk>,
environmentName: () => string,
filterStackFrame: (url: string, functionName: string) => boolean,
filterStackFrame: (
url: string,
functionName: string,
lineNumber: number,
columnNumber: number,
) => boolean,
didWarnForKey: null | WeakSet<ReactComponentInfo>,
writtenDebugObjects: WeakMap<Reference, string>,
deferredDebugObjects: null | DeferredDebugStore,
@ -2180,7 +2189,14 @@ function visitAsyncNode(
const callsite = fullStack[firstFrame];
const functionName = callsite[0];
const url = devirtualizeURL(callsite[1]);
isAwaitInUserspace = filterStackFrame(url, functionName);
const lineNumber = callsite[2];
const columnNumber = callsite[3];
isAwaitInUserspace = filterStackFrame(
url,
functionName,
lineNumber,
columnNumber,
);
}
if (!isAwaitInUserspace) {
// If this await was fully filtered out, then it was inside third party code