0
# Function Maps
1
2
Facebook-specific extensions for generating function maps that provide enhanced debugging support in Hermes and React Native environments.
3
4
## Capabilities
5
6
### Function Map Generation
7
8
Generate function maps from Abstract Syntax Trees (ASTs) to enable better debugging and profiling in Hermes and React Native.
9
10
```javascript { .api }
11
/**
12
* Generates a function map from a Babel AST
13
* Function maps provide debugging information about function locations and names
14
* @param ast - Babel AST node (typically a Program node)
15
* @param context - Optional context object with filename information
16
* @returns Facebook-format function map with names and mappings
17
*/
18
function generateFunctionMap(ast: BabelNode, context?: Context): FBSourceFunctionMap;
19
20
/**
21
* Babel plugin that automatically generates function maps during transformation
22
* @returns Babel plugin object for integration into Babel transformation pipeline
23
*/
24
function functionMapBabelPlugin(): PluginObj;
25
```
26
27
**Usage Examples:**
28
29
```javascript
30
const { generateFunctionMap, functionMapBabelPlugin } = require("metro-source-map");
31
const parser = require("@babel/parser");
32
const babel = require("@babel/core");
33
34
// Generate function map from AST
35
const code = `
36
function greet(name) {
37
return 'Hello ' + name;
38
}
39
40
const calculate = (a, b) => a + b;
41
42
class Calculator {
43
add(x, y) {
44
return x + y;
45
}
46
}
47
`;
48
49
const ast = parser.parse(code, {
50
sourceType: "module",
51
plugins: ["jsx", "typescript"]
52
});
53
54
const functionMap = generateFunctionMap(ast, {});
55
console.log(functionMap);
56
// {
57
// names: ["greet", "calculate", "Calculator", "add"],
58
// mappings: "AAAA;IAII;QAII"
59
// }
60
61
// Use as Babel plugin
62
const result = babel.transformSync(code, {
63
plugins: [functionMapBabelPlugin()]
64
});
65
66
// The plugin adds function map data to the transformation result
67
console.log(result.metadata.functionMap);
68
```
69
70
### Function Map Types
71
72
```javascript { .api }
73
/**
74
* Facebook source function map format
75
*/
76
interface FBSourceFunctionMap {
77
/** Array of function names in order of appearance */
78
names: Array<string>;
79
/** Base64 VLQ encoded mappings for function positions */
80
mappings: string;
81
}
82
83
/**
84
* Facebook source metadata containing function map
85
*/
86
type FBSourceMetadata = [?FBSourceFunctionMap];
87
88
/**
89
* Array of source metadata for multiple sources
90
*/
91
type FBSourcesArray = Array<?FBSourceMetadata>;
92
93
/**
94
* Hermes function offsets for bytecode debugging
95
*/
96
interface HermesFunctionOffsets {
97
/** Maps function IDs to arrays of bytecode offsets */
98
[functionId: number]: Array<number>;
99
}
100
```
101
102
### Integration with Metro Source Maps
103
104
```javascript
105
const { generateFunctionMap, fromRawMappings } = require("metro-source-map");
106
const parser = require("@babel/parser");
107
108
// Generate source map with function map integration
109
function generateSourceMapWithFunctions(modules) {
110
const processedModules = modules.map(module => {
111
// Parse the source code to generate function map
112
const ast = parser.parse(module.source, {
113
sourceType: "module",
114
plugins: ["jsx", "flow"]
115
});
116
117
const functionMap = generateFunctionMap(ast, {});
118
119
return {
120
...module,
121
functionMap: functionMap
122
};
123
});
124
125
// Generate source map with function maps included
126
const generator = fromRawMappings(processedModules);
127
return generator.toMap();
128
}
129
130
// Usage
131
const modules = [{
132
map: [[1, 0, 1, 0], [2, 0, 2, 0]],
133
path: "src/utils.js",
134
source: "function helper() { return true; }",
135
code: "function helper() { return true; }",
136
isIgnored: false
137
}];
138
139
const sourceMapWithFunctions = generateSourceMapWithFunctions(modules);
140
console.log(sourceMapWithFunctions.x_facebook_sources);
141
```
142
143
### Babel Plugin Integration
144
145
```javascript
146
const { functionMapBabelPlugin } = require("metro-source-map");
147
const babel = require("@babel/core");
148
149
// Configure Babel with function map plugin
150
const babelConfig = {
151
plugins: [
152
functionMapBabelPlugin(),
153
// ... other plugins
154
],
155
presets: [
156
"@babel/preset-react",
157
"@babel/preset-typescript"
158
]
159
};
160
161
// Transform code with function map generation
162
const sourceCode = `
163
import React from 'react';
164
165
function MyComponent({ title }) {
166
const handleClick = () => {
167
console.log('Clicked');
168
};
169
170
return (
171
<div onClick={handleClick}>
172
<h1>{title}</h1>
173
</div>
174
);
175
}
176
177
export default MyComponent;
178
`;
179
180
const result = babel.transformSync(sourceCode, babelConfig);
181
182
// Access generated function map
183
const functionMap = result.metadata?.functionMap;
184
if (functionMap) {
185
console.log('Function names:', functionMap.names);
186
console.log('Function mappings:', functionMap.mappings);
187
}
188
```
189
190
### Advanced Function Map Features
191
192
```javascript
193
const { generateFunctionMap } = require("metro-source-map");
194
const parser = require("@babel/parser");
195
196
// Complex code with various function types
197
const complexCode = `
198
// Named function
199
function namedFunction() {}
200
201
// Arrow function
202
const arrowFn = () => {};
203
204
// Method in object
205
const obj = {
206
method() {},
207
asyncMethod: async function() {}
208
};
209
210
// Class with methods
211
class MyClass {
212
constructor() {}
213
214
instanceMethod() {}
215
216
static staticMethod() {}
217
218
get getter() {}
219
220
set setter(value) {}
221
}
222
223
// Anonymous function expression
224
const anonymous = function() {};
225
226
// Generator function
227
function* generator() {}
228
229
// Async function
230
async function asyncFn() {}
231
`;
232
233
const ast = parser.parse(complexCode, {
234
sourceType: "module",
235
plugins: ["classProperties", "asyncGenerators"]
236
});
237
238
const functionMap = generateFunctionMap(ast, {
239
// Additional options can be passed here
240
});
241
242
console.log('Detected functions:', functionMap.names);
243
// Output: All function names including constructors, methods, getters, setters
244
```
245
246
### React Native and Hermes Integration
247
248
```javascript
249
const { generateFunctionMap, fromRawMappings } = require("metro-source-map");
250
251
// Generate source maps optimized for React Native/Hermes debugging
252
function generateReactNativeSourceMap(modules) {
253
return fromRawMappings(modules.map(module => ({
254
...module,
255
// Generate function map for better Hermes debugging
256
functionMap: module.ast ? generateFunctionMap(module.ast, {
257
// Hermes-specific optimizations
258
includeConstructors: true,
259
includeGettersSetters: true
260
}) : null
261
})));
262
}
263
264
// Usage in Metro bundler integration
265
const reactNativeModules = [
266
{
267
map: rawMappings,
268
path: "App.js",
269
source: reactComponentCode,
270
code: transformedCode,
271
ast: parsedAST,
272
isIgnored: false
273
}
274
];
275
276
const generator = generateReactNativeSourceMap(reactNativeModules);
277
const sourceMap = generator.toMap("bundle.js");
278
279
// The resulting source map includes function maps for Hermes debugging
280
console.log(sourceMap.x_facebook_sources);
281
console.log(sourceMap.x_hermes_function_offsets);
282
```
283
284
## Error Handling
285
286
Function map generation may encounter errors in the following cases:
287
288
- **Invalid AST**: When the provided AST is malformed or missing required nodes
289
- **Parsing errors**: When source code cannot be parsed into a valid AST
290
- **Plugin configuration errors**: When the Babel plugin is misconfigured
291
292
```javascript
293
const { generateFunctionMap } = require("metro-source-map");
294
295
try {
296
const functionMap = generateFunctionMap(ast, options);
297
} catch (error) {
298
if (error.message.includes('Invalid AST')) {
299
console.error('AST is malformed:', error);
300
} else {
301
console.error('Function map generation failed:', error);
302
}
303
}
304
305
// Safe function map generation
306
function safeGenerateFunctionMap(ast, options = {}) {
307
try {
308
if (!ast || ast.type !== 'Program') {
309
return null;
310
}
311
return generateFunctionMap(ast, options);
312
} catch (error) {
313
console.warn('Function map generation failed, continuing without function map:', error);
314
return null;
315
}
316
}
317
```