or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

decorator-support.mdfeature-management.mdfield-transformation.mdindex.mdplugin-creation.mdutilities.md
tile.json

decorator-support.mddocs/

Decorator Support

Multi-version decorator transformation supporting various decorator specifications with proper handling of decorator metadata and class modification.

Capabilities

Has Decorators

Checks if a class or class member has decorators.

/**
 * Checks if a class has decorators (on class or any member)
 * @param node - Class AST node to check
 * @returns true if the class has any decorators
 */
function hasDecorators(node: t.Class): boolean;

/**
 * Checks if a node has its own decorators
 * @param node - Class or class member node to check
 * @returns true if the node has decorators directly attached
 */
function hasOwnDecorators(node: t.Class | t.ClassBody["body"][number]): boolean;

Usage Examples:

import { hasDecorators, hasOwnDecorators } from "@babel/helper-create-class-features-plugin";

// Check if class has any decorators
if (hasDecorators(classNode)) {
  // Class or its members have decorators
  applyDecoratorTransform(classNode);
}

// Check specific decorator placement
if (hasOwnDecorators(classNode)) {
  // Class itself has decorators
}

for (const member of classNode.body.body) {
  if (hasOwnDecorators(member)) {
    // This member has decorators
  }
}

Build Named Evaluation Visitor

Creates a visitor for handling named evaluation patterns in decorators.

/**
 * Creates a visitor for handling named evaluation in decorator contexts
 * @param needsName - Function to determine if a path needs named evaluation
 * @param visitor - Callback to handle paths that need named evaluation
 * @returns Visitor object for traversing and handling named evaluations
 */
function buildNamedEvaluationVisitor(
  needsName: (path: NodePath) => boolean,
  visitor: (
    path: NodePath,
    state: PluginPass,
    name: string | t.Identifier | t.StringLiteral | t.NumericLiteral | t.BigIntLiteral
  ) => void
): Visitor;

Usage Examples:

import { buildNamedEvaluationVisitor } from "@babel/helper-create-class-features-plugin";

// Create visitor for decorator evaluation with custom logic
const namedEvaluationVisitor = buildNamedEvaluationVisitor(
  (path) => {
    // Determine if path needs named evaluation
    return path.isCallExpression() || path.isIdentifier();
  },
  (path, state, name) => {
    // Handle named evaluation
    console.log(`Processing ${name} for path:`, path.type);
    // Custom transformation logic here
  }
);

// Use in transformation pipeline
path.traverse(namedEvaluationVisitor, state);

Decorator Version Support

The helper supports multiple decorator specification versions.

/**
 * Supported decorator specification versions
 */
type DecoratorVersionKind = 
  | "2023-11"  // Final stage-3 specification (Babel 8 default)
  | "2023-05"  // Near-final stage-3 specification
  | "2023-01"  // Refined stage-3 specification
  | "2022-03"  // Updated stage-3 specification
  | "2021-12"; // Early stage-3 specification

// Legacy decorator support (pre-standardization)
type LegacyDecoratorVersion = "2018-09";

type AllDecoratorVersions = DecoratorVersionKind | LegacyDecoratorVersion;

Usage Examples:

import { createClassFeaturePlugin, FEATURES } from "@babel/helper-create-class-features-plugin";

// Modern decorators (stage-3)
export default createClassFeaturePlugin({
  name: "transform-decorators",
  api,
  feature: FEATURES.decorators,
  decoratorVersion: "2023-11"
});

// Legacy decorators (pre-standard)
export default createClassFeaturePlugin({
  name: "transform-decorators-legacy",
  api,
  feature: FEATURES.decorators,
  decoratorVersion: "2018-09"
});

Decorator Transform Function

Main decorator transformation function (default export).

/**
 * Main decorator transformation function
 * @param api - Babel plugin API
 * @param options - Decorator transformation options
 * @param decoratorVersion - Decorator specification version
 * @param inherits - Plugin inheritance configuration
 * @returns Configured PluginObject for decorator transformation
 */
export default function createDecoratorTransform(
  api: PluginAPI,
  options: { loose?: boolean },
  decoratorVersion: DecoratorVersionKind,
  inherits?: PluginObject["inherits"]
): PluginObject;

Legacy Decorator Support (2018-09)

Special handling for legacy decorator specification.

/**
 * Builds decorated class for legacy decorators (2018-09)
 * @param classRefForDefine - Class reference identifier
 * @param path - Class path to transform
 * @param elements - Class body elements
 * @param file - Babel file instance
 * @returns Transformation result with instance nodes and wrapper
 */
function buildDecoratedClass(
  classRefForDefine: t.Identifier,
  path: NodePath<t.Class>,
  elements: NodePath<t.ClassMethod | t.ClassProperty>[],
  file: File
): {
  instanceNodes: t.ExpressionStatement[];
  wrapClass: (path: NodePath<t.Class>) => NodePath;
};

Decorator Usage Patterns

The system handles various decorator patterns:

Class Decorators:

@decorator
@decorator2(options)
class MyClass {}

Method Decorators:

class MyClass {
  @methodDecorator
  @methodDecorator2(options)
  method() {}
}

Property Decorators:

class MyClass {
  @propertyDecorator
  @propertyDecorator2(options)
  property = "value";
}

Accessor Decorators:

class MyClass {
  @accessorDecorator
  get value() { return this._value; }
  
  @accessorDecorator
  set value(v) { this._value = v; }
}

Decorator Evaluation Order

The system follows proper decorator evaluation order:

  1. Member decorators are evaluated from bottom to top
  2. Class decorators are evaluated after all member decorators
  3. Decorator expressions are evaluated left to right, top to bottom
  4. Decorator functions are called right to left, bottom to top

Version Differences

2018-09 (Legacy):

  • Pre-standardization syntax and semantics
  • Different metadata handling
  • Legacy descriptor-based approach

2021-12 to 2023-11 (Modern):

  • Progressive refinements of stage-3 proposal
  • Context-based decorator functions
  • Enhanced metadata capabilities
  • Improved auto-accessor support

Decorator Metadata

Modern decorators support rich metadata:

// Decorator context includes:
interface DecoratorContext {
  kind: "class" | "method" | "getter" | "setter" | "field" | "accessor";
  name: string | symbol;
  access: { get?(): any; set?(value: any): void };
  private?: boolean;
  static?: boolean;
  addInitializer(initializer: () => void): void;
}

Private Member Compatibility

Decorator support with private members has limitations:

  • Private fields in decorated classes are not supported in early versions
  • Private methods in decorated classes require specific handling
  • Modern decorator versions have better private member integration

Error Handling

The system provides detailed error messages for:

  • Incompatible decorator and private member combinations
  • Missing required features for decorator usage
  • Invalid decorator version configurations
  • Decorator evaluation failures