Robust Call-Bound JavaScript Intrinsics
call-bound is a utility library that provides robust, call-bound versions of JavaScript intrinsic functions, ensuring they work correctly even if `Function.prototype.call` or `Function.prototype.bind` are removed or modified from the global scope. It achieves this by internally leveraging `call-bind` and `get-intrinsic` to fetch and bind the original intrinsic methods securely. The current stable version is 1.0.4. This package is part of a suite of libraries by @ljharb focused on shims and polyfills, often released on an as-needed basis rather than a strict time-based cadence, with updates typically driven by bug fixes, security patches, or new ECMAScript features. Its key differentiator is its resilience against prototype pollution, making it vital for libraries that need to rely on core JavaScript functionality without fear of tampering in hostile environments.
Common errors
-
TypeError: Cannot convert undefined or null to object
cause `callBound` returned `undefined` because the intrinsic name was misspelled or does not exist, and the resulting `undefined` function was called.fixVerify the intrinsic string name passed to `callBound` is correct (e.g., 'Array.prototype.slice'). Ensure the intrinsic exists in your target JavaScript environment. -
ReferenceError: require is not defined
cause Attempting to use `require` in an ESM context (e.g., in a file with `type: module` in `package.json` or an `.mjs` file).fixUse the ES module import syntax: `import callBound from 'call-bound';`
Warnings
- gotcha This package relies on the integrity of `Object.prototype.hasOwnProperty` and other fundamental intrinsics during its initialization. While it protects against *subsequent* pollution, if the environment is already compromised at the point of library loading, its robustness might be limited. Always load robust utility libraries early in your application lifecycle.
- breaking Older versions of Node.js (prior to 0.4) are not supported. While `engines` field specifies `>=0.4`, using it on extremely outdated environments might lead to unexpected behavior or missing intrinsics.
- gotcha The library fetches intrinsics by string name (e.g., 'Array.prototype.slice'). Typos or incorrect intrinsic names will lead to `undefined` or errors, as `callBound` will not be able to locate the requested intrinsic.
Install
-
npm install call-bound -
yarn add call-bound -
pnpm add call-bound
Imports
- callBound
import { callBound } from 'call-bound';import callBound from 'call-bound';
- callBound
const callBound = require('call-bound'); - CallBoundFunction
import type { CallBoundFunction } from 'call-bound';
Quickstart
const assert = require('assert');
const callBound = require('call-bound');
// Get a robust, bound version of Array.prototype.slice
const slice = callBound('Array.prototype.slice');
// Simulate a hostile environment where intrinsics might be tampered with
delete Function.prototype.call;
delete Function.prototype.bind;
delete Array.prototype.slice;
// The call-bound slice still works, unaffected by the deletions
const originalArray = [1, 2, 3, 4, 5];
const slicedArray = slice(originalArray, 1, -1); // Should be [2, 3, 4]
assert.deepStrictEqual(slicedArray, [2, 3, 4]);
console.log('Array.prototype.slice (call-bound) works correctly:', slicedArray);
// Example with Object.prototype.hasOwnProperty
const hasOwnProperty = callBound('Object.prototype.hasOwnProperty');
const obj = { a: 1, b: 2 };
assert.strictEqual(hasOwnProperty(obj, 'a'), true);
assert.strictEqual(hasOwnProperty(obj, 'c'), false);
console.log('Object.prototype.hasOwnProperty (call-bound) works correctly.');