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

function-maps.mddocs/

Function Maps

Facebook-specific extensions for generating function maps that provide enhanced debugging support in Hermes and React Native environments.

Capabilities

Function Map Generation

Generate function maps from Abstract Syntax Trees (ASTs) to enable better debugging and profiling in Hermes and React Native.

/**
 * Generates a function map from a Babel AST
 * Function maps provide debugging information about function locations and names
 * @param ast - Babel AST node (typically a Program node)
 * @param context - Optional context object with filename information
 * @returns Facebook-format function map with names and mappings
 */
function generateFunctionMap(ast: BabelNode, context?: Context): FBSourceFunctionMap;

/**
 * Babel plugin that automatically generates function maps during transformation
 * @returns Babel plugin object for integration into Babel transformation pipeline
 */
function functionMapBabelPlugin(): PluginObj;

Usage Examples:

const { generateFunctionMap, functionMapBabelPlugin } = require("metro-source-map");
const parser = require("@babel/parser");
const babel = require("@babel/core");

// Generate function map from AST
const code = `
function greet(name) {
  return 'Hello ' + name;
}

const calculate = (a, b) => a + b;

class Calculator {
  add(x, y) {
    return x + y;
  }
}
`;

const ast = parser.parse(code, {
  sourceType: "module",
  plugins: ["jsx", "typescript"]
});

const functionMap = generateFunctionMap(ast, {});
console.log(functionMap);
// {
//   names: ["greet", "calculate", "Calculator", "add"],
//   mappings: "AAAA;IAII;QAII"
// }

// Use as Babel plugin
const result = babel.transformSync(code, {
  plugins: [functionMapBabelPlugin()]
});

// The plugin adds function map data to the transformation result
console.log(result.metadata.functionMap);

Function Map Types

/**
 * Facebook source function map format
 */
interface FBSourceFunctionMap {
  /** Array of function names in order of appearance */
  names: Array<string>;
  /** Base64 VLQ encoded mappings for function positions */
  mappings: string;
}

/**
 * Facebook source metadata containing function map
 */
type FBSourceMetadata = [?FBSourceFunctionMap];

/**
 * Array of source metadata for multiple sources
 */
type FBSourcesArray = Array<?FBSourceMetadata>;

/**
 * Hermes function offsets for bytecode debugging
 */
interface HermesFunctionOffsets {
  /** Maps function IDs to arrays of bytecode offsets */
  [functionId: number]: Array<number>;
}

Integration with Metro Source Maps

const { generateFunctionMap, fromRawMappings } = require("metro-source-map");
const parser = require("@babel/parser");

// Generate source map with function map integration
function generateSourceMapWithFunctions(modules) {
  const processedModules = modules.map(module => {
    // Parse the source code to generate function map
    const ast = parser.parse(module.source, {
      sourceType: "module",
      plugins: ["jsx", "flow"]
    });
    
    const functionMap = generateFunctionMap(ast, {});
    
    return {
      ...module,
      functionMap: functionMap
    };
  });
  
  // Generate source map with function maps included
  const generator = fromRawMappings(processedModules);
  return generator.toMap();
}

// Usage
const modules = [{
  map: [[1, 0, 1, 0], [2, 0, 2, 0]],
  path: "src/utils.js",
  source: "function helper() { return true; }",
  code: "function helper() { return true; }",
  isIgnored: false
}];

const sourceMapWithFunctions = generateSourceMapWithFunctions(modules);
console.log(sourceMapWithFunctions.x_facebook_sources);

Babel Plugin Integration

const { functionMapBabelPlugin } = require("metro-source-map");
const babel = require("@babel/core");

// Configure Babel with function map plugin
const babelConfig = {
  plugins: [
    functionMapBabelPlugin(),
    // ... other plugins
  ],
  presets: [
    "@babel/preset-react",
    "@babel/preset-typescript"
  ]
};

// Transform code with function map generation
const sourceCode = `
import React from 'react';

function MyComponent({ title }) {
  const handleClick = () => {
    console.log('Clicked');
  };
  
  return (
    <div onClick={handleClick}>
      <h1>{title}</h1>
    </div>
  );
}

export default MyComponent;
`;

const result = babel.transformSync(sourceCode, babelConfig);

// Access generated function map
const functionMap = result.metadata?.functionMap;
if (functionMap) {
  console.log('Function names:', functionMap.names);
  console.log('Function mappings:', functionMap.mappings);
}

Advanced Function Map Features

const { generateFunctionMap } = require("metro-source-map");
const parser = require("@babel/parser");

// Complex code with various function types
const complexCode = `
// Named function
function namedFunction() {}

// Arrow function
const arrowFn = () => {};

// Method in object
const obj = {
  method() {},
  asyncMethod: async function() {}
};

// Class with methods
class MyClass {
  constructor() {}
  
  instanceMethod() {}
  
  static staticMethod() {}
  
  get getter() {}
  
  set setter(value) {}
}

// Anonymous function expression
const anonymous = function() {};

// Generator function
function* generator() {}

// Async function
async function asyncFn() {}
`;

const ast = parser.parse(complexCode, {
  sourceType: "module",
  plugins: ["classProperties", "asyncGenerators"]
});

const functionMap = generateFunctionMap(ast, {
  // Additional options can be passed here
});

console.log('Detected functions:', functionMap.names);
// Output: All function names including constructors, methods, getters, setters

React Native and Hermes Integration

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

// Generate source maps optimized for React Native/Hermes debugging
function generateReactNativeSourceMap(modules) {
  return fromRawMappings(modules.map(module => ({
    ...module,
    // Generate function map for better Hermes debugging
    functionMap: module.ast ? generateFunctionMap(module.ast, {
      // Hermes-specific optimizations
      includeConstructors: true,
      includeGettersSetters: true
    }) : null
  })));
}

// Usage in Metro bundler integration
const reactNativeModules = [
  {
    map: rawMappings,
    path: "App.js",
    source: reactComponentCode,
    code: transformedCode,
    ast: parsedAST,
    isIgnored: false
  }
];

const generator = generateReactNativeSourceMap(reactNativeModules);
const sourceMap = generator.toMap("bundle.js");

// The resulting source map includes function maps for Hermes debugging
console.log(sourceMap.x_facebook_sources);
console.log(sourceMap.x_hermes_function_offsets);

Error Handling

Function map generation may encounter errors in the following cases:

  • Invalid AST: When the provided AST is malformed or missing required nodes
  • Parsing errors: When source code cannot be parsed into a valid AST
  • Plugin configuration errors: When the Babel plugin is misconfigured
const { generateFunctionMap } = require("metro-source-map");

try {
  const functionMap = generateFunctionMap(ast, options);
} catch (error) {
  if (error.message.includes('Invalid AST')) {
    console.error('AST is malformed:', error);
  } else {
    console.error('Function map generation failed:', error);
  }
}

// Safe function map generation
function safeGenerateFunctionMap(ast, options = {}) {
  try {
    if (!ast || ast.type !== 'Program') {
      return null;
    }
    return generateFunctionMap(ast, options);
  } catch (error) {
    console.warn('Function map generation failed, continuing without function map:', error);
    return null;
  }
}

docs

bundle-building.md

composition.md

consumption.md

function-maps.md

generation.md

index.md

utilities.md

tile.json