babel-helper-function-name is a Babel helper library that automatically assigns names to anonymous functions in JavaScript code during compilation. It intelligently handles complex scenarios such as function expressions in object properties, variable assignments, and method definitions, ensuring that functions receive appropriate names for better debugging and stack traces.
npm install babel-helper-function-nameimport functionNameHelper from "babel-helper-function-name";For CommonJS:
const functionNameHelper = require("babel-helper-function-name");import functionNameHelper from "babel-helper-function-name";
import * as t from "babel-types";
// During Babel AST transformation
const result = functionNameHelper({
node: functionNode, // The function AST node
parent: parentNode, // Parent AST node
scope: scope, // Babel scope object
id: identifierNode // Optional: suggested identifier
});
// The function now has an appropriate name assignedbabel-helper-function-name operates within the Babel compilation pipeline and provides:
Assigns names to anonymous functions based on their context in the AST.
/**
* Assigns a name to an anonymous function based on its context
* @param options - Configuration object containing AST nodes and scope information
* @param options.node - The function AST node to name
* @param options.parent - The parent AST node providing context
* @param options.scope - Babel scope object for the function
* @param options.id - Optional identifier to use as the function name
* @returns The original node, a wrapped version, or undefined if no naming needed
*/
export default function functionNameHelper({
node,
parent,
scope,
id
});Supported Naming Patterns:
The helper automatically detects and handles these function naming scenarios:
{ foo() {} } → function name becomes "foo"let foo = function() {} → function name becomes "foo"foo = function() {} → function name becomes "foo"{ [key]: function() {} } → uses literal key values onlySelf-Reference Handling:
When functions reference themselves by name, the helper creates wrapper functions to avoid scope conflicts:
// Input: self-referencing function
let factorial = function(n) {
return n <= 1 ? 1 : n * factorial(n - 1);
};
// Output: wrapped to prevent scope issues
let factorial = (function(FUNCTION_KEY) {
function factorial() {
return FUNCTION_KEY.apply(this, arguments);
}
factorial.toString = function() {
return FUNCTION_KEY.toString();
};
return factorial;
})(function(n) {
return n <= 1 ? 1 : n * factorial(n - 1);
});Usage Examples:
import functionNameHelper from "babel-helper-function-name";
import * as t from "babel-types";
// Example 1: Object method
const objectMethod = t.objectMethod(
"method",
t.identifier("myMethod"),
[],
t.blockStatement([])
);
const result1 = functionNameHelper({
node: objectMethod,
parent: t.objectExpression([objectMethod]),
scope: scope
});
// Example 2: Variable assignment
const funcExpression = t.functionExpression(null, [], t.blockStatement([]));
const variableDeclarator = t.variableDeclarator(
t.identifier("myFunc"),
funcExpression
);
const result2 = functionNameHelper({
node: funcExpression,
parent: variableDeclarator,
scope: scope
});
// Example 3: With explicit ID
const result3 = functionNameHelper({
node: functionNode,
parent: parentNode,
scope: scope,
id: t.identifier("customName")
});// Babel AST Node types (from babel-types)
interface Node {
type: string;
// Additional properties vary by node type
}
interface Identifier extends Node {
type: "Identifier";
name: string;
}
interface FunctionExpression extends Node {
type: "FunctionExpression";
id: Identifier | null;
params: Identifier[];
body: BlockStatement;
generator: boolean;
async: boolean;
}
interface ArrowFunctionExpression extends Node {
type: "ArrowFunctionExpression";
id: null;
params: Identifier[];
body: BlockStatement | Expression;
generator: false;
async: boolean;
}
interface FunctionDeclaration extends Node {
type: "FunctionDeclaration";
id: Identifier;
params: Identifier[];
body: BlockStatement;
generator: boolean;
async: boolean;
}
interface ObjectProperty extends Node {
type: "ObjectProperty";
key: Identifier | Literal;
value: Expression;
computed: boolean;
shorthand: boolean;
}
interface ObjectMethod extends Node {
type: "ObjectMethod";
kind: "method" | "get" | "set";
key: Identifier | Literal;
params: Identifier[];
body: BlockStatement;
computed: boolean;
generator: boolean;
async: boolean;
}
interface VariableDeclarator extends Node {
type: "VariableDeclarator";
id: Identifier;
init: Expression | null;
}
interface AssignmentExpression extends Node {
type: "AssignmentExpression";
operator: "=";
left: Identifier | MemberExpression;
right: Expression;
}
interface Literal extends Node {
type: "Literal";
value: string | number | boolean | null;
raw: string;
}
interface BlockStatement extends Node {
type: "BlockStatement";
body: Statement[];
}
interface MemberExpression extends Node {
type: "MemberExpression";
object: Expression;
property: Identifier | Literal;
computed: boolean;
}
interface VariableDeclaration extends Node {
type: "VariableDeclaration";
declarations: VariableDeclarator[];
kind: "var" | "let" | "const";
}
// Union types for common patterns
type Expression = FunctionExpression | ArrowFunctionExpression | Identifier | Literal | AssignmentExpression | MemberExpression;
type Statement = FunctionDeclaration | BlockStatement | VariableDeclaration;
type Function = FunctionExpression | ArrowFunctionExpression | FunctionDeclaration | ObjectMethod;
// Babel Scope object (from babel-traverse)
interface Scope {
getBinding(name: string): Binding | undefined;
getOwnBinding(name: string): Binding | undefined;
getBindingIdentifier(name: string): Identifier | undefined;
hasBinding(name: string): boolean;
hasGlobal(name: string): boolean;
hasOwnBinding(name: string): boolean;
generateUidIdentifier(name: string): Identifier;
rename(oldName: string, newName?: string): void;
traverse(node: Node, visitor: object, state?: any): void;
getProgramParent(): Scope;
parent?: Scope;
references: { [key: string]: boolean };
}
interface Binding {
kind: "param" | "local" | "hoisted" | "module" | "const" | "let" | "var";
constant: boolean;
// Additional properties
}This helper requires the following Babel packages:
The helper gracefully handles edge cases:
undefined when function already has a nameThe module contains several internal helper components that work together to implement function naming:
Pre-defined babel-template constructs for creating wrapper functions when self-reference is detected:
// Template for regular function wrapping
const buildPropertyMethodAssignmentWrapper = template(`
(function (FUNCTION_KEY) {
function FUNCTION_ID() {
return FUNCTION_KEY.apply(this, arguments);
}
FUNCTION_ID.toString = function () {
return FUNCTION_KEY.toString();
}
return FUNCTION_ID;
})(FUNCTION)
`);
// Template for generator function wrapping
const buildGeneratorPropertyMethodAssignmentWrapper = template(`
(function (FUNCTION_KEY) {
function* FUNCTION_ID() {
return yield* FUNCTION_KEY.apply(this, arguments);
}
FUNCTION_ID.toString = function () {
return FUNCTION_KEY.toString();
};
return FUNCTION_ID;
})(FUNCTION)
`);Internal visitor object for traversing function bodies to detect self-references:
const visitor = {
"ReferencedIdentifier|BindingIdentifier"(path, state) {
// Detects when function references itself by name
// Sets state.selfReference = true when found
}
};Internal functions that support the main functionality:
/**
* Wraps a function with appropriate template when self-reference is detected
* @param state - Analysis state containing selfReference flag
* @param method - The function node to potentially wrap
* @param id - The identifier to use for the function name
* @param scope - Babel scope object
* @returns Wrapped function expression or original method
*/
function wrap(state, method, id, scope);
/**
* Analyzes function body for self-references and binding conflicts
* @param node - Function node to analyze
* @param name - Proposed function name
* @param scope - Babel scope object
* @returns State object with analysis results
*/
function visit(node, name, scope);This helper is designed for use within Babel plugins and presets during JavaScript compilation. It should be called during AST traversal when encountering function nodes that need naming. The helper integrates with Babel's scope analysis system and requires a properly initialized scope object to function correctly.