or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

index.mddocs/

@babel/plugin-transform-block-scoping

A Babel plugin that transforms ES2015 block-scoped declarations (const and let) into ES5-compatible var declarations while preserving correct scoping semantics. It handles complex scenarios including temporal dead zones (TDZ), loop closures, variable capturing, and binding conflicts.

Package Information

  • Package Name: @babel/plugin-transform-block-scoping
  • Package Type: npm (Babel plugin)
  • Language: TypeScript
  • Installation: npm install --save-dev @babel/plugin-transform-block-scoping
  • Node.js: >=6.9.0

Core Imports

// Import as Babel plugin (most common)
const blockScopingPlugin = require("@babel/plugin-transform-block-scoping");

ES Module:

import blockScopingPlugin from "@babel/plugin-transform-block-scoping";

Basic Usage

Babel Configuration

// babel.config.js
module.exports = {
  plugins: [
    "@babel/plugin-transform-block-scoping"
  ]
};

With options:

// babel.config.js
module.exports = {
  plugins: [
    ["@babel/plugin-transform-block-scoping", {
      tdz: false,
      throwIfClosureRequired: false
    }]
  ]
};

Programmatic Usage

import { transform } from "@babel/core";
import blockScopingPlugin from "@babel/plugin-transform-block-scoping";

const result = transform(code, {
  plugins: [
    [blockScopingPlugin, { tdz: true }]
  ]
});

Capabilities

Block Scoping Transformation

Transforms ES2015 let and const declarations to ES5 var while preserving block scoping behavior.

/**
 * Main plugin export - Babel plugin factory function
 * Requires @babel/core ^7.0.0-0 as peer dependency
 */
declare function blockScopingPlugin(
  api: any,
  options: Options
): BabelPlugin;

export default blockScopingPlugin;

interface Options {
  /** Enable temporal dead zone enforcement (default: false) */
  tdz?: boolean;
  /** Throw error when closure wrapping is required (default: false) */
  throwIfClosureRequired?: boolean;
}

interface BabelPlugin {
  name: string;
  visitor: Visitor;
}

Runtime Helpers: When TDZ is enabled or const violations occur, the plugin uses Babel runtime helpers:

  • temporalUndefined: Sentinel value for uninitialized TDZ variables
  • temporalRef: Runtime check for TDZ access
  • tdz: Throws ReferenceError for definite TDZ violations
  • readOnlyError: Throws TypeError for const reassignments

Input:

{
  let x = 1;
  const y = 2;
}

Output:

{
  var x = 1;
  var y = 2;
}

Temporal Dead Zone (TDZ) Support

When tdz: true is enabled, the plugin enforces temporal dead zone behavior by injecting runtime checks using Babel's helper functions (temporalRef, temporalUndefined, tdz).

Input with TDZ enabled:

console.log(x); // Should throw ReferenceError
let x = 1;

Output with TDZ:

var _temporalUndefined = {};
var x = _temporalUndefined;
console.log((x !== _temporalUndefined ? x : (() => {
  throw new ReferenceError('x is not defined - temporal dead zone');
})())); // Throws at runtime
x = 1;

### Loop Variable Handling

Special processing for block-scoped variables in loops, with automatic closure wrapping when variables are captured.

**Input:**
```javascript
for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100);
}

Output (with closure wrapping):

var _loop = function _loop() {
  setTimeout(() => console.log(i), 100);
};
for (var i = 0; i < 3; i++) {
  _loop();
}

Constant Violation Detection

Runtime errors for const reassignments to maintain ES2015 semantics. The plugin uses Babel's readOnlyError helper to generate appropriate error messages.

Input:

const x = 1;
x = 2; // Should throw TypeError

Output:

var x = 1;
x = ((() => {
  throw new TypeError('"x" is read-only');
})(), 2);

Error Types:

  • TypeError: Thrown for const reassignments ("varName" is read-only)
  • ReferenceError: Thrown for TDZ violations when tdz: true (cannot access 'varName' before initialization)

Variable Hoisting (Annex B.3.3)

Implements ECMAScript Annex B.3.3 function hoisting behavior for compatibility.

Input:

{
  function foo() {}
}
console.log(foo); // Should be accessible

Output:

{
  var foo = function foo() {};
}
console.log(foo);

Configuration Options

tdz (boolean, default: false)

Enable temporal dead zone enforcement with runtime checks.

// Enable TDZ
{
  "plugins": [["@babel/plugin-transform-block-scoping", { "tdz": true }]]
}

When enabled:

  • Adds runtime checks for accessing variables before declaration
  • Throws ReferenceError for TDZ violations
  • Increases bundle size due to additional runtime checks

throwIfClosureRequired (boolean, default: false)

Throw compilation error when closure wrapping would be required for loop variables.

// Strict mode - no closure wrapping allowed
{
  "plugins": [["@babel/plugin-transform-block-scoping", { "throwIfClosureRequired": true }]]
}

When enabled:

  • Prevents automatic closure wrapping in loops
  • Throws compilation error instead of transforming
  • Useful for performance-sensitive code where closures are not desired

Transformation Features

Core Capabilities

  1. Block Scope Transformation: Converts let/const to var with proper scoping
  2. Loop Variable Handling: Special processing for block-scoped variables in loops
  3. Temporal Dead Zone: Optional TDZ enforcement with runtime checks
  4. Closure Wrapping: Automatic loop body wrapping when variables are captured
  5. Constant Violation Detection: Runtime errors for const reassignments
  6. Variable Hoisting: Implements Annex B.3.3 function hoisting behavior
  7. Scope Conflict Resolution: Handles variable name conflicts across scope boundaries

Transformation Modes

  • Standard Mode: Basic let/const to var transformation
  • TDZ Mode: With temporal dead zone enforcement (tdz: true)
  • Strict Mode: Throws errors when closures are required (throwIfClosureRequired: true)

Browser Compatibility

This plugin enables let and const syntax to work in environments that don't support ES2015 block scoping:

  • Internet Explorer (all versions)
  • Chrome < 49
  • Firefox < 44
  • Safari < 10
  • Node.js < 6

Types

export interface Options {
  /** Enable temporal dead zone enforcement */
  tdz?: boolean;
  /** Throw error when closure wrapping is required */  
  throwIfClosureRequired?: boolean;
}

interface BabelPlugin {
  name: string;
  visitor: Visitor;
}

interface Visitor {
  Loop(path: NodePath<t.Loop>, state: PluginPass): void;
  VariableDeclaration(path: NodePath<t.VariableDeclaration>, state: PluginPass): void;
  ClassDeclaration(path: NodePath<t.ClassDeclaration>): void;
}