Babel Helper Bindify Decorators is a utility function that transforms decorator member expressions to use Function.prototype.bind, ensuring proper 'this' context binding when decorators reference methods on objects.
npm install babel-helper-bindify-decoratorsimport bindifyDecorators from "babel-helper-bindify-decorators";For CommonJS:
const bindifyDecorators = require("babel-helper-bindify-decorators");import bindifyDecorators from "babel-helper-bindify-decorators";
import * as t from "babel-types";
// Assume you have an array of decorator NodePath objects
const decoratorPaths = [
// NodePath for @obj.method
// NodePath for @anotherObj.anotherMethod
];
// Transform member expression decorators to use .bind()
bindifyDecorators(decoratorPaths);
// After transformation:
// @obj.method becomes @obj.method.bind(obj)
// @anotherObj.anotherMethod becomes @anotherObj.anotherMethod.bind(anotherObj)This helper is designed as a specialized transformation utility within the Babel ecosystem:
babel-helper-explode-classTransforms decorator member expressions to use Function.prototype.bind for proper context binding.
/**
* Transforms decorator member expressions to bind them to their object context
* @param decorators - Array of NodePath objects representing decorator expressions
* @returns Array<NodePath> - Source declares this return type, but function actually modifies decorators in-place and returns undefined
*/
function bindifyDecorators(decorators: Array<NodePath>): Array<NodePath>;Transformation Details:
@obj.method (member expression decorator)@obj.method.bind(obj) (bound method call)Note on Return Type: While the source code declares a return type of Array<NodePath>, the function actually modifies the input decorators in-place and returns undefined. The declared return type appears to be incorrect but is documented here to match the source code signature.
Usage Example:
import bindifyDecorators from "babel-helper-bindify-decorators";
import traverse from "babel-traverse";
import * as t from "babel-types";
// Example AST traversal and transformation
traverse(ast, {
Class(path) {
const decoratorPaths = path.get("decorators");
if (decoratorPaths.length > 0) {
// Transform @obj.method to @obj.method.bind(obj)
bindifyDecorators(decoratorPaths);
}
}
});// Flow types from babel-traverse and babel-types
type NodePath = {
node: Node;
scope: Scope;
parent: Object;
hub: Hub;
parentPath: ?NodePath;
context: TraversalContext;
container: any;
key: string | number;
listKey: ?string;
type: ?string;
// ... other NodePath properties
};
type Scope = {
maybeGenerateMemoised(node: Node): ?Node;
// ... other Scope properties
};
type Node = {
type: string;
// ... AST node properties
};The package depends on:
The function processes each decorator in the input array:
obj.method)For complex object expressions:
// Before: @complexObject.property.method
// After: @(_temp = complexObject.property, _temp.method.bind(_temp))For simple object references:
// Before: @obj.method
// After: @obj.method.bind(obj)The transformation creates:
callExpression(memberExpression(original, "bind"), [objectRef])sequenceExpression([assignment, callExpression])This ensures that decorator expressions like @obj.method are transformed to @obj.method.bind(obj), preserving the correct this context when the decorator is applied.