A Babel plugin that transforms JSBI (JavaScript BigInt) library calls into native BigInt syntax, enabling developers to write BigInt code that works in older environments through JSBI while automatically transpiling to modern native BigInt operations for better performance and cleaner code.
npm install babel-plugin-transform-jsbi-to-bigintSince this is a Babel plugin, it's not imported directly in your code. Instead, it's configured in your Babel configuration.
{
"plugins": ["transform-jsbi-to-bigint"]
}babel --plugins transform-jsbi-to-bigint script.jsrequire('@babel/core').transform(code, {
'plugins': ['transform-jsbi-to-bigint']
});import transformJSBIToBigInt from 'babel-plugin-transform-jsbi-to-bigint';This plugin transforms JSBI code to native BigInt code. Write your code using JSBI syntax and the plugin will transform it during compilation.
Input code using JSBI:
import JSBI from 'jsbi';
const a = JSBI.BigInt(Number.MAX_SAFE_INTEGER);
const b = JSBI.BigInt('42');
JSBI.add(a, b);
JSBI.subtract(a, b);
JSBI.multiply(a, b);
JSBI.equal(a, b);
JSBI.lessThan(a, b);
JSBI.unaryMinus(a);
JSBI.bitwiseNot(a);
a instanceof JSBI;
JSBI.toNumber(a);Transpiled output using native BigInt:
const a = BigInt(Number.MAX_SAFE_INTEGER);
const b = 42n;
a + b;
a - b;
a * b;
a === b;
a < b;
-a;
~a;
typeof a === 'bigint';
Number(a);The plugin works by:
instanceof JSBI to typeof x === 'bigint'The main export is a Babel plugin factory function.
/**
* Babel plugin factory function that transforms JSBI calls to native BigInt
* @param {Object} babel - Babel core object containing types and utilities
* @param {Object} babel.types - Babel types helper functions for AST manipulation
* @returns {BabelPlugin} Babel plugin configuration object with visitor methods
*/
export default function(babel): BabelPlugin;
interface BabelPlugin {
pre?(): void;
visitor: {
Program?: {
exit(): void;
};
ImportDeclaration?(path: NodePath<ImportDeclaration>): void;
VariableDeclarator?(path: NodePath<VariableDeclarator>): void;
CallExpression?(path: NodePath<CallExpression>): void;
BinaryExpression?(path: NodePath<BinaryExpression>): void;
};
}Usage in Babel configuration:
// babel.config.js
module.exports = {
plugins: [
require('babel-plugin-transform-jsbi-to-bigint')
]
};Transforms JSBI binary operations to native BigInt operators.
// Arithmetic operations
JSBI.add(a, b) → a + b
JSBI.subtract(a, b) → a - b
JSBI.multiply(a, b) → a * b
JSBI.divide(a, b) → a / b
JSBI.remainder(a, b) → a % b
JSBI.exponentiate(a, b) → a ** b
// Bitwise operations
JSBI.leftShift(a, b) → a << b
JSBI.signedRightShift(a, b) → a >> b
JSBI.bitwiseAnd(a, b) → a & b
JSBI.bitwiseOr(a, b) → a | b
JSBI.bitwiseXor(a, b) → a ^ b
// Comparison operations (strict)
JSBI.equal(a, b) → a === b
JSBI.notEqual(a, b) → a !== b
JSBI.lessThan(a, b) → a < b
JSBI.lessThanOrEqual(a, b) → a <= b
JSBI.greaterThan(a, b) → a > b
JSBI.greaterThanOrEqual(a, b) → a >= b
// Comparison operations (loose)
JSBI.EQ(a, b) → a == b
JSBI.NE(a, b) → a != b
JSBI.LT(a, b) → a < b
JSBI.LE(a, b) → a <= b
JSBI.GT(a, b) → a > b
JSBI.GE(a, b) → a >= b
// Special case for ADD
JSBI.ADD(a, b) → a + bTransforms JSBI unary operations to native BigInt operators.
JSBI.unaryMinus(a) → -a
JSBI.bitwiseNot(a) → ~aTransforms JSBI static methods to native BigInt static methods.
JSBI.asIntN(bits, value) → BigInt.asIntN(bits, value)
JSBI.asUintN(bits, value) → BigInt.asUintN(bits, value)Usage example:
// Input
JSBI.asIntN(64, JSBI.BigInt('42'));
JSBI.asUintN(64, JSBI.BigInt('42'));
// Output
BigInt.asIntN(64, 42n);
BigInt.asUintN(64, 42n);Transforms JSBI DataView methods to native DataView BigInt methods.
JSBI.DataViewGetBigInt64(view, offset, ...) → view.getBigInt64(offset, ...)
JSBI.DataViewSetBigInt64(view, offset, ...) → view.setBigInt64(offset, ...)
JSBI.DataViewGetBigUint64(view, offset, ...) → view.getBigUint64(offset, ...)
JSBI.DataViewSetBigUint64(view, offset, ...) → view.setBigUint64(offset, ...)Usage example:
// Input
const buffer = new ArrayBuffer(16);
const view = new DataView(buffer);
const max = JSBI.BigInt('9223372036854775807');
JSBI.DataViewSetBigInt64(view, 0, max);
const result = JSBI.DataViewGetBigInt64(view, 0);
// Output
const buffer = new ArrayBuffer(16);
const view = new DataView(buffer);
const max = 9223372036854775807n;
view.setBigInt64(0, max);
const result = view.getBigInt64(0);Transforms JSBI constructor and utility methods to native BigInt equivalents.
/**
* Constructor transformation - converts to BigInt literal when possible
* @param {number|string} value - Value to convert to BigInt
* @returns {BigIntLiteral|CallExpression} BigInt literal or constructor call
*/
JSBI.BigInt(value) → BigInt(value) | ${value}n
/**
* Utility method transformation - converts to Number constructor
* @param {BigInt} value - BigInt value to convert to number
* @returns {CallExpression} Number constructor call
*/
JSBI.toNumber(value) → Number(value)
/**
* Type checking transformation - converts instanceof to typeof check
* @param {any} x - Value to check
* @returns {BinaryExpression} typeof comparison expression
*/
x instanceof JSBI → typeof x === 'bigint'Constructor Optimization Examples:
// Numeric literals are converted to BigInt literals
JSBI.BigInt(42); // → 42n
JSBI.BigInt(0); // → 0n
// String literals with valid integers become BigInt literals
JSBI.BigInt('123'); // → 123n
JSBI.BigInt('0'); // → 0n
// Complex strings or variables use constructor call
JSBI.BigInt('00034'); // → BigInt('00034') (preserves leading zeros)
JSBI.BigInt(variable); // → BigInt(variable)
JSBI.BigInt('0x10'); // → BigInt('0x10') (hex format preserved)The plugin handles various JSBI import and usage patterns.
// Supported import patterns
import JSBI from 'jsbi';
import JSBI from './path/to/jsbi.mjs';
// Supported destructuring patterns
const JSBigInt = JSBI.BigInt;
const JSBigInt2 = JSBI['BigInt'];
const JSBIadd = JSBI.add;
// All these are transformed appropriately
JSBigInt(34); // → 34n
JSBigInt2(56); // → 56n
JSBIadd(7, 8); // → 7 + 8The plugin provides descriptive error messages for incorrect usage:
.BigInt or ['BigInt'] patterns allowed// Input
import JSBI from 'jsbi';
function calculateCompoundInterest(principal, rate, time) {
const p = JSBI.BigInt(principal);
const r = JSBI.BigInt(rate);
const t = JSBI.BigInt(time);
const hundred = JSBI.BigInt(100);
const rateDecimal = JSBI.divide(r, hundred);
const onePlusRate = JSBI.add(JSBI.BigInt(1), rateDecimal);
const compound = JSBI.exponentiate(onePlusRate, t);
return JSBI.multiply(p, compound);
}
// Check if result is greater than threshold
const result = calculateCompoundInterest('1000', '5', '10');
const threshold = JSBI.BigInt('1500');
if (JSBI.greaterThan(result, threshold)) {
console.log('Investment exceeded threshold');
}// Output
function calculateCompoundInterest(principal, rate, time) {
const p = BigInt(principal);
const r = BigInt(rate);
const t = BigInt(time);
const hundred = 100n;
const rateDecimal = r / hundred;
const onePlusRate = 1n + rateDecimal;
const compound = onePlusRate ** t;
return p * compound;
}
// Check if result is greater than threshold
const result = calculateCompoundInterest('1000', '5', '10');
const threshold = 1500n;
if (result > threshold) {
console.log('Investment exceeded threshold');
}// Input
import JSBI from 'jsbi';
const BigIntConstructor = JSBI.BigInt;
const add = JSBI.add;
const isEqual = JSBI.equal;
const a = BigIntConstructor('100');
const b = BigIntConstructor('200');
const sum = add(a, b);
if (isEqual(sum, BigIntConstructor('300'))) {
console.log('Math checks out!');
}
// Output
const a = 100n;
const b = 200n;
const sum = a + b;
if (sum === 300n) {
console.log('Math checks out!');
}The plugin uses several internal helper functions for AST manipulation:
/**
* Creates appropriate expression based on JSBI method name
* @param {NodePath} path - Current AST node path for error reporting
* @param {string} name - JSBI method name (e.g., 'add', 'BigInt', 'asIntN')
* @param {Node[]} args - Array of argument nodes
* @returns {Node} Transformed AST node (BinaryExpr, UnaryExpr, CallExpr, etc.)
* @throws {Error} When method is unknown or has incorrect argument count
*/
function createExpression(path: NodePath, name: string, args: Node[]): Node;
/**
* Creates BigInt constructor call or literal when possible
* @param {NodePath} path - Current AST node path
* @returns {Node} BigIntLiteral or CallExpression node
*/
function createBigIntConstructor(path: NodePath): Node;
/**
* Extracts property name from member expression or string literal
* @param {NodePath} path - Property node path
* @returns {string} Property name
* @throws {Error} When property access pattern is not supported
*/
function getPropertyName(path: NodePath): string;
/**
* Resolves variable binding through the scope chain
* @param {NodePath} path - Current path
* @param {string} name - Variable name to resolve
* @returns {Binding|undefined} Resolved binding or undefined
*/
function resolveBinding(path: NodePath, name: string): Binding | undefined;
/**
* Gets JSBI-related data from variable binding
* @param {NodePath} path - Current path
* @param {string} name - Variable name
* @returns {string|undefined} JSBI property name or undefined
*/
function getJSBIProperty(path: NodePath, name: string): string | undefined;
/**
* Sets JSBI-related data on path for tracking
* @param {NodePath} path - Path to mark
* @param {string} data - JSBI property identifier
* @returns {NodePath} The marked path
*/
function setJSBIProperty(path: NodePath, data: string): NodePath;
/**
* Checks if variable has JSBI-related data
* @param {NodePath} path - Current path
* @param {string} name - Variable name to check
* @returns {boolean} True if variable is JSBI-related
*/
function hasJSBIProperty(path: NodePath, name: string): boolean;The plugin provides specific error messages for various invalid usage patterns:
// Error messages thrown by the plugin:
// Binary operators (add, subtract, multiply, etc.)
"Binary operators must have exactly two arguments"
// Unary operators (unaryMinus, bitwiseNot)
"Unary operators must have exactly one argument"
// Static methods (asIntN, asUintN)
"Static methods must have exactly two arguments"
// DataView methods with variable argument counts
"${methodName}: incorrect number of arguments"
// toNumber method
"toNumber must have exactly one argument"
// Unknown JSBI functions
"Unknown JSBI function '${functionName}'"
// Invalid property access patterns
"Only .BigInt or ['BigInt'] allowed here."Error Example:
// This will throw an error during compilation:
import JSBI from 'jsbi';
JSBI.add(a); // Error: Binary operators must have exactly two arguments
JSBI.unknownMethod(a); // Error: Unknown JSBI function 'unknownMethod'The plugin returns a standard Babel plugin configuration object:
The returned plugin object contains:
instanceof JSBI transformations to typeof x === 'bigint'