Helper to wrap functions inside function calls while preserving behavior, scope, and context for Babel AST transformations.
npx @tessl/cli install tessl/npm-babel--helper-wrap-function@7.28.0@babel/helper-wrap-function is a specialized utility library for JavaScript/TypeScript code transformations, designed to wrap different types of functions inside protective function calls while preserving their original behavior, scope, and context. It's primarily used within the Babel ecosystem for Abstract Syntax Tree (AST) manipulations in plugins and transformers.
npm install @babel/helper-wrap-functionimport wrapFunction from "@babel/helper-wrap-function";For CommonJS:
const wrapFunction = require("@babel/helper-wrap-function").default;import { NodePath } from "@babel/traverse";
import { callExpression, identifier } from "@babel/types";
import type * as t from "@babel/types";
import wrapFunction from "@babel/helper-wrap-function";
// Wrap an async function with asyncToGenerator helper
function transformAsyncFunction(path: NodePath<t.Function>) {
const helperId = callExpression(identifier("_asyncToGenerator"), []);
wrapFunction(path, helperId);
}
// Wrap a generator function with a custom helper
function wrapGeneratorWithHelper(path: NodePath<t.Function>) {
const helperId = callExpression(identifier("skipFirstGeneratorNext"), []);
wrapFunction(path, helperId, true, false);
}The helper is built around sophisticated function wrapping strategies:
this binding, arguments object access, and lexical scopeWraps functions inside protective function calls while preserving behavior, scope, and context.
/**
* Wraps a function inside a protective function call while preserving behavior, scope, and context
* @param path - Babel AST NodePath representing the function to wrap
* @param callId - Expression used to wrap the function (typically a helper call)
* @param noNewArrows - Controls arrow function conversion behavior (default: true)
* @param ignoreFunctionLength - Controls function.length preservation (default: false)
*/
function wrapFunction(
path: NodePath<t.Function>,
callId: t.Expression,
noNewArrows?: boolean,
ignoreFunctionLength?: boolean
): void;Parameters:
path: The Babel AST node path representing the function to wrap. Supports all function types:
callId: The expression used to wrap the function, typically a helper call like _asyncToGenerator(...) or skipFirstGeneratorNext(...)
noNewArrows (optional): When true (default), prevents creation of new arrow functions during transformation. When false, allows arrow function creation in the wrapping process.
ignoreFunctionLength (optional): When true, skips parameter forwarding optimizations that preserve function.length. When false (default), maintains function arity through parameter forwarding.
Wrapping Strategies:
The function automatically selects the appropriate wrapping strategy based on the function type:
1. Declaration Wrapper (for function declarations):
function NAME(PARAMS) { return REF.apply(this, arguments); }
function REF() {
REF = FUNCTION;
return REF.apply(this, arguments);
}2. Named Expression Wrapper (for named function expressions):
(function () {
var REF = FUNCTION;
function NAME(PARAMS) {
return REF.apply(this, arguments);
}
return NAME;
})()3. Anonymous Expression Wrapper (for anonymous function expressions):
(function () {
var REF = FUNCTION;
return function NAME(PARAMS) {
return REF.apply(this, arguments);
};
})()Usage Examples:
import { NodePath } from "@babel/traverse";
import { callExpression, identifier } from "@babel/types";
import wrapFunction from "@babel/helper-wrap-function";
import type * as t from "@babel/types";
// Example 1: Wrap async function for async-to-generator transformation
function wrapAsyncFunction(path: NodePath<t.Function>) {
const asyncToGeneratorCall = callExpression(
identifier("_asyncToGenerator"),
[]
);
wrapFunction(path, asyncToGeneratorCall);
}
// Example 2: Wrap generator with helper, preserving arrow functions
function wrapGeneratorFunction(path: NodePath<t.Function>) {
const helperCall = callExpression(
identifier("skipFirstGeneratorNext"),
[]
);
wrapFunction(path, helperCall, false, true);
}
// Example 3: Wrap method while preserving function length
function wrapMethodPreservingLength(path: NodePath<t.Method>) {
const wrapperCall = callExpression(
identifier("_wrapNativeSuper"),
[]
);
wrapFunction(path, wrapperCall, true, false);
}Context Preservation:
this binding in all contextsarguments objectsuper calls correctly in class methodsParameter Handling:
Scope Management:
Type Safety:
// Core types from @babel/types and @babel/traverse
import type { NodePath } from "@babel/traverse";
import type * as t from "@babel/types";
// Template builder type for internal wrapper generation
type ExpressionWrapperBuilder<ExtraBody extends t.Node[]> = (
replacements?: Parameters<ReturnType<typeof template.expression>>[0],
) => t.CallExpression & {
callee: t.FunctionExpression & {
body: {
body: [
t.VariableDeclaration & {
declarations: [
{ init: t.FunctionExpression | t.ArrowFunctionExpression },
];
},
...ExtraBody,
];
};
};
};This package requires the following Babel ecosystem dependencies:
_asyncToGenerator helperskipFirstGeneratorNextThe function performs in-place AST modifications and expects:
Common issues: