or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-babel--helper-function-name

Helper function to infer and assign names to anonymous function expressions and class expressions in JavaScript/TypeScript AST nodes

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@babel/helper-function-name@7.24.x

To install, run

npx @tessl/cli install tessl/npm-babel--helper-function-name@7.24.0

index.mddocs/

@babel/helper-function-name

@babel/helper-function-name is a utility function that intelligently infers and assigns names to anonymous function expressions and class expressions in JavaScript/TypeScript AST nodes. It's designed to work with Babel's AST transformation pipeline to improve debugging and code readability by ensuring functions have meaningful names in the compiled output.

Package Information

  • Package Name: @babel/helper-function-name
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install @babel/helper-function-name

Core Imports

import helperFunctionName from "@babel/helper-function-name";

For CommonJS:

const helperFunctionName = require("@babel/helper-function-name");

Basic Usage

import helperFunctionName from "@babel/helper-function-name";
import { traverse } from "@babel/traverse";
import * as t from "@babel/types";

// Example: Adding names to anonymous functions during AST transformation
traverse(ast, {
  FunctionExpression(path) {
    if (!path.node.id) {
      // Use the helper to infer and assign a name
      const result = helperFunctionName(path);
      
      if (result && result !== path.node) {
        // Replace with wrapped function if needed
        path.replaceWith(result);
      }
    }
  }
});

// Example: Usage in a Babel plugin (simplified)
export default function myPlugin() {
  return {
    visitor: {
      FunctionExpression(path) {
        const replacement = helperFunctionName(path);
        if (replacement) path.replaceWith(replacement);
      },
      
      ObjectProperty(path) {
        const value = path.get("value");
        if (value.isFunction()) {
          const newNode = helperFunctionName(value, false, true);
          if (newNode) value.replaceWith(newNode);
        }
      }
    }
  };
}

Architecture

The helper uses several key strategies to infer function names:

  • Context Analysis: Examines parent AST nodes (object properties, variable declarations, assignments) to determine appropriate names
  • Scope Awareness: Analyzes function scope to detect and handle self-references and binding conflicts
  • Wrapper Generation: Creates IIFE (Immediately Invoked Function Expression) wrappers when necessary to preserve function behavior while adding names
  • Unicode Support: Optional handling of non-BMP Unicode characters based on compilation target
  • Safari Compatibility: Special handling for Safari browser strict mode parameter naming issues

Capabilities

Function Name Inference

The primary capability that infers and assigns names to anonymous function expressions and class expressions.

/**
 * Add id to function/class expression inferred from the AST
 * @param nodePathLike - The NodePath-like input containing node, parent, scope, and optional id
 * @param localBinding - Whether a name could shadow a self-reference (default: false)
 * @param supportUnicodeId - Whether the compilation target supports Unicode identifiers (default: false)
 * @returns Modified node, IIFE wrapper, or void
 */
export default function <N extends t.FunctionExpression | t.Class>(
  nodePathLike: {
    node: N;
    parent?: NodePath<N>["parent"];
    scope: Scope;
    id?:
      | t.AssignmentExpression["left"]
      | t.StringLiteral
      | t.NumericLiteral
      | t.BigIntLiteral;
  } | NodePath<N>,
  localBinding?: boolean,
  supportUnicodeId?: boolean,
): N | t.CallExpression | void;

Parameters:

  • nodePathLike (required): Either a NodePath object or an object containing:
    • node: The function expression or class expression AST node to name
    • parent (optional): The parent AST node for contextual name inference
    • scope: Babel traverse scope object for analyzing bindings and references
    • id (optional): Fallback naming source when name cannot be inferred from AST context
  • localBinding (optional, default: false): Boolean indicating if the name could shadow a self-reference (relevant when converting arrow functions)
  • supportUnicodeId (optional, default: false): Boolean indicating whether the compilation target supports Unicode/non-BMP characters in identifiers

Return Values:

  • Modified node: When a name can be successfully inferred and assigned
  • IIFE wrapper (t.CallExpression): When the node contains bindings that would shadow the inferred function name
  • void: When the node already has an id, name cannot be inferred, or contains unsupported Unicode characters

Usage Examples:

import helperFunctionName from "@babel/helper-function-name";
import { traverse } from "@babel/traverse";
import * as t from "@babel/types";

// Usage with NodePath (most common in Babel plugins)
traverse(ast, {
  FunctionExpression(path) {
    const result = helperFunctionName(path);
    if (result && result !== path.node) {
      path.replaceWith(result);
    }
  }
});

// Usage with manual object construction
const functionExpr = t.functionExpression(null, [], t.blockStatement([]));
const objectProperty = t.objectProperty(t.identifier("foo"), functionExpr);

const result = helperFunctionName({
  node: functionExpr,
  parent: objectProperty,
  scope: currentScope
});
// Result: function expression with id "foo"

// Usage with variable declarator
const variableDeclarator = t.variableDeclarator(
  t.identifier("myFunction"), 
  t.functionExpression(null, [], t.blockStatement([]))
);

const result2 = helperFunctionName({
  node: variableDeclarator.init as t.FunctionExpression,
  parent: variableDeclarator,
  scope: currentScope
});
// Result: function expression with id "myFunction"

// Usage with assignment expression
const assignment = t.assignmentExpression(
  "=",
  t.identifier("handler"),
  t.functionExpression(null, [], t.blockStatement([]))
);

const result3 = helperFunctionName({
  node: assignment.right as t.FunctionExpression,
  parent: assignment,
  scope: currentScope
});
// Result: function expression with id "handler"

// Usage with Unicode support
const result4 = helperFunctionName({
  node: functionWithUnicodeContext,
  parent: parentWithUnicodeName,
  scope: currentScope
}, false, true); // Enable Unicode support

Name Inference Contexts

The helper can infer names from various AST contexts:

Object Properties and Methods:

// { foo: function() {} } -> function foo() {}
// { foo() {} } -> function foo() {}

Variable Declarations:

// let foo = function() {} -> let foo = function foo() {}
// const bar = class {} -> const bar = class bar {}

Assignment Expressions:

// obj.method = function() {} -> obj.method = function method() {}
// handler = function() {} -> handler = function handler() {}

Literal Keys:

// { "my-function": function() {} } -> function myFunction() {}
// { 123: function() {} } -> function _123() {}

Self-Reference Handling

When functions reference themselves by name, the helper intelligently handles the situation:

// Case 1: Local scope rename (preferred)
let foo = function() { return foo(); };
// Becomes: let foo = function foo() { return foo(); };

// Case 2: IIFE wrapper (when scope conflicts exist)
let foo = function(foo) { return foo(); };
// Becomes: let foo = (function(key) {
//   function foo() { return key.apply(this, arguments); }
//   foo.toString = function() { return key.toString(); };
//   return foo;
// })(function(foo) { return foo(); });

Types

// Re-exported from @babel/types and @babel/traverse
import type * as t from "@babel/types";
import type { NodePath, Scope } from "@babel/traverse";

// Internal state type used during analysis
interface State {
  name: string;
  outerDeclar: t.Identifier;
  selfAssignment: boolean;
  selfReference: boolean;
}

Error Handling

The helper gracefully handles various edge cases:

  • Missing parent context: Returns void when name cannot be inferred
  • Existing function names: Returns immediately if node.id already exists
  • Unicode characters: Optionally filters out non-BMP characters based on target support
  • Scope conflicts: Creates wrapper functions to preserve semantics when necessary
  • Safari strict mode: Avoids parameter naming conflicts that cause Safari errors

Dependencies

This package requires:

  • @babel/template: For creating AST wrapper templates
  • @babel/types: For AST node type checking and creation
  • @babel/traverse: For scope analysis (peer dependency)