or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-babel--plugin-transform-async-generator-functions

Babel plugin that transforms async generator functions into ES2015 generators

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@babel/plugin-transform-async-generator-functions@7.28.x

To install, run

npx @tessl/cli install tessl/npm-babel--plugin-transform-async-generator-functions@7.28.0

index.mddocs/

@babel/plugin-transform-async-generator-functions

A Babel plugin that transforms async generator functions and for-await-of loops into ES2015 generators and manual iterator handling, enabling async generators to run in environments that support generators but not async generators.

Package Information

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

Core Imports

// babel.config.js or .babelrc.js
module.exports = {
  plugins: ["@babel/plugin-transform-async-generator-functions"]
};

For programmatic usage:

import { transform } from "@babel/core";
import asyncGeneratorPlugin from "@babel/plugin-transform-async-generator-functions";

const result = transform(code, {
  plugins: [asyncGeneratorPlugin]
});

Basic Usage

This plugin automatically transforms async generator functions and for-await-of loops. No configuration is required.

Input:

async function* asyncGenerator() {
  await 1;
  yield 2;
  yield* otherAsyncGenerator();
}

async function example() {
  for await (const item of asyncIterable) {
    console.log(item);
  }
}

Output:

function asyncGenerator() {
  return _asyncGenerator.apply(this, arguments);
}
function _asyncGenerator() {
  _asyncGenerator = babelHelpers.wrapAsyncGenerator(function* () {
    yield babelHelpers.awaitAsyncGenerator(1);
    yield 2;
    yield* babelHelpers.asyncGeneratorDelegate(
      babelHelpers.asyncIterator(otherAsyncGenerator())
    );
  });
  return _asyncGenerator.apply(this, arguments);
}

function example() {
  return _example.apply(this, arguments);
}
function _example() {
  _example = babelHelpers.wrapAsyncGenerator(function* () {
    var _iteratorAbruptCompletion = false;
    var _didIteratorError = false;
    var _iteratorError;
    try {
      for (var _iterator = babelHelpers.asyncIterator(asyncIterable), _step; 
           _iteratorAbruptCompletion = !(_step = yield babelHelpers.awaitAsyncGenerator(_iterator.next())).done; 
           _iteratorAbruptCompletion = false) {
        const item = _step.value;
        console.log(item);
      }
    } catch (err) {
      _didIteratorError = true;
      _iteratorError = err;
    } finally {
      try {
        if (_iteratorAbruptCompletion && _iterator.return != null) {
          yield babelHelpers.awaitAsyncGenerator(_iterator.return());
        }
      } finally {
        if (_didIteratorError) {
          throw _iteratorError;
        }
      }
    }
  });
  return _example.apply(this, arguments);
}

Architecture

The plugin operates through a two-phase transformation process:

  1. For-await-of Loop Transformation: Converts for await (... of ...) loops into try/catch/finally blocks with manual iterator handling
  2. Async Generator Function Transformation: Converts async function* name() declarations into regular generators wrapped with helper functions

The plugin uses Babel's helper system to inject runtime utilities that handle async iteration protocols and generator wrapping.

Capabilities

Plugin Function

The main plugin export that integrates with Babel's transformation pipeline.

/**
 * Main Babel plugin function created using declare() from @babel/helper-plugin-utils
 * @param api - Babel API object with version assertion and utilities
 * @returns Babel plugin object with visitor and metadata
 */
declare function createPlugin(api: BabelAPI): BabelPlugin;
export default createPlugin;

interface BabelPlugin {
  name: string;
  visitor: {
    Program(path: NodePath<t.Program>, state: PluginPass): void;
  };
  manipulateOptions?: (opts: any, parserOpts: { plugins: string[] }) => void;
}

Async Generator Function Transformation

Transforms async generator functions into regular generators wrapped with async helpers.

Transformation Scope:

  • async function* name() { ... } declarations
  • const fn = async function* () { ... } expressions
  • { async *method() { ... } } object methods
  • class { async *method() { ... } } class methods

Key Transformations:

  • await expryield babelHelpers.awaitAsyncGenerator(expr)
  • yield* expryield* babelHelpers.asyncGeneratorDelegate(babelHelpers.asyncIterator(expr), babelHelpers.awaitAsyncGenerator) (Babel 7)
  • yield* expryield* babelHelpers.asyncGeneratorDelegate(babelHelpers.asyncIterator(expr)) (Babel 8)
  • Function wrapper → babelHelpers.wrapAsyncGenerator(function* () { ... })
  • Function metadata → path.setData("@babel/plugin-transform-async-generator-functions/async_generator_function", true)

For-await-of Loop Transformation

Transforms for-await-of loops into equivalent try/catch/finally iterator handling code.

Transformation Scope:

  • for await (item of iterable) { ... } loops within async functions and async generators
  • All variable declaration patterns: const item, let { prop }, var [index]
  • Labeled statements: label: for await (...) { ... }

Generated Structure:

  • Iterator initialization with babelHelpers.asyncIterator(iterable)
  • Try/catch/finally blocks for proper cleanup
  • Manual iterator stepping with .next() calls
  • Proper handling of iterator .return() method

Runtime Helper Integration

The plugin automatically injects these Babel runtime helpers when needed:

// Async iterator creation
declare function asyncIterator(iterable: any): AsyncIterator<any>;

// Async generator delegation for yield* (Babel 7 includes awaitWrap, Babel 8 does not)
declare function asyncGeneratorDelegate(
  iterable: AsyncIterable<any>,
  awaitWrap?: Function
): AsyncGenerator<any>;

// Wraps await expressions in async generators  
declare function awaitAsyncGenerator(value: any): any;

// Wraps entire async generator functions
declare function wrapAsyncGenerator(fn: GeneratorFunction): Function;

Parser Plugin Integration

Automatically enables the "asyncGenerators" parser plugin in Babel 7 to parse async generator syntax. In Babel 8, this is handled automatically and the manipulateOptions function is undefined.

interface ManipulateOptions {
  (opts: any, parserOpts: { plugins: string[] }): void;
}

// The actual manipulateOptions implementation (Babel 7 only)
manipulateOptions: process.env.BABEL_8_BREAKING
  ? undefined
  : (_, parser) => parser.plugins.push("asyncGenerators")

Visitor Pattern

Uses Babel's visitor pattern to traverse and transform AST nodes.

interface PluginVisitor {
  Program(path: NodePath<t.Program>, state: PluginPass): void;
}

// Internal visitor used by the plugin
interface InternalVisitor {
  Function(path: NodePath<t.Function>, state: PluginPass): void;
}

// Environment visitors for specific transformations
interface ForAwaitVisitor {
  ArrowFunctionExpression(path: NodePath<t.ArrowFunctionExpression>): void;
  ForOfStatement(path: NodePath<t.ForOfStatement>, state: { file: BabelFile }): void;  
}

interface YieldStarVisitor {
  ArrowFunctionExpression(path: NodePath<t.ArrowFunctionExpression>): void;
  YieldExpression(path: NodePath<t.YieldExpression>, state: PluginPass): void;
}

Types

// Babel API types
interface BabelAPI {
  assertVersion(version: number | string): void;
}

// Babel File object
interface BabelFile {
  addHelper(name: string): t.Identifier;
}

// Babel types namespace
declare namespace t {
  interface Program extends Node {}
  interface Function extends Node {}
  interface ForOfStatement extends Node {
    await?: boolean;
    left: VariableDeclaration | LVal;
    right: Expression;
    body: Statement;
  }
  interface YieldExpression extends Node {
    delegate?: boolean;
    argument?: Expression;
  }
  interface ArrowFunctionExpression extends Function {}
  interface Identifier extends LVal {
    name: string;
  }
  interface CallExpression extends Expression {
    callee: Expression;
    arguments: Array<Expression | SpreadElement>;
  }
}

interface PluginPass {
  addHelper(name: string): t.Identifier;
  file: BabelFile;
}

interface NodePath<T> {
  node: T;
  scope: Scope;
  parent: Node;
  parentPath: NodePath<Node>;
  traverse(visitor: Visitor, state?: any): void;
  skip(): void;
  replaceWithMultiple(nodes: Node[]): void;
  ensureBlock(): void;
  setData(key: string, value: any): void;
}

// Base types referenced above
interface Node {
  type: string;
}

interface Expression extends Node {}
interface Statement extends Node {}
interface LVal extends Node {}
interface VariableDeclaration extends Statement {}
interface SpreadElement extends Node {}

interface Scope {
  generateUidIdentifier(name: string): t.Identifier;
  parent: Scope;
  crawl(): void;
}

interface Visitor<T = any> {
  [key: string]: (path: NodePath<Node>, state?: T) => void;
}

// Transform result types
interface RewriteResult {
  replaceParent: boolean;
  node: t.Statement[];
  declar: t.Statement | undefined;
  loop: t.ForStatement;
}

Compatibility

  • Babel Version: 7.x (with Babel 8 preparation)
  • Node.js: >= 6.9.0 (Babel 7), >= 20.19.0 || >= 22.12.0 (Babel 8)
  • Target Environments: ES2015+ (requires generator support)
  • Dependencies:
    • @babel/core as peer dependency
    • @babel/helper-plugin-utils (internal)
    • @babel/helper-remap-async-to-generator (internal)
    • @babel/traverse (internal)

Error Handling

The plugin handles various edge cases:

  • Nested Functions: Skips transformation inside arrow functions and nested non-async functions
  • Iterator Cleanup: Properly calls iterator .return() method in finally blocks
  • Exception Propagation: Maintains proper error handling in for-await loops
  • Label Preservation: Maintains labeled statements when transforming for-await loops

Configuration

This plugin accepts no configuration options. It transforms all async generator functions and for-await-of loops encountered in the code.

Usage in babel.config.js:

module.exports = {
  plugins: [
    "@babel/plugin-transform-async-generator-functions"
  ]
};

Usage with other plugins:

module.exports = {
  plugins: [
    "@babel/plugin-transform-async-generator-functions",
    "@babel/plugin-transform-async-to-generator"
  ]
};