or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-babel-plugin-minify-constant-folding

A Babel plugin for constant folding optimization that evaluates compile-time expressions and replaces them with their computed values

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/babel-plugin-minify-constant-folding@0.5.x

To install, run

npx @tessl/cli install tessl/npm-babel-plugin-minify-constant-folding@0.5.0

index.mddocs/

babel-plugin-minify-constant-folding

A Babel plugin that performs constant folding optimization during JavaScript compilation. It evaluates expressions at compile-time that can be computed statically and replaces them with their literal values, reducing runtime computation and improving performance.

Package Information

  • Package Name: babel-plugin-minify-constant-folding
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install babel-plugin-minify-constant-folding --save-dev

Core Imports

As a Babel plugin, this package is typically imported and used through Babel configuration:

const constantFoldingPlugin = require("babel-plugin-minify-constant-folding");

Dependencies:

  • babel-helper-evaluate-path: Used internally for safe expression evaluation

Basic Usage

Via .babelrc (Recommended)

.babelrc

{
  "plugins": ["minify-constant-folding"]
}

Via CLI

babel --plugins minify-constant-folding script.js

Via Node API

const babel = require("@babel/core");

const result = babel.transform("code", {
  plugins: ["minify-constant-folding"]
});

Configuration Options

// With options
{
  "plugins": [
    ["minify-constant-folding", { "tdz": true }]
  ]
}

Architecture

The plugin operates through Babel's visitor pattern, transforming AST nodes during compilation:

  • Expression Evaluation: Uses babel-helper-evaluate-path to determine if expressions can be safely computed
  • Binary Expression Optimization: Combines adjacent string literals in concatenation expressions
  • Method Call Replacement: Replaces array and string methods with computed values when inputs are static
  • Member Access Replacement: Replaces property access on static arrays and strings with their values

Capabilities

Transformation Examples

The plugin performs various compile-time optimizations as demonstrated in these examples:

Basic arithmetic and string concatenation:

// Input
"a" + "b";        // → "ab"
2 * 3;            // → 6
4 | 3;            // → 7
"b" + a + "c" + "d" + g + z + "f" + "h" + "z";  // → "b" + a + "cd" + g + z + "fhz"

Array literal optimizations:

// Input
[1, 2, 3].length;     // → 3
[1, 2, 3][1];         // → 2
[1, 2, 3].join();     // → "1,2,3"
["a", "b", "c"].join("@");  // → "a@b@c"
[1, 2, 3].pop();      // → 3
[1, 2, 3].shift();    // → 2 (new length after removing first element)
[1, 2, 3].slice(0, 2); // → [1, 2]

String literal optimizations:

// Input
"abc"[0];             // → "a"
"abc".charAt(1);      // → "b"
"abc".charCodeAt(1);  // → 98
"abc".length;         // → 3
"a,b,c".split(",");   // → ["a", "b", "c"]

Plugin Factory Function

The main export that creates a Babel plugin configuration. The plugin uses a replacement system to handle array and string literal optimizations.

/**
 * Creates a Babel plugin for constant folding optimization
 * @param {object} babel - Babel core object containing types and utilities
 * @returns {object} Plugin configuration with name and visitor methods
 */
function constantFoldingPlugin(babel);

/** Symbol used to mark processed nodes and prevent infinite recursion */
const SEEN_SYMBOL: symbol;

/** Symbol used as fallback handler for dynamic property access */
const FALLBACK_HANDLER: symbol;

Returns: Plugin configuration object with the following structure:

interface PluginConfig {
  name: "minify-constant-folding";
  visitor: {
    BinaryExpression: (path: NodePath) => void;
    Expression: (path: NodePath, state: { opts?: PluginOptions }) => void;
    CallExpression: (path: NodePath) => void;
    MemberExpression: (path: NodePath) => void;
  };
}

Plugin Options

interface PluginOptions {
  /** Account for Temporal Dead Zone when evaluating expressions (default: false) */
  tdz?: boolean;
}

Expression Optimization

The plugin optimizes various types of expressions:

Binary Expressions

  • String concatenation: "a" + "b""ab"
  • Arithmetic operations: 2 * 36
  • Bitwise operations: 4 | 37
  • Complex concatenation: "b" + a + "c" + "d""b" + a + "cd"

Array Method Calls

Array methods are replaced with computed values when the array is static:

// Array method optimizations (when array has no spread elements)
interface ArrayOptimizations {
  /** ["a", "b", "c"].join() → "a,b,c" */
  join(separator?: string): string;
  /** [1, 2, 3].length → 3 */
  length: number;
  /** [1, 2, 3][1] → 2 */
  [index: number]: any;
  /** [1, 2, 3].slice(0, 2) → [1, 2] */
  slice(start?: number, end?: number): any[];
  /** [1, 2, 3].shift() → returns new length after removing first element (2) */
  shift(): number | undefined;
  /** [a, b, c].pop() → c */
  pop(): any;
  /** [a, b, c].reverse() → [c, b, a] */
  reverse(): any[];
  /** [a, b, c].push(d, e) → returns new length */
  push(...items: any[]): number;
  /** [1, 2, 3].splice(1) → [2, 3], [1, 2, 3, 4].splice(1, 2) → [2, 3] */
  splice(start: number, deleteCount?: number, ...items: any[]): any[];
}

String Method Calls

String methods are replaced with computed values when the string is static:

// String method optimizations
interface StringOptimizations {
  /** "abc".length → 3 */
  length: number;
  /** "abc"[0] → "a", "abc"[4] → undefined */
  [index: number]: string | undefined;
  /** "abc".charAt() → "a", "abc".charAt(1) → "b" */
  charAt(index?: number): string;
  /** "abc".charCodeAt() → 97, "abc".charCodeAt(1) → 98 */
  charCodeAt(index?: number): number;
  /** "abc".codePointAt() → 97, "abc".codePointAt(1) → 98 */
  codePointAt(index?: number): number;
  /** "a,b,c".split(",") → ["a", "b", "c"], "a,b,c".split() → ["a,b,c"] */
  split(separator?: string | undefined): string[];
}

Safety Constraints

The plugin includes several safety mechanisms to prevent incorrect optimizations:

  • Pure Expression Check: Only optimizes expressions that have no side effects
  • Export Specifier Protection: Avoids replacing values in export specifiers
  • Negative Zero Preservation: Maintains -0 vs 0 distinction
  • Unary Expression Handling: Preserves !0/!1 patterns and void 0 for undefined
  • Fraction Avoidance: Skips non-integer results to avoid precision issues
  • Object Literal Skipping: Avoids converting objects to prevent environment-specific issues
  • Temporal Dead Zone: Optional TDZ consideration for safer transformations
  • Infinite Recursion Prevention: Uses internal symbol marking to avoid re-processing already optimized nodes

Replacement System Architecture

The plugin uses a sophisticated replacement system to handle array and string method optimizations:

interface ReplacementSystem {
  /** Handlers for ArrayExpression nodes */
  ArrayExpression: {
    /** Check if array can be safely replaced (no spread elements) */
    canReplace(): boolean;
    /** Member access handlers (length, [index]) */
    members: Record<string | symbol, Function>;
    /** Method call handlers (join, push, pop, etc.) */
    calls: Record<string, Function>;
  };
  /** Handlers for StringLiteral nodes */
  StringLiteral: {
    /** Member access handlers (length, [index]) */
    members: Record<string | symbol, Function>;
    /** Method call handlers (split, charAt, etc.) */
    calls: Record<string, Function>;
  };
}

/** Fallback handler for dynamic property access */
interface FallbackHandler {
  /** Called when specific property handler not found */
  [FALLBACK_HANDLER]: (propertyName: string | number) => any;
}

Types

/** Babel NodePath representing an AST node */
interface NodePath {
  node: any;
  parent: any;
  replaceWith(node: any): void;
  get(key: string): NodePath;
  isLiteral(): boolean;
  isPure(): boolean;
  isBinaryExpression(opts?: object): boolean;
  isStringLiteral(): boolean;
  // ... other Babel NodePath methods
}

/** Babel types utility object */
interface BabelTypes {
  stringLiteral(value: string): any;
  numericLiteral(value: number): any;
  arrayExpression(elements: any[]): any;
  unaryExpression(operator: string, argument: any, prefix?: boolean): any;
  valueToNode(value: any): any;
  isMemberExpression(node: any): boolean;
  isExportSpecifier(node: any): boolean;
  isUnaryExpression(node: any, opts?: object): boolean;
  isNumericLiteral(node: any, opts?: object): boolean;
  isIdentifier(node: any, opts?: object): boolean;
  // ... other Babel type methods
}