Skip to content

Commit

Permalink
feat[devtools]: ship source maps for content scripts and ignore list …
Browse files Browse the repository at this point in the history
…installHook script (#28730)

## Summary

1. RDT browser extension's content scripts will now ship source maps
(without source in prod, to save some bundle size).
2. `installHook` content script will be ignore listed via `ignoreList`
field in the corresponding source map.
3. Previously, source map for backend file used `x_google_ignoreList`
naming, now `ignoreList`.

## How did you test this change?

1. `ignoreList-test.js`
2. Tested manually that I don't see `installHook` in stack traces when
`console.error` is called.
  • Loading branch information
hoxyq authored and rickhanlonii committed Apr 11, 2024
1 parent f35b382 commit f765aa5
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 33 deletions.
1 change: 0 additions & 1 deletion packages/react-devtools-extensions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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, '..', '..');
Expand All @@ -30,26 +30,16 @@ 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,
});

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([]);
});
});

Expand All @@ -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);
});
});
});
19 changes: 9 additions & 10 deletions packages/react-devtools-extensions/webpack.backend.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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',
},
Expand Down Expand Up @@ -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: {
Expand Down
24 changes: 23 additions & 1 deletion packages/react-devtools-extensions/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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',
Expand Down Expand Up @@ -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: [
Expand Down
73 changes: 73 additions & 0 deletions packages/react-devtools-shared/SourceMapIgnoreListPlugin.js
Original file line number Diff line number Diff line change
@@ -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;
5 changes: 0 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down

0 comments on commit f765aa5

Please sign in to comment.