or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-babel--plugin-proposal-explicit-resource-management

Babel plugin that transforms JavaScript's explicit resource management syntax (using and await using declarations) into ES2015-compatible code

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@babel/plugin-proposal-explicit-resource-management@7.27.x

To install, run

npx @tessl/cli install tessl/npm-babel--plugin-proposal-explicit-resource-management@7.27.0

index.mddocs/

@babel/plugin-proposal-explicit-resource-management

@babel/plugin-proposal-explicit-resource-management is a Babel plugin that transforms JavaScript's explicit resource management syntax (using and await using declarations) into ES2015-compatible code. It implements the ECMAScript Explicit Resource Management proposal by converting resource acquisition declarations into try-catch-finally blocks with proper disposal patterns.

Package Information

  • Package Name: @babel/plugin-proposal-explicit-resource-management
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install --save-dev @babel/plugin-proposal-explicit-resource-management
  • Dependencies: @babel/helper-plugin-utils, @babel/plugin-transform-destructuring
  • Peer Dependencies: @babel/core ^7.0.0-0
  • Node Version: >=6.9.0

Core Imports

The plugin is not imported directly in application code but configured in Babel configuration:

{
  "plugins": ["@babel/plugin-proposal-explicit-resource-management"]
}

Plugin Development Imports

For plugin development and understanding the source code:

import { declare } from "@babel/helper-plugin-utils";
import { unshiftForXStatementBody } from "@babel/plugin-transform-destructuring";
import { types as t, template, traverse } from "@babel/core";
import type { NodePath, Visitor, PluginPass } from "@babel/core";

Note: REQUIRED_VERSION is a build-time macro available in Babel plugin development, not a regular import. It's transformed during the build process to version strings.

Basic Usage

This plugin transforms explicit resource management syntax from:

{
  using resource = acquireResource();
  await using asyncResource = acquireAsyncResource();
  // Resources automatically disposed when leaving scope
}

Into ES2015-compatible code with proper disposal handling:

{
  try {
    var _usingCtx = _usingCtx();
    const resource = _usingCtx.u(acquireResource());
    const asyncResource = _usingCtx.a(acquireAsyncResource());
    // Original code here
  } catch (_) {
    _usingCtx.e = _;
  } finally {
    await _usingCtx.d();
  }
}

Architecture

The plugin operates as a standard Babel transform plugin with the following key components:

  • Plugin Factory Function: Returns a Babel plugin object with visitor methods
  • AST Visitors: Transform using declarations in different contexts (blocks, modules, async functions)
  • Helper Integration: Uses Babel helper functions for runtime resource management
  • Parser Integration: Automatically enables the explicitResourceManagement parser plugin

Capabilities

Plugin Factory Function

Creates the Babel plugin object that transforms explicit resource management syntax.

/**
 * Main plugin factory function exported as default
 * Uses declare helper to create the plugin with version assertion
 */
declare((api: PluginAPI) => {
  api.assertVersion(REQUIRED_VERSION("^7.22.0"));
  
  return {
    name: "proposal-explicit-resource-management";
    manipulateOptions: (_: any, p: { plugins: string[] }) => p.plugins.push("explicitResourceManagement");
    visitor: Visitor<PluginPass>;
  };
});

interface PluginObject {
  /** Plugin identifier name */
  name: "proposal-explicit-resource-management";
  /** Function to enable explicitResourceManagement parser plugin */
  manipulateOptions: (_: any, parserOpts: { plugins: string[] }) => void;
  /** AST visitor object for transformations merged from multiple visitors */
  visitor: Visitor<PluginPass>;
}

AST Visitor Methods

The plugin uses specific visitor methods to transform different AST node types:

/**
 * Main transformation visitor that handles using declarations
 */
interface TransformUsingDeclarationsVisitor {
  /** Transforms using declarations in for-of statements by creating temporary variables */
  ForOfStatement(path: NodePath<t.ForOfStatement>): void;
  /** Transforms using declarations in block statements and static blocks with try-catch-finally */
  "BlockStatement|StaticBlock"(path: NodePath<t.BlockStatement | t.StaticBlock>, state: PluginPass): void;
}

/**
 * Complete plugin visitor merged from multiple visitors
 */
interface CompletePluginVisitor extends TransformUsingDeclarationsVisitor {
  /** Handles top-level using declarations by wrapping module body and hoisting exports */
  Program(path: NodePath<t.Program>): void;
  /** Pre-processes async functions with using declarations before async-to-generator transform */
  Function(path: NodePath<t.Function>, state: PluginPass): void;
}

/**
 * Visitor that skips function processing for specific transformation phases
 */
interface SkipFunctionVisitor extends TransformUsingDeclarationsVisitor {
  /** Skips function body traversal */
  Function(path: NodePath<t.Function>): void;
}

Transformation Features

The plugin transforms the following syntax patterns:

Block-Level Using Declarations

Transforms using and await using declarations in block statements and static blocks.

// Input syntax
using resource = acquireResource();
await using asyncResource = acquireAsyncResource();

// Transforms to try-catch-finally with disposal

Top-Level Using Declarations

Handles using declarations at module scope by wrapping the module body.

// Module-level using declarations
using moduleResource = acquireResource();
export { someValue };

// Transforms entire module body into block with disposal

For-Of Loop Using Declarations

Transforms using declarations in for-of loop iteration variables.

// Input syntax
for (using item of items) {
  // item is disposed after each iteration
}

// Transforms to proper disposal pattern

Async Function Using Declarations

Special handling for await using in async functions before async-to-generator transformation.

async function example() {
  await using resource = acquireAsyncResource();
  // Proper async disposal handling
}

Core Transformation Logic

The plugin implements dual transformation strategies based on Babel version and helper availability:

/**
 * Babel 8 transformation strategy using usingCtx helper
 * Generated when state.availableHelper("usingCtx") returns true
 */
interface Babel8TransformStrategy {
  /** Creates disposal context variable */
  contextId: t.Identifier;
  /** Wraps using declarations in try-catch-finally with context calls */
  transformPattern: "try { var ctx = usingCtx(); const resource = ctx.u(acquire()); } catch(_) { ctx.e = _; } finally { await ctx.d(); }";
}

/**
 * Legacy transformation strategy using using/dispose helpers
 * Used when usingCtx helper is not available
 */
interface LegacyTransformStrategy {
  /** Creates disposal stack array */
  stackId: t.Identifier;
  /** Uses stack-based disposal with using() and dispose() helpers */
  transformPattern: "try { var stack = []; const resource = using(stack, acquire()); } catch(_) { var error = _; var hasError = true; } finally { dispose(stack, error, hasError); }";
}

Helper Functions Integration

The plugin integrates with Babel's helper system for runtime functionality:

/**
 * Runtime helpers used by the plugin
 */
interface BabelHelpers {
  /** Sets function name for anonymous functions */
  setFunctionName(fn: Function, name: string): Function;
  /** Creates disposal context (Babel 8 mode) */
  usingCtx(): DisposalContext;
  /** Registers resource for disposal (legacy mode) */
  using(stack: any[], resource: any, isAsync?: boolean): any;
  /** Performs resource disposal (legacy mode) */
  dispose(stack: any[], error: any, hasError: boolean): Promise<void> | void;
}

interface DisposalContext {
  /** Add synchronous disposable resource */
  u(resource: any): any;
  /** Add asynchronous disposable resource */
  a(resource: any): any;
  /** Dispose all resources */
  d(): Promise<void>;
  /** Error to be rethrown after disposal */
  e?: any;
}

Configuration Requirements

The plugin has specific requirements for proper operation:

interface PluginRequirements {
  /** Minimum Babel version required (checked via REQUIRED_VERSION macro) */
  babelVersion: "^7.22.0";
  /** Parser plugin automatically enabled by manipulateOptions */
  parserPlugin: "explicitResourceManagement";
  /** Peer dependency requirement from package.json */
  babelCore: "^7.0.0-0";
  /** Node.js version requirement */
  nodeVersion: ">=6.9.0";
  /** Helper availability determines transformation strategy */
  helperAvailability: {
    /** Babel 8 mode: uses usingCtx() helper */
    modern: "state.availableHelper('usingCtx')";
    /** Legacy mode: uses using() and dispose() helpers */
    legacy: "!state.availableHelper('usingCtx')";
  };
}

/**
 * REQUIRED_VERSION macro usage in plugin
 * This is a compile-time macro that gets replaced with version strings
 */
interface RequiredVersionMacro {
  /** Macro function signature (not a real function) */
  REQUIRED_VERSION(version: "^7.22.0"): string;
  /** Transformed at build time to actual version requirement */
  transformedTo: "^7.22.0" | "^7.22.0 || >8.0.0-alpha <8.0.0-beta";
}

Error Handling

The plugin generates robust error handling patterns:

  • Exception Safety: Resources are disposed even when exceptions occur
  • Disposal Errors: Handles errors during resource disposal
  • Async Disposal: Proper handling of both sync and async disposal patterns
  • Nested Contexts: Supports nested using declarations with proper disposal ordering

Supported Syntax Transformations

Complete list of syntax patterns the plugin handles:

/**
 * Supported syntax transformations
 */
interface SupportedSyntax {
  /** Synchronous resource management */
  using: "using resource = acquireResource();";
  /** Asynchronous resource management */
  awaitUsing: "await using resource = acquireAsyncResource();";
  /** Block-scoped declarations */
  blockScope: "{ using resource = acquire(); }";
  /** Module-scoped declarations */
  moduleScope: "using moduleResource = acquire(); export default value;";
  /** For-of loop declarations */
  forOfLoop: "for (using item of items) { }";
  /** Anonymous function name setting */
  anonymousFunction: "using fn = class { };";
}

Types

/**
 * Internal enums and types used by the plugin
 */
enum USING_KIND {
  NORMAL = 0,
  AWAIT = 1
}

/**
 * Babel API types used by the plugin
 */
import type {
  NodePath,
  Visitor,
  PluginPass,
  PluginAPI,
  PluginObject
} from "@babel/core";

import type { types as t } from "@babel/core";

/**
 * Internal helper functions used by the plugin
 */
interface InternalHelpers {
  /** Checks if node is an anonymous function definition (class expression without id) */
  isAnonymousFunctionDefinition(node: t.Node): node is t.ClassExpression;
  /** Checks if node is a using declaration (using or await using) */
  isUsingDeclaration(node: t.Node): node is t.VariableDeclaration;
  /** Creates a call to setFunctionName helper for anonymous functions */
  emitSetFunctionNameCall(state: PluginPass, expression: t.Expression, name: string): t.CallExpression;
}

/**
 * Top-level using declaration tracking map used internally
 * Maps nodes to their using kind (NORMAL or AWAIT)
 */
const TOP_LEVEL_USING: Map<t.Node, USING_KIND>;

/**
 * Transform visitor that skips function bodies for specific transformations
 */
const transformUsingDeclarationsVisitorSkipFn: Visitor<PluginPass>;

/**
 * Main transformation visitor for using declarations
 */
const transformUsingDeclarationsVisitor: Visitor<PluginPass>;

/**
 * Helper function from @babel/plugin-transform-destructuring
 * Used for transforming for-of statements with using declarations
 */
function unshiftForXStatementBody(
  path: NodePath<t.ForOfStatement>,
  nodes: t.Statement[]
): void;