CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-babel--helper-create-class-features-plugin

Babel helper plugin that provides essential functionality for transforming modern JavaScript class features to ES6-compatible code

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

utilities.mddocs/

Utilities

Helper utilities for class initialization, computed key extraction, and AST manipulation.

Capabilities

Inject Initialization

Injects initialization code into class constructors.

/**
 * Injects initialization code into a class constructor
 * Creates constructor if none exists, or augments existing constructor
 * @param path - Class path to modify
 * @param constructor - Existing constructor path (undefined if none)
 * @param instanceNodes - Initialization expressions to inject
 * @param referenceVisitor - Callback for handling property references
 * @param lastInstanceNodeReturnsThis - Whether last node returns 'this'
 */
function injectInitialization(
  path: NodePath<t.Class>,
  constructor: NodePath<t.ClassMethod> | undefined,
  instanceNodes: t.ExpressionStatement[],
  referenceVisitor: (visitor: Visitor, state: any) => void,
  lastInstanceNodeReturnsThis: boolean
): void;

type Visitor = {
  [key: string]: (path: NodePath, state: any) => void;
};

Usage Examples:

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

// Inject field initialization into constructor
injectInitialization(
  classPath,
  constructorPath, // may be undefined
  [
    t.expressionStatement(
      t.assignmentExpression("=", 
        t.memberExpression(t.thisExpression(), t.identifier("field")),
        t.stringLiteral("value")
      )
    )
  ],
  (referenceVisitor, state) => {
    // Handle property references during injection
    for (const prop of props) {
      if (!prop.node.static) {
        prop.traverse(referenceVisitor, state);
      }
    }
  },
  false // last node doesn't return this
);

Extract Computed Keys

Extracts and memoizes computed property keys from class members.

/**
 * Extracts computed keys from class methods and properties
 * Hoists computed key expressions to avoid re-evaluation
 * @param path - Class path containing computed keys
 * @param computedPaths - Paths with computed keys to extract  
 * @param file - Babel file instance
 * @returns Array of statement nodes for hoisted key variables
 */
function extractComputedKeys(
  path: NodePath<t.Class>,
  computedPaths: NodePath<t.ClassProperty | t.ClassMethod>[],
  file: File
): t.Statement[];

Usage Examples:

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

// Find computed properties
const computedPaths: NodePath<t.ClassProperty | t.ClassMethod>[] = [];
for (const memberPath of classPath.get("body.body")) {
  if ((memberPath.isClassProperty() || memberPath.isClassMethod()) && 
      memberPath.node.computed) {
    computedPaths.push(memberPath);
  }
}

// Extract computed keys
const keyNodes = extractComputedKeys(classPath, computedPaths, file);

// Insert hoisted key variables before class
classPath.insertBefore(keyNodes);

Build Check In RHS

Builds a right-hand side expression for private property 'in' checks with proper validation.

/**
 * Builds a right-hand side expression for private property 'in' checks
 * Wraps expressions with helper when available for proper validation
 * @param rhs - The right-hand side expression to check
 * @param file - Babel file instance for helper access
 * @param inRHSIsObject - Whether RHS is known to be an object
 * @returns Enhanced expression with proper validation
 */
function buildCheckInRHS(
  rhs: t.Expression,
  file: File,
  inRHSIsObject?: boolean
): t.Expression;

Usage Examples:

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

// Build RHS check for private 'in' operation
const rhs = t.identifier("obj");
const checkedRHS = buildCheckInRHS(rhs, file);

// Use in private property 'in' check
const privateInCheck = t.binaryExpression(
  "in",
  privateNameId,
  checkedRHS
);

// With known object type (skips validation)
const checkedRHSOptimized = buildCheckInRHS(rhs, file, true);

Initialization Patterns

Constructor Creation

When no constructor exists, one is created:

// Before transformation
class Example {
  field = "value";
}

// After initialization injection
class Example {
  constructor() {
    this.field = "value";
  }
}

Constructor Augmentation

When constructor exists, initialization is injected:

// Before transformation  
class Example {
  field = "value";
  
  constructor(param) {
    console.log("constructor");
  }
}

// After initialization injection
class Example {
  constructor(param) {
    this.field = "value";
    console.log("constructor");
  }
}

Super Call Handling

Initialization respects super call requirements:

// Before transformation
class Child extends Parent {
  field = "value";
  
  constructor() {
    super();
    console.log("after super");
  }
}

// After initialization injection
class Child extends Parent {
  constructor() {
    super();
    this.field = "value";
    console.log("after super");
  }
}

Computed Key Patterns

Simple Computed Keys

// Before extraction
class Example {
  [computeKey()] = "value";
  [expensive.calculation] = "value2";
}

// After extraction
const _computeKey = computeKey();
const _expensive$calculation = expensive.calculation;
class Example {
  [_computeKey] = "value";
  [_expensive$calculation] = "value2";
}

Complex Expressions

// Before extraction
class Example {
  [prefix + Math.random()] = "value";
  [getKey() + suffix] = "value2";
}

// After extraction  
const _prefix$Math$random = prefix + Math.random();
const _getKey$suffix = getKey() + suffix;
class Example {
  [_prefix$Math$random] = "value";
  [_getKey$suffix] = "value2";
}

Reference Visitor Pattern

The reference visitor pattern handles property references during initialization:

const referenceVisitor: Visitor = {
  ThisExpression(path) {
    // Handle 'this' references in initializers
  },
  
  Super(path) {
    // Handle 'super' references in initializers
  },
  
  PrivateName(path) {
    // Handle private name references
  }
};

// Used in injectInitialization callback
(visitor, state) => {
  for (const prop of instanceProps) {
    prop.traverse(visitor, state);
  }
}

Scope and Binding Management

Utilities properly handle scope and binding:

  • Generate unique identifiers for memoized keys
  • Preserve binding references during transformation
  • Handle closure captures in initializer expressions
  • Maintain proper execution order for side effects

docs

decorator-support.md

feature-management.md

field-transformation.md

index.md

plugin-creation.md

utilities.md

tile.json