From ced2c204639152fdbd019844c66a909c4cc3202b Mon Sep 17 00:00:00 2001 From: Ruslan Lesiutin Date: Wed, 3 Apr 2024 15:49:54 +0100 Subject: [PATCH] feat[devtools]: ship source maps for content scripts and ignore list installHook script --- .../react-devtools-extensions/package.json | 1 - ...eIgnoreList-test.js => ignoreList-test.js} | 22 ++---- .../webpack.backend.js | 19 +++-- .../webpack.config.js | 24 +++++- .../SourceMapIgnoreListPlugin.js | 73 +++++++++++++++++++ yarn.lock | 8 +- 6 files changed, 113 insertions(+), 34 deletions(-) rename packages/react-devtools-extensions/src/__tests__/{xGoogleIgnoreList-test.js => ignoreList-test.js} (65%) create mode 100644 packages/react-devtools-shared/SourceMapIgnoreListPlugin.js diff --git a/packages/react-devtools-extensions/package.json b/packages/react-devtools-extensions/package.json index d284c02edf54a..5f9d473e2349e 100644 --- a/packages/react-devtools-extensions/package.json +++ b/packages/react-devtools-extensions/package.json @@ -39,7 +39,6 @@ "chrome-launch": "^1.1.4", "crx": "^5.0.0", "css-loader": "^1.0.1", - "devtools-ignore-webpack-plugin": "^0.1.1", "file-loader": "^6.1.0", "filesize": "^6.0.1", "find": "^0.3.0", diff --git a/packages/react-devtools-extensions/src/__tests__/xGoogleIgnoreList-test.js b/packages/react-devtools-extensions/src/__tests__/ignoreList-test.js similarity index 65% rename from packages/react-devtools-extensions/src/__tests__/xGoogleIgnoreList-test.js rename to packages/react-devtools-extensions/src/__tests__/ignoreList-test.js index 58571d2655d96..70845d0582d77 100644 --- a/packages/react-devtools-extensions/src/__tests__/xGoogleIgnoreList-test.js +++ b/packages/react-devtools-extensions/src/__tests__/ignoreList-test.js @@ -12,7 +12,7 @@ import {readFileSync} from 'fs'; import path from 'path'; import {rimrafSync} from 'rimraf'; -describe('x_google_ignoreList source map extension', () => { +describe('ignoreList source map extension', () => { jest.setTimeout(60 * 1000); const pathToExtensionsPackage = path.resolve(__dirname, '..', '..'); @@ -30,7 +30,7 @@ describe('x_google_ignoreList source map extension', () => { }); describe('for dev builds', () => { - it('should include only sources with /node_modules/ and /webpack/ in path', async () => { + it('should not ignore list anything', async () => { await exec('yarn build:chrome:local', { cwd: pathToExtensionsPackage, }); @@ -38,18 +38,8 @@ describe('x_google_ignoreList source map extension', () => { const sourceMapJSON = readFileSync(pathToSourceMap); const sourceMap = JSON.parse(sourceMapJSON); - const {sources, x_google_ignoreList} = sourceMap; - - const expectedIgnoreList = []; - for (let sourceIndex = 0; sourceIndex < sources.length; ++sourceIndex) { - const source = sources[sourceIndex]; - - if (source.includes('/node_modules/') || source.includes('/webpack/')) { - expectedIgnoreList.push(sourceIndex); - } - } - - expect(x_google_ignoreList).toEqual(expectedIgnoreList); + const {ignoreList} = sourceMap; + expect(ignoreList).toEqual([]); }); }); @@ -60,9 +50,9 @@ describe('x_google_ignoreList source map extension', () => { const sourceMapJSON = readFileSync(pathToSourceMap); const sourceMap = JSON.parse(sourceMapJSON); - const {sources, x_google_ignoreList} = sourceMap; + const {sources, ignoreList} = sourceMap; - expect(sources.length).toBe(x_google_ignoreList.length); + expect(sources.length).toBe(ignoreList.length); }); }); }); diff --git a/packages/react-devtools-extensions/webpack.backend.js b/packages/react-devtools-extensions/webpack.backend.js index 87d4d8e2fbd02..4c4af3ac076fb 100644 --- a/packages/react-devtools-extensions/webpack.backend.js +++ b/packages/react-devtools-extensions/webpack.backend.js @@ -2,9 +2,10 @@ const {resolve} = require('path'); const Webpack = require('webpack'); -const DevToolsIgnorePlugin = require('devtools-ignore-webpack-plugin'); const {resolveFeatureFlags} = require('react-devtools-shared/buildUtils'); +const SourceMapIgnoreListPlugin = require('react-devtools-shared/SourceMapIgnoreListPlugin'); + const { DARK_MODE_DIMMED_WARNING_COLOR, DARK_MODE_DIMMED_ERROR_COLOR, @@ -42,7 +43,7 @@ const featureFlagTarget = process.env.FEATURE_FLAG_TARGET || 'extension-oss'; module.exports = { mode: __DEV__ ? 'development' : 'production', - devtool: __DEV__ ? 'cheap-module-source-map' : 'nosources-cheap-source-map', + devtool: false, entry: { backend: './src/backend.js', }, @@ -87,14 +88,12 @@ module.exports = { 'process.env.IS_FIREFOX': IS_FIREFOX, 'process.env.IS_EDGE': IS_EDGE, }), - new DevToolsIgnorePlugin({ - shouldIgnorePath: function (path) { - if (!__DEV__) { - return true; - } - - return path.includes('/node_modules/') || path.includes('/webpack/'); - }, + new Webpack.SourceMapDevToolPlugin({ + filename: '[file].map', + noSources: !__DEV__, + }), + new SourceMapIgnoreListPlugin({ + shouldIgnoreSource: () => !__DEV__, }), ], module: { diff --git a/packages/react-devtools-extensions/webpack.config.js b/packages/react-devtools-extensions/webpack.config.js index 917ee42594428..4195a43abfe58 100644 --- a/packages/react-devtools-extensions/webpack.config.js +++ b/packages/react-devtools-extensions/webpack.config.js @@ -14,6 +14,7 @@ const { getVersionString, } = require('./utils'); const {resolveFeatureFlags} = require('react-devtools-shared/buildUtils'); +const SourceMapIgnoreListPlugin = require('react-devtools-shared/SourceMapIgnoreListPlugin'); const NODE_ENV = process.env.NODE_ENV; if (!NODE_ENV) { @@ -54,7 +55,7 @@ const babelOptions = { module.exports = { mode: __DEV__ ? 'development' : 'production', - devtool: __DEV__ ? 'cheap-module-source-map' : false, + devtool: false, entry: { background: './src/background/index.js', backendManager: './src/contentScripts/backendManager.js', @@ -134,6 +135,27 @@ module.exports = { 'process.env.LIGHT_MODE_DIMMED_ERROR_COLOR': `"${LIGHT_MODE_DIMMED_ERROR_COLOR}"`, 'process.env.LIGHT_MODE_DIMMED_LOG_COLOR': `"${LIGHT_MODE_DIMMED_LOG_COLOR}"`, }), + new Webpack.SourceMapDevToolPlugin({ + filename: '[file].map', + noSources: !__DEV__, + }), + new SourceMapIgnoreListPlugin({ + shouldIgnoreSource: (assetName, _source) => { + if (__DEV__) { + // Don't ignore list anything in DEV build for debugging purposes + return false; + } + + const contentScriptNamesToIgnoreList = [ + // This is where we override console + 'installHook', + ]; + + return contentScriptNamesToIgnoreList.some(ignoreListName => + assetName.startsWith(ignoreListName), + ); + }, + }), ], module: { defaultRules: [ diff --git a/packages/react-devtools-shared/SourceMapIgnoreListPlugin.js b/packages/react-devtools-shared/SourceMapIgnoreListPlugin.js new file mode 100644 index 0000000000000..b6ba81ffd15b7 --- /dev/null +++ b/packages/react-devtools-shared/SourceMapIgnoreListPlugin.js @@ -0,0 +1,73 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/** + * The implementation of this plugin is based on similar webpack plugin in Angular CLI + * https://github.com/angular/angular-cli/blob/16d8c552e99bfe65ded9e843e917dbb95eb8ec01/packages/angular_devkit/build_angular/src/tools/webpack/plugins/devtools-ignore-plugin.ts + * and devtools-ignore-webpack-plugin + * https://github.com/mondaychen/devtools-ignore-webpack-plugin/blob/d15274e4d2fdb74f73aa644f14773a5523823999/src/index.ts + * which both are licensed under MIT + */ + +const {Compilation} = require('webpack'); + +const IGNORE_LIST = 'ignoreList'; +const PLUGIN_NAME = 'source-map-ignore-list-plugin'; + +class SourceMapIgnoreListPlugin { + constructor({shouldIgnoreSource}) { + this.shouldIgnoreSource = shouldIgnoreSource; + } + + apply(compiler) { + const {RawSource} = compiler.webpack.sources; + + compiler.hooks.compilation.tap(PLUGIN_NAME, compilation => { + compilation.hooks.processAssets.tap( + { + name: PLUGIN_NAME, + stage: 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.endsWith('.map')) { + continue; + } + + const mapContent = asset.source().toString(); + if (!mapContent) { + continue; + } + + const map = JSON.parse(mapContent); + const ignoreList = []; + + const sourcesCount = map.sources.length; + for ( + let potentialSourceIndex = 0; + potentialSourceIndex < sourcesCount; + ++potentialSourceIndex + ) { + const source = map.sources[potentialSourceIndex]; + + if (this.shouldIgnoreSource(name, source)) { + ignoreList.push(potentialSourceIndex); + } + } + + map[IGNORE_LIST] = ignoreList; + compilation.updateAsset(name, new RawSource(JSON.stringify(map))); + } + }, + ); + }); + } +} + +module.exports = SourceMapIgnoreListPlugin; diff --git a/yarn.lock b/yarn.lock index 71c9174c1c238..e4cb632b2434e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6417,11 +6417,6 @@ detect-node@^2.0.4: resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c" integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw== -devtools-ignore-webpack-plugin@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/devtools-ignore-webpack-plugin/-/devtools-ignore-webpack-plugin-0.1.1.tgz#8f4fcf83019bc361e8a3cf7b7d466a33693de14e" - integrity sha512-pJ/NGZTQxK1VDoyy8fLm0UV3ugOanostztLKUmzqYnUIKqyUm2ZkIpon6No0gWlpOSMoSpBWTnzrx1cdsbpuyw== - diff-sequences@^27.0.6: version "27.0.6" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.0.6.tgz#3305cb2e55a033924054695cc66019fd7f8e5723" @@ -6997,6 +6992,7 @@ eslint-plugin-no-unsanitized@3.1.2: "eslint-plugin-react-internal@link:./scripts/eslint-rules": version "0.0.0" + uid "" eslint-plugin-react@^6.7.1: version "6.10.3" @@ -12991,7 +12987,7 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.2.8: object-assign "^4.1.1" scheduler "^0.20.2" -react-is@^16.8.1, react-is@^17.0.1, "react-is@npm:react-is": +react-is@^16.8.1, react-is@^17.0.1, react-is@^18.0.0, react-is@^18.2.0, "react-is@npm:react-is": version "17.0.2" resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==