Skip to content

Commit

Permalink
Emit x_google_ignoreList, add serializer.isThirdPartyModule config …
Browse files Browse the repository at this point in the history
…option

Summary:
Changelog:

* **[Feature]**: Support [`x_google_ignoreList`](https://developer.chrome.com/articles/x-google-ignore-list/) source map extension.

Emits `x_google_ignoreList` as part of Metro's source maps in order to support ["Just My Code"](https://developer.chrome.com/blog/devtools-modern-web-debugging/#just-my-code) debugging in Chrome DevTools and other compatible debuggers.

By default, the ignore list consists of modules whose code was generated directly by Metro, and any module whose path contains a `node_modules` component. The latter is configurable using the new `serializer.isThirdPartyModule` option.

The infrastructure for working with the `x_google_ignoreList` field was added and tested in D43554204.

Reviewed By: GijsWeterings

Differential Revision: D43555494

fbshipit-source-id: ca614994599600dfaff21a59cb2106590873e090
  • Loading branch information
motiz88 authored and facebook-github-bot committed Apr 25, 2023
1 parent 1e54752 commit 82bd64a
Show file tree
Hide file tree
Showing 24 changed files with 521 additions and 58 deletions.
12 changes: 12 additions & 0 deletions docs/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,18 @@ Type: `(module: Array<Module>) => boolean`
A filter function to discard specific modules from the output.
#### `isThirdPartyModule`
Type: `(module: {path: string, ...}) => boolean`
A function that determines which modules are added to the [`x_google_ignoreList`](https://developer.chrome.com/articles/x-google-ignore-list/) field of the source map. This supports ["Just My Code"](https://developer.chrome.com/blog/devtools-modern-web-debugging/#just-my-code) debugging in Chrome DevTools and other compatible debuggers.
Defaults to returning `true` for modules with a path component named `node_modules`.
:::note
In addition to modules marked as ignored by `isThirdPartyModule`, Metro will also automatically add modules generated by the bundler itself to the ignore list.
:::
---
### Server Options
Expand Down
4 changes: 4 additions & 0 deletions docs/SourceMapFormat.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,7 @@ decoded.push({column, name: names[nameIndex] /* 'b' */, line});
]
*/
```

## `x_google_ignoreList`

Metro's source maps include the [`x_google_ignoreList`](https://developer.chrome.com/articles/x-google-ignore-list/) field by default. The [`serializer.isThirdPartyModule`](./Configuration.md#isthirdpartymodule) option can be used to control which modules are ignore-listed.
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ Object {
"getModulesRunBeforeMainModule": [Function],
"getPolyfills": [Function],
"getRunModuleStatement": [Function],
"isThirdPartyModule": [Function],
"polyfillModuleNames": Array [],
"processModuleFilter": [Function],
},
Expand Down Expand Up @@ -271,6 +272,7 @@ Object {
"getModulesRunBeforeMainModule": [Function],
"getPolyfills": [Function],
"getRunModuleStatement": [Function],
"isThirdPartyModule": [Function],
"polyfillModuleNames": Array [],
"processModuleFilter": [Function],
},
Expand Down Expand Up @@ -449,6 +451,7 @@ Object {
"getModulesRunBeforeMainModule": [Function],
"getPolyfills": [Function],
"getRunModuleStatement": [Function],
"isThirdPartyModule": [Function],
"polyfillModuleNames": Array [],
"processModuleFilter": [Function],
},
Expand Down Expand Up @@ -627,6 +630,7 @@ Object {
"getModulesRunBeforeMainModule": [Function],
"getPolyfills": [Function],
"getRunModuleStatement": [Function],
"isThirdPartyModule": [Function],
"polyfillModuleNames": Array [],
"processModuleFilter": [Function],
},
Expand Down
1 change: 1 addition & 0 deletions packages/metro-config/src/configTypes.flow.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ type SerializerConfigT = {
getRunModuleStatement: (number | string) => string,
polyfillModuleNames: $ReadOnlyArray<string>,
processModuleFilter: (modules: Module<>) => boolean,
isThirdPartyModule: (module: $ReadOnly<{path: string, ...}>) => boolean,
};

type TransformerConfigT = {
Expand Down
2 changes: 2 additions & 0 deletions packages/metro-config/src/defaults/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ const getDefaultValues = (projectRoot: ?string): ConfigT => ({
createModuleIdFactory: defaultCreateModuleIdFactory,
experimentalSerializerHook: () => {},
customSerializer: null,
isThirdPartyModule: module =>
/(?:^|[/\\])node_modules[/\\]/.test(module.path),
},

server: {
Expand Down
1 change: 1 addition & 0 deletions packages/metro-config/types/configTypes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ export interface SerializerConfigT {
getRunModuleStatement: (moduleId: number | string) => string;
polyfillModuleNames: ReadonlyArray<string>;
processModuleFilter: (modules: Module) => boolean;
isThirdPartyModule: (module: {readonly path: string}) => boolean;
}

export interface TransformerConfigT extends JsTransformerConfig {
Expand Down
7 changes: 7 additions & 0 deletions packages/metro-source-map/src/__tests__/source-map-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ describe('build map from raw mappings', () => {
],
source: 'code1',
path: 'path1',
isIgnored: false,
},
{
code: lines(3),
Expand All @@ -73,6 +74,7 @@ describe('build map from raw mappings', () => {
],
source: 'code2',
path: 'path2',
isIgnored: true,
},
{
code: lines(23),
Expand All @@ -85,6 +87,7 @@ describe('build map from raw mappings', () => {
],
source: 'code3',
path: 'path3',
isIgnored: false,
},
];

Expand All @@ -99,6 +102,7 @@ describe('build map from raw mappings', () => {
[{names: ['<global>'], mappings: 'AAA'}],
null,
],
x_google_ignoreList: [1],
version: 3,
});
});
Expand Down Expand Up @@ -129,6 +133,7 @@ describe('build map from raw mappings', () => {
],
source: 'code1',
path: 'path1',
isIgnored: false,
},
{
code: lines(3),
Expand All @@ -139,6 +144,7 @@ describe('build map from raw mappings', () => {
],
source: 'code2',
path: 'path2',
isIgnored: false,
},
{
code: lines(23),
Expand All @@ -151,6 +157,7 @@ describe('build map from raw mappings', () => {
],
source: 'code3',
path: 'path3',
isIgnored: false,
},
];

Expand Down
16 changes: 11 additions & 5 deletions packages/metro-source-map/src/source-map.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ function fromRawMappingsImpl(
+path: string,
+source: string,
+code: string,
...
+isIgnored: boolean,
+lineCount?: number,
}>,
offsetLines: number,
): void {
Expand Down Expand Up @@ -173,7 +174,8 @@ function fromRawMappings(
+path: string,
+source: string,
+code: string,
...
+isIgnored: boolean,
+lineCount?: number,
}>,
offsetLines: number = 0,
): Generator {
Expand All @@ -199,7 +201,8 @@ async function fromRawMappingsNonBlocking(
+path: string,
+source: string,
+code: string,
...
+isIgnored: boolean,
+lineCount?: number,
}>,
offsetLines: number = 0,
): Promise<Generator> {
Expand Down Expand Up @@ -274,11 +277,14 @@ function addMappingsForFile(
+map: ?Array<MetroSourceMapSegmentTuple>,
+path: string,
+source: string,
...
+isIgnored: boolean,
+lineCount?: number,
},
carryOver: number,
) {
generator.startFile(module.path, module.source, module.functionMap);
generator.startFile(module.path, module.source, module.functionMap, {
addToIgnoreList: module.isIgnored,
});

for (let i = 0, n = mappings.length; i < n; ++i) {
addMapping(generator, mappings[i], carryOver);
Expand Down
11 changes: 10 additions & 1 deletion packages/metro-transform-worker/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,16 @@ const minifyCode = async (
...
}> => {
const sourceMap = fromRawMappings([
{code, source, map, functionMap: null, path: filename},
{
code,
source,
map,
// functionMap is overridden by the serializer
functionMap: null,
path: filename,
// isIgnored is overriden by the serializer
isIgnored: false,
},
]).toMap(undefined, {});

const minify = getMinifier(config.minifierPath);
Expand Down
Loading

0 comments on commit 82bd64a

Please sign in to comment.