A tool to find the source location from JS bundles and stack traces.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Processing of Google's ignore list extension for source maps, used to mark generated or third-party code that should be ignored during debugging.
Processes x_google_ignoreList metadata from source maps to identify sources that should be ignored during debugging and error reporting.
/**
* Consumes Google ignore list metadata from source maps
* @param map - Source map object (BasicSourceMap or IndexMap)
* @param normalizeSourceFn - Optional function to normalize source names
*/
class GoogleIgnoreListConsumer {
constructor(map: MixedSourceMap, normalizeSourceFn?: SourceNameNormalizer);
/**
* Checks if a source is in the ignore list
* @param {source} - Object containing source file name to check (can be null)
* @returns true if source should be ignored, false otherwise
*/
isIgnored({source}: {source: ?string}): boolean;
/**
* Returns this map's ignore list as a new array with indices based on sources
* @param sources - Array of source names
* @returns Array of indices representing ignored sources
*/
toArray(sources: Array<?string>): Array<number>;
}Usage Examples:
const GoogleIgnoreListConsumer = require('metro-symbolicate/private/GoogleIgnoreListConsumer');
const fs = require('fs');
// Load source map with ignore list
const sourceMap = JSON.parse(fs.readFileSync('bundle.js.map', 'utf8'));
const ignoreListConsumer = new GoogleIgnoreListConsumer(sourceMap);
// Check if sources should be ignored
const shouldIgnore = ignoreListConsumer.isIgnored({source: 'node_modules/react/index.js'});
if (shouldIgnore) {
console.log('Source is in ignore list - skip in stack traces');
}
// Filter stack traces to exclude ignored sources
const filterStackTrace = (trace, ignoreConsumer) => {
return trace
.split('\n')
.filter(line => {
const match = line.match(/at .* \((.*?):\d+:\d+\)/);
if (match) {
const source = match[1];
return !ignoreConsumer.isIgnored({source});
}
return true;
})
.join('\n');
};Seamlessly integrates with debugging tools and stack trace processing to hide generated or third-party code.
Common Use Cases:
// Example: Enhanced stack trace symbolication with ignore list filtering
const Symbolication = require('metro-symbolicate/private/Symbolication');
const GoogleIgnoreListConsumer = require('metro-symbolicate/private/GoogleIgnoreListConsumer');
const { SourceMapConsumer } = require('source-map');
const processStackTraceWithFiltering = (sourceMapContent, stackTrace) => {
// Create symbolication context
const context = Symbolication.createContext(SourceMapConsumer, sourceMapContent);
// Create ignore list consumer
const sourceMap = JSON.parse(sourceMapContent);
const ignoreList = new GoogleIgnoreListConsumer(sourceMap);
// Symbolicate the stack trace
const symbolicatedTrace = context.symbolicate(stackTrace);
// Filter out ignored sources
const filteredTrace = symbolicatedTrace
.split('\n')
.filter(line => {
const match = line.match(/at .* \((.*?):\d+:\d+\)/);
if (match) {
const source = match[1];
return !ignoreList.isIgnored({source});
}
return true; // Keep non-source lines (error messages, etc.)
})
.join('\n');
return filteredTrace;
};Handles source name normalization to ensure consistent matching between source maps and ignore lists.
Default Normalization:
Uses the same normalization logic as the source-map@0.5.6 package to ensure consistency:
const GoogleIgnoreListConsumer = require('metro-symbolicate/private/GoogleIgnoreListConsumer');
// Default normalization (same as source-map library)
const consumer = new GoogleIgnoreListConsumer(sourceMap);
// Custom normalization for specific bundler configurations
const customConsumer = new GoogleIgnoreListConsumer(sourceMap, (source, options) => {
// Remove webpack-specific prefixes
if (source.startsWith('webpack:///')) {
source = source.slice('webpack:///'.length);
}
// Handle source root
if (options.sourceRoot && !source.startsWith('/')) {
source = options.sourceRoot.replace(/\/$/, '') + '/' + source;
}
return source;
});Usage Examples:
// Working with different bundler outputs
const createIgnoreListConsumer = (sourceMap, bundlerType) => {
let normalizer;
switch (bundlerType) {
case 'webpack':
normalizer = (source) => source.replace(/^webpack:\/\/\//, '');
break;
case 'metro':
normalizer = (source) => source; // Metro uses standard normalization
break;
default:
normalizer = undefined; // Use default normalization
}
return new GoogleIgnoreListConsumer(sourceMap, normalizer);
};Understands the standard Google ignore list format used in source maps.
Source Map Ignore List Structure:
// Example source map with ignore list
{
"version": 3,
"sources": [
"src/app.js", // index 0 - application code
"src/utils.js", // index 1 - application code
"node_modules/react/index.js", // index 2 - library code
"webpack/bootstrap" // index 3 - generated code
],
"x_google_ignoreList": [2, 3], // Ignore sources at indices 2 and 3
// ... other source map fields
}Ignore List Processing:
const consumer = new GoogleIgnoreListConsumer(sourceMap);
// Check specific sources
console.log(consumer.isIgnored({source: 'src/app.js'})); // false
console.log(consumer.isIgnored({source: 'src/utils.js'})); // false
console.log(consumer.isIgnored({source: 'node_modules/react/index.js'})); // true
console.log(consumer.isIgnored({source: 'webpack/bootstrap'})); // true
// Handle null/undefined sources gracefully
console.log(consumer.isIgnored({source: null})); // false
console.log(consumer.isIgnored({source: undefined})); // falseEfficiently processes ignore lists using internal caching for repeated queries.
// Internal ignore set is built lazily and cached
const consumer = new GoogleIgnoreListConsumer(largeSourceMap);
// First call builds the ignore set
const isIgnored1 = consumer.isIgnored({source: 'some/source.js'});
// Subsequent calls use cached set for fast lookups
const isIgnored2 = consumer.isIgnored({source: 'another/source.js'});
const isIgnored3 = consumer.isIgnored({source: 'third/source.js'});Gracefully handles missing or malformed ignore list data.
// Missing ignore list - no sources are ignored
const sourceMapWithoutIgnoreList = {
version: 3,
sources: ['src/app.js'],
mappings: '...'
// No x_google_ignoreList field
};
const consumer = new GoogleIgnoreListConsumer(sourceMapWithoutIgnoreList);
console.log(consumer.isIgnored({source: 'src/app.js'})); // false
// Invalid ignore list indices are handled gracefully
const sourceMapWithInvalidIgnoreList = {
version: 3,
sources: ['src/app.js'],
mappings: '...',
x_google_ignoreList: [999] // Index out of bounds
};
const invalidConsumer = new GoogleIgnoreListConsumer(sourceMapWithInvalidIgnoreList);
console.log(invalidConsumer.isIgnored({source: 'src/app.js'})); // falsetype MixedSourceMap = BasicSourceMap | IndexMap;
type BasicSourceMap = {
version: number;
sources: Array<string>;
names: Array<string>;
mappings: string;
file?: string;
sourceRoot?: string;
sourcesContent?: Array<?string>;
x_google_ignoreList?: Array<number>; // Array of source indices to ignore
};
type IndexMap = {
version: number;
file?: string;
sections: Array<IndexMapSection>;
x_google_ignoreList?: Array<number>; // Array of source indices to ignore
};
type SourceNameNormalizer = (
source: string,
options: { sourceRoot?: ?string }
) => string;