CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-metro-source-map

Source map generator for Metro bundler with advanced mapping capabilities and Facebook/Hermes extensions.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

generation.mddocs/

Source Map Generation

Core functionality for creating source maps from raw mappings with support for Metro's specific requirements, Facebook extensions, and Hermes integration.

Capabilities

Raw Mappings to Source Map

Create source maps from raw mappings data, which are arrays of tuples representing the relationship between generated and original code positions.

/**
 * Creates a source map from modules with raw mappings (synchronous)
 * @param modules - Array of module objects with mappings and metadata
 * @param offsetLines - Number of lines to offset in the resulting bundle
 * @returns Generator instance for creating the final source map
 */
function fromRawMappings(
  modules: Array<{
    map: ?Array<MetroSourceMapSegmentTuple>,
    functionMap: ?FBSourceFunctionMap,
    path: string,
    source: string,
    code: string,
    isIgnored: boolean,
    lineCount?: number
  }>,
  offsetLines?: number = 0
): Generator;

/**
 * Creates a source map from modules with raw mappings (asynchronous, non-blocking)
 * @param modules - Array of module objects with mappings and metadata
 * @param offsetLines - Number of lines to offset in the resulting bundle
 * @returns Promise resolving to Generator instance
 */
function fromRawMappingsNonBlocking(
  modules: Array<{
    map: ?Array<MetroSourceMapSegmentTuple>,
    functionMap: ?FBSourceFunctionMap,
    path: string,
    source: string,
    code: string,
    isIgnored: boolean,
    lineCount?: number
  }>,
  offsetLines?: number = 0
): Promise<Generator>;

Usage Examples:

const { fromRawMappings, fromRawMappingsNonBlocking } = require("metro-source-map");

// Synchronous generation
const modules = [
  {
    map: [
      [1, 0, 1, 0],           // Line 1, Col 0 -> Line 1, Col 0
      [1, 12, 1, 12, "log"],  // Line 1, Col 12 -> Line 1, Col 12, name "log"
      [2, 0, 2, 0]            // Line 2, Col 0 -> Line 2, Col 0
    ],
    functionMap: null,
    path: "src/utils.js",
    source: "console.log('hello');\nmodule.exports = {};",
    code: "console.log('hello');\nmodule.exports = {};",
    isIgnored: false,
    lineCount: 2
  }
];

const generator = fromRawMappings(modules, 0);
const sourceMap = generator.toMap("bundle.js");

// Asynchronous generation (non-blocking)
const generatorAsync = await fromRawMappingsNonBlocking(modules, 0);
const sourceMapAsync = generatorAsync.toMap("bundle.js");

Generator Class

The Generator class is used internally by fromRawMappings functions. It is not directly exported but is returned by those functions for building source maps incrementally.

/**
 * Generator class for creating source maps from raw mappings
 * (Returned by fromRawMappings functions, not directly constructible)
 */
class Generator {
  
  /**
   * Start processing a new source file
   * @param file - Path to the source file
   * @param code - Source code content for the file  
   * @param functionMap - Optional Facebook function map for debugging
   * @param options - Optional file processing flags
   */
  startFile(
    file: string, 
    code: string, 
    functionMap?: FBSourceFunctionMap, 
    options?: FileFlags
  ): void;
  
  /**
   * End processing of the current source file
   */
  endFile(): void;
  
  /**
   * Add a simple mapping (generated position only)
   * @param line - Generated line number (1-based)
   * @param column - Generated column number (0-based)
   */
  addSimpleMapping(line: number, column: number): void;
  
  /**
   * Add a source mapping (generated to original position)
   * @param line - Generated line number (1-based)
   * @param column - Generated column number (0-based)
   * @param originalLine - Original line number (1-based)
   * @param originalColumn - Original column number (0-based)
   */
  addSourceMapping(
    line: number, 
    column: number, 
    originalLine: number, 
    originalColumn: number
  ): void;
  
  /**
   * Add a named source mapping (includes symbol name)
   * @param line - Generated line number (1-based)
   * @param column - Generated column number (0-based)
   * @param originalLine - Original line number (1-based)
   * @param originalColumn - Original column number (0-based)
   * @param name - Symbol name in original source
   */
  addNamedSourceMapping(
    line: number, 
    column: number, 
    originalLine: number, 
    originalColumn: number, 
    name: string
  ): void;
  
  /**
   * Generate the final source map object
   * @param file - Optional file name for the generated source map
   * @param options - Optional generation options
   * @returns Complete source map object
   */
  toMap(file?: string, options?: {excludeSource?: boolean}): BasicSourceMap;
  
  /**
   * Serialize the source map to a JSON string
   * @param file - Optional file name for the generated source map
   * @param options - Optional generation options
   * @returns JSON string representation of the source map
   */
  toString(file?: string, options?: {excludeSource?: boolean}): string;
}

Usage Examples:

const { fromRawMappings } = require("metro-source-map");

// Get Generator instance through fromRawMappings
const modules = [/* ... */];
const generator = fromRawMappings(modules);

// Start a file
generator.startFile("src/app.js", "console.log('hello');", null, { addToIgnoreList: false });

// Add mappings
generator.addSimpleMapping(1, 0);                    // Generated only
generator.addSourceMapping(1, 8, 1, 8);             // Generated -> Original
generator.addNamedSourceMapping(1, 12, 1, 12, "console"); // With name

// End the file
generator.endFile();

// Generate the source map
const sourceMap = generator.toMap("dist/bundle.js");
console.log(sourceMap.mappings); // Base64 VLQ encoded mappings

Segment Tuple Types

Raw mapping segments can have 2, 4, or 5 elements representing different levels of mapping detail.

/**
 * Metro source map segment tuple formats:
 * - GeneratedCodeMapping: [generatedLine, generatedColumn]
 * - SourceMapping: [generatedLine, generatedColumn, originalLine, originalColumn]  
 * - SourceMappingWithName: [generatedLine, generatedColumn, originalLine, originalColumn, symbolName]
 */
type MetroSourceMapSegmentTuple =
  | [number, number]                           // Generated position only
  | [number, number, number, number]           // Generated -> Original position
  | [number, number, number, number, string];  // Generated -> Original position + name

/**
 * File processing options
 */
interface FileFlags {
  /** Whether to add this file to the ignore list for debugging */
  addToIgnoreList?: boolean;
}

Error Handling

The generation functions and Generator class methods may throw errors in the following cases:

  • Invalid mapping format: When segment tuples don't have 2, 4, or 5 elements
  • File processing errors: When startFile/endFile calls are not properly paired
  • Invalid coordinates: When line/column numbers are negative or invalid
try {
  const generator = fromRawMappings(modules);
  const sourceMap = generator.toMap();
} catch (error) {
  if (error.message.includes('Invalid mapping')) {
    console.error('Mapping data is malformed:', error);
  }
}

docs

bundle-building.md

composition.md

consumption.md

function-maps.md

generation.md

index.md

utilities.md

tile.json