mirror of
https://github.com/nodejs/node.git
synced 2024-11-30 07:27:22 +01:00
6ce87c027d
PR-URL: https://github.com/nodejs/node/pull/29322 Reviewed-By: James M Snell <jasnell@gmail.com>
121 lines
3.3 KiB
JavaScript
121 lines
3.3 KiB
JavaScript
'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;
|
|
const ReflectConstruct = Reflect.construct;
|
|
|
|
// 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 copyPrototype(src, dest) {
|
|
for (const key of Reflect.ownKeys(src)) {
|
|
if (!Reflect.getOwnPropertyDescriptor(dest, key)) {
|
|
const desc = Reflect.getOwnPropertyDescriptor(src, key);
|
|
if (typeof desc.value === 'function') {
|
|
desc.value = uncurryThis(desc.value);
|
|
}
|
|
Reflect.defineProperty(dest, key, 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) => {
|
|
const target = primordials[name] = Object.create(null);
|
|
copyProps(global[name], target);
|
|
});
|
|
|
|
// Create copies of intrinsic objects
|
|
[
|
|
'Array',
|
|
'BigInt',
|
|
'Boolean',
|
|
'Date',
|
|
'Error',
|
|
'Function',
|
|
'Map',
|
|
'Number',
|
|
'Object',
|
|
'RegExp',
|
|
'Set',
|
|
'String',
|
|
'Symbol',
|
|
].forEach((name) => {
|
|
const original = global[name];
|
|
const target = primordials[name] = Object.setPrototypeOf({
|
|
[name]: function(...args) {
|
|
return new.target ?
|
|
ReflectConstruct(original, args, new.target) :
|
|
ReflectApply(original, this, args);
|
|
}
|
|
}[name], null);
|
|
copyProps(original, target);
|
|
const proto = primordials[name + 'Prototype'] = Object.create(null);
|
|
copyPrototype(original.prototype, proto);
|
|
});
|
|
|
|
Object.setPrototypeOf(primordials, null);
|
|
Object.freeze(primordials);
|