diff options
author | Joyee Cheung <joyeec9h3@gmail.com> | 2019-04-10 11:31:52 +0300 |
---|---|---|
committer | Joyee Cheung <joyeec9h3@gmail.com> | 2019-04-13 12:53:25 +0300 |
commit | 3da36d0e94987dc6594fdffc3678d3f970cdac75 (patch) | |
tree | 78aea15a41bd5da3861bf1b58b0cd891a8b0fd71 /lib/internal/per_context | |
parent | dfd7e994258a36f3941c74295a8c037cb4850418 (diff) |
lib: create primordials in every context
This allows us to use primordials in other per-context scripts.
PR-URL: https://github.com/nodejs/node/pull/27171
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Michaƫl Zasso <targos@protonmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Diffstat (limited to 'lib/internal/per_context')
-rw-r--r-- | lib/internal/per_context/primordials.js | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/lib/internal/per_context/primordials.js b/lib/internal/per_context/primordials.js new file mode 100644 index 00000000000..8d2150b7b76 --- /dev/null +++ b/lib/internal/per_context/primordials.js @@ -0,0 +1,112 @@ +'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 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 target = primordials[name] = Object.create(null); + copyProps(global[name], target); + const proto = primordials[name + 'Prototype'] = Object.create(null); + copyPrototype(global[name].prototype, proto); +}); + +Object.setPrototypeOf(primordials, null); +Object.freeze(primordials); |