or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-babel--plugin-transform-class-static-block

Babel plugin that transforms ES2022 class static blocks into compatible code for older JavaScript environments

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@babel/plugin-transform-class-static-block@7.28.x

To install, run

npx @tessl/cli install tessl/npm-babel--plugin-transform-class-static-block@7.28.0

index.mddocs/

@babel/plugin-transform-class-static-block

A Babel plugin that transforms ES2022 class static blocks into compatible code for older JavaScript environments. The plugin handles complex transformations while maintaining proper initialization order and scoping semantics.

Package Information

  • Package Name: @babel/plugin-transform-class-static-block
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install --save-dev @babel/plugin-transform-class-static-block
  • Main Export: ./lib/index.js
  • Type Definitions: ./lib/index.d.ts
  • Module Type: ESM (with CommonJS support)

Core Imports

// CommonJS - default plugin export
const plugin = require("@babel/plugin-transform-class-static-block");

// ESM - default plugin export
import plugin from "@babel/plugin-transform-class-static-block";

// Plugin internal imports (from source)
import { declare } from "@babel/helper-plugin-utils";
import type { NodePath, Scope, types as t } from "@babel/core";
import {
  buildNamedEvaluationVisitor,
  enableFeature,
  FEATURES,
} from "@babel/helper-create-class-features-plugin";

Basic Usage

Add the plugin to your Babel configuration:

// babel.config.js
module.exports = {
  plugins: ["@babel/plugin-transform-class-static-block"]
};

// or with explicit plugin import
module.exports = {
  plugins: [require("@babel/plugin-transform-class-static-block")]
};

Example transformation:

// Input (ES2022 class static block)
class Foo {
  static bar = 42;
  static {
    this.foo = this.bar;
  }
}

// Output (transformed for older environments)
var _Foo;
class Foo {}
_Foo = Foo;
babelHelpers.defineProperty(Foo, "bar", 42);
_Foo.foo = _Foo.bar;

Capabilities

Babel Plugin Function

The main export is the plugin function that integrates with Babel's transformation pipeline.

/**
 * Babel plugin that transforms class static blocks
 * Uses declare() from @babel/helper-plugin-utils to create the plugin
 * @param api - Babel API object containing types, template, traverse, and assertVersion
 * @returns Babel plugin configuration object
 */
declare function plugin(api: {
  types: typeof t;
  template: any;
  traverse: any;
  assertVersion: (version: string) => void;
}): BabelPlugin;

export default plugin;

interface BabelPlugin {
  /** Plugin identifier */
  name: "transform-class-static-block";
  /** Parser configuration function (Babel 7 only) */
  manipulateOptions?: (opts: any, parser: { plugins: string[] }) => void;
  /** Pre-transformation lifecycle method */
  pre?(): void;
  /** AST visitor configuration */
  visitor: {
    ClassBody(path: NodePath<t.ClassBody>): void;
  };
}

Transformation Features

The plugin provides comprehensive transformation of class static blocks:

  • Static Block Conversion: Transforms static { ... } blocks into immediately invoked function expressions or inlined expressions
  • Initialization Order: Maintains proper execution order of static initialization relative to static properties
  • Class Expression Support: Handles both class declarations and class expressions
  • Named Evaluation: Supports proper named evaluation for anonymous class expressions using buildNamedEvaluationVisitor
  • Integration: Works seamlessly with other Babel class feature plugins via @babel/helper-create-class-features-plugin
  • Private Property Integration: Creates synthetic private properties when no static properties exist to hold transformation logic
  • Sequence Expression Optimization: Uses sequence expressions for single-expression static blocks to avoid unnecessary IIFEs

Multiple Static Blocks:

// Input
class Foo {
  static #bar = 21;
  static {
    this.foo = this.#bar;
    this.qux1 = this.qux;
  }
  static qux = 21;
  static {
    this.qux2 = this.qux;
  }
}

// Output (when using private fields plugin)
var _Foo;
class Foo {}
_Foo = Foo;
var _bar = {
  _: 21
};
(() => {
  _Foo.foo = babelHelpers.assertClassBrand(_Foo, _Foo, _bar)._;
  _Foo.qux1 = _Foo.qux;
})();
babelHelpers.defineProperty(Foo, "qux", 21);
_Foo.qux2 = _Foo.qux;

Static Block without Static Properties:

// Input
class Foo {
  static {
    this.foo = 42;
  }
}

// Output - creates private property to hold the static block
var _staticBlock;
class Foo {
  static #_ = _staticBlock = () => this.foo = 42;
}
_staticBlock();

Advanced Transformation Patterns

The plugin handles several complex scenarios:

Class Expressions with Named Evaluation:

// Input - anonymous class expression
const MyClass = class {
  static {
    this.name = "MyClass";
  }
};

// Output - adds named evaluation support
const MyClass = class {
  static {
    setFunctionName(this, "MyClass");
    this.name = "MyClass";
  }
};

Integration with Class Features Plugin:

/**
 * Enables static block support in the class features plugin system
 * This allows coordination with other class transformation plugins
 */
enableFeature(file: any, feature: FEATURES.staticBlocks, loose: boolean): void;

/**
 * Builds visitor for handling named evaluation of anonymous class expressions
 * @param predicate - Function to determine if named evaluation is needed
 * @param visitor - Function to perform the named evaluation transformation
 */
buildNamedEvaluationVisitor(
  predicate: (path: NodePath) => boolean,
  visitor: (classPath: NodePath<t.ClassExpression>, state: any, name: string | t.Expression) => void
): TraversalVisitor;

Private Property Generation:

/**
 * Generates unique identifier names avoiding conflicts with existing private properties
 * @param scope - Babel scope for generating unique identifiers
 * @param denyList - Set of existing private property names to avoid
 * @returns Unique identifier name
 */
function generateUid(scope: Scope, denyList: Set<string>): string;

Transformation Algorithm:

The plugin follows this transformation algorithm:

  1. Collection Phase: Iterates through class body collecting static blocks and identifying static properties
  2. Block Processing: Converts static block bodies to expressions, optimizing single expressions to avoid IIFEs
  3. Insertion Strategy:
    • If static properties exist: Prepends block expressions to the next static property initializer
    • If no static properties exist: Creates a synthetic private property to hold the transformation
  4. Execution: Generates function calls after the class declaration/expression to execute remaining static blocks
/**
 * Converts static block AST nodes to executable expressions
 * Optimizes single expression blocks to avoid unnecessary IIFEs
 */
const blocksToExpressions = (blocks: Array<t.StaticBlock>) => t.Expression[];

/**
 * Prepends expressions to a static property initializer using sequence expressions
 */
const prependToInitializer = (
  prop: t.ClassProperty | t.ClassPrivateProperty,
  expressions: t.Expression[]
) => void;

/**
 * Creates a sequence expression or returns single expression if only one
 */
const maybeSequenceExpression = (expressions: t.Expression[]) => t.Expression;

Plugin Configuration

/**
 * Core Babel types and utilities used by the plugin
 */
import type { NodePath, Scope, types as t } from "@babel/core";
import { declare } from "@babel/helper-plugin-utils";
import {
  buildNamedEvaluationVisitor,
  enableFeature,
  FEATURES,
} from "@babel/helper-create-class-features-plugin";

interface PluginConfiguration {
  /** Plugin name identifier */
  name: "transform-class-static-block";
  
  /** Parser plugin registration (Babel 7 only) */
  manipulateOptions?: (opts: any, parser: { plugins: string[] }) => void;
  
  /** Enable static block features in class features plugin */
  pre(): void;
  
  /** AST transformation visitor */
  visitor: {
    ClassBody(path: NodePath<t.ClassBody>): void;
  };
}

Dependencies

Peer Dependencies:

  • @babel/core (^7.12.0) - Required Babel transformation core

Runtime Dependencies:

  • @babel/helper-create-class-features-plugin - Class feature transformation utilities
  • @babel/helper-plugin-utils - Plugin declaration utilities

Browser and Environment Support

  • Node.js: >=6.9.0 (Babel 8: ^20.19.0 || >=22.12.0)
  • Babel: >=7.12.0 (enforced by assertVersion)
  • Target: Transforms ES2022 class static blocks for older JavaScript environments
  • Integration: Works with Babel's class features plugin system
  • Parser Support: Automatically registers classStaticBlock parser plugin (Babel 7 only)

Usage Examples

Basic Babel Configuration:

// babel.config.js
module.exports = {
  presets: ["@babel/preset-env"],
  plugins: ["@babel/plugin-transform-class-static-block"]
};

With Class Properties Plugin:

module.exports = {
  plugins: [
    "@babel/plugin-transform-class-properties",
    "@babel/plugin-transform-class-static-block"
  ]
};

Programmatic Usage:

const babel = require("@babel/core");
const plugin = require("@babel/plugin-transform-class-static-block");

const result = babel.transformSync(code, {
  plugins: [plugin]
});

Types

/**
 * Babel AST node types used by the plugin
 */
interface t {
  isStaticBlock(node: any): node is t.StaticBlock;
  isClassProperty(node: any): node is t.ClassProperty;
  isClassPrivateProperty(node: any): node is t.ClassPrivateProperty;
  isExpressionStatement(node: any): node is t.ExpressionStatement;
  staticBlock(body: t.Statement[]): t.StaticBlock;
  privateName(id: t.Identifier): t.PrivateName;
  classPrivateProperty(
    key: t.PrivateName,
    value: t.Expression | null,
    decorators: any[],
    static: boolean
  ): t.ClassPrivateProperty;
  sequenceExpression(expressions: t.Expression[]): t.SequenceExpression;
  unaryExpression(operator: string, argument: t.Expression): t.UnaryExpression;
  callExpression(callee: t.Expression, arguments: t.Expression[]): t.CallExpression;
  thisExpression(): t.ThisExpression;
  returnStatement(argument: t.Expression | null): t.ReturnStatement;
  blockStatement(body: t.Statement[]): t.BlockStatement;
  inheritsComments<T extends t.Node>(child: T, parent: t.Node): T;
  cloneNode<T extends t.Node>(node: T): T;
}

interface NodePath<T = t.Node> {
  node: T;
  parent: t.Node;
  parentPath: NodePath;
  scope: Scope;
  get(key: string): NodePath;
  isClassExpression(): boolean;
  isStaticBlock(): boolean;
  isClassProperty(opts?: { static?: boolean }): boolean;
  isClassPrivateProperty(opts?: { static?: boolean }): boolean;
  isPrivate(): boolean;
  isExpression(): boolean;
  isStatement(): boolean;
  remove(): void;
  replaceWith(node: t.Node): void;
  insertAfter(nodes: t.Node | t.Node[]): void;
  unshiftContainer(key: string, nodes: t.Node | t.Node[]): void;
  pushContainer(key: string, nodes: t.Node | t.Node[]): void;
}

interface Scope {
  generateDeclaredUidIdentifier(name?: string): t.Identifier;
}

interface t.StaticBlock {
  type: "StaticBlock";
  body: t.Statement[];
}

interface t.ClassBody {
  type: "ClassBody";
  body: Array<t.ClassMethod | t.ClassProperty | t.ClassPrivateProperty | t.StaticBlock>;
}