Skip to content

Commit c21ce4a

Browse files
authored
feat: display message if user ended up opening hook script (#31000)
In #30596 we've moved console patching to the global hook. Generally speaking, the patching happens even before React is loaded on the page. If browser DevTools were opened after when `console.error` or `console.warn` were called, the source script will be `hook.js`, because of the patching. ![devtools-opened-after-the-message](https://github.com/user-attachments/assets/3d3dbc16-96b8-4234-b061-57b21b60cf2e) This is because ignore listing is not applied retroactively by Chrome DevTools. If you had it open before console calls, Hook script would be correctly filtered out from the stack: ![devtools-opened-before-the-message](https://github.com/user-attachments/assets/3e99cb22-97b0-4b49-9a76-f7bc948e6452) I had hopes that the fix for https://issues.chromium.org/issues/345248263 will also apply ignore listing retroactively, but looks like we need to open a separate feature request for the Chrome DevTools team. With these changes, if user attempts to open `hook.js` script, they are going to see this message: ![Screenshot 2024-09-19 at 11 30 59](https://github.com/user-attachments/assets/5850b74c-329f-4fbe-a3dd-33f9ac717ee9)
1 parent 632f88d commit c21ce4a

File tree

1 file changed

+56
-0
lines changed

1 file changed

+56
-0
lines changed

Diff for: packages/react-devtools-extensions/webpack.config.js

+56
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,62 @@ module.exports = {
154154
);
155155
},
156156
}),
157+
{
158+
apply(compiler) {
159+
if (__DEV__) {
160+
return;
161+
}
162+
163+
const {RawSource} = compiler.webpack.sources;
164+
compiler.hooks.compilation.tap(
165+
'CustomContentForHookScriptPlugin',
166+
compilation => {
167+
compilation.hooks.processAssets.tap(
168+
{
169+
name: 'CustomContentForHookScriptPlugin',
170+
stage: Webpack.Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING,
171+
additionalAssets: true,
172+
},
173+
assets => {
174+
// eslint-disable-next-line no-for-of-loops/no-for-of-loops
175+
for (const [name, asset] of Object.entries(assets)) {
176+
if (name !== 'installHook.js.map') {
177+
continue;
178+
}
179+
180+
const mapContent = asset.source().toString();
181+
if (!mapContent) {
182+
continue;
183+
}
184+
185+
const map = JSON.parse(mapContent);
186+
map.sourcesContent = map.sources.map(sourceName => {
187+
if (!sourceName.endsWith('/hook.js')) {
188+
return null;
189+
}
190+
191+
return (
192+
'/*\n' +
193+
' * This script is from React DevTools.\n' +
194+
" * You're likely here because you thought it sent an error or warning to the console.\n" +
195+
' * React DevTools patches the console to support features like appending component stacks, \n' +
196+
' * so this file appears as a source. However, the console call actually came from another script.\n' +
197+
" * To remove this script from stack traces, open your browser's DevTools (to enable source mapping) before these console calls happen.\n" +
198+
' */'
199+
);
200+
});
201+
202+
compilation.updateAsset(
203+
name,
204+
new RawSource(JSON.stringify(map)),
205+
);
206+
}
207+
},
208+
);
209+
},
210+
);
211+
},
212+
},
157213
],
158214
module: {
159215
defaultRules: [

0 commit comments

Comments
 (0)