CtrlK
BlogDocsLog inGet started
Tessl Logo

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

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

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)

docs

index.md

tile.json