Skip to content

Commit

Permalink
feat: display message if user ended up opening hook script (#31000)
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
hoxyq authored Sep 19, 2024
1 parent 632f88d commit c21ce4a
Showing 1 changed file with 56 additions and 0 deletions.
56 changes: 56 additions & 0 deletions packages/react-devtools-extensions/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,62 @@ module.exports = {
);
},
}),
{
apply(compiler) {
if (__DEV__) {
return;
}

const {RawSource} = compiler.webpack.sources;
compiler.hooks.compilation.tap(
'CustomContentForHookScriptPlugin',
compilation => {
compilation.hooks.processAssets.tap(
{
name: 'CustomContentForHookScriptPlugin',
stage: Webpack.Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING,
additionalAssets: true,
},
assets => {
// eslint-disable-next-line no-for-of-loops/no-for-of-loops
for (const [name, asset] of Object.entries(assets)) {
if (name !== 'installHook.js.map') {
continue;
}

const mapContent = asset.source().toString();
if (!mapContent) {
continue;
}

const map = JSON.parse(mapContent);
map.sourcesContent = map.sources.map(sourceName => {
if (!sourceName.endsWith('/hook.js')) {
return null;
}

return (
'/*\n' +
' * This script is from React DevTools.\n' +
" * You're likely here because you thought it sent an error or warning to the console.\n" +
' * React DevTools patches the console to support features like appending component stacks, \n' +
' * so this file appears as a source. However, the console call actually came from another script.\n' +
" * To remove this script from stack traces, open your browser's DevTools (to enable source mapping) before these console calls happen.\n" +
' */'
);
});

compilation.updateAsset(
name,
new RawSource(JSON.stringify(map)),
);
}
},
);
},
);
},
},
],
module: {
defaultRules: [
Expand Down

0 comments on commit c21ce4a

Please sign in to comment.