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

feat: display message if user ended up opening hook script (#31000)

In https://github.com/facebook/react/pull/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)

Ruslan Lesiutin committed Sep 19, 2024 at 15:44 UTC c21ce4a39667c4094208bc35dc86fc9f49fceec6
1 file changed +56
packages/react-devtools-extensions/webpack.config.js
+56
@@ -154,6 +154,62 @@ module.exports = {
154 );
155 },
156 }),
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 + },
213 ],
214 module: {
215 defaultRules: [