CtrlK
BlogDocsLog inGet started
Tessl Logo

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

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-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;

docs

index.md

tile.json