es-intrinsic-cache

Get the pristine, unmodified JavaScript built-ins and cache them before anyone can tamper with them

MIT 4 个版本
安装
npm install es-intrinsic-cache
yarn add es-intrinsic-cache
pnpm add es-intrinsic-cache
bun add es-intrinsic-cache
README

es-intrinsic-cache

Get and robustly cache all JavaScript language-level intrinsics at first require time

npm version

What is this?

es-intrinsic-cache provides safe, cached access to JavaScript's built-in objects and functions (intrinsics) before they can be modified by other code. This is essential for building robust libraries that need to rely on pristine versions of native JavaScript functionality.

Why would you need this?

JavaScript allows modification of built-in prototypes and globals, which can break your code:

// Malicious or buggy code could do this:
Array.prototype.push = function() { 
  console.log("hacked") 
}

// Now normal array operations break:
const arr = [1, 2, 3]
arr.push(4) // Logs "hacked" instead of working correctly
console.log(arr) // Logs [1,2,3] - nothing actually modified

es-intrinsic-cache solves this by caching the original intrinsics when your module first loads:

const GetIntrinsic = require("es-intrinsic-cache")

// Hack the Array.prototype.push
Array.prototype.push = function() { 
  console.log("hacked") 
}

// Get the REAL Array.prototype.push, cached at module load time
const $push = GetIntrinsic("%Array.prototype.push%")

// This always works, even if Array.prototype.push was modified
const arr = [1, 2, 3]
$push.call(arr, 4) // ✅ Works correctly
console.log(arr) // Logs [1, 2, 3, 4]

Installation

Using NPM:

npm install es-intrinsic-cache

Using Yarn:

yarn add es-intrinsic-cache

Using PNPM:

pnpm add es-intrinsic-cache

Using Bun:

bun add es-intrinsic-cache

Usage

const GetIntrinsic = require("es-intrinsic-cache")

// Access intrinsics with % wrapper syntax
const ArrayProto = GetIntrinsic("%Array.prototype%")
const ObjectCreate = GetIntrinsic("%Object.create%")
const JSONParse = GetIntrinsic("%JSON.parse%")

// Or without % wrappers (they're optional)
const Array = GetIntrinsic("Array")
const push = GetIntrinsic("Array.prototype.push")

Accessor Properties

For accessor properties (getters/setters), GetIntrinsic returns the getter function. (Note: If a getter is emulating a data property (indicated by an originalValue property on the getter), the actual value is returned instead.)

Example:

const GetIntrinsic = require("es-intrinsic-cache")

// Get the getter for Map.prototype.size
const $mapSize = GetIntrinsic("%Map.prototype.size%")

const myMap = new Map([["a", 1], ["b", 2]])
console.log($mapSize.call(myMap)) // 2

allowMissing parameter

Some intrinsics may not exist in all environments. Use the second parameter to avoid errors. This also applies to nested properties: if the base intrinsic exists but the requested property does not, it returns undefined instead of throwing.

const GetIntrinsic = require("es-intrinsic-cache")

// Throws TypeError if AsyncGeneratorPrototype doesn't exist
const AsyncGenProto = GetIntrinsic("%AsyncGeneratorPrototype%")

// Returns undefined if AsyncGeneratorPrototype doesn't exist
const AsyncGenProto = GetIntrinsic("%AsyncGeneratorPrototype%", true)

⚠️ Important Note: Load Order Matters

es-intrinsic-cache must be loaded as early as possible in your application, ideally before any other code runs. If other code modifies built-ins before es-intrinsic-cache is loaded, those modifications will be cached.

// ✅ GOOD - Load es-intrinsic-cache first
const GetIntrinsic = require("es-intrinsic-cache")
// ... rest of your application

// ❌ BAD - Other code runs first
require("some-library-that-modifies-prototypes")
const GetIntrinsic = require("es-intrinsic-cache") // Too late!

Available Intrinsics

See the full list of available intrinsics that you can cache with es-intrinsic-cache in the TypeScript definitions (index.d.ts).

API

GetIntrinsic(name, [allowMissing])

Parameters:

  • name (string, required): The name of the intrinsic to retrieve. Can be wrapped in % or not.
  • allowMissing (boolean, optional): If true, returns undefined for missing intrinsics instead of throwing. Default: false

Returns: The requested intrinsic value.

Throws:

  • TypeError if name is not a non-empty string.
  • TypeError if allowMissing is not a boolean.
  • SyntaxError if % appears in the middle of the name (e.g., %Array%.push).
  • SyntaxError if quoted property paths have mismatched or invalid quotes.
  • TypeError if the intrinsic (or a base property) is missing/unavailable (unless allowMissing is true).

Common Use Case

const GetIntrinsic = require("es-intrinsic-cache")

const susLibrary = require("sus-library") // library that we're not sure about that might replace an intrinsic

const $JSONParse = GetIntrinsic("%JSON.parse%")
const $ObjectKeys = GetIntrinsic("%Object.keys%")

function safeJSONParse(str) {
  // Always uses pristine JSON.parse, even if JSON.parse was replaced
  return $JSONParse(str)
}

Why es-intrinsic-cache instead of get-intrinsic?

es-intrinsic-cache is a modernized refactor of get-intrinsic that maintains 100% API compatibility while improving internal clarity, dependency focus, and developer experience. Both libraries cache JavaScript intrinsics to protect against prototype pollution, but they differ in implementation philosophy.

Key Advantages

  • Cleaner internals 🧹
    Removes the legacy needsEval / doEval mechanism and initializes intrinsics explicitly at module load time. This results in simpler, more readable code with less state-machine complexity.

  • Complete TypeScript definitions 🧠
    Includes 240+ fully typed intrinsics, covering missing entries from @types/get-intrinsic (such as %Float16Array%, %FinalizationRegistry%, %WeakRef%, and legacy aliases). Types are auto-generated and always stay in sync with the implementation.

  • Comprehensive JSDoc documentation 📚
    Provides detailed JSDoc comments with parameter descriptions, edge cases, and examples, enabling better IDE hover docs and easier contributor onboarding.

  • Smaller, more focused dependencies 📦
    Uses single-responsibility helper modules instead of multi-purpose utilities, reducing unused code and dependency surface area.

  • Identical public API 🔁
    Fully compatible with get-intrinsic, including the same function signature, intrinsic naming syntax, legacy aliases, error handling, and edge-case protections.

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for any new functionality
  4. Ensure all tests pass
  5. Submit a pull request

License

MIT © Fox Jones See license in LICENSE (or don't, because it's just your regular MIT license)

Support


Remember: Load es-intrinsic-cache early in your application to ensure you get pristine intrinsics! 🛡️

版本列表
1.0.4 2026-01-13
1.0.3 2026-01-12
1.0.1 2025-12-22
1.0.0 2025-12-21