A Babel helper plugin that provides essential functionality for transforming modern JavaScript class features to ES6-compatible code. It handles compilation of class public and private fields, private methods, and decorators, serving as a foundational component for other Babel plugins that need to transform class-related syntax.
npm install @babel/helper-create-class-features-pluginimport { createClassFeaturePlugin, FEATURES } from "@babel/helper-create-class-features-plugin";For specific utilities:
import {
enableFeature,
injectInitialization,
buildCheckInRHS,
buildNamedEvaluationVisitor
} from "@babel/helper-create-class-features-plugin";import { createClassFeaturePlugin, FEATURES } from "@babel/helper-create-class-features-plugin";
// Create a plugin for class properties
export default createClassFeaturePlugin({
name: "transform-class-properties",
api,
feature: FEATURES.fields,
loose: options.loose,
manipulateOptions(opts, parserOpts) {
parserOpts.plugins.push("classProperties");
},
});
// Create a plugin for private methods
export default createClassFeaturePlugin({
name: "transform-private-methods",
api,
feature: FEATURES.privateMethods | FEATURES.fields,
loose: options.loose,
});This helper is built around several key components:
createClassFeaturePlugin function that generates configured Babel pluginsPrimary factory function for creating Babel plugins that transform class features with configurable options and feature flags.
function createClassFeaturePlugin(options: Options): PluginObject;
interface Options {
name: string;
feature: number;
loose?: boolean;
inherits?: PluginObject["inherits"];
manipulateOptions?: PluginObject["manipulateOptions"];
api?: PluginAPI;
decoratorVersion?: DecoratorVersionKind | "2018-09";
}Core feature enablement and configuration system that manages the bit flag-based feature system and ensures consistency across multiple class feature plugins.
const FEATURES: {
readonly fields: number; // 1 << 1 (2)
readonly privateMethods: number; // 1 << 2 (4)
readonly decorators: number; // 1 << 3 (8)
readonly privateIn: number; // 1 << 4 (16)
readonly staticBlocks: number; // 1 << 5 (32)
};
function enableFeature(file: File, feature: number, loose: boolean): void;
function isLoose(file: File, feature: number): boolean;
function shouldTransform(path: NodePath<t.Class>, file: File): boolean;Comprehensive private and public field transformation including private name mapping, field initialization, and usage transformation.
function buildPrivateNamesMap(
className: string,
privateFieldsAsSymbolsOrProperties: boolean,
props: PropPath[],
file: File
): PrivateNamesMap;
function buildFieldsInitNodes(
ref: t.Identifier | null,
superClass: t.Expression | null,
props: PropPath[],
privateNamesMap: PrivateNamesMap,
file: File,
setPublicClassFields: boolean,
privateFieldsAsSymbolsOrProperties: boolean,
noUninitializedPrivateFieldAccess: boolean,
constantSuper: boolean,
innerBinding: t.Identifier | null
): FieldsInitResult;Multi-version decorator transformation supporting various decorator specifications with proper handling of decorator metadata and class modification.
function hasDecorators(node: t.Class): boolean;
function buildNamedEvaluationVisitor(): Visitor;
type DecoratorVersionKind =
| "2023-11" | "2023-05" | "2023-01"
| "2022-03" | "2021-12";Helper utilities for class initialization, computed key extraction, and AST manipulation.
function injectInitialization(
path: NodePath<t.Class>,
constructor: NodePath<t.ClassMethod> | undefined,
instanceNodes: t.ExpressionStatement[],
referenceVisitor: (visitor: Visitor, state: any) => void,
lastInstanceNodeReturnsThis: boolean
): void;
function buildCheckInRHS(
rhs: t.Expression,
file: File,
inRHSIsObject?: boolean
): t.Expression;type PropNode =
| t.ClassProperty
| t.ClassPrivateProperty
| t.ClassPrivateMethod
| t.StaticBlock;
type PropPath = NodePath<PropNode>;
interface PrivateNameMetadata {
id: t.Identifier;
static: boolean;
method: boolean;
getId?: t.Identifier;
setId?: t.Identifier;
methodId?: t.Identifier;
initAdded?: boolean;
getterDeclared?: boolean;
setterDeclared?: boolean;
}
type PrivateNamesMap = Map<string, PrivateNameMetadata>;