@samitouri / QOS-React-1 / commits / bb402876f7

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

Sebastian "Sebbie" Silbermann committed Jul 7, 2025 at 13:51 UTC bb402876f7413ae2e6809ad442405a5a90c69b45
2 files changed +27 -6
packages/react-client/src/__tests__/ReactFlight-test.js
+7 -2
@@ -1309,6 +1309,8 @@ describe('ReactFlight', () => {
1309 // third-party RSC frame
1310 // Ideally this would be a real frame produced by React not a mocked one.
1311 ' at ThirdParty (rsc://React/ThirdParty/file:///code/%5Broot%2520of%2520the%2520server%5D.js?42:1:1)',
1312 + // We'll later filter this out based on line/column in `filterStackFrame`.
1313 + ' at ThirdPartyModule (file:///file-with-index-source-map.js:52656:16374)',
1314 // host component in parent stack
1315 ' at div (<anonymous>)',
1316 ...originalStackLines.slice(2),
@@ -1357,7 +1359,10 @@ describe('ReactFlight', () => {
1359 }
1360 return `digest(${String(x)})`;
1361 },
1360 - filterStackFrame(filename, functionName) {
1362 + filterStackFrame(filename, functionName, lineNumber, columnNumber) {
1363 + if (lineNumber === 52656 && columnNumber === 16374) {
1364 + return false;
1365 + }
1366 if (!filename) {
1367 // Allow anonymous
1368 return functionName === 'div';
@@ -3682,7 +3687,7 @@ describe('ReactFlight', () => {
3687 onError(x) {
3688 return `digest("${x.message}")`;
3689 },
3685 - filterStackFrame(url, functionName) {
3690 + filterStackFrame(url, functionName, lineNumber, columnNumber) {
3691 return functionName !== 'intermediate';
3692 },
3693 },
packages/react-server/src/ReactFlightServer.js
+20 -4
@@ -204,11 +204,13 @@ function findCalledFunctionNameFromStackTrace(
204 const callsite = stack[i];
205 const functionName = callsite[0];
206 const url = devirtualizeURL(callsite[1]);
207 + const lineNumber = callsite[2];
208 + const columnNumber = callsite[3];
209 if (functionName === 'new Promise') {
210 // Ignore Promise constructors.
211 } else if (url === 'node:internal/async_hooks') {
212 // Ignore the stack frames from the async hooks themselves.
211 - } else if (filterStackFrame(url, functionName)) {
213 + } else if (filterStackFrame(url, functionName, lineNumber, columnNumber)) {
214 if (bestMatch === '') {
215 // If we had no good stack frames for internal calls, just use the last
216 // first party function name.
@@ -236,7 +238,9 @@ function filterStackTrace(
238 const callsite = stack[i];
239 const functionName = callsite[0];
240 const url = devirtualizeURL(callsite[1]);
239 - if (filterStackFrame(url, functionName)) {
241 + const lineNumber = callsite[2];
242 + const columnNumber = callsite[3];
243 + if (filterStackFrame(url, functionName, lineNumber, columnNumber)) {
244 // Use a clone because the Flight protocol isn't yet resilient to deduping
245 // objects in the debug info. TODO: Support deduping stacks.
246 const clone: ReactCallSite = (callsite.slice(0): any);
@@ -466,7 +470,12 @@ export type Request = {
470 // DEV-only
471 completedDebugChunks: Array<Chunk | BinaryChunk>,
472 environmentName: () => string,
469 - filterStackFrame: (url: string, functionName: string) => boolean,
473 + filterStackFrame: (
474 + url: string,
475 + functionName: string,
476 + lineNumber: number,
477 + columnNumber: number,
478 + ) => boolean,
479 didWarnForKey: null | WeakSet<ReactComponentInfo>,
480 writtenDebugObjects: WeakMap<Reference, string>,
481 deferredDebugObjects: null | DeferredDebugStore,
@@ -2180,7 +2189,14 @@ function visitAsyncNode(
2189 const callsite = fullStack[firstFrame];
2190 const functionName = callsite[0];
2191 const url = devirtualizeURL(callsite[1]);
2183 - isAwaitInUserspace = filterStackFrame(url, functionName);
2192 + const lineNumber = callsite[2];
2193 + const columnNumber = callsite[3];
2194 + isAwaitInUserspace = filterStackFrame(
2195 + url,
2196 + functionName,
2197 + lineNumber,
2198 + columnNumber,
2199 + );
2200 }
2201 if (!isAwaitInUserspace) {
2202 // If this await was fully filtered out, then it was inside third party code