# Node.js `primordials` object

🧊 The native primordials object from Node.js for anywhere

<div align="center">

![](https://user-images.githubusercontent.com/61068799/250172175-b8a00130-d315-4345-b176-7b6614342626.png)

<!-- prettier-ignore -->
[Docs website](https://nodefill.github.io/primordials/)
| [Node.js `primordials.js`](https://github.com/nodejs/node/blob/master/lib/internal/bootstrap/primordials.js)
| [About Node.js primordials](https://github.com/nodejs/node/blob/main/doc/contributing/primordials.md)

</div>

🤩 Great for authors who want safe intrinsics \
📦 Works in Node.js, Deno, Bun and the browser \
🍰 Comes with individual files to allow deep imports \
🧱 Based on the internal [`primordials.js`] from Node.js core

## Installation

![npm](https://img.shields.io/static/v1?style=for-the-badge&message=npm&color=CB3837&logo=npm&logoColor=FFFFFF&label=)
![Yarn](https://img.shields.io/static/v1?style=for-the-badge&message=Yarn&color=2C8EBB&logo=Yarn&logoColor=FFFFFF&label=)
![pnpm](https://img.shields.io/static/v1?style=for-the-badge&message=pnpm&color=222222&logo=pnpm&logoColor=F69220&label=)
![jsDelivr](https://img.shields.io/static/v1?style=for-the-badge&message=jsDelivr&color=E84D3D&logo=jsDelivr&logoColor=FFFFFF&label=)

Install this package using npm, [Yarn], or [pnpm]!

```sh
npm install @nodefill/primordials
```

This package is also compatible with Deno via their compatibility layer. You can
import the package directly using [the new `npm:` specifier], or a
Deno-compatible ESM CDN like [esm.sh] or [jsDelivr].

```js
import {} from "npm:@nodefill/primordials";
import {} from "https://esm.sh/@nodefill/primordials";
```

If you're using not using a build tool and you just want to use the package in
your browser, you can use an npm CDN like [esm.sh] or [jsDelivr].

```js
import {} from "https://esm.sh/@nodefill/primordials";
import {} from "https://esm.run/@nodefill/primordials";
```

## Usage

![Node.js](https://img.shields.io/static/v1?style=for-the-badge&message=Node.js&color=339933&logo=Node.js&logoColor=FFFFFF&label=)
![Deno](https://img.shields.io/static/v1?style=for-the-badge&message=Deno&color=000000&logo=Deno&logoColor=FFFFFF&label=)
![Browser](https://img.shields.io/static/v1?style=for-the-badge&message=Browser&color=4285F4&logo=Google+Chrome&logoColor=FFFFFF&label=)
![Bun](https://img.shields.io/static/v1?style=for-the-badge&message=Bun&color=000000&logo=Bun&logoColor=FFFFFF&label=)

This package provides the `primordials` object from Node.js. Each primordial is
also exposed as a separate `*.js` file if you feel like manually tree-shaking.

```js
import { ArrayIsArray } from "@nodefill/primordials";
import ArrayPrototypeReduce from "@nodefill/primordials/ArrayPrototypeReduce.js";

const sum = (array) => {
  if (!Array.isArray(array)) {
    throw new TypeError(`${array} is not an array`);
  }
  return array.reduce((n, x) => n + x, 0);
};
const safeSum = (array) => {
  if (!ArrayIsArray(array)) {
    throw new TypeError(`${array} is not an array`);
  }
  return ArrayPrototypeReduce(array, (n, x) => n + x, 0);
};

Array.prototype.reduce = () => 100;

console.log(sum([1, 2, 3]));
//=> 100
console.log(safeSum([1, 2, 3]));
//=> 6
```

We also offer a `polyfill.js` export for to emulate the Node.js `primordials`
global object.

```js
import "@nodefill/primordials/polyfill.js";

console.log(primordials.ArrayIsArray([]));
//=> true
```

💾 If you want to be frugal with bundle size, you can explicitly deep-import
only specific primordials that you use. This means we won't import the massive
700 item `index.js` file which can be **huge size savings** if you're willing to
type a few extra words.

```js
import StringPrototypeSlice from "@nodefill/primordials/StringPrototypeSlice.js";
import ArrayBufferIsView from "@nodefill/primordials/ArrayBufferIsView.js";
```

⚠️ If you import `ArrayPrototypeFindLast` on Node.js 16, there is no
`.findLast()` function. So what happens? The export will just be `undefined`.
It's on **you** to `ArrayPrototypeFindLast?.(array, ...)` if you want to
conditionally use it. Just note that it will **always be exported** but
**sometimes could be `undefined`**.

```js
import ArrayPrototypeFindLast from "@nodefill/primordials/ArrayPrototypeFindLast.js";

console.log(process.version);
//=> v16.0.0 OR v20.0.0

console.log(ArrayPrototypeFindLast);
//=> undefined OR function findLast() { [native code] }
```

ℹ Files like `RegExpGet$&.js` are named `RegExpGet$amp.js` (replaced with HTML
entity names) to avoid issues with restrictive file systems like Windows. 😉

## Alternatives

**[isaacs/node-primordials]**

- Has `processCwd()` and friends. See also `import { cwd } from "node:process"`.
- Doesn't have a `polyfill.js` export to shim the global `primordials` object.
- **A single file.** Very easy to copy-paste into your own project.
- Dual release as ESM and CJS. Can encounter the [dual package hazard].
- Doesn't have helper `SafePromise*` exports.
- Doesn't have any `Safe*` exports yet. See [isaacs/node-primordials#9].

**[ljharb/get-intrinsic]**

- Different from Node.js core `primordials` object, but similar goal.
- Uses `getIntrinsic("%Math.pow%")` instead of `import MathPow from "..."`.
- Uses `eval()`-like magic instead of an explicit list.
- **Far smaller in size.**
- Doesn't have a `polyfill.js` export to shim the global `primordials` object.

**[dwlib-js/primordials]**

- Uses `.mjs` and `.js` files, not TypeScript.
- Relies on multiple layers of indirection for what is essentially the same
  thing as this package.
- Doesn't have a `polyfill.js` export to shim the global `primordials` object.
- Doesn't have helper `SafePromise*` exports.
- Doesn't have `Safe*` exports.

💡 You can always just _not use bound primordials_ like `ArrayPrototypePush()`
and just use plain prototype lookup `.push()` if you want to save bundle size
and general tooling complexity. 🤷‍♀️ The tradeoff is that you are susceptible to
users monkey-patching said global primordials. 😜

## Development

![TypeScript](https://img.shields.io/static/v1?style=for-the-badge&message=TypeScript&color=3178C6&logo=TypeScript&logoColor=FFFFFF&label=)
![Vitest](https://img.shields.io/static/v1?style=for-the-badge&message=Vitest&color=6E9F18&logo=Vitest&logoColor=FFFFFF&label=)

This project embraces TypeScript! At the scale of 700+ files, you really just
_can't_ with normal JavaScript. 😆 To get started, just run:

```sh
npm run build
npm test
```

To regenerate the latest `primordials.json` list, just make sure you're on the
latest Node.js version and run:

```sh
node --expose-internals \
  -r internal/test/binding \
  -p "JSON.stringify(Object.getOwnPropertyNames(primordials).sort())" \
  > test/primordials.json
```

<!-- prettier-ignore-start -->
[esm.sh]: https://esm.sh/
[jsDelivr]: https://www.jsdelivr.com/esm
[Yarn]: https://yarnpkg.com/
[pnpm]: https://pnpm.io/
[the new `npm:` specifier]: https://deno.land/manual/node/npm_specifiers
[isaacs/node-primordials]: https://github.com/isaacs/node-primordials
[dual package hazard]: https://nodejs.org/api/packages.html#packages_dual_package_hazard
[isaacs/node-primordials#9]: https://github.com/isaacs/node-primordials/pull/9
[ljharb/get-intrinsic]: https://github.com/ljharb/get-intrinsic
[dwlib-js/primordials]: https://github.com/dwlib-js/primordials
[`primordials.js`]: https://github.com/nodejs/node/blob/main/lib/internal/per_context/primordials.js
<!-- prettier-ignore-end -->
