[Flight] Consistent format of virtual `rsc:` sources (#33706)
Sebastian "Sebbie" Silbermann committed
Jul 6, 2025 at 09:45 UTC
4aad5e45bafe213cf2993614633d5f8d22d5d793
3 files changed
+10
-4
packages/react-client/src/ReactFlightReplyClient.js
+1
-1
@@ -1106,7 +1106,7 @@ function createFakeServerFunction<A: Iterable<any>, T>(
1106
'\n//# sourceURL=rsc://React/' +
1107
encodeURIComponent(environmentName) +
1108
'/' +
1109
- filename +
1109
+ encodeURI(filename) +
1110
'?s' + // We add an extra s here to distinguish from the fake stack frames
1111
fakeServerFunctionIdx++;
1112
code += '\n//# sourceMappingURL=' + sourceMap;
packages/react-client/src/__tests__/ReactFlight-test.js
+7
-1
@@ -1306,6 +1306,9 @@ describe('ReactFlight', () => {
1306
' at file:///testing.js:42:3',
1307
// async anon function (https://github.com/ChromeDevTools/devtools-frontend/blob/831be28facb4e85de5ee8c1acc4d98dfeda7a73b/test/unittests/front_end/panels/console/ErrorStackParser_test.ts#L130C9-L130C41)
1308
' at async file:///testing.js:42:3',
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
// host component in parent stack
1313
' at div (<anonymous>)',
1314
...originalStackLines.slice(2),
@@ -1360,7 +1363,10 @@ describe('ReactFlight', () => {
1363
return functionName === 'div';
1364
}
1365
return (
1363
- !filename.startsWith('node:') && !filename.includes('node_modules')
1366
+ !filename.startsWith('node:') &&
1367
+ !filename.includes('node_modules') &&
1368
+ // sourceURL from an ES module in `/code/[root of the server].js`
1369
+ filename !== 'file:///code/[root%20of%20the%20server].js'
1370
);
1371
},
1372
});
packages/react-server/src/ReactFlightServer.js
+2
-2
@@ -184,10 +184,10 @@ function devirtualizeURL(url: string): string {
184
// We need to reverse it back into the original location by stripping its prefix
185
// and suffix. We don't need the environment name because it's available on the
186
// parent object that will contain the stack.
187
- const envIdx = url.indexOf('/', 12);
187
+ const envIdx = url.indexOf('/', 'rsc://React/'.length);
188
const suffixIdx = url.lastIndexOf('?');
189
if (envIdx > -1 && suffixIdx > -1) {
190
- return url.slice(envIdx + 1, suffixIdx);
190
+ return decodeURI(url.slice(envIdx + 1, suffixIdx));
191
}
192
}
193
return url;