Source Map Format
Metro produces standard source maps along with its JavaScript bundle output. In addition to the standard information, Metro encodes extra information in vendor-specific fields within the source map. This page specifies these fields.
It's for authors of tools that read, generate or transform Metro's source maps, such as debuggers, symbolication services or bundle post-processors. App developers can skip it: their tools consume these fields.
The content on this page assumes familiarity with the source map specification. Check out Anatomy of source maps for a general introduction to source maps and how they work.
x_facebook_sources
The x_facebook_sources field encodes metadata about source files in a source map, each piece representing some attribute intrinsic to that file's source code, e.g. the result of running some analysis over the AST. This lets tools such as debuggers and JS engines access such analyses efficiently, without parsing or even having access to the source code.
In the same way that the standard sources field is a list of source URLs and sourcesContent is a list of (optional) source code strings, x_facebook_sources is a list of optional metadata tuples. The i-th metadata tuple (x_facebook_sources[i]) corresponds to the source file whose URL is sources[i].
In nested (indexed) source maps, x_facebook_sources may appear as part of any nested source map in sections that itself has a sources field.
If present, x_facebook_sources may be a different length than sources (but usually shouldn't be). If it's shorter, it's interpreted as if padded with null values to the length of sources.
For a tool that processes Metro's source maps to output a valid x_facebook_sources field, it mainly needs to ensure that x_facebook_sources[i] still corresponds to sources[i] in the output - even if it reorders, adds or deletes elements in sources. This can be done without parsing/decoding the metadata tuples: unless your tool needs the information within them, treat them as opaque blobs of JSON.
If a tool cannot guarantee that the sources and x_facebook_sources arrays will stay in sync, it should delete the x_facebook_sources field from its output.
Metadata tuple
Each metadata tuple is encoded as an array of zero or more entries. Each entry may be null to signify that it's missing. A run of trailing nulls may be truncated from the end of the tuple with no change in meaning. The metadata tuple itself may also be null to signify that the source file has no associated metadata.
The indices in each metadata tuple are assigned as follows:
- Index 0: Function map or
null.- In Metro, this is the result of calling
generateFunctionMapon the source AST.
- In Metro, this is the result of calling
- Index 1- ∞: Reserved for future use.
Function map
A function map records the name of the function that encloses each region of a source file, so that tools can show function names for code locations, e.g. in stack traces. It is encoded as an object with two fields:
names: An array of strings.mappings: A string following the encoding described below.
When decoded, mappings represents a list of 3-tuples of integers: (column, nameIndex, line), (column, nameIndex, line), .... The list is ordered by line and then column.
The presence of a 3-tuple (column, nameIndex, line) means that the local function name in the code region beginning at line and column (in the source file described by the current metadata tuple) is names[nameIndex].
Function map mappings field encoding
The mappings field follows the Mappings production of this grammar:
Mappings = [ ";" ] LineMappings { ";" { ";" } LineMappings }LineMappings = FirstColumnMapping { "," ColumnMapping }FirstColumnMapping = VLQ VLQ VLQColumnMapping = VLQ VLQ [ VLQ ]VLQ =A single Base64-encoded variable-length quantity, as defined in the source map specification.
The above grammar uses the following BNF-like notation:
| Notation | Meaning |
|---|---|
[ X ] | X appears 0 or 1 times. |
{ X } | X appears 0 or more times. |
"foo" | The literal characters foo. |
The three VLQs in FirstColumnMapping or ColumnMapping represent, in this order:
- Column delta:
- In FirstColumnMapping: The column offset from the beginning of the line. (0 = first column)
- In ColumnMapping: The column offset from the last-encountered FirstColumnMapping or ColumnMapping.
- Name delta: The name index offset from the last-encountered FirstColumnMapping or ColumnMapping. This is not reset between lines.
- Line delta: The line offset from the last-encountered FirstColumnMapping or ColumnMapping. This is not reset between lines.
- This MUST be 0 (Base64 VLQ:
A) if it is part of a ColumnMapping. - Implementations SHOULD omit this field from the encoded form of ColumnMapping.
- This MUST be 0 (Base64 VLQ:
Example
A complete source map for a single source file file.js might look like this:
Comments are for illustrative purposes - the source map format does not allow comments.
{
"version": 3,
"sources": ["file.js"],
"sourcesContent": ["function a(){} function b(){}"],
"mappings": "AAAA", // NOTE: Simplified
"x_facebook_sources": [
// Metadata tuple for source #0 (file.js)
[
// Metadata item #0.0 = function map for source #0 (file.js)
{
// a from 1:0
// <global> from 1:14
// b from 1:15
// (See detailed decoding procedure below.)
"mappings": "AAA,cC,CC",
"names": ["a", "<global>", "b"]
}
]
]
}
Decoding the function map in the above example:
const decoded = [];
const names = ['a', '<global>', 'b']; // From the function map
let column = 0, nameIndex = 0, line = 1;
column += 0 /* A */; nameIndex += 0 /* A */; line += 0 /* A */;
decoded.push({column, name: names[nameIndex] /* 'a' */, line});
column += 14 /* c */; nameIndex += 1 /* C */; // no line delta
decoded.push({column, name: names[nameIndex] /* '<global>' */, line});
column += 1 /* C */; nameIndex += 1 /* C */; // no line delta
decoded.push({column, name: names[nameIndex] /* 'b' */, line});
/*
decoded = [
{column: 0, name: 'a', line: 1},
{column: 14, name: '<global>', line: 1},
{column: 15, name: 'b', line: 1},
]
*/
x_google_ignoreList
Metro's source maps include the x_google_ignoreList field by default, listing sources that debuggers should treat as third-party code, e.g. by hiding them from stack traces and skipping them when stepping. Use the serializer.isThirdPartyModule option to control which modules are ignore-listed.
The field lists indices into sources. By default, files under node_modules are ignore-listed:
{
"sources": ["index.js", "node_modules/react/index.js"],
"x_google_ignoreList": [1]
}