From 10b701926c91d4982640309424b389d345a99fb5 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Tue, 25 Apr 2023 07:04:19 -0700 Subject: [PATCH] Support x_google_ignoreList in source map infra (#973) Summary: Pull Request resolved: https://github.com/facebook/metro/pull/973 Changelog: * **[Feature]**: Basic support for `x_google_ignoreList` in `metro-source-map` and `metro-symbolicate` Enables Metro's source map infrastructure to produce and consume the `x_google_ignoreList` field, documented [here](https://developer.chrome.com/blog/devtools-better-angular-debugging/#the-x_google_ignorelist-source-map-extension). An upcoming diff will use this infra support to add ignore lists to Metro's source maps by default. The changes here include: * An option to mark source files as ignored in `metro-source-map`'s `Generator` (used by the serializer). * Preserving ignore lists in `composeSourceMaps`. `composeSourceMaps` is used by React Native in [OSS](https://github.com/facebook/react-native/blob/c1304d938da9cd5016da0bded4d618c42efbd7e4/scripts/compose-source-maps.js#L13) to generate source maps for Hermes bytecode compiled from Metro bundles. * Including an `isIgnored` field in source locations returned via the `metro-symbolicate` API. `metro-symbolicate` is the reference implementation of symbolication based on Metro's source maps. Reviewed By: GijsWeterings Differential Revision: D43554204 fbshipit-source-id: f49f65827ccb1d346eec192c81c53e39597025ab --- packages/metro-source-map/src/Generator.js | 82 ++++-- .../src/__tests__/Generator-test.js | 40 ++- .../src/__tests__/composeSourceMaps-test.js | 87 ++++++ .../metro-source-map/src/composeSourceMaps.js | 6 + packages/metro-source-map/src/source-map.js | 2 + .../src/GoogleIgnoreListConsumer.js | 134 ++++++++++ .../metro-symbolicate/src/Symbolication.js | 14 + .../GoogleIgnoreListConsumer-test.js | 53 ++++ .../src/__tests__/Symbolication-test.js | 27 ++ .../__fixtures__/with-ignore-list.js.map | 249 ++++++++++++++++++ .../__fixtures__/with-ignore-list.stack | 2 + .../__snapshots__/symbolicate-test.js.snap | 19 ++ 12 files changed, 691 insertions(+), 24 deletions(-) create mode 100644 packages/metro-symbolicate/src/GoogleIgnoreListConsumer.js create mode 100644 packages/metro-symbolicate/src/__tests__/GoogleIgnoreListConsumer-test.js create mode 100644 packages/metro-symbolicate/src/__tests__/__fixtures__/with-ignore-list.js.map create mode 100644 packages/metro-symbolicate/src/__tests__/__fixtures__/with-ignore-list.stack diff --git a/packages/metro-source-map/src/Generator.js b/packages/metro-source-map/src/Generator.js index 6a2b6442b3..d6fc48f3c8 100644 --- a/packages/metro-source-map/src/Generator.js +++ b/packages/metro-source-map/src/Generator.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format * @oncall react_native */ @@ -19,6 +19,10 @@ import type { const B64Builder = require('./B64Builder'); +type FileFlags = $ReadOnly<{ + addToIgnoreList?: boolean, +}>; + /** * Generates a source map from raw mappings. * @@ -45,6 +49,8 @@ class Generator { sources: Array; sourcesContent: Array; x_facebook_sources: Array; + // https://developer.chrome.com/blog/devtools-better-angular-debugging/#the-x_google_ignorelist-source-map-extension + x_google_ignoreList: Array; constructor() { this.builder = new B64Builder(); @@ -61,15 +67,26 @@ class Generator { this.sources = []; this.sourcesContent = []; this.x_facebook_sources = []; + this.x_google_ignoreList = []; } /** * Mark the beginning of a new source file. */ - startFile(file: string, code: string, functionMap: ?FBSourceFunctionMap) { - this.source = this.sources.push(file) - 1; + startFile( + file: string, + code: string, + functionMap: ?FBSourceFunctionMap, + flags?: FileFlags, + ) { + const {addToIgnoreList = false} = flags ?? {}; + const sourceIndex = this.sources.push(file) - 1; + this.source = sourceIndex; this.sourcesContent.push(code); this.x_facebook_sources.push(functionMap ? [functionMap] : null); + if (addToIgnoreList) { + this.x_google_ignoreList.push(sourceIndex); + } } /** @@ -159,32 +176,41 @@ class Generator { file?: string, options?: {excludeSource?: boolean, ...}, ): BasicSourceMap { - let content, sourcesMetadata; + const content: { + sourcesContent?: Array, + } = + options && options.excludeSource === true + ? {} + : {sourcesContent: this.sourcesContent.slice()}; - if (options && options.excludeSource) { - content = {}; - } else { - content = {sourcesContent: this.sourcesContent.slice()}; - } + const sourcesMetadata: { + x_facebook_sources?: Array, + } = this.hasSourcesMetadata() + ? { + x_facebook_sources: JSON.parse( + JSON.stringify(this.x_facebook_sources), + ), + } + : {}; - if (this.hasSourcesMetadata()) { - sourcesMetadata = { - x_facebook_sources: JSON.parse(JSON.stringify(this.x_facebook_sources)), - }; - } else { - sourcesMetadata = {}; - } + const ignoreList: { + x_google_ignoreList?: Array, + } = this.x_google_ignoreList.length + ? { + x_google_ignoreList: this.x_google_ignoreList, + } + : {}; - return { + return ({ version: 3, file, sources: this.sources.slice(), - // $FlowFixMe[exponential-spread] ...content, ...sourcesMetadata, + ...ignoreList, names: this.names.items(), mappings: this.builder.toString(), - }; + }: BasicSourceMap); } /** @@ -193,14 +219,14 @@ class Generator { * This is ~2.5x faster than calling `JSON.stringify(generator.toMap())` */ toString(file?: string, options?: {excludeSource?: boolean, ...}): string { - let content, sourcesMetadata; - - if (options && options.excludeSource) { + let content; + if (options && options.excludeSource === true) { content = ''; } else { content = `"sourcesContent":${JSON.stringify(this.sourcesContent)},`; } + let sourcesMetadata; if (this.hasSourcesMetadata()) { sourcesMetadata = `"x_facebook_sources":${JSON.stringify( this.x_facebook_sources, @@ -209,13 +235,23 @@ class Generator { sourcesMetadata = ''; } + let ignoreList; + if (this.x_google_ignoreList.length) { + ignoreList = `"x_google_ignoreList":${JSON.stringify( + this.x_google_ignoreList, + )},`; + } else { + ignoreList = ''; + } + return ( '{' + '"version":3,' + - (file ? `"file":${JSON.stringify(file)},` : '') + + (file != null ? `"file":${JSON.stringify(file)},` : '') + `"sources":${JSON.stringify(this.sources)},` + content + sourcesMetadata + + ignoreList + `"names":${JSON.stringify(this.names.items())},` + `"mappings":"${this.builder.toString()}"` + '}' diff --git a/packages/metro-source-map/src/__tests__/Generator-test.js b/packages/metro-source-map/src/__tests__/Generator-test.js index b62f2f641b..f63f3ab934 100644 --- a/packages/metro-source-map/src/__tests__/Generator-test.js +++ b/packages/metro-source-map/src/__tests__/Generator-test.js @@ -100,7 +100,9 @@ describe('full map generation', () => { generator.addSimpleMapping(1, 2); generator.addNamedSourceMapping(3, 4, 5, 6, 'plums'); generator.endFile(); - generator.startFile('lemons', 'oranges'); + generator.startFile('lemons', 'oranges', undefined, { + addToIgnoreList: true, + }); generator.addNamedSourceMapping(7, 8, 9, 10, 'tangerines'); generator.addNamedSourceMapping(11, 12, 13, 14, 'tangerines'); generator.addSimpleMapping(15, 16); @@ -113,6 +115,7 @@ describe('full map generation', () => { sources: ['apples', 'lemons'], sourcesContent: ['pears', 'oranges'], names: ['plums', 'tangerines'], + x_google_ignoreList: [1], }); }); @@ -133,3 +136,38 @@ describe('full map generation', () => { expect(JSON.parse(generator.toString(file))).toEqual(generator.toMap(file)); }); }); + +describe('x_google_ignoreList', () => { + it('add files to ignore list', () => { + const file1 = 'just/a/file'; + const file2 = 'another/file'; + const file3 = 'file3'; + const source1 = 'var a = 1;'; + const source2 = 'var a = 2;'; + + generator.startFile(file1, source1, undefined, {addToIgnoreList: true}); + generator.startFile(file2, source2, undefined, {addToIgnoreList: false}); + generator.startFile(file3, source2, undefined, {addToIgnoreList: true}); + + expect(generator.toMap()).toEqual( + objectContaining({ + sources: [file1, file2, file3], + x_google_ignoreList: [0, 2], + }), + ); + }); + + it('not emitted if no files are ignored', () => { + const file1 = 'just/a/file'; + const file2 = 'another/file'; + const file3 = 'file3'; + const source1 = 'var a = 1;'; + const source2 = 'var a = 2;'; + + generator.startFile(file1, source1); + generator.startFile(file2, source2, undefined, {addToIgnoreList: false}); + generator.startFile(file3, source2, undefined, {addToIgnoreList: false}); + + expect(generator.toMap()).not.toHaveProperty('x_google_ignoreList'); + }); +}); diff --git a/packages/metro-source-map/src/__tests__/composeSourceMaps-test.js b/packages/metro-source-map/src/__tests__/composeSourceMaps-test.js index 9893987379..3a8dfc0530 100644 --- a/packages/metro-source-map/src/__tests__/composeSourceMaps-test.js +++ b/packages/metro-source-map/src/__tests__/composeSourceMaps-test.js @@ -20,6 +20,8 @@ const {add0, add1} = require('ob1'); const path = require('path'); const terser = require('terser'); +const {objectContaining} = expect; + /* eslint-disable no-multi-str */ const TestScript1 = @@ -165,6 +167,91 @@ describe('composeSourceMaps', () => { ]); }); + it('preserves and reindexes x_google_ignoreList', () => { + const map1 = { + version: 3, + sections: [ + { + offset: {line: 0, column: 0}, + map: { + version: 3, + sources: ['unused.js', 'src.js'], + x_google_ignoreList: [1], + names: ['global'], + mappings: ';CCCCA', + }, + }, + ], + }; + + const map2 = { + version: 3, + sources: ['src-transformed.js'], + names: ['gLoBAl'], + mappings: ';CACCA', + }; + + const mergedMap = composeSourceMaps([map1, map2]); + + expect(mergedMap).toEqual( + objectContaining({ + sources: ['src.js'], + x_google_ignoreList: [0], + }), + ); + }); + + it('x_google_ignoreList: a source with inconsistent ignore status is considered to be ignored', () => { + const map1 = { + version: 3, + sections: [ + { + offset: {line: 0, column: 0}, + map: { + version: 3, + sources: ['unused.js', 'src.js'], + x_google_ignoreList: [1], + names: ['global'], + // First line of src-transformed.js maps to src.js (source #1 here) + mappings: 'ACAAA', + }, + }, + { + offset: {line: 1, column: 0}, + map: { + version: 3, + sources: ['src.js', 'other.js'], + x_google_ignoreList: ([]: Array), + names: ['global'], + + mappings: + // Second line of src-transformed.js maps to src.js (source #0 here) + 'AAAAA' + + // Third line of src-transformed.js maps to other.js (source #1 here) + ';ACAAA', + }, + }, + ], + }; + + const map2 = { + version: 3, + sources: ['src-transformed.js'], + names: ['gLoBAl'], + // Map each line to itself + mappings: 'AAAAA;AACAA;AACAA', + }; + + const mergedMap = composeSourceMaps([map1, map2]); + + expect(mergedMap).toEqual( + objectContaining({ + sources: ['src.js', 'other.js'], + x_google_ignoreList: [0], + }), + ); + }); + it('preserves sourcesContent', () => { const map1 = { version: 3, diff --git a/packages/metro-source-map/src/composeSourceMaps.js b/packages/metro-source-map/src/composeSourceMaps.js index 4d6b0972d6..b97d84668e 100644 --- a/packages/metro-source-map/src/composeSourceMaps.js +++ b/packages/metro-source-map/src/composeSourceMaps.js @@ -27,6 +27,7 @@ function composeSourceMaps( ): MixedSourceMap { // NOTE: require() here to break dependency cycle const SourceMetadataMapConsumer = require('metro-symbolicate/src/SourceMetadataMapConsumer'); + const GoogleIgnoreListConsumer = require('metro-symbolicate/src/GoogleIgnoreListConsumer'); if (maps.length < 1) { throw new Error('composeSourceMaps: Expected at least one map'); } @@ -81,6 +82,11 @@ function composeSourceMaps( if (function_offsets) { composedMap.x_hermes_function_offsets = function_offsets; } + const ignoreListConsumer = new GoogleIgnoreListConsumer(firstMap); + const x_google_ignoreList = ignoreListConsumer.toArray(composedMap.sources); + if (x_google_ignoreList.length) { + composedMap.x_google_ignoreList = x_google_ignoreList; + } return composedMap; } diff --git a/packages/metro-source-map/src/source-map.js b/packages/metro-source-map/src/source-map.js index 890b68dc5b..800cb25d07 100644 --- a/packages/metro-source-map/src/source-map.js +++ b/packages/metro-source-map/src/source-map.js @@ -59,6 +59,7 @@ export type BasicSourceMap = { +x_facebook_sources?: FBSourcesArray, +x_facebook_segments?: FBSegmentMap, +x_hermes_function_offsets?: HermesFunctionOffsets, + +x_google_ignoreList?: Array, }; export type IndexMapSection = { @@ -82,6 +83,7 @@ export type IndexMap = { +x_facebook_sources?: void, +x_facebook_segments?: FBSegmentMap, +x_hermes_function_offsets?: HermesFunctionOffsets, + +x_google_ignoreList?: void, }; export type MixedSourceMap = IndexMap | BasicSourceMap; diff --git a/packages/metro-symbolicate/src/GoogleIgnoreListConsumer.js b/packages/metro-symbolicate/src/GoogleIgnoreListConsumer.js new file mode 100644 index 0000000000..e0f28a56fe --- /dev/null +++ b/packages/metro-symbolicate/src/GoogleIgnoreListConsumer.js @@ -0,0 +1,134 @@ +/** + * 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. + * + * @flow + * @format + * @oncall react_native + */ + +'use strict'; + +import type {BasicSourceMap, IndexMap, MixedSourceMap} from 'metro-source-map'; + +const {normalizeSourcePath} = require('metro-source-map'); + +type SourceNameNormalizer = (string, {+sourceRoot?: ?string, ...}) => string; + +/** + * Consumes the `x_google_ignoreList` metadata field from a source map and + * exposes various queries on it. + * + * By default, source names are normalized using the same logic that the + * `source-map@0.5.6` package uses internally. This is crucial for keeping the + * sources list in sync with a `SourceMapConsumer` instance. + + * If you're using this with a different source map reader (e.g. one that + * doesn't normalize source names at all), you can switch out the normalization + * function in the constructor, e.g. + * + * new GoogleIgnoreListConsumer(map, source => source) // Don't normalize + */ +class GoogleIgnoreListConsumer { + constructor( + map: MixedSourceMap, + normalizeSourceFn: SourceNameNormalizer = normalizeSourcePath, + ) { + this._sourceMap = map; + this._normalizeSource = normalizeSourceFn; + } + + _sourceMap: MixedSourceMap; + _normalizeSource: SourceNameNormalizer; + _ignoredSourceSet: ?Set; + + /** + * Returns `true` if the given source is in this map's ignore list, `false` + * otherwise. + * + * When used with the `source-map` package, you'll first use + * `SourceMapConsumer#originalPositionFor` to retrieve a source location, + * then pass that location to `isIgnored`. + */ + isIgnored({source}: {+source: ?string, ...}): boolean { + return source != null && this._getIgnoredSourceSet().has(source); + } + + /** + * Returns this map's ignore list as a new array with indices based on + * `sources`. + * + * This array can be used as the `x_google_ignoreList` field of a map whose + * `sources` field is the array that was passed into this method. + */ + toArray(sources: $ReadOnlyArray): Array { + const ignoredSourceSet = this._getIgnoredSourceSet(); + const encoded = []; + for (const [sourceIndex, source] of sources.entries()) { + if (source != null && ignoredSourceSet.has(source)) { + encoded.push(sourceIndex); + } + } + return encoded; + } + + /** + * Prepares and caches a set of ignored sources for this map. + */ + _getIgnoredSourceSet(): $ReadOnlySet { + if (!this._ignoredSourceSet) { + const ignoredSourceSet = new Set(); + + this._buildIgnoredSourceSet(this._sourceMap, ignoredSourceSet); + this._ignoredSourceSet = ignoredSourceSet; + } + return this._ignoredSourceSet; + } + + /** + * Collects ignored sources from the given map using the current source name + * normalization function. Handles both index maps (with sections) and plain + * maps. + * + * NOTE: If any sources are repeated in the map, we consider a source to be + * ignored as long as a source with the same normalized name is listed in AT + * LEAST one `x_google_ignoreList` array. Technically, this means we lose + * the granularity afforded by index maps and by the ability to repeat source + * names within a single `sources` array. + * + * Chrome's handling of duplicates is different: only the first occurrence of + * a given source is considered when determining if a source is ignored. It's + * unclear whether this is intentional. Absent a formal spec for + * `x_google_ignoreList`, we will diverge from Chrome for now. + * + * See: https://github.com/ChromeDevTools/devtools-frontend/blob/7afc9157b8d05de06e273284119e9c55a4eadb72/front_end/core/sdk/SourceMap.ts#L425-L429 + */ + _buildIgnoredSourceSet( + map: MixedSourceMap, + ignoredSourceSet: Set, + ): void { + // eslint-disable-next-line lint/strictly-null + if (map.mappings === undefined) { + const indexMap: IndexMap = map; + indexMap.sections.forEach(section => + this._buildIgnoredSourceSet(section.map, ignoredSourceSet), + ); + return; + } + + if ('x_google_ignoreList' in map) { + const basicMap: BasicSourceMap = map; + (basicMap.x_google_ignoreList || []).forEach(sourceIndex => { + let source = basicMap.sources[sourceIndex]; + if (source != null) { + source = this._normalizeSource(source, basicMap); + ignoredSourceSet.add(source); + } + }); + } + } +} + +module.exports = GoogleIgnoreListConsumer; diff --git a/packages/metro-symbolicate/src/Symbolication.js b/packages/metro-symbolicate/src/Symbolication.js index ba13d670cf..08672d2f0e 100644 --- a/packages/metro-symbolicate/src/Symbolication.js +++ b/packages/metro-symbolicate/src/Symbolication.js @@ -16,6 +16,7 @@ import type {HermesFunctionOffsets, MixedSourceMap} from 'metro-source-map'; import {typeof SourceMapConsumer} from 'source-map'; const {ChromeHeapSnapshotProcessor} = require('./ChromeHeapSnapshot'); +const GoogleIgnoreListConsumer = require('./GoogleIgnoreListConsumer'); const SourceMetadataMapConsumer = require('./SourceMetadataMapConsumer'); const fs = require('fs'); const invariant = require('invariant'); @@ -104,6 +105,7 @@ type SymbolicatedStackFrame = $ReadOnly<{ source: ?string, functionName: ?string, name: ?string, + isIgnored: boolean, }>; const UNKNOWN_MODULE_IDS: SingleMapModuleIds = { @@ -499,6 +501,7 @@ class SingleMapSymbolicationContext extends SymbolicationContext, +sourceFunctionsConsumer: ?SourceMetadataMapConsumer, +hermesOffsets: ?HermesFunctionOffsets, + +googleIgnoreListConsumer: GoogleIgnoreListConsumer, }, ... }; @@ -557,6 +560,14 @@ class SingleMapSymbolicationContext extends SymbolicationContext { source: filename, name: null, functionName: null, + isIgnored: false, }; } return this._loadMap(mapFilename).getOriginalPositionDetailsFor( diff --git a/packages/metro-symbolicate/src/__tests__/GoogleIgnoreListConsumer-test.js b/packages/metro-symbolicate/src/__tests__/GoogleIgnoreListConsumer-test.js new file mode 100644 index 0000000000..da63a1de38 --- /dev/null +++ b/packages/metro-symbolicate/src/__tests__/GoogleIgnoreListConsumer-test.js @@ -0,0 +1,53 @@ +/** + * 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. + * + * @flow strict-local + * @format + * @oncall react_native + */ + +'use strict'; + +const GoogleIgnoreListConsumer = require('../GoogleIgnoreListConsumer.js'); + +describe('GoogleIgnoreListConsumer', () => { + it('discards indices beyond the range of the sources array', () => { + const consumer = new GoogleIgnoreListConsumer({ + version: 3, + mappings: '', + sources: ['foo'], + names: [], + x_google_ignoreList: [9000], + }); + expect(consumer.toArray(['foo'])).toEqual([]); + }); + + it('discards the index of a null source', () => { + const consumer = new GoogleIgnoreListConsumer( + // $FlowIgnore[incompatible-call] intentionally malformed source map + { + version: 3, + mappings: '', + sources: ['foo', null], + names: [], + x_google_ignoreList: [0, 1], + }, + ); + expect(consumer.toArray(['foo', null])).toEqual([0]); + }); + + it('isIgnored works with a basic map', () => { + const consumer = new GoogleIgnoreListConsumer({ + version: 3, + mappings: '', + sources: ['foo', 'bar'], + names: [], + x_google_ignoreList: [1], + }); + expect(consumer.isIgnored({source: 'foo'})).toBe(false); + expect(consumer.isIgnored({source: 'bar'})).toBe(true); + }); +}); diff --git a/packages/metro-symbolicate/src/__tests__/Symbolication-test.js b/packages/metro-symbolicate/src/__tests__/Symbolication-test.js index 908b340a76..6f62d33a8c 100644 --- a/packages/metro-symbolicate/src/__tests__/Symbolication-test.js +++ b/packages/metro-symbolicate/src/__tests__/Symbolication-test.js @@ -19,6 +19,7 @@ const resolve = fileName => path.resolve(__dirname, '__fixtures__', fileName); const read = fileName => fs.readFileSync(resolve(fileName), 'utf8'); const TESTFILE_MAP = resolve('testfile.js.map'); +const WITH_IGNORE_LIST_MAP = resolve('with-ignore-list.js.map'); const UNKNOWN_MODULE_IDS = { segmentId: 0, @@ -97,3 +98,29 @@ test('constructs consumer instances lazily and caches them afterwards', () => { context.getOriginalPositionFor(31, 0, context.parseFileName('seg-1.js')); expect(consumerCount).toBe(2); }); + +test('returns ignore status of sources through getOriginalPositionDetailsFor', async () => { + const map = JSON.parse(read(WITH_IGNORE_LIST_MAP)); + const context = Symbolication.createContext(SourceMapConsumer, map); + expect(context.getOriginalPositionDetailsFor(3, 0)).toMatchInlineSnapshot(` + Object { + "column": 0, + "functionName": null, + "isIgnored": true, + "line": 12, + "name": null, + "source": "/node_modules/metro/src/lib/polyfills/require.js", + } + `); + expect(context.getOriginalPositionDetailsFor(427, 124)) + .toMatchInlineSnapshot(` + Object { + "column": 0, + "functionName": null, + "isIgnored": false, + "line": 3, + "name": "module", + "source": "/js/RKJSModules/segmented/biz.js", + } + `); +}); diff --git a/packages/metro-symbolicate/src/__tests__/__fixtures__/with-ignore-list.js.map b/packages/metro-symbolicate/src/__tests__/__fixtures__/with-ignore-list.js.map new file mode 100644 index 0000000000..019e802a31 --- /dev/null +++ b/packages/metro-symbolicate/src/__tests__/__fixtures__/with-ignore-list.js.map @@ -0,0 +1,249 @@ +{ + "version": 3, + "file": "/output", + "sections": [ + { + "map": { + "version": 3, + "sources": [ + "/../../node_modules/metro/src/lib/polyfills/require.js" + ], + "x_google_ignoreList": [0], + "names": [ + "global", + "__r", + "metroRequire", + "__d", + "define", + "__c", + "clear", + "__registerSegment", + "registerSegment", + "modules", + "EMPTY", + "hasOwnProperty", + "Object", + "create", + "__DEV__", + "verboseNamesToModuleIds", + "initializingModuleIds", + "factory", + "moduleId", + "dependencyMap", + "inverseDependencies", + "arguments", + "__accept", + "hasError", + "importedAll", + "importedDefault", + "isInitialized", + "publicModule", + "exports", + "hot", + "createHotReloadingObject", + "verboseName", + "Error", + "console", + "warn", + "moduleIdReallyIsNumber", + "initializingIndex", + "indexOf", + "cycle", + "slice", + "map", + "id", + "push", + "join", + "module", + "guardedLoadModule", + "metroImportDefault", + "__esModule", + "default", + "importDefault", + "metroImportAll", + "key", + "call", + "importAll", + "inGuard", + "ErrorUtils", + "returnValue", + "loadModuleImplementation", + "e", + "reportFatalError", + "ID_MASK_SHIFT", + "LOCAL_ID_MASK", + "unpackModuleId", + "segmentId", + "localId", + "packModuleId", + "value", + "hooks", + "registerHook", + "cb", + "hook", + "release", + "::release", + "i", + "length", + "splice", + "moduleDefinersBySegmentID", + "segmentID", + "moduleDefiner", + "definer", + "nativeRequire", + "unknownModuleError", + "moduleThrewError", + "error", + "Systrace", + "beginEvent", + "moduleObject", + "undefined", + "endEvent", + "pop", + "message", + "displayName", + "metroRequire.Systrace::beginEvent", + "metroRequire.Systrace::endEvent", + "getModules", + "metroRequire::getModules", + "acceptCallback", + "accept", + "hot::accept", + "callback", + "disposeCallback", + "dispose", + "hot::dispose", + "metroAcceptAll", + "dependentModules", + "patchedModules", + "notAccepted", + "filter", + "metroAccept", + "parents", + "apply", + "mod" + ], + "mappings": "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" + }, + "offset": { + "column": 0, + "line": 1 + } + }, + { + "map": { + "version": 3, + "sources": [ + "/js/RKJSModules/foo.js" + ], + "names": [ + "global", + "__promise", + "require" + ], + "mappings": "iGAAA,aAEAA,MAAM,CAACC,SAAPD,CAAmBE,WAAO,GAAA,OAAA,CAAPA,EAAnBF" + }, + "offset": { + "column": 0, + "line": 423 + } + }, + { + "map": { + "version": 3, + "sources": [ + "/js/RKJSModules/bar.js" + ], + "names": [ + "bar", + "_$$_REQUIRE", + "then", + "glo", + "makeItThrow", + "makeItThrowInner", + "throwSmth", + "module", + "exports" + ], + "mappings": "iGAAA,aAEAA,QAASA,CAAAA,GAATA,EAAeA,CACb,MAAOC,CAAAA,WAAA,GAAA,cAAA,CAAA,GAAA,oBAAA,EAA6BC,IAA7B,CAAkC,SAAAC,GAAA,CAAO,CAC9CC,WAAW,CAACD,GAAD,CAAXC,CADK,CAAA,CAAP,CAGD,CAEDA,QAASA,CAAAA,WAATA,CAAqBD,GAArBC,CAA0BA,CACxBC,gBAAgB,CAACF,GAAD,CAAhBE,CACD,CAEDA,QAASA,CAAAA,gBAATA,CAA0BF,GAA1BE,CAA+BA,CAC7BF,GAAG,CAACG,SAAJH,GACD,CAEDI,MAAM,CAACC,OAAPD,CAAiBP,GAAjBO" + }, + "offset": { + "column": 0, + "line": 424 + } + }, + { + "map": { + "version": 3, + "sources": [ + "/js/RKJSModules/segmented/glo.js" + ], + "names": [ + "biz", + "require", + "module", + "exports", + "throwSmth", + "module.exports::throwSmth", + "throwSmthInner" + ], + "mappings": "iGAAA,aAEA,GAAMA,CAAAA,GAAG,CAAGC,WAAO,GAAA,OAAA,CAAnB,CAEAC,MAAM,CAACC,OAAPD,CAAiB,CACfE,SADe,CACHC,QAAAA,CAAAA,SAAAA,EAAAA,CACV,MAAOL,CAAAA,GAAG,CAACM,cAAJN,EAAP,CACD,CAHc,CAAjBE" + }, + "offset": { + "column": 0, + "line": 425 + } + }, + { + "map": { + "version": 3, + "sources": [ + "/js/RKJSModules/segmented/biz.js" + ], + "names": [ + "module", + "exports", + "throwSmthInner", + "module.exports::throwSmthInner", + "Error" + ], + "mappings": "iGAAA,aAEAA,MAAM,CAACC,OAAPD,CAAiB,CACfE,cADe,CACEC,QAAAA,CAAAA,cAAAA,EAAAA,CACf,KAAM,IAAIC,CAAAA,KAAJ,CAAU,uBAAV,CAAN,CACD,CAHc,CAAjBJ" + }, + "offset": { + "column": 0, + "line": 426 + } + }, + { + "map": { + "version": 3, + "sources": [ + "/js/RKJSModules/asyncRequire.js" + ], + "names": [ + "dynReq", + "require", + "module", + "exports", + "module::exports", + "asyncRequire", + "moduleId", + "Promise", + "resolve", + "then", + "_require$unpackModule", + "unpackModuleId", + "segmentId", + "global", + "__runSegment" + ], + "mappings": "iGAAA,aAEA,GAAMA,CAAAA,MAAM,CAAGC,WAAf,CACAC,MAAM,CAACC,OAAPD,CAAiBE,QAASC,CAAAA,YAATD,CAAsBE,QAAtBF,CAAgCA,CAC/C,MAAOG,CAAAA,OAAO,CAACC,OAARD,GAAkBE,IAAlBF,CAAuB,UAAM,CAAA,GAAAG,CAAAA,qBAAA,CACdT,WAAO,CAACU,cAARV,CAAuBK,QAAvBL,CADc,CAC3BW,SAD2B,CAAAF,qBAAA,CAC3BE,SAD2B,CAElC,GAAIA,SAAS,CAAG,CAAhB,CAAmBC,MAAM,CAACC,YAAPD,CAAoBD,SAApBC,EACnB,MAAOb,CAAAA,MAAM,CAACM,QAAD,CAAb,CAHK,CAAAC,CAAP,CADF,CAAAL" + }, + "offset": { + "column": 0, + "line": 427 + } + } + ], + "x_facebook_segments": {} +} diff --git a/packages/metro-symbolicate/src/__tests__/__fixtures__/with-ignore-list.stack b/packages/metro-symbolicate/src/__tests__/__fixtures__/with-ignore-list.stack new file mode 100644 index 0000000000..8b89310863 --- /dev/null +++ b/packages/metro-symbolicate/src/__tests__/__fixtures__/with-ignore-list.stack @@ -0,0 +1,2 @@ +Object.throwSmthInner@bundle.js:427:174 +r@bundle.js:2:0 diff --git a/packages/metro-symbolicate/src/__tests__/__snapshots__/symbolicate-test.js.snap b/packages/metro-symbolicate/src/__tests__/__snapshots__/symbolicate-test.js.snap index b3564821a6..e2b6639165 100644 --- a/packages/metro-symbolicate/src/__tests__/__snapshots__/symbolicate-test.js.snap +++ b/packages/metro-symbolicate/src/__tests__/__snapshots__/symbolicate-test.js.snap @@ -15,6 +15,7 @@ Array [ Object { "column": 2, "functionName": "", + "isIgnored": false, "line": 16, "name": null, "source": "/js/react-native-github/Libraries/Utilities/createPerformanceLogger.js", @@ -22,6 +23,7 @@ Array [ Object { "column": 2, "functionName": "", + "isIgnored": false, "line": 25, "name": null, "source": "/js/RKJSModules/Libraries/MobileConfig/MobileConfig.js", @@ -29,6 +31,7 @@ Array [ Object { "column": 0, "functionName": "", + "isIgnored": false, "line": 8, "name": null, "source": "/js/RKJSModules/Apps/HermesModulesTest/HMTLazyFetched.js", @@ -41,6 +44,7 @@ Array [ Object { "column": 9, "functionName": "", + "isIgnored": false, "line": 162, "name": "param", "source": "/js/RKJSModules/Libraries/MobileConfig/MobileConfig.js", @@ -48,6 +52,7 @@ Array [ Object { "column": 21, "functionName": "", + "isIgnored": false, "line": 100, "name": null, "source": "/js/RKJSModules/Libraries/MobileConfig/MobileConfig.js", @@ -55,6 +60,7 @@ Array [ Object { "column": 15, "functionName": "getValue", + "isIgnored": false, "line": 10, "name": "getValue", "source": "/js/RKJSModules/Apps/HermesModulesTest/HMTLazyFetched.js", @@ -87,6 +93,7 @@ Array [ Object { "column": 21, "functionName": "columns.forEach$argument_0", + "isIgnored": false, "line": 480, "name": "rows", "source": "/js/node_modules/react-native/Libraries/polyfills/console.js", @@ -94,6 +101,7 @@ Array [ Object { "column": 8, "functionName": "setEnabled", + "isIgnored": false, "line": 101, "name": "_enabled", "source": "/js/react-native-github/Libraries/Performance/Systrace.js", @@ -101,6 +109,7 @@ Array [ Object { "column": 2, "functionName": "getValue", + "isIgnored": false, "line": 13, "name": null, "source": "/js/RKJSModules/Apps/HermesModulesTest/HMTLazyFetched.js", @@ -108,6 +117,7 @@ Array [ Object { "column": null, "functionName": null, + "isIgnored": false, "line": null, "name": null, "source": null, @@ -115,6 +125,7 @@ Array [ Object { "column": 2, "functionName": "getValue", + "isIgnored": false, "line": 13, "name": null, "source": "/js/RKJSModules/Apps/HermesModulesTest/HMTLazyFetched.js", @@ -130,6 +141,7 @@ Array [ Object { "column": 36, "functionName": "result.clearExceptTimespans", + "isIgnored": false, "line": 160, "name": null, "source": "/js/react-native-github/Libraries/Utilities/createPerformanceLogger.js", @@ -137,6 +149,7 @@ Array [ Object { "column": 2, "functionName": "getValue", + "isIgnored": false, "line": 13, "name": null, "source": "/js/RKJSModules/Apps/HermesModulesTest/HMTLazyFetched.js", @@ -144,6 +157,7 @@ Array [ Object { "column": 2, "functionName": "getValue", + "isIgnored": false, "line": 13, "name": null, "source": "/js/RKJSModules/Apps/HermesModulesTest/HMTLazyFetched.js", @@ -151,6 +165,7 @@ Array [ Object { "column": 2, "functionName": "getValue", + "isIgnored": false, "line": 13, "name": null, "source": "/js/RKJSModules/Apps/HermesModulesTest/HMTLazyFetched.js", @@ -166,6 +181,7 @@ Array [ Object { "column": 36, "functionName": "result.clearExceptTimespans", + "isIgnored": false, "line": 160, "name": null, "source": "/js/react-native-github/Libraries/Utilities/createPerformanceLogger.js", @@ -173,6 +189,7 @@ Array [ Object { "column": 2, "functionName": "getValue", + "isIgnored": false, "line": 13, "name": null, "source": "/js/RKJSModules/Apps/HermesModulesTest/HMTLazyFetched.js", @@ -180,6 +197,7 @@ Array [ Object { "column": 2, "functionName": "getValue", + "isIgnored": false, "line": 13, "name": null, "source": "/js/RKJSModules/Apps/HermesModulesTest/HMTLazyFetched.js", @@ -187,6 +205,7 @@ Array [ Object { "column": 2, "functionName": "getValue", + "isIgnored": false, "line": 13, "name": null, "source": "/js/RKJSModules/Apps/HermesModulesTest/HMTLazyFetched.js",