@samitouri / QOS-React-1 / commits / 3d14fcf03f

[Flight] Use about: protocol instead of rsc: protocol for fake evals (#33977)

Chrome DevTools Extensions has a silly problem where they block access to load Resources from all protocols except [an allow list](https://github.com/ChromeDevTools/devtools-frontend/blob/eb970fbc6482f281b95bbec1c33c1c539f6d50f0/front_end/models/extensions/ExtensionServer.ts#L60). https://issues.chromium.org/issues/416196401 Even though these are `eval()` and not actually loaded from the network they're blocked. They can really be any string. We just have to pick one of: ```js 'http:', 'https:', 'file:', 'data:', 'chrome-extension:', 'about:' ``` That way React DevTools extensions can load this content to source map them. Webpack has the same issue with its `webpack://` and `webpack-internal://` urls.

Sebastian Markbåge committed Jul 24, 2025 at 11:07 UTC 3d14fcf03f4e296d21b52b362f5adefd9e366375
4 files changed +9 -9
packages/react-client/src/ReactFlightClient.js
+2 -2
@@ -3154,7 +3154,7 @@ function createFakeFunction<T>(
3154 }
3155
3156 if (sourceMap) {
3157 - // We use the prefix rsc://React/ to separate these from other files listed in
3157 + // We use the prefix about://React/ to separate these from other files listed in
3158 // the Chrome DevTools. We need a "host name" and not just a protocol because
3159 // otherwise the group name becomes the root folder. Ideally we don't want to
3160 // show these at all but there's two reasons to assign a fake URL.
@@ -3162,7 +3162,7 @@ function createFakeFunction<T>(
3162 // 2) If source maps are disabled or fails, you should at least be able to tell
3163 // which file it was.
3164 code +=
3165 - '\n//# sourceURL=rsc://React/' +
3165 + '\n//# sourceURL=about://React/' +
3166 encodeURIComponent(environmentName) +
3167 '/' +
3168 encodeURI(filename) +
packages/react-client/src/ReactFlightReplyClient.js
+2 -2
@@ -1095,7 +1095,7 @@ function createFakeServerFunction<A: Iterable<any>, T>(
1095 }
1096
1097 if (sourceMap) {
1098 - // We use the prefix rsc://React/ to separate these from other files listed in
1098 + // We use the prefix about://React/ to separate these from other files listed in
1099 // the Chrome DevTools. We need a "host name" and not just a protocol because
1100 // otherwise the group name becomes the root folder. Ideally we don't want to
1101 // show these at all but there's two reasons to assign a fake URL.
@@ -1103,7 +1103,7 @@ function createFakeServerFunction<A: Iterable<any>, T>(
1103 // 2) If source maps are disabled or fails, you should at least be able to tell
1104 // which file it was.
1105 code +=
1106 - '\n//# sourceURL=rsc://React/' +
1106 + '\n//# sourceURL=about://React/' +
1107 encodeURIComponent(environmentName) +
1108 '/' +
1109 encodeURI(filename) +
packages/react-client/src/__tests__/ReactFlight-test.js
+3 -3
@@ -1314,7 +1314,7 @@ describe('ReactFlight', () => {
1314 ' at async file:///testing.js:42:3',
1315 // third-party RSC frame
1316 // Ideally this would be a real frame produced by React not a mocked one.
1317 - ' at ThirdParty (rsc://React/ThirdParty/file:///code/%5Broot%2520of%2520the%2520server%5D.js?42:1:1)',
1317 + ' at ThirdParty (about://React/ThirdParty/file:///code/%5Broot%2520of%2520the%2520server%5D.js?42:1:1)',
1318 // We'll later filter this out based on line/column in `filterStackFrame`.
1319 ' at ThirdPartyModule (file:///file-with-index-source-map.js:52656:16374)',
1320 // host component in parent stack
@@ -3073,7 +3073,7 @@ describe('ReactFlight', () => {
3073 ReactNoopFlightClient.read(transport, {
3074 findSourceMapURL(url) {
3075 // By giving a source map url we're saying that we can't use the original
3076 - // file as the sourceURL, which gives stack traces a rsc://React/ prefix.
3076 + // file as the sourceURL, which gives stack traces a about://React/ prefix.
3077 return 'source-map://' + url;
3078 },
3079 }),
@@ -3147,7 +3147,7 @@ describe('ReactFlight', () => {
3147 expectedErrorStack={expectedErrorStack}>
3148 {ReactNoopFlightClient.read(transport, {
3149 findSourceMapURL(url, environmentName) {
3150 - if (url.startsWith('rsc://React/')) {
3150 + if (url.startsWith('about://React/')) {
3151 // We don't expect to see any React prefixed URLs here.
3152 sawReactPrefix = true;
3153 }
packages/react-server/src/ReactFlightServer.js
+2 -2
@@ -179,12 +179,12 @@ function defaultFilterStackFrame(
179 }
180
181 function devirtualizeURL(url: string): string {
182 - if (url.startsWith('rsc://React/')) {
182 + if (url.startsWith('about://React/')) {
183 // This callsite is a virtual fake callsite that came from another Flight client.
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('/', 'rsc://React/'.length);
187 + const envIdx = url.indexOf('/', 'about://React/'.length);
188 const suffixIdx = url.lastIndexOf('?');
189 if (envIdx > -1 && suffixIdx > -1) {
190 return decodeURI(url.slice(envIdx + 1, suffixIdx));