CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-babel--plugin-transform-object-rest-spread

Babel plugin that transforms ES6+ object rest and spread syntax to ES5-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-transform-object-rest-spread

The @babel/plugin-transform-object-rest-spread plugin transforms ECMAScript object rest and spread syntax into ES5-compatible code. It enables developers to use modern object destructuring and spread operations while maintaining compatibility with older JavaScript environments.

Package Information

  • Package Name: @babel/plugin-transform-object-rest-spread
  • Package Type: npm (Babel plugin)
  • Language: TypeScript (compiled to JavaScript)
  • Installation: npm install --save-dev @babel/plugin-transform-object-rest-spread

Core Imports

This is a Babel plugin, so it's typically configured in your Babel configuration:

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

With options:

// babel.config.js
module.exports = {
  plugins: [
    ["@babel/plugin-transform-object-rest-spread", {
      useBuiltIns: true,
      loose: false
    }]
  ]
};

For programmatic usage with Babel's API:

import transformObjectRestSpread from "@babel/plugin-transform-object-rest-spread";
import { transform } from "@babel/core";

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

Basic Usage

Once configured, the plugin automatically transforms object rest and spread syntax in your code:

// Input: Object rest in destructuring
const { a, b, ...rest } = obj;

// Input: Object spread in object literals
const newObj = { ...obj1, prop: 'value', ...obj2 };

// Input: Object rest in function parameters
function fn({ param1, ...restParams }) {
  // Function body
}

// All of the above are transformed to ES5-compatible code

Architecture

The plugin operates as a Babel transformation plugin that:

  • AST Visitor: Traverses the Abstract Syntax Tree to find object rest/spread patterns
  • Transformation Engine: Converts modern syntax to ES5-compatible helper function calls
  • Helper System: Uses Babel helpers like objectWithoutProperties and objectSpread2
  • Configuration System: Respects Babel assumptions and plugin options for optimization
  • Compatibility Layer: Supports both ES modules and CommonJS output formats

Capabilities

Plugin Configuration

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

import { declare } from "@babel/helper-plugin-utils";
import type { PluginPass } from "@babel/core";

/**
 * Main plugin export - default export from the package
 * This is a Babel plugin factory function created using declare()
 * @param api - Babel API object
 * @param opts - Plugin options
 * @returns Babel plugin configuration object
 */
export default declare((api: any, opts: Options) => {
  api.assertVersion(7);
  // Plugin implementation returns PluginVisitor object
});

interface Options {
  /** Whether to use built-in Object.assign instead of helper functions (default: auto-detected based on targets) */
  useBuiltIns?: boolean;
  /** Enable loose mode for more compact but less spec-compliant output (default: false) */
  loose?: boolean;
}

/**
 * Plugin visitor interface - returned by the main plugin function
 */
interface PluginVisitor {
  name: "transform-object-rest-spread";
  manipulateOptions?: (opts: any, parser: any) => void;
  visitor: {
    Function(path: NodePath<t.Function>): void;
    VariableDeclarator(path: NodePath<t.VariableDeclarator>, file: PluginPass): void;
    ExportNamedDeclaration(path: NodePath<t.ExportNamedDeclaration>): void;
    CatchClause(path: NodePath<t.CatchClause>): void;
    AssignmentExpression(path: NodePath<t.AssignmentExpression>, file: PluginPass): void;
    ForXStatement(path: NodePath<t.ForXStatement>): void;
    ArrayPattern(path: NodePath<t.ArrayPattern>): void;
    ObjectExpression(path: NodePath<t.ObjectExpression>, file: PluginPass): void;
  };
}

Transformation Patterns

The plugin handles several distinct patterns of object rest and spread syntax:

Object Rest in Variable Declarations

Transforms object rest patterns in variable declarations:

// Input
const { a, b, ...rest } = obj;

// Output (conceptual - actual output uses helper functions)
const a = obj.a;
const b = obj.b;
const rest = objectWithoutProperties(obj, ["a", "b"]);

Object Spread in Object Expressions

Transforms object spread syntax in object literals:

// Input
const result = { ...obj1, prop: 'value', ...obj2 };

// Output (conceptual - actual output uses helper functions)
const result = objectSpread2({}, obj1, { prop: 'value' }, obj2);

Object Rest in Function Parameters

Transforms object rest patterns in function parameter lists:

// Input
function fn({ param1, ...restParams }) {
  // Function body
}

// Output (simplified - actual transformation is more complex)
function fn(_ref) {
  const param1 = _ref.param1;
  const restParams = objectWithoutProperties(_ref, ["param1"]);
  // Function body
}

Object Rest in Assignment Expressions

Transforms object rest patterns in assignment contexts:

// Input
({ a, ...rest } = obj);

// Output (conceptual)
var _obj = obj;
a = _obj.a;
rest = objectWithoutProperties(_obj, ["a"]);

Object Rest in Control Flow

Transforms object rest patterns in for-in/for-of loops and catch clauses:

// Input: for-of with object rest
for (const { key, ...rest } of items) {
  // Loop body
}

// Input: catch clause with object rest
try {
  // Code
} catch ({ message, ...errorDetails }) {
  // Error handling
}

Plugin Options

useBuiltIns Option

Controls whether to use native Object.assign or Babel helper functions:

interface UseBuiltInsOption {
  /** 
   * When true, uses native Object.assign for object spread operations
   * When false, uses Babel's _extends helper function
   * When undefined, auto-detects based on compilation targets
   */
  useBuiltIns?: boolean;
}

Usage Example:

// With useBuiltIns: true
const result = Object.assign({}, obj1, obj2);

// With useBuiltIns: false
const result = _extends({}, obj1, obj2);

loose Option

Controls whether to use loose mode for more compact output:

interface LooseOption {
  /**
   * When true, generates more compact but less spec-compliant code
   * Affects symbol handling and property enumeration behavior
   * Default: false
   */
  loose?: boolean;
}

Usage Example:

// With loose: false (strict mode)
// Generates more comprehensive checks for symbols and getters

// With loose: true  
// Generates simpler, faster code with fewer edge case checks

Helper Functions

While not directly exposed as public API, the plugin uses several internal helper functions that are worth understanding:

shouldStoreRHSInTemporaryVariable

Utility function to determine if the right-hand side of an assignment should be stored in a temporary variable to avoid duplication:

import type { types as t } from "@babel/core";

/**
 * Utility function exported from shouldStoreRHSInTemporaryVariable.ts
 * Determines if RHS should be stored in temporary variable to avoid duplication
 * @param node - AST node representing the left-hand side pattern  
 * @returns Whether to store RHS in temporary variable
 */
export default function shouldStoreRHSInTemporaryVariable(
  node: t.LVal | t.PatternLike
): boolean;

Compatibility Data

Browser compatibility information for Object.assign feature detection:

/**
 * Browser compatibility data exported from compat-data.ts
 * Contains minimum version information for Object.assign support
 */
export default {
  "Object.assign": {
    chrome: "49",
    opera: "36",
    edge: "13",
    firefox: "36",
    safari: "10",
    node: "6",
    deno: "1",
    ios: "10",
    samsung: "5",
    opera_mobile: "36",
    electron: "0.37"
  }
};

interface CompatData {
  "Object.assign": {
    [browser: string]: string;
  };
}

Internal Helper Functions

The plugin uses several internal functions that transform AST nodes. While not part of the public API, understanding these functions helps explain the plugin's behavior:

/**
 * Internal utility functions used by the plugin (not exported)
 */

/**
 * Checks if a node contains object rest elements
 * @param path - AST node path to check
 * @returns true if the node contains object rest patterns
 */
function hasObjectRestElement(
  path: NodePath<t.LVal | t.PatternLike | t.TSParameterProperty>
): boolean;

/**
 * Checks if an object expression contains spread elements
 * @param node - Object expression node to check
 * @returns true if the object contains spread syntax
 */
function hasSpread(node: t.ObjectExpression): boolean;

/**
 * Extracts all keys from an object pattern for rest transformation
 * @param node - Object pattern to extract keys from
 * @returns Object containing keys array and metadata
 */
function extractNormalizedKeys(node: t.ObjectPattern): {
  keys: t.Expression[];
  allPrimitives: boolean;
  hasTemplateLiteral: boolean;
};

/**
 * Creates the object rest transformation call expression
 * @param path - Object pattern path
 * @param file - Plugin pass instance
 * @param objRef - Reference to the source object
 * @returns Tuple containing declarators, argument, and call expression
 */
function createObjectRest(
  path: NodePath<t.ObjectPattern>,
  file: PluginPass,
  objRef: t.Identifier | t.MemberExpression
): [t.VariableDeclarator[], t.AssignmentExpression["left"], t.CallExpression];

/**
 * Gets the appropriate helper function for object spread operations
 * @param file - Plugin pass instance
 * @returns Helper function reference (Object.assign or _extends)
 */
function getExtendsHelper(file: PluginPass): t.MemberExpression | t.Identifier;

Required Type Imports

The plugin requires several Babel types and utilities:

import { declare } from "@babel/helper-plugin-utils";
import { types as t } from "@babel/core";
import type { PluginPass, NodePath, Scope } from "@babel/core";
import { convertFunctionParams } from "@babel/plugin-transform-parameters";
import { isRequired } from "@babel/helper-compilation-targets";
import { unshiftForXStatementBody } from "@babel/plugin-transform-destructuring";

Babel Integration

The plugin integrates with Babel's ecosystem through several mechanisms:

Babel Assumptions

The plugin respects the following Babel assumptions for optimization:

  • ignoreFunctionLength: Whether to ignore function.length when transforming parameters
  • objectRestNoSymbols: Whether object rest excludes symbol properties
  • pureGetters: Whether getters are side-effect free (enables optimizations)
  • setSpreadProperties: Whether to use simple property assignment for spread

Version Compatibility

The plugin requires Babel 7.0.0 or higher and handles version-specific differences. The plugin automatically adapts its behavior based on the Babel version being used, with enhanced features available in Babel 8+.

Dependencies

The plugin has the following dependencies:

/**
 * Package dependencies as specified in package.json
 */
interface Dependencies {
  "@babel/helper-compilation-targets": string;
  "@babel/helper-plugin-utils": string;
  "@babel/plugin-transform-destructuring": string;
  "@babel/plugin-transform-parameters": string;
  "@babel/traverse": string;
}

/**
 * Peer dependencies - must be installed by consuming applications
 */
interface PeerDependencies {
  "@babel/core": "^7.0.0-0";
}

/**
 * Engine requirements
 */
interface Engines {
  node: ">=6.9.0";
}

Error Handling

The plugin validates configuration options and throws descriptive errors for invalid settings:

// Invalid loose option
{
  plugins: [
    ["@babel/plugin-transform-object-rest-spread", { loose: "invalid" }]
  ]
}
// Throws: ".loose must be a boolean, or undefined"

Performance Considerations

  • Loose Mode: Enables faster but less compliant transformations
  • useBuiltIns: Reduces bundle size when targeting modern environments
  • Assumption Flags: Allow fine-tuned optimizations based on code patterns
  • Helper Hoisting: Reuses helper functions to minimize code duplication

docs

index.md

tile.json