CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-babel--plugin-transform-logical-assignment-operators

Transforms logical assignment operators into short-circuited assignments for JavaScript environments that don't natively support these ES2021 operators

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

Babel Plugin Transform Logical Assignment Operators

This Babel plugin transforms logical assignment operators (&&=, ||=, ??=) into equivalent short-circuited assignment expressions for JavaScript environments that don't natively support these ES2021 operators. The plugin provides comprehensive transformation logic with proper memoization to handle complex assignment targets safely.

Package Information

  • Package Name: @babel/plugin-transform-logical-assignment-operators
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install @babel/plugin-transform-logical-assignment-operators

Core Imports

This is a Babel plugin used through Babel configuration. It is not imported directly in user code:

{
  "plugins": ["@babel/plugin-transform-logical-assignment-operators"]
}

Basic Usage

Add the plugin to your Babel configuration to transform logical assignment operators:

{
  "plugins": ["@babel/plugin-transform-logical-assignment-operators"]
}

Input:

// Logical OR assignment
obj.x ||= 1;
arr[0] ||= "default";

// Logical AND assignment
user.preferences &&= { theme: "dark" };

// Nullish coalescing assignment
config.apiUrl ??= "https://api.example.com";

Output:

// Logical OR assignment
obj.x || (obj.x = 1);
arr[0] || (arr[0] = "default");

// Logical AND assignment
user.preferences && (user.preferences = { theme: "dark" });

// Nullish coalescing assignment
config.apiUrl ?? (config.apiUrl = "https://api.example.com");

Architecture

This plugin follows Babel's standard plugin architecture:

  • Build-time Transformation: Transforms source code at compile time, not runtime
  • Zero Configuration: No options or configuration required
  • Safe Operation: Preserves the original semantics of logical assignment operators
  • Memoization: Prevents side effects by evaluating complex expressions only once

Capabilities

Plugin Factory Function

The plugin exports a default function created using declare() from @babel/helper-plugin-utils that returns a Babel plugin object.

declare function PluginFactory(api: PluginAPI): PluginObject;
export default PluginFactory;

interface PluginAPI {
  assertVersion(version: number): void;
}

interface PluginObject {
  name: "transform-logical-assignment-operators";
  manipulateOptions?: (opts: any, parser: { plugins: string[] }) => void;
  visitor: {
    AssignmentExpression(path: NodePath<AssignmentExpression>): void;
  };
}

Plugin Configuration

This plugin accepts no configuration options and operates with fixed transformation behavior.

// Plugin options interface (empty)
interface PluginOptions {}

Usage Examples:

{
  "plugins": [
    "@babel/plugin-transform-logical-assignment-operators"
  ]
}

Transformation Logic

The plugin transforms three types of logical assignment operators into equivalent expressions that preserve evaluation semantics.

Logical OR Assignment (||=)

Transforms logical OR assignment operators into conditional assignment expressions.

Input: x ||= y
Output: x || (x = y)

// Handles expressions like:
// obj.prop ||= value
// arr[index] ||= value
// computed[key] ||= value

Logical AND Assignment (&&=)

Transforms logical AND assignment operators into conditional assignment expressions.

Input: x &&= y
Output: x && (x = y)

// Handles expressions like:
// obj.prop &&= value
// arr[index] &&= value  
// computed[key] &&= value

Nullish Coalescing Assignment (??=)

Transforms nullish coalescing assignment operators into logical expressions using the nullish coalescing operator with conditional assignment.

Input: x ??= y
Output: x ?? (x = y)

// Handles expressions like:
// obj.prop ??= value → obj.prop ?? (obj.prop = value)
// arr[index] ??= value → arr[index] ?? (arr[index] = value)
// computed[key] ??= value → computed[key] ?? (computed[key] = value)

Safe Memoization

The plugin uses Babel's scope.maybeGenerateMemoised() to intelligently determine when memoization is needed for complex member expressions, preventing side effects during property access.

// The plugin memoizes complex object expressions and computed properties separately
// Uses t.assignmentExpression("=", memo, originalExpression) for memoization

Memoization Examples:

// Simple properties don't need memoization
// Input: obj.x ||= 1
// Output: obj.x || (obj.x = 1)

// Complex objects are memoized
// Input: deep.obj.x ||= 1
// Output: (_deep$obj = deep.obj).x || (_deep$obj.x = 1)

// Computed properties with side effects are memoized
// Input: obj[++key] ||= 1
// Output: obj[_key = ++key] || (obj[_key] = 1)

// Both object and property memoization when needed
// Input: deep.obj[++key] ||= 1  
// Output: (_deep$obj = deep.obj)[_key = ++key] || (_deep$obj[_key] = 1)

Parser Plugin Integration

Conditionally adds parser support for logical assignment operators based on Babel version. The behavior differs between Babel 7 and Babel 8.

// Babel version-specific conditional logic
manipulateOptions: process.env.BABEL_8_BREAKING
  ? undefined
  : (_, parser) => parser.plugins.push("logicalAssignment");

Babel Version Behavior:

  • Babel 7: Adds "logicalAssignment" parser plugin to enable syntax parsing
  • Babel 8: undefined - logical assignment syntax is built-in to the parser

Implementation Details:

  • Uses process.env.BABEL_8_BREAKING environment variable for version detection
  • Only modifies parser plugins when running under Babel 7
  • The logicalAssignment parser plugin enables recognition of ||=, &&=, and ??= operators

Error Handling

The plugin handles transformation errors gracefully within Babel's error reporting system. It does not throw custom exceptions but relies on Babel's built-in AST validation and error handling.

Version Requirements

// Plugin version requirements
interface VersionRequirements {
  babel: "^7.0.0-0";  // Peer dependency
  node: ">=6.9.0";    // Minimum Node.js version
}

TypeScript Support

The plugin is written in TypeScript and provides full type definitions:

  • Source: src/index.ts
  • Compiled Output: lib/index.js
  • Type Definitions: lib/index.d.ts
  • Type Safety: Full AST type annotations using @babel/types

Implementation Details

AST Node Types

The plugin works with these Babel AST node types and validates operators using t.LOGICAL_OPERATORS:

interface AssignmentExpression {
  type: "AssignmentExpression";
  operator: string; // "||=", "&&=", or "??="
  left: LVal;
  right: Expression;
}

// The plugin extracts logical operator using operator.slice(0, -1)
// Then validates against t.LOGICAL_OPERATORS: ["||", "&&", "??"]

type LVal = 
  | Identifier
  | MemberExpression
  | ArrayPattern
  | ObjectPattern
  | RestElement
  | TSParameterProperty;

// Key AST utilities used:
// - t.cloneNode() for safe node duplication
// - t.logicalExpression() for creating logical expressions
// - t.assignmentExpression() for creating assignment expressions
// - scope.maybeGenerateMemoised() for intelligent memoization

Visitor Method

The core transformation logic is implemented in the AssignmentExpression visitor:

interface Visitor {
  AssignmentExpression(path: NodePath<AssignmentExpression>): void;
}

interface NodePath<T> {
  node: T;
  replaceWith(node: Expression): void;
  // ... other NodePath methods
}

The visitor method implementation:

  1. Operator Validation: Uses operator.slice(0, -1) to extract logical part, validates with t.LOGICAL_OPERATORS.includes(operatorTrunc)
  2. Node Cloning: Creates safe copies using t.cloneNode(left) to avoid mutation issues
  3. Memoization Logic:
    • For MemberExpression: Uses scope.maybeGenerateMemoised(object) for object memoization
    • For computed properties: Uses scope.maybeGenerateMemoised(property) for property memoization
    • Generates assignment expressions to store memoized values
  4. Transformation: Creates t.logicalExpression() with original operator and assignment expression
  5. Replacement: Uses path.replaceWith() to substitute the transformed expression

Special Handling:

  • Super Objects: Includes special logic to handle Super objects in memoization
  • TypeScript Casts: Uses specific type assertions for complex member expression handling
  • Property Types: Handles both regular properties and PrivateName properties with type guards
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@babel/plugin-transform-logical-assignment-operators@7.27.x
Publish Source
CLI
Badge
tessl/npm-babel--plugin-transform-logical-assignment-operators badge