This is a part of _http_server.js
file from NodeJS source.
// node/lib/_http_server.js
'use strict';
const {
ArrayIsArray,
Error,
MathMin,
ObjectKeys,
ObjectSetPrototypeOf,
ReflectApply,
Symbol,
SymbolAsyncDispose,
SymbolFor,
} = primordials;
const net = require('net');
const EE = require('events');
const assert = require('internal/assert');
I was panic. How did I miss this global variable for so many years working with
NodeJS? It contains Javascripts builtin classes like Error
, Symbol
, … And
under 'use strict'
flag, it must be some thing legal to use, right?
I immediately open up the node
repl to check what it is. But the result was a disappointment.
$ node
Welcome to Node.js v22.5.1.
Type ".help" for more information.
> primordials
Uncaught ReferenceError: primordials is not defined
>
MDN doesn’t have any documents about primordials
as well. So it must be some
hijacking variable created by NodeJS developers. Luckily someone found it and
posted a question on
stackoverflow
before. So I follow the link, on the main
branch.
As stated in source code document.
// This file subclasses and stores the JS builtins that come from the VM
// so that Node.js's builtin modules do not need to later look these up from
// the global proxy, which can be mutated by users.
So the intention is clear, this helps NodeJS developers quickly access builtins, and worry about them being mutated by users.
This is the full source code at commit 141a6e3 in 2019.
'use strict';
/* eslint-disable no-restricted-globals */
// This file subclasses and stores the JS builtins that come from the VM
// so that Node.js's builtin modules do not need to later look these up from
// the global proxy, which can be mutated by users.
// TODO(joyeecheung): we can restrict access to these globals in builtin
// modules through the JS linter, for example: ban access such as `Object`
// (which falls back to a lookup in the global proxy) in favor of
// `primordials.Object` where `primordials` is a lexical variable passed
// by the native module compiler.
const ReflectApply = Reflect.apply;
// This function is borrowed from the function with the same name on V8 Extras'
// `utils` object. V8 implements Reflect.apply very efficiently in conjunction
// with the spread syntax, such that no additional special case is needed for
// function calls w/o arguments.
// Refs: https://github.com/v8/v8/blob/d6ead37d265d7215cf9c5f768f279e21bd170212/src/js/prologue.js#L152-L156
function uncurryThis(func) {
return (thisArg, ...args) => ReflectApply(func, thisArg, args);
}
primordials.uncurryThis = uncurryThis;
function copyProps(src, dest) {
for (const key of Reflect.ownKeys(src)) {
if (!Reflect.getOwnPropertyDescriptor(dest, key)) {
Reflect.defineProperty(
dest,
key,
Reflect.getOwnPropertyDescriptor(src, key));
}
}
}
function copyPropsRenamed(src, dest, prefix) {
for (const key of Reflect.ownKeys(src)) {
if (typeof key === 'string') {
Reflect.defineProperty(
dest,
`${prefix}${key[0].toUpperCase()}${key.slice(1)}`,
Reflect.getOwnPropertyDescriptor(src, key));
}
}
}
function copyPrototype(src, dest, prefix) {
for (const key of Reflect.ownKeys(src)) {
if (typeof key === 'string') {
const desc = Reflect.getOwnPropertyDescriptor(src, key);
if (typeof desc.value === 'function') {
desc.value = uncurryThis(desc.value);
}
Reflect.defineProperty(
dest,
`${prefix}${key[0].toUpperCase()}${key.slice(1)}`,
desc);
}
}
}
function makeSafe(unsafe, safe) {
copyProps(unsafe.prototype, safe.prototype);
copyProps(unsafe, safe);
Object.setPrototypeOf(safe.prototype, null);
Object.freeze(safe.prototype);
Object.freeze(safe);
return safe;
}
// Subclass the constructors because we need to use their prototype
// methods later.
primordials.SafeMap = makeSafe(
Map,
class SafeMap extends Map {}
);
primordials.SafeWeakMap = makeSafe(
WeakMap,
class SafeWeakMap extends WeakMap {}
);
primordials.SafeSet = makeSafe(
Set,
class SafeSet extends Set {}
);
primordials.SafePromise = makeSafe(
Promise,
class SafePromise extends Promise {}
);
// Create copies of the namespace objects
[
'JSON',
'Math',
'Reflect'
].forEach((name) => {
copyPropsRenamed(global[name], primordials, name);
});
// Create copies of intrinsic objects
[
'Array',
'ArrayBuffer',
'BigInt',
'Boolean',
'Date',
'Error',
'Function',
'Map',
'Number',
'Object',
'RegExp',
'Set',
'String',
'Symbol',
'WeakMap',
'WeakSet',
].forEach((name) => {
const original = global[name];
primordials[name] = original;
copyPropsRenamed(original, primordials, name);
copyPrototype(original.prototype, primordials, `${name}Prototype`);
});
Object.setPrototypeOf(primordials, null);
Object.freeze(primordials);
In 2025, the file is about 700 lines of code compare to 128 LOC in 2019. After, 6 years, the amount of features added to Javascripts is massive.
Now we know what primordials
is and why it was created. The remaining question is
can we access it from node
, if so, how?
node --expose-internals
Welcome to Node.js v22.5.1.
Type ".help" for more information.
> primodials
Uncaught ReferenceError: primodials is not defined
>
Enabling expose-internals
flag doesn’t help us. I will continue this when I find a way.