summaryrefslogtreecommitdiff
path: root/lib/internal/bootstrap
diff options
context:
space:
mode:
Diffstat (limited to 'lib/internal/bootstrap')
-rw-r--r--lib/internal/bootstrap/cache.js1
-rw-r--r--lib/internal/bootstrap/loaders.js76
-rw-r--r--lib/internal/bootstrap/primordials.js84
3 files changed, 111 insertions, 50 deletions
diff --git a/lib/internal/bootstrap/cache.js b/lib/internal/bootstrap/cache.js
index 10d5c18334..8273b6f27f 100644
--- a/lib/internal/bootstrap/cache.js
+++ b/lib/internal/bootstrap/cache.js
@@ -22,6 +22,7 @@ const cannotBeRequired = [
'internal/test/binding',
+ 'internal/bootstrap/primordials',
'internal/bootstrap/loaders',
'internal/bootstrap/node'
];
diff --git a/lib/internal/bootstrap/loaders.js b/lib/internal/bootstrap/loaders.js
index 7078707b83..1007b41069 100644
--- a/lib/internal/bootstrap/loaders.js
+++ b/lib/internal/bootstrap/loaders.js
@@ -40,33 +40,20 @@
'use strict';
// This file is compiled as if it's wrapped in a function with arguments
-// passed by node::LoadEnvironment()
+// passed by node::RunBootstrapping()
/* global process, getBinding, getLinkedBinding, getInternalBinding */
-/* global debugBreak, experimentalModules, exposeInternals */
+/* global experimentalModules, exposeInternals, primordials */
-if (debugBreak)
- debugger; // eslint-disable-line no-debugger
-
-const {
- apply: ReflectApply,
- deleteProperty: ReflectDeleteProperty,
- get: ReflectGet,
- getOwnPropertyDescriptor: ReflectGetOwnPropertyDescriptor,
- has: ReflectHas,
- set: ReflectSet,
-} = Reflect;
const {
- prototype: {
- hasOwnProperty: ObjectHasOwnProperty,
- },
- create: ObjectCreate,
- defineProperty: ObjectDefineProperty,
- keys: ObjectKeys,
-} = Object;
+ Reflect,
+ Object,
+ ObjectPrototype,
+ SafeSet
+} = primordials;
// Set up process.moduleLoadList.
const moduleLoadList = [];
-ObjectDefineProperty(process, 'moduleLoadList', {
+Object.defineProperty(process, 'moduleLoadList', {
value: moduleLoadList,
configurable: true,
enumerable: true,
@@ -78,7 +65,7 @@ ObjectDefineProperty(process, 'moduleLoadList', {
// that are whitelisted for access via process.binding()... This is used
// to provide a transition path for modules that are being moved over to
// internalBinding.
-const internalBindingWhitelist = [
+const internalBindingWhitelist = new SafeSet([
'async_wrap',
'buffer',
'cares_wrap',
@@ -108,20 +95,17 @@ const internalBindingWhitelist = [
'uv',
'v8',
'zlib'
-];
-// We will use a lazy loaded SafeSet in internalBindingWhitelistHas
-// for checking existence in this list.
-let internalBindingWhitelistSet;
+]);
// Set up process.binding() and process._linkedBinding().
{
- const bindingObj = ObjectCreate(null);
+ const bindingObj = Object.create(null);
process.binding = function binding(module) {
module = String(module);
// Deprecated specific process.binding() modules, but not all, allow
// selective fallback to internalBinding for the deprecated ones.
- if (internalBindingWhitelistHas(module)) {
+ if (internalBindingWhitelist.has(module)) {
return internalBinding(module);
}
let mod = bindingObj[module];
@@ -144,7 +128,7 @@ let internalBindingWhitelistSet;
// Set up internalBinding() in the closure.
let internalBinding;
{
- const bindingObj = ObjectCreate(null);
+ const bindingObj = Object.create(null);
internalBinding = function internalBinding(module) {
let mod = bindingObj[module];
if (typeof mod !== 'object') {
@@ -245,8 +229,8 @@ NativeModule.requireWithFallbackInDeps = function(request) {
};
const getOwn = (target, property, receiver) => {
- return ReflectApply(ObjectHasOwnProperty, target, [property]) ?
- ReflectGet(target, property, receiver) :
+ return Reflect.apply(ObjectPrototype.hasOwnProperty, target, [property]) ?
+ Reflect.get(target, property, receiver) :
undefined;
};
@@ -255,12 +239,12 @@ const getOwn = (target, property, receiver) => {
// as the entire namespace (module.exports) and wrapped in a proxy such
// that APMs and other behavior are still left intact.
NativeModule.prototype.proxifyExports = function() {
- this.exportKeys = ObjectKeys(this.exports);
+ this.exportKeys = Object.keys(this.exports);
const update = (property, value) => {
if (this.reflect !== undefined &&
- ReflectApply(ObjectHasOwnProperty,
- this.reflect.exports, [property]))
+ Reflect.apply(ObjectPrototype.hasOwnProperty,
+ this.reflect.exports, [property]))
this.reflect.exports[property].set(value);
};
@@ -269,12 +253,12 @@ NativeModule.prototype.proxifyExports = function() {
defineProperty: (target, prop, descriptor) => {
// Use `Object.defineProperty` instead of `Reflect.defineProperty`
// to throw the appropriate error if something goes wrong.
- ObjectDefineProperty(target, prop, descriptor);
+ Object.defineProperty(target, prop, descriptor);
if (typeof descriptor.get === 'function' &&
- !ReflectHas(handler, 'get')) {
+ !Reflect.has(handler, 'get')) {
handler.get = (target, prop, receiver) => {
- const value = ReflectGet(target, prop, receiver);
- if (ReflectApply(ObjectHasOwnProperty, target, [prop]))
+ const value = Reflect.get(target, prop, receiver);
+ if (Reflect.apply(ObjectPrototype.hasOwnProperty, target, [prop]))
update(prop, value);
return value;
};
@@ -283,15 +267,15 @@ NativeModule.prototype.proxifyExports = function() {
return true;
},
deleteProperty: (target, prop) => {
- if (ReflectDeleteProperty(target, prop)) {
+ if (Reflect.deleteProperty(target, prop)) {
update(prop, undefined);
return true;
}
return false;
},
set: (target, prop, value, receiver) => {
- const descriptor = ReflectGetOwnPropertyDescriptor(target, prop);
- if (ReflectSet(target, prop, value, receiver)) {
+ const descriptor = Reflect.getOwnPropertyDescriptor(target, prop);
+ if (Reflect.set(target, prop, value, receiver)) {
if (descriptor && typeof descriptor.set === 'function') {
for (const key of this.exportKeys) {
update(key, getOwn(target, key, receiver));
@@ -319,7 +303,7 @@ NativeModule.prototype.compile = function() {
NativeModule.require;
const fn = compileFunction(id);
- fn(this.exports, requireFn, this, process, internalBinding);
+ fn(this.exports, requireFn, this, process, internalBinding, primordials);
if (experimentalModules && this.canBeRequiredByUsers) {
this.proxifyExports();
@@ -344,13 +328,5 @@ if (process.env.NODE_V8_COVERAGE) {
}
}
-function internalBindingWhitelistHas(name) {
- if (!internalBindingWhitelistSet) {
- const { SafeSet } = NativeModule.require('internal/safe_globals');
- internalBindingWhitelistSet = new SafeSet(internalBindingWhitelist);
- }
- return internalBindingWhitelistSet.has(name);
-}
-
// This will be passed to internal/bootstrap/node.js.
return loaderExports;
diff --git a/lib/internal/bootstrap/primordials.js b/lib/internal/bootstrap/primordials.js
new file mode 100644
index 0000000000..2a97e74542
--- /dev/null
+++ b/lib/internal/bootstrap/primordials.js
@@ -0,0 +1,84 @@
+'use strict';
+
+/* global breakAtBootstrap, primordials */
+
+// 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.
+
+if (breakAtBootstrap) {
+ debugger; // eslint-disable-line no-debugger
+}
+
+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 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',
+ 'Date',
+ 'Function',
+ 'Object',
+ 'RegExp',
+ 'String'
+].forEach((name) => {
+ const target = primordials[name] = Object.create(null);
+ copyProps(global[name], target);
+ const proto = primordials[name + 'Prototype'] = Object.create(null);
+ copyProps(global[name].prototype, proto);
+});
+
+Object.setPrototypeOf(primordials, null);
+Object.freeze(primordials);