diff --git a/lib/internal/bootstrap/node.js b/lib/internal/bootstrap/node.js index d6fd67fe5d2c85..6477c2d8282f43 100644 --- a/lib/internal/bootstrap/node.js +++ b/lib/internal/bootstrap/node.js @@ -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++) diff --git a/lib/internal/process.js b/lib/internal/process.js index 6d1958db6db0a2..bcefca316a236e 100644 --- a/lib/internal/process.js +++ b/lib/internal/process.js @@ -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) { diff --git a/lib/internal/process/methods.js b/lib/internal/process/methods.js index 1a720c5cb0e5e4..209702ed7b9b76 100644 --- a/lib/internal/process/methods.js +++ b/lib/internal/process/methods.js @@ -1,65 +1,49 @@ 'use strict'; -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(...args) { + process.chdir = function chdir(...args) { return _chdir(...args); - } + }; - function umask(...args) { + process.umask = function umask(...args) { return _umask(...args); - } + }; } -function setupPosixMethods() { - const { - initgroups: _initgroups, - setegid: _setegid, - seteuid: _seteuid, - setgid: _setgid, - setuid: _setuid, - setgroups: _setgroups - } = process; - - process.initgroups = initgroups; - process.setegid = setegid; - process.seteuid = seteuid; - process.setgid = setgid; - process.setuid = setuid; - process.setgroups = setgroups; +function setupPosixMethods(_initgroups, _setegid, _seteuid, + _setgid, _setuid, _setgroups) { - function initgroups(...args) { + process.initgroups = function initgroups(...args) { return _initgroups(...args); - } + }; - function setegid(...args) { + process.setegid = function setegid(...args) { return _setegid(...args); - } + }; - function seteuid(...args) { + process.seteuid = function seteuid(...args) { return _seteuid(...args); - } + }; - function setgid(...args) { + process.setgid = function setgid(...args) { return _setgid(...args); - } + }; - function setuid(...args) { + process.setuid = function setuid(...args) { return _setuid(...args); - } + }; - function setgroups(...args) { + process.setgroups = function setgroups(...args) { return _setgroups(...args); - } + }; } exports.setup = setupProcessMethods; diff --git a/lib/internal/process/next_tick.js b/lib/internal/process/next_tick.js index dbe0ce8cdbdacf..df6984aabc8c07 100644 --- a/lib/internal/process/next_tick.js +++ b/lib/internal/process/next_tick.js @@ -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; diff --git a/lib/internal/process/promises.js b/lib/internal/process/promises.js index 6cc366d8b2b09a..f54f34b9ae92f4 100644 --- a/lib/internal/process/promises.js +++ b/lib/internal/process/promises.js @@ -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, { diff --git a/node.gyp b/node.gyp index d6b32cd3b75b6c..709ce226033af0 100644 --- a/node.gyp +++ b/node.gyp @@ -308,6 +308,7 @@ 'sources': [ 'src/async_wrap.cc', + 'src/bootstrapper.cc', 'src/callback_scope.cc', 'src/cares_wrap.cc', 'src/connection_wrap.cc', diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc new file mode 100644 index 00000000000000..6c7c1af3e31cf6 --- /dev/null +++ b/src/bootstrapper.cc @@ -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& args) { + Environment* env = Environment::GetCurrent(args); + CHECK(args[0]->IsFunction()); + env->set_push_values_to_array_function(args[0].As()); +} + +void RunMicrotasks(const FunctionCallbackInfo& args) { + args.GetIsolate()->RunMicrotasks(); +} + +void SetupNextTick(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + Isolate* isolate = env->isolate(); + Local context = env->context(); + + CHECK(args[0]->IsFunction()); + + env->set_tick_callback_function(args[0].As()); + + Local run_microtasks_fn = + env->NewFunctionTemplate(RunMicrotasks)->GetFunction(context) + .ToLocalChecked(); + run_microtasks_fn->SetName(FIXED_ONE_BYTE_STRING(isolate, "runMicrotasks")); + + Local 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 = message.GetPromise(); + Isolate* isolate = promise->GetIsolate(); + PromiseRejectEvent event = message.GetEvent(); + + Environment* env = Environment::GetCurrent(isolate); + Local callback; + Local 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 args[] = { promise, value }; + MaybeLocal 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& 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()); + env->set_promise_reject_handled_function(args[1].As()); +} + +#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 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 diff --git a/src/node.cc b/src/node.cc index 8d2389c557c282..4973fea636afd5 100644 --- a/src/node.cc +++ b/src/node.cc @@ -158,7 +158,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; @@ -612,97 +611,6 @@ bool ShouldAbortOnUncaughtException(Isolate* isolate) { !env->inside_should_not_abort_on_uncaught_scope(); } - -void RunMicrotasks(const FunctionCallbackInfo& args) { - args.GetIsolate()->RunMicrotasks(); -} - - -void SetupProcessObject(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); - - CHECK(args[0]->IsFunction()); - - env->set_push_values_to_array_function(args[0].As()); - env->process_object()->Delete( - env->context(), - FIXED_ONE_BYTE_STRING(env->isolate(), "_setupProcessObject")).FromJust(); -} - - -void SetupNextTick(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); - - CHECK(args[0]->IsFunction()); - - env->set_tick_callback_function(args[0].As()); - - env->process_object()->Delete( - env->context(), - FIXED_ONE_BYTE_STRING(env->isolate(), "_setupNextTick")).FromJust(); - - v8::Local run_microtasks_fn = - env->NewFunctionTemplate(RunMicrotasks)->GetFunction(env->context()) - .ToLocalChecked(); - run_microtasks_fn->SetName( - FIXED_ONE_BYTE_STRING(env->isolate(), "runMicrotasks")); - - Local 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 = message.GetPromise(); - Isolate* isolate = promise->GetIsolate(); - v8::PromiseRejectEvent event = message.GetEvent(); - - Environment* env = Environment::GetCurrent(isolate); - Local callback; - Local 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 args[] = { promise, value }; - MaybeLocal 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& 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()); - env->set_promise_reject_handled_function(args[1].As()); - - env->process_object()->Delete( - env->context(), - FIXED_ONE_BYTE_STRING(isolate, "_setupPromises")).FromJust(); -} - } // anonymous namespace @@ -1310,7 +1218,7 @@ static void Abort(const FunctionCallbackInfo& args) { } -static void Chdir(const FunctionCallbackInfo& args) { +void Chdir(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); if (args.Length() != 1 || !args[0]->IsString()) { @@ -1348,7 +1256,7 @@ static void Cwd(const FunctionCallbackInfo& args) { } -static void Umask(const FunctionCallbackInfo& args) { +void Umask(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); uint32_t old; @@ -1509,7 +1417,7 @@ static void GetEGid(const FunctionCallbackInfo& args) { } -static void SetGid(const FunctionCallbackInfo& args) { +void SetGid(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); if (!args[0]->IsUint32() && !args[0]->IsString()) { @@ -1528,7 +1436,7 @@ static void SetGid(const FunctionCallbackInfo& args) { } -static void SetEGid(const FunctionCallbackInfo& args) { +void SetEGid(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); if (!args[0]->IsUint32() && !args[0]->IsString()) { @@ -1547,7 +1455,7 @@ static void SetEGid(const FunctionCallbackInfo& args) { } -static void SetUid(const FunctionCallbackInfo& args) { +void SetUid(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); if (!args[0]->IsUint32() && !args[0]->IsString()) { @@ -1566,7 +1474,7 @@ static void SetUid(const FunctionCallbackInfo& args) { } -static void SetEUid(const FunctionCallbackInfo& args) { +void SetEUid(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); if (!args[0]->IsUint32() && !args[0]->IsString()) { @@ -1623,7 +1531,7 @@ static void GetGroups(const FunctionCallbackInfo& args) { } -static void SetGroups(const FunctionCallbackInfo& args) { +void SetGroups(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); if (!args[0]->IsArray()) { @@ -1654,7 +1562,7 @@ static void SetGroups(const FunctionCallbackInfo& args) { } -static void InitGroups(const FunctionCallbackInfo& args) { +void InitGroups(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); if (!args[0]->IsUint32() && !args[0]->IsString()) { @@ -1743,7 +1651,7 @@ static void Uptime(const FunctionCallbackInfo& args) { } -static void MemoryUsage(const FunctionCallbackInfo& args) { +void MemoryUsage(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); size_t rss; @@ -1795,7 +1703,7 @@ static void Kill(const FunctionCallbackInfo& 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& args) { +void Hrtime(const FunctionCallbackInfo& args) { uint64_t t = uv_hrtime(); Local ab = args[0].As()->Buffer(); @@ -1814,7 +1722,7 @@ static void Hrtime(const FunctionCallbackInfo& 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& args) { +void CPUUsage(const FunctionCallbackInfo& args) { uv_rusage_t rusage; // Call libuv to get the values we'll return. @@ -2839,13 +2747,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, @@ -2988,17 +2889,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); @@ -3014,10 +2907,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); } @@ -3042,7 +2931,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& args) { +void RawDebug(const FunctionCallbackInfo& args) { CHECK(args.Length() == 1 && args[0]->IsString() && "must be called with a single string"); node::Utf8Value message(args.GetIsolate(), args[0]); @@ -3173,9 +3062,12 @@ void LoadEnvironment(Environment* env) { } // Bootstrap Node.js + Local bootstrapper = Object::New(env->isolate()); + SetupBootstrapObject(env, bootstrapper); Local bootstrapped_node; Local node_bootstrapper_args[] = { env->process_object(), + bootstrapper, bootstrapped_loaders }; if (!ExecuteBootstrapper(env, node_bootstrapper, diff --git a/src/node_internals.h b/src/node_internals.h index 1ba56458b194c2..3014a0e5f7a442 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -357,6 +357,8 @@ inline v8::Local FillGlobalStatsArray(Environment* env, return node::FillStatsArray(env->fs_stats_field_array(), s, offset); } +void SetupBootstrapObject(Environment* env, + v8::Local 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& args); +void CPUUsage(const v8::FunctionCallbackInfo& args); +void Hrtime(const v8::FunctionCallbackInfo& args); +void MemoryUsage(const v8::FunctionCallbackInfo& args); +void RawDebug(const v8::FunctionCallbackInfo& args); +void Umask(const v8::FunctionCallbackInfo& args); + +#if defined(__POSIX__) && !defined(__ANDROID__) && !defined(__CloudABI__) +void SetGid(const v8::FunctionCallbackInfo& args); +void SetEGid(const v8::FunctionCallbackInfo& args); +void SetUid(const v8::FunctionCallbackInfo& args); +void SetEUid(const v8::FunctionCallbackInfo& args); +void SetGroups(const v8::FunctionCallbackInfo& args); +void InitGroups(const v8::FunctionCallbackInfo& args); +#endif // __POSIX__ && !defined(__ANDROID__) && !defined(__CloudABI__) + } // namespace node void napi_module_register_by_symbol(v8::Local exports,