src: refactor bootstrap to use bootstrap object

PR-URL: https://github.com/nodejs/node/pull/20917
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
This commit is contained in:
James M Snell 2018-05-23 15:04:23 -07:00
parent dcecfb7508
commit cb3d049bad
9 changed files with 244 additions and 200 deletions

View File

@ -10,10 +10,19 @@
// process.binding(), process._linkedBinding(), internalBinding() and
// NativeModule. And then { internalBinding, NativeModule } will be passed
// into this bootstrapper to bootstrap Node.js core.
'use strict';
(function bootstrapNodeJSCore(process, { internalBinding, NativeModule }) {
(function bootstrapNodeJSCore(process,
// bootstrapper properties... destructured to
// avoid retaining a reference to the bootstrap
// object.
{ _setupProcessObject, _setupNextTick,
_setupPromises, _chdir, _cpuUsage,
_hrtime, _memoryUsage, _rawDebug,
_umask, _initgroups, _setegid, _seteuid,
_setgid, _setuid, _setgroups,
_shouldAbortOnUncaughtToggle },
{ internalBinding, NativeModule }) {
const exceptionHandlerState = { captureFn: null };
function startup() {
@ -36,11 +45,24 @@
const _process = NativeModule.require('internal/process');
_process.setupConfig(NativeModule._source);
_process.setupSignalHandlers();
_process.setupUncaughtExceptionCapture(exceptionHandlerState);
_process.setupUncaughtExceptionCapture(exceptionHandlerState,
_shouldAbortOnUncaughtToggle);
NativeModule.require('internal/process/warning').setup();
NativeModule.require('internal/process/next_tick').setup();
NativeModule.require('internal/process/next_tick').setup(_setupNextTick,
_setupPromises);
NativeModule.require('internal/process/stdio').setup();
NativeModule.require('internal/process/methods').setup();
NativeModule.require('internal/process/methods').setup(_chdir,
_cpuUsage,
_hrtime,
_memoryUsage,
_rawDebug,
_umask,
_initgroups,
_setegid,
_seteuid,
_setgid,
_setuid,
_setgroups);
const perf = process.binding('performance');
const {
@ -55,9 +77,9 @@
NODE_PERFORMANCE_MILESTONE_PRELOAD_MODULE_LOAD_END
} = perf.constants;
_process.setup_hrtime();
_process.setup_cpuUsage();
_process.setupMemoryUsage();
_process.setup_hrtime(_hrtime);
_process.setup_cpuUsage(_cpuUsage);
_process.setupMemoryUsage(_memoryUsage);
_process.setupKillAndExit();
if (global.__coverage__)
NativeModule.require('internal/process/write-coverage').setup();
@ -79,7 +101,7 @@
}
_process.setupChannel();
_process.setupRawDebug();
_process.setupRawDebug(_rawDebug);
const browserGlobals = !process._noBrowserGlobals;
if (browserGlobals) {
@ -294,7 +316,7 @@
}
function setupProcessObject() {
process._setupProcessObject(pushValueToArray);
_setupProcessObject(pushValueToArray);
function pushValueToArray() {
for (var i = 0; i < arguments.length; i++)

View File

@ -25,10 +25,7 @@ process.assert = deprecate(
'DEP0100');
// Set up the process.cpuUsage() function.
function setup_cpuUsage() {
// Get the native function, which will be replaced with a JS version.
const _cpuUsage = process.cpuUsage;
function setup_cpuUsage(_cpuUsage) {
// Create the argument array that will be passed to the native function.
const cpuValues = new Float64Array(2);
@ -92,8 +89,7 @@ function setup_cpuUsage() {
// The 3 entries filled in by the original process.hrtime contains
// the upper/lower 32 bits of the second part of the value,
// and the remaining nanoseconds of the value.
function setup_hrtime() {
const _hrtime = process.hrtime;
function setup_hrtime(_hrtime) {
const hrValues = new Uint32Array(3);
process.hrtime = function hrtime(time) {
@ -120,12 +116,11 @@ function setup_hrtime() {
};
}
function setupMemoryUsage() {
const memoryUsage_ = process.memoryUsage;
function setupMemoryUsage(_memoryUsage) {
const memValues = new Float64Array(4);
process.memoryUsage = function memoryUsage() {
memoryUsage_(memValues);
_memoryUsage(memValues);
return {
rss: memValues[0],
heapTotal: memValues[1],
@ -245,18 +240,17 @@ function setupChannel() {
}
function setupRawDebug() {
const rawDebug = process._rawDebug;
function setupRawDebug(_rawDebug) {
process._rawDebug = function() {
rawDebug(util.format.apply(null, arguments));
_rawDebug(util.format.apply(null, arguments));
};
}
function setupUncaughtExceptionCapture(exceptionHandlerState) {
// This is a typed array for faster communication with JS.
const shouldAbortOnUncaughtToggle = process._shouldAbortOnUncaughtToggle;
delete process._shouldAbortOnUncaughtToggle;
function setupUncaughtExceptionCapture(exceptionHandlerState,
shouldAbortOnUncaughtToggle) {
// shouldAbortOnUncaughtToggle is a typed array for faster
// communication with JS.
process.setUncaughtExceptionCaptureCallback = function(fn) {
if (fn === null) {

View File

@ -9,55 +9,36 @@ const {
validateUint32
} = require('internal/validators');
function setupProcessMethods() {
function setupProcessMethods(_chdir, _cpuUsage, _hrtime, _memoryUsage,
_rawDebug, _umask, _initgroups, _setegid,
_seteuid, _setgid, _setuid, _setgroups) {
// Non-POSIX platforms like Windows don't have certain methods.
if (process.setgid !== undefined) {
setupPosixMethods();
if (_setgid !== undefined) {
setupPosixMethods(_initgroups, _setegid, _seteuid,
_setgid, _setuid, _setgroups);
}
const {
chdir: _chdir,
umask: _umask,
} = process;
process.chdir = chdir;
process.umask = umask;
function chdir(directory) {
process.chdir = function chdir(directory) {
if (typeof directory !== 'string') {
throw new ERR_INVALID_ARG_TYPE('directory', 'string', directory);
}
return _chdir(directory);
}
};
function umask(mask) {
process.umask = function umask(mask) {
if (mask === undefined) {
// Get the mask
return _umask(mask);
}
mask = validateAndMaskMode(mask, 'mask');
return _umask(mask);
}
};
}
function setupPosixMethods() {
const {
initgroups: _initgroups,
setegid: _setegid,
seteuid: _seteuid,
setgid: _setgid,
setuid: _setuid,
setgroups: _setgroups
} = process;
function setupPosixMethods(_initgroups, _setegid, _seteuid,
_setgid, _setuid, _setgroups) {
process.initgroups = initgroups;
process.setegid = setegid;
process.seteuid = seteuid;
process.setgid = setgid;
process.setuid = setuid;
process.setgroups = setgroups;
function initgroups(user, extraGroup) {
process.initgroups = function initgroups(user, extraGroup) {
validateId(user, 'user');
validateId(extraGroup, 'extraGroup');
// Result is 0 on success, 1 if user is unknown, 2 if group is unknown.
@ -67,25 +48,25 @@ function setupPosixMethods() {
} else if (result === 2) {
throw new ERR_UNKNOWN_CREDENTIAL('Group', extraGroup);
}
}
};
function setegid(id) {
process.setegid = function setegid(id) {
return execId(id, 'Group', _setegid);
}
};
function seteuid(id) {
process.seteuid = function seteuid(id) {
return execId(id, 'User', _seteuid);
}
};
function setgid(id) {
process.setgid = function setgid(id) {
return execId(id, 'Group', _setgid);
}
};
function setuid(id) {
process.setuid = function setuid(id) {
return execId(id, 'User', _setuid);
}
};
function setgroups(groups) {
process.setgroups = function setgroups(groups) {
if (!Array.isArray(groups)) {
throw new ERR_INVALID_ARG_TYPE('groups', 'Array', groups);
}
@ -98,7 +79,7 @@ function setupPosixMethods() {
if (result > 0) {
throw new ERR_UNKNOWN_CREDENTIAL('Group', groups[result - 1]);
}
}
};
function execId(id, type, method) {
validateId(id, 'id');

View File

@ -2,7 +2,7 @@
exports.setup = setupNextTick;
function setupNextTick() {
function setupNextTick(_setupNextTick, _setupPromises) {
const {
getDefaultTriggerAsyncId,
newAsyncId,
@ -14,10 +14,10 @@ function setupNextTick() {
emitDestroy,
symbols: { async_id_symbol, trigger_async_id_symbol }
} = require('internal/async_hooks');
const promises = require('internal/process/promises');
const emitPromiseRejectionWarnings =
require('internal/process/promises').setup(_setupPromises);
const { ERR_INVALID_CALLBACK } = require('internal/errors').codes;
const FixedQueue = require('internal/fixed_queue');
const { emitPromiseRejectionWarnings } = promises;
// tickInfo is used so that the C++ code in src/node.cc can
// have easy access to our nextTick state, and avoid unnecessary
@ -26,7 +26,7 @@ function setupNextTick() {
const [
tickInfo,
runMicrotasks
] = process._setupNextTick(_tickCallback);
] = _setupNextTick(_tickCallback);
// *Must* match Environment::TickInfo::Fields in src/env.h.
const kHasScheduled = 0;

View File

@ -7,11 +7,12 @@ const pendingUnhandledRejections = [];
const asyncHandledRejections = [];
let lastPromiseId = 0;
module.exports = {
emitPromiseRejectionWarnings
};
exports.setup = setupPromises;
process._setupPromises(unhandledRejection, handledRejection);
function setupPromises(_setupPromises) {
_setupPromises(unhandledRejection, handledRejection);
return emitPromiseRejectionWarnings;
}
function unhandledRejection(promise, reason) {
maybeUnhandledPromises.set(promise, {

View File

@ -309,6 +309,7 @@
'sources': [
'src/async_wrap.cc',
'src/bootstrapper.cc',
'src/callback_scope.cc',
'src/cares_wrap.cc',
'src/connection_wrap.cc',

133
src/bootstrapper.cc Normal file
View File

@ -0,0 +1,133 @@
#include "node.h"
#include "env.h"
#include "env-inl.h"
#include "node_internals.h"
#include "v8.h"
namespace node {
using v8::Array;
using v8::Context;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::MaybeLocal;
using v8::Object;
using v8::Promise;
using v8::PromiseRejectEvent;
using v8::PromiseRejectMessage;
using v8::Value;
void SetupProcessObject(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
CHECK(args[0]->IsFunction());
env->set_push_values_to_array_function(args[0].As<Function>());
}
void RunMicrotasks(const FunctionCallbackInfo<Value>& args) {
args.GetIsolate()->RunMicrotasks();
}
void SetupNextTick(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
Isolate* isolate = env->isolate();
Local<Context> context = env->context();
CHECK(args[0]->IsFunction());
env->set_tick_callback_function(args[0].As<Function>());
Local<Function> run_microtasks_fn =
env->NewFunctionTemplate(RunMicrotasks)->GetFunction(context)
.ToLocalChecked();
run_microtasks_fn->SetName(FIXED_ONE_BYTE_STRING(isolate, "runMicrotasks"));
Local<Array> ret = Array::New(isolate, 2);
ret->Set(context, 0, env->tick_info()->fields().GetJSArray()).FromJust();
ret->Set(context, 1, run_microtasks_fn).FromJust();
args.GetReturnValue().Set(ret);
}
void PromiseRejectCallback(PromiseRejectMessage message) {
Local<Promise> promise = message.GetPromise();
Isolate* isolate = promise->GetIsolate();
PromiseRejectEvent event = message.GetEvent();
Environment* env = Environment::GetCurrent(isolate);
Local<Function> callback;
Local<Value> value;
if (event == v8::kPromiseRejectWithNoHandler) {
callback = env->promise_reject_unhandled_function();
value = message.GetValue();
if (value.IsEmpty())
value = Undefined(isolate);
} else if (event == v8::kPromiseHandlerAddedAfterReject) {
callback = env->promise_reject_handled_function();
value = Undefined(isolate);
} else {
UNREACHABLE();
}
Local<Value> args[] = { promise, value };
MaybeLocal<Value> ret = callback->Call(env->context(),
Undefined(isolate),
arraysize(args),
args);
if (!ret.IsEmpty() && ret.ToLocalChecked()->IsTrue())
env->tick_info()->promise_rejections_toggle_on();
}
void SetupPromises(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
Isolate* isolate = env->isolate();
CHECK(args[0]->IsFunction());
CHECK(args[1]->IsFunction());
isolate->SetPromiseRejectCallback(PromiseRejectCallback);
env->set_promise_reject_unhandled_function(args[0].As<Function>());
env->set_promise_reject_handled_function(args[1].As<Function>());
}
#define BOOTSTRAP_METHOD(name, fn) env->SetMethod(bootstrapper, #name, fn)
// The Bootstrapper object is an ephemeral object that is used only during
// the bootstrap process of the Node.js environment. A reference to the
// bootstrap object must not be kept around after the bootstrap process
// completes so that it can be gc'd as soon as possible.
void SetupBootstrapObject(Environment* env,
Local<Object> bootstrapper) {
BOOTSTRAP_METHOD(_setupProcessObject, SetupProcessObject);
BOOTSTRAP_METHOD(_setupNextTick, SetupNextTick);
BOOTSTRAP_METHOD(_setupPromises, SetupPromises);
BOOTSTRAP_METHOD(_chdir, Chdir);
BOOTSTRAP_METHOD(_cpuUsage, CPUUsage);
BOOTSTRAP_METHOD(_hrtime, Hrtime);
BOOTSTRAP_METHOD(_memoryUsage, MemoryUsage);
BOOTSTRAP_METHOD(_rawDebug, RawDebug);
BOOTSTRAP_METHOD(_umask, Umask);
#if defined(__POSIX__) && !defined(__ANDROID__) && !defined(__CloudABI__)
BOOTSTRAP_METHOD(_initgroups, InitGroups);
BOOTSTRAP_METHOD(_setegid, SetEGid);
BOOTSTRAP_METHOD(_seteuid, SetEUid);
BOOTSTRAP_METHOD(_setgid, SetGid);
BOOTSTRAP_METHOD(_setuid, SetUid);
BOOTSTRAP_METHOD(_setgroups, SetGroups);
#endif // __POSIX__ && !defined(__ANDROID__) && !defined(__CloudABI__)
auto should_abort_on_uncaught_toggle =
FIXED_ONE_BYTE_STRING(env->isolate(), "_shouldAbortOnUncaughtToggle");
CHECK(bootstrapper->Set(env->context(),
should_abort_on_uncaught_toggle,
env->should_abort_on_uncaught_toggle().GetJSArray())
.FromJust());
}
#undef BOOTSTRAP_METHOD
} // namespace node

View File

@ -159,7 +159,6 @@ using v8::Number;
using v8::Object;
using v8::ObjectTemplate;
using v8::Promise;
using v8::PromiseRejectMessage;
using v8::PropertyCallbackInfo;
using v8::ScriptOrigin;
using v8::SealHandleScope;
@ -617,97 +616,6 @@ bool ShouldAbortOnUncaughtException(Isolate* isolate) {
!env->inside_should_not_abort_on_uncaught_scope();
}
void RunMicrotasks(const FunctionCallbackInfo<Value>& args) {
args.GetIsolate()->RunMicrotasks();
}
void SetupProcessObject(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
CHECK(args[0]->IsFunction());
env->set_push_values_to_array_function(args[0].As<Function>());
env->process_object()->Delete(
env->context(),
FIXED_ONE_BYTE_STRING(env->isolate(), "_setupProcessObject")).FromJust();
}
void SetupNextTick(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
CHECK(args[0]->IsFunction());
env->set_tick_callback_function(args[0].As<Function>());
env->process_object()->Delete(
env->context(),
FIXED_ONE_BYTE_STRING(env->isolate(), "_setupNextTick")).FromJust();
v8::Local<v8::Function> run_microtasks_fn =
env->NewFunctionTemplate(RunMicrotasks)->GetFunction(env->context())
.ToLocalChecked();
run_microtasks_fn->SetName(
FIXED_ONE_BYTE_STRING(env->isolate(), "runMicrotasks"));
Local<Array> ret = Array::New(env->isolate(), 2);
ret->Set(env->context(), 0,
env->tick_info()->fields().GetJSArray()).FromJust();
ret->Set(env->context(), 1, run_microtasks_fn).FromJust();
args.GetReturnValue().Set(ret);
}
void PromiseRejectCallback(PromiseRejectMessage message) {
Local<Promise> promise = message.GetPromise();
Isolate* isolate = promise->GetIsolate();
v8::PromiseRejectEvent event = message.GetEvent();
Environment* env = Environment::GetCurrent(isolate);
Local<Function> callback;
Local<Value> value;
if (event == v8::kPromiseRejectWithNoHandler) {
callback = env->promise_reject_unhandled_function();
value = message.GetValue();
if (value.IsEmpty())
value = Undefined(isolate);
} else if (event == v8::kPromiseHandlerAddedAfterReject) {
callback = env->promise_reject_handled_function();
value = Undefined(isolate);
} else {
UNREACHABLE();
}
Local<Value> args[] = { promise, value };
MaybeLocal<Value> ret = callback->Call(env->context(),
Undefined(isolate),
arraysize(args),
args);
if (!ret.IsEmpty() && ret.ToLocalChecked()->IsTrue())
env->tick_info()->promise_rejections_toggle_on();
}
void SetupPromises(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
Isolate* isolate = env->isolate();
CHECK(args[0]->IsFunction());
CHECK(args[1]->IsFunction());
isolate->SetPromiseRejectCallback(PromiseRejectCallback);
env->set_promise_reject_unhandled_function(args[0].As<Function>());
env->set_promise_reject_handled_function(args[1].As<Function>());
env->process_object()->Delete(
env->context(),
FIXED_ONE_BYTE_STRING(isolate, "_setupPromises")).FromJust();
}
} // anonymous namespace
@ -1315,7 +1223,7 @@ static void Abort(const FunctionCallbackInfo<Value>& args) {
}
static void Chdir(const FunctionCallbackInfo<Value>& args) {
void Chdir(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
CHECK_EQ(args.Length(), 1);
@ -1351,7 +1259,7 @@ static void Cwd(const FunctionCallbackInfo<Value>& args) {
}
static void Umask(const FunctionCallbackInfo<Value>& args) {
void Umask(const FunctionCallbackInfo<Value>& args) {
uint32_t old;
CHECK_EQ(args.Length(), 1);
@ -1496,7 +1404,7 @@ static void GetEGid(const FunctionCallbackInfo<Value>& args) {
}
static void SetGid(const FunctionCallbackInfo<Value>& args) {
void SetGid(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
CHECK_EQ(args.Length(), 1);
@ -1515,7 +1423,7 @@ static void SetGid(const FunctionCallbackInfo<Value>& args) {
}
static void SetEGid(const FunctionCallbackInfo<Value>& args) {
void SetEGid(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
CHECK_EQ(args.Length(), 1);
@ -1534,7 +1442,7 @@ static void SetEGid(const FunctionCallbackInfo<Value>& args) {
}
static void SetUid(const FunctionCallbackInfo<Value>& args) {
void SetUid(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
CHECK_EQ(args.Length(), 1);
@ -1553,7 +1461,7 @@ static void SetUid(const FunctionCallbackInfo<Value>& args) {
}
static void SetEUid(const FunctionCallbackInfo<Value>& args) {
void SetEUid(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
CHECK_EQ(args.Length(), 1);
@ -1610,7 +1518,7 @@ static void GetGroups(const FunctionCallbackInfo<Value>& args) {
}
static void SetGroups(const FunctionCallbackInfo<Value>& args) {
void SetGroups(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
CHECK_EQ(args.Length(), 1);
@ -1644,7 +1552,7 @@ static void SetGroups(const FunctionCallbackInfo<Value>& args) {
}
static void InitGroups(const FunctionCallbackInfo<Value>& args) {
void InitGroups(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
CHECK_EQ(args.Length(), 2);
@ -1733,7 +1641,7 @@ static void Uptime(const FunctionCallbackInfo<Value>& args) {
}
static void MemoryUsage(const FunctionCallbackInfo<Value>& args) {
void MemoryUsage(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
size_t rss;
@ -1785,7 +1693,7 @@ static void Kill(const FunctionCallbackInfo<Value>& args) {
// broken into the upper/lower 32 bits to be converted back in JS,
// because there is no Uint64Array in JS.
// The third entry contains the remaining nanosecond part of the value.
static void Hrtime(const FunctionCallbackInfo<Value>& args) {
void Hrtime(const FunctionCallbackInfo<Value>& args) {
uint64_t t = uv_hrtime();
Local<ArrayBuffer> ab = args[0].As<Uint32Array>()->Buffer();
@ -1804,7 +1712,7 @@ static void Hrtime(const FunctionCallbackInfo<Value>& args) {
// which are uv_timeval_t structs (long tv_sec, long tv_usec).
// Returns those values as Float64 microseconds in the elements of the array
// passed to the function.
static void CPUUsage(const FunctionCallbackInfo<Value>& args) {
void CPUUsage(const FunctionCallbackInfo<Value>& args) {
uv_rusage_t rusage;
// Call libuv to get the values we'll return.
@ -2829,13 +2737,6 @@ void SetupProcessObject(Environment* env,
FIXED_ONE_BYTE_STRING(env->isolate(), "ppid"),
GetParentProcessId).FromJust());
auto should_abort_on_uncaught_toggle =
FIXED_ONE_BYTE_STRING(env->isolate(), "_shouldAbortOnUncaughtToggle");
CHECK(process->Set(env->context(),
should_abort_on_uncaught_toggle,
env->should_abort_on_uncaught_toggle().GetJSArray())
.FromJust());
// -e, --eval
if (eval_string) {
READONLY_PROPERTY(process,
@ -2978,17 +2879,9 @@ void SetupProcessObject(Environment* env,
#if defined(__POSIX__) && !defined(__ANDROID__) && !defined(__CloudABI__)
env->SetMethod(process, "getuid", GetUid);
env->SetMethod(process, "geteuid", GetEUid);
env->SetMethod(process, "setuid", SetUid);
env->SetMethod(process, "seteuid", SetEUid);
env->SetMethod(process, "setgid", SetGid);
env->SetMethod(process, "setegid", SetEGid);
env->SetMethod(process, "getgid", GetGid);
env->SetMethod(process, "getegid", GetEGid);
env->SetMethod(process, "getgroups", GetGroups);
env->SetMethod(process, "setgroups", SetGroups);
env->SetMethod(process, "initgroups", InitGroups);
#endif // __POSIX__ && !defined(__ANDROID__) && !defined(__CloudABI__)
env->SetMethod(process, "_kill", Kill);
@ -3004,10 +2897,6 @@ void SetupProcessObject(Environment* env,
env->SetMethod(process, "uptime", Uptime);
env->SetMethod(process, "memoryUsage", MemoryUsage);
env->SetMethod(process, "_setupProcessObject", SetupProcessObject);
env->SetMethod(process, "_setupNextTick", SetupNextTick);
env->SetMethod(process, "_setupPromises", SetupPromises);
}
@ -3032,7 +2921,7 @@ void SignalExit(int signo) {
// to the process.stderr stream. However, in some cases, such as
// when debugging the stream.Writable class or the process.nextTick
// function, it is useful to bypass JavaScript entirely.
static void RawDebug(const FunctionCallbackInfo<Value>& args) {
void RawDebug(const FunctionCallbackInfo<Value>& args) {
CHECK(args.Length() == 1 && args[0]->IsString() &&
"must be called with a single string");
node::Utf8Value message(args.GetIsolate(), args[0]);
@ -3163,9 +3052,12 @@ void LoadEnvironment(Environment* env) {
}
// Bootstrap Node.js
Local<Object> bootstrapper = Object::New(env->isolate());
SetupBootstrapObject(env, bootstrapper);
Local<Value> bootstrapped_node;
Local<Value> node_bootstrapper_args[] = {
env->process_object(),
bootstrapper,
bootstrapped_loaders
};
if (!ExecuteBootstrapper(env, node_bootstrapper,

View File

@ -357,6 +357,8 @@ inline v8::Local<v8::Value> FillGlobalStatsArray(Environment* env,
return node::FillStatsArray(env->fs_stats_field_array(), s, offset);
}
void SetupBootstrapObject(Environment* env,
v8::Local<v8::Object> bootstrapper);
void SetupProcessObject(Environment* env,
int argc,
const char* const* argv,
@ -873,6 +875,24 @@ static inline const char *errno_string(int errorno) {
TRACING_CATEGORY_NODE "." #one "," \
TRACING_CATEGORY_NODE "." #one "." #two
// Functions defined in node.cc that are exposed via the bootstrapper object
void Chdir(const v8::FunctionCallbackInfo<v8::Value>& args);
void CPUUsage(const v8::FunctionCallbackInfo<v8::Value>& args);
void Hrtime(const v8::FunctionCallbackInfo<v8::Value>& args);
void MemoryUsage(const v8::FunctionCallbackInfo<v8::Value>& args);
void RawDebug(const v8::FunctionCallbackInfo<v8::Value>& args);
void Umask(const v8::FunctionCallbackInfo<v8::Value>& args);
#if defined(__POSIX__) && !defined(__ANDROID__) && !defined(__CloudABI__)
void SetGid(const v8::FunctionCallbackInfo<v8::Value>& args);
void SetEGid(const v8::FunctionCallbackInfo<v8::Value>& args);
void SetUid(const v8::FunctionCallbackInfo<v8::Value>& args);
void SetEUid(const v8::FunctionCallbackInfo<v8::Value>& args);
void SetGroups(const v8::FunctionCallbackInfo<v8::Value>& args);
void InitGroups(const v8::FunctionCallbackInfo<v8::Value>& args);
#endif // __POSIX__ && !defined(__ANDROID__) && !defined(__CloudABI__)
} // namespace node
void napi_module_register_by_symbol(v8::Local<v8::Object> exports,