CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-babel--plugin-transform-destructuring

Compile ES2015 destructuring to ES5

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

index.mddocs/

@babel/plugin-transform-destructuring

@babel/plugin-transform-destructuring is a Babel plugin that compiles ES2015 (ES6) destructuring syntax to ES5-compatible code. It transforms array destructuring, object destructuring, destructuring in function parameters, catch clauses, and for-in/for-of loops. The plugin handles complex patterns including nested destructuring, default values, and rest patterns while preserving the semantic behavior of destructuring operations.

Package Information

  • Package Name: @babel/plugin-transform-destructuring
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install --save-dev @babel/plugin-transform-destructuring

Core Imports

import transformDestructuring from "@babel/plugin-transform-destructuring";
import { 
  Options,
  buildObjectExcludingKeys,
  unshiftForXStatementBody
} from "@babel/plugin-transform-destructuring";

For CommonJS:

const transformDestructuring = require("@babel/plugin-transform-destructuring");
const { buildObjectExcludingKeys, unshiftForXStatementBody } = require("@babel/plugin-transform-destructuring");

Basic Usage

// babel.config.js
module.exports = {
  plugins: [
    ["@babel/plugin-transform-destructuring", {
      allowArrayLike: false,
      loose: false,
      useBuiltIns: false
    }]
  ]
};
// Input code (ES2015+ destructuring)
const { name, age } = user;
const [first, second, ...rest] = items;
function greet({ name = "World" }) {
  console.log(`Hello, ${name}!`);
}

// Output after transformation (ES5 compatible)
const name = user.name, age = user.age;
const first = items[0], second = items[1], rest = items.slice(2);
function greet(_ref) {
  const name = _ref.name === void 0 ? "World" : _ref.name;
  console.log("Hello, " + name + "!");
}

Architecture

The plugin is built around several key components:

  • Babel Plugin Interface: Standard Babel plugin architecture using declare() from @babel/helper-plugin-utils
  • Visitor Pattern: AST visitors for different destructuring contexts (variables, assignments, loops, etc.)
  • DestructuringTransformer: Core transformation engine that converts destructuring patterns to sequential assignments
  • Utility Functions: Helper functions for handling object rest patterns, array conversions, and variable declarations
  • Configuration Options: Plugin options for controlling transformation behavior and assumptions

Capabilities

Plugin Configuration

Main plugin export that integrates with Babel's transformation pipeline.

/**
 * Main Babel plugin export for destructuring transformation
 * @param api - Babel API object with version checking and assumptions
 * @param options - Plugin configuration options
 * @returns Babel plugin object with visitor methods
 */
declare function transformDestructuring(api: any, options: Options): {
  name: string;
  visitor: PluginVisitor;
};

export default transformDestructuring;

interface Options {
  /** Enable transformation of array-like objects (e.g., arguments, NodeList) */
  allowArrayLike?: boolean;
  /** Enable loose mode transformations for better performance */
  loose?: boolean;
  /** Use built-in methods when available instead of helper functions */
  useBuiltIns?: boolean;
}

interface PluginVisitor {
  ExportNamedDeclaration(path: NodePath): void;
  ForXStatement(path: NodePath<ForXStatement>): void;
  CatchClause(path: NodePath): void;
  AssignmentExpression(path: NodePath, state: any): void;
  VariableDeclaration(path: NodePath, state: any): void;
}

DestructuringTransformer Class

Core transformation engine for converting destructuring patterns to sequential assignments.

/**
 * Main class for transforming destructuring patterns into sequential assignments
 */
export class DestructuringTransformer {
  arrayRefSet: Set<string>;
  
  constructor(opts: DestructuringTransformerOption);
  
  /**
   * Initialize destructuring transformation for a given pattern and reference
   * @param pattern - The destructuring pattern (ArrayPattern, ObjectPattern, etc.)
   * @param ref - The expression being destructured
   */
  init(pattern: LVal, ref: Expression): void;
  
  /**
   * Add a destructuring assignment to the transformation
   * @param id - The target identifier or pattern
   * @param init - The initialization expression
   */
  push(id: LVal | PatternLike, init: Expression | null): void;
  
  /**
   * Convert an expression to an array for array destructuring
   * @param node - The expression to convert
   * @param count - Optional specific number of elements needed
   * @returns Expression that evaluates to an array
   */
  toArray(node: Expression, count?: false | number): Expression;
  
  /**
   * Build a variable assignment statement
   * @param id - The assignment target
   * @param init - The initialization expression
   * @returns Variable assignment node
   */
  buildVariableAssignment(
    id: AssignmentExpression["left"], 
    init: Expression
  ): ExpressionStatement | VariableDeclaration;
  
  /**
   * Build a variable declaration statement
   * @param id - The identifier being declared
   * @param init - The initialization expression
   * @returns Variable declaration node
   */
  buildVariableDeclaration(id: Identifier, init: Expression): VariableDeclaration;
  
  /**
   * Returns the appropriate extends helper (Object.assign or helper function)
   * @returns Member expression or helper call
   */
  getExtendsHelper(): MemberExpression | CallExpression;
}

interface DestructuringTransformerOption {
  /** Block hoisting priority for generated nodes */
  blockHoist?: number;
  /** Assignment operator for generated assignments */
  operator?: AssignmentExpression["operator"];
  /** Array to collect generated transformation nodes */
  nodes?: DestructuringTransformerNode[];
  /** Variable declaration kind (var, let, const) */
  kind?: VariableDeclarationKindAllowsPattern;
  /** Babel scope object for identifier generation and binding management (required) */
  scope: Scope;
  /** Whether array-like objects should be treated as iterable (required) */
  arrayLikeIsIterable: boolean;
  /** Whether iterables should be assumed to be arrays for optimization (required) */
  iterableIsArray: boolean;
  /** Whether object rest should exclude symbol properties (required) */
  objectRestNoSymbols: boolean;
  /** Whether to use built-in methods instead of helper functions (required) */
  useBuiltIns: boolean;
  /** Function to register Babel helper functions (required) */
  addHelper: File["addHelper"];
}

Utility Functions

Helper functions for specific destructuring transformations.

/**
 * Build an object excluding specified keys (used for object rest patterns)
 * @param excludedKeys - Array of properties to exclude
 * @param objRef - Reference to the source object
 * @param scope - Babel scope object
 * @param addHelper - Helper function registration
 * @param objectRestNoSymbols - Whether to exclude symbol properties
 * @param useBuiltIns - Whether to use built-in Object.assign
 * @returns Call expression creating the filtered object
 */
export function buildObjectExcludingKeys<T extends ExcludingKey>(
  excludedKeys: T[],
  objRef: Expression,
  scope: Scope,
  addHelper: File["addHelper"],
  objectRestNoSymbols: boolean,
  useBuiltIns: boolean
): CallExpression;

/**
 * Convert a variable declaration containing destructuring patterns
 * @param path - NodePath for the variable declaration
 * @param addHelper - Helper function registration
 * @param arrayLikeIsIterable - Array-like transformation assumption
 * @param iterableIsArray - Iterable transformation assumption
 * @param objectRestNoSymbols - Object rest symbol handling assumption
 * @param useBuiltIns - Whether to use built-in methods
 */
export function convertVariableDeclaration(
  path: NodePath<VariableDeclaration>,
  addHelper: File["addHelper"],
  arrayLikeIsIterable: boolean,
  iterableIsArray: boolean,
  objectRestNoSymbols: boolean,
  useBuiltIns: boolean
): void;

/**
 * Convert an assignment expression containing destructuring patterns
 * @param path - NodePath for the assignment expression
 * @param addHelper - Helper function registration
 * @param arrayLikeIsIterable - Array-like transformation assumption
 * @param iterableIsArray - Iterable transformation assumption
 * @param objectRestNoSymbols - Object rest symbol handling assumption
 * @param useBuiltIns - Whether to use built-in methods
 */
export function convertAssignmentExpression(
  path: NodePath<AssignmentExpression & { left: Pattern }>,
  addHelper: File["addHelper"],
  arrayLikeIsIterable: boolean,
  iterableIsArray: boolean,
  objectRestNoSymbols: boolean,
  useBuiltIns: boolean
): void;

/**
 * Insert statements at the beginning of a for-X statement body
 * @param statementPath - NodePath for the ForXStatement
 * @param newStatements - Array of statements to insert
 */
export function unshiftForXStatementBody(
  statementPath: NodePath<ForXStatement>,
  newStatements: Statement[]
): void;

Types

/** Union type for nodes generated by the destructuring transformer */
export type DestructuringTransformerNode = 
  | VariableDeclaration 
  | ExpressionStatement 
  | ReturnStatement;

/** Variable declaration kinds that support destructuring patterns */
export type VariableDeclarationKindAllowsPattern = Exclude<
  VariableDeclaration["kind"], 
  "using" | "await using"
>;

/** Interface for objects with excludable keys used in object rest patterns */
interface ExcludingKey {
  key: Expression | PrivateName;
  computed: boolean;
}

/** Babel AST types used by the plugin */
interface LVal {} // From @babel/types
interface Pattern {} // From @babel/types  
interface PatternLike {} // From @babel/types
interface Expression {} // From @babel/types
interface Statement {} // From @babel/types
interface Identifier {} // From @babel/types
interface VariableDeclaration {} // From @babel/types
interface AssignmentExpression {} // From @babel/types
interface CallExpression {} // From @babel/types
interface MemberExpression {} // From @babel/types
interface ExpressionStatement {} // From @babel/types
interface ReturnStatement {} // From @babel/types
interface PrivateName {} // From @babel/types
interface ForXStatement {} // From @babel/types
interface NodePath<T = any> {} // From @babel/traverse
interface Scope {} // From @babel/traverse
interface File {} // From @babel/core

Plugin Behavior

Transformation Contexts

The plugin handles destructuring in the following contexts:

  1. Variable Declarations: const { x, y } = obj;const x = obj.x, y = obj.y;
  2. Assignment Expressions: ({ x, y } = obj);x = obj.x, y = obj.y;
  3. Function Parameters: function f({ x }) {}function f(_ref) { const x = _ref.x; }
  4. For-X Statements: for (const { x } of arr) {}for (const _ref of arr) { const x = _ref.x; }
  5. Catch Clauses: catch ({ message }) {}catch (_ref) { const message = _ref.message; }
  6. Export Declarations: export const { x } = obj; → Split into separate export and declaration

Pattern Types

Supports all ES2015+ destructuring patterns:

  • Object Patterns: { prop, nested: { deep } }
  • Array Patterns: [first, second, ...rest]
  • Assignment Patterns: { prop = defaultValue }
  • Rest Patterns: { ...rest } and [...rest]
  • Nested Patterns: { obj: { nested } } and [[nested]]

Configuration Options

  • allowArrayLike: When enabled, treats array-like objects (NodeList, arguments) as iterable
  • loose: Enables performance optimizations with slightly different semantics
  • useBuiltIns: Uses native Object.assign instead of helper functions when available

Error Handling

The plugin handles various edge cases:

  • Empty destructuring patterns are transformed to runtime checks
  • Missing properties default to undefined
  • Array holes are properly handled
  • Invalid destructuring targets throw runtime errors

docs

index.md

tile.json