From 54ea1ccf2d0b0be1376bf40adc2a12b6994c10ce Mon Sep 17 00:00:00 2001 From: James M Snell Date: Fri, 13 Jul 2018 09:35:21 -0700 Subject: [PATCH] src: refactor bootstrap to use bootstrap object MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backport-PR-URL: https://github.com/nodejs/node/pull/21798 PR-URL: https://github.com/nodejs/node/pull/20917 Reviewed-By: Gus Caplan Reviewed-By: Michaƫl Zasso Reviewed-By: Ruben Bridgewater Reviewed-By: Ben Noordhuis Reviewed-By: Joyee Cheung Reviewed-By: Refael Ackermann --- lib/internal/bootstrap_node.js | 27 ++++-- lib/internal/process.js | 18 ++-- lib/internal/process/next_tick.js | 7 +- lib/internal/process/promises.js | 4 +- node.gyp | 1 + src/bootstrapper.cc | 97 ++++++++++++++++++++ src/node.cc | 146 +++++++----------------------- src/node_internals.h | 32 +++++++ 8 files changed, 196 insertions(+), 136 deletions(-) create mode 100644 src/bootstrapper.cc diff --git a/lib/internal/bootstrap_node.js b/lib/internal/bootstrap_node.js index 6b7ac044f638af..1af12795513083 100644 --- a/lib/internal/bootstrap_node.js +++ b/lib/internal/bootstrap_node.js @@ -7,7 +7,19 @@ 'use strict'; -(function(process) { +(function(process, + // bootstrapper properties... destructured to + // avoid retaining a reference to the bootstrap + // object. + { + _setupProcessObject, + _setupNextTick, + _setupPromises, + _cpuUsage, + _hrtime, + _memoryUsage, + _rawDebug + }) { function startup() { const EventEmitter = NativeModule.require('events'); @@ -31,7 +43,8 @@ _process.setupConfig(NativeModule._source); _process.setupSignalHandlers(); 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(); const perf = process.binding('performance'); @@ -47,10 +60,10 @@ NODE_PERFORMANCE_MILESTONE_PRELOAD_MODULE_LOAD_END } = perf.constants; - _process.setup_hrtime(); + _process.setup_hrtime(_hrtime); _process.setup_performance(); - _process.setup_cpuUsage(); - _process.setupMemoryUsage(); + _process.setup_cpuUsage(_cpuUsage); + _process.setupMemoryUsage(_memoryUsage); _process.setupKillAndExit(); if (global.__coverage__) NativeModule.require('internal/process/write-coverage').setup(); @@ -59,7 +72,7 @@ NativeModule.require('internal/inspector_async_hook').setup(); _process.setupChannel(); - _process.setupRawDebug(); + _process.setupRawDebug(_rawDebug); const browserGlobals = !process._noBrowserGlobals; if (browserGlobals) { @@ -244,7 +257,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 1613ae6bfddd66..4573b9429ed0cd 100644 --- a/lib/internal/process.js +++ b/lib/internal/process.js @@ -17,10 +17,7 @@ function setup_performance() { } // 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); @@ -71,8 +68,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) { @@ -96,12 +92,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], @@ -251,10 +246,9 @@ 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)); }; } diff --git a/lib/internal/process/next_tick.js b/lib/internal/process/next_tick.js index 54a6bdd0298c85..849565bba71997 100644 --- a/lib/internal/process/next_tick.js +++ b/lib/internal/process/next_tick.js @@ -46,12 +46,13 @@ class NextTickQueue { } } -function setupNextTick() { +function setupNextTick(_setupNextTick, _setupPromises) { const async_wrap = process.binding('async_wrap'); const async_hooks = require('internal/async_hooks'); const promises = require('internal/process/promises'); const errors = require('internal/errors'); - const emitPendingUnhandledRejections = promises.setup(scheduleMicrotasks); + const emitPendingUnhandledRejections = promises.setup(scheduleMicrotasks, + _setupPromises); const getDefaultTriggerAsyncId = async_hooks.getDefaultTriggerAsyncId; // Two arrays that share state between C++ and JS. const { async_hook_fields, async_id_fields } = async_wrap; @@ -81,7 +82,7 @@ function setupNextTick() { // This tickInfo thing is used so that the C++ code in src/node.cc // can have easy access to our nextTick state, and avoid unnecessary // calls into JS land. - const tickInfo = process._setupNextTick(_tickCallback, _runMicrotasks); + const tickInfo = _setupNextTick(_tickCallback, _runMicrotasks); _runMicrotasks = _runMicrotasks.runMicrotasks; diff --git a/lib/internal/process/promises.js b/lib/internal/process/promises.js index 82f15f9f9df51e..33c9354c908e9c 100644 --- a/lib/internal/process/promises.js +++ b/lib/internal/process/promises.js @@ -15,10 +15,10 @@ function getAsynchronousRejectionWarningObject(uid) { `asynchronously (rejection id: ${uid})`); } -function setupPromises(scheduleMicrotasks) { +function setupPromises(scheduleMicrotasks, _setupPromises) { let deprecationWarned = false; - process._setupPromises(function(event, promise, reason) { + _setupPromises(function(event, promise, reason) { if (event === promiseRejectEvent.unhandled) unhandledRejection(promise, reason); else if (event === promiseRejectEvent.handled) diff --git a/node.gyp b/node.gyp index c1079283a052f7..60522114920b87 100644 --- a/node.gyp +++ b/node.gyp @@ -265,6 +265,7 @@ 'sources': [ 'src/async_wrap.cc', + 'src/bootstrapper.cc', 'src/cares_wrap.cc', 'src/connection_wrap.cc', 'src/connect_wrap.cc', diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc new file mode 100644 index 00000000000000..f1084ab03aebce --- /dev/null +++ b/src/bootstrapper.cc @@ -0,0 +1,97 @@ +#include "node.h" +#include "env-inl.h" +#include "node_internals.h" +#include "v8.h" + +namespace node { + +using v8::Array; +using v8::ArrayBuffer; +using v8::Function; +using v8::FunctionCallbackInfo; +using v8::Integer; +using v8::Isolate; +using v8::Local; +using v8::Object; +using v8::Promise; +using v8::PromiseRejectMessage; +using v8::Uint32Array; +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); + + CHECK(args[0]->IsFunction()); + CHECK(args[1]->IsObject()); + + env->set_tick_callback_function(args[0].As()); + + env->SetMethod(args[1].As(), "runMicrotasks", RunMicrotasks); + + // Values use to cross communicate with processNextTick. + uint32_t* const fields = env->tick_info()->fields(); + uint32_t const fields_count = env->tick_info()->fields_count(); + + Local array_buffer = + ArrayBuffer::New(env->isolate(), fields, sizeof(*fields) * fields_count); + + args.GetReturnValue().Set(Uint32Array::New(array_buffer, 0, fields_count)); +} + +void PromiseRejectCallback(PromiseRejectMessage message) { + Local promise = message.GetPromise(); + Isolate* isolate = promise->GetIsolate(); + Local value = message.GetValue(); + Local event = Integer::New(isolate, message.GetEvent()); + + Environment* env = Environment::GetCurrent(isolate); + Local callback = env->promise_reject_function(); + + if (value.IsEmpty()) + value = Undefined(isolate); + + Local args[] = { event, promise, value }; + Local process = env->process_object(); + + callback->Call(process, arraysize(args), args); +} + +void SetupPromises(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + Isolate* isolate = env->isolate(); + + CHECK(args[0]->IsFunction()); + + isolate->SetPromiseRejectCallback(PromiseRejectCallback); + env->set_promise_reject_function(args[0].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(_cpuUsage, CPUUsage); + BOOTSTRAP_METHOD(_hrtime, Hrtime); + BOOTSTRAP_METHOD(_memoryUsage, MemoryUsage); + BOOTSTRAP_METHOD(_rawDebug, RawDebug); +} +#undef BOOTSTRAP_METHOD + +} // namespace node diff --git a/src/node.cc b/src/node.cc index b8a1f59707d847..93e16813c70c16 100644 --- a/src/node.cc +++ b/src/node.cc @@ -157,7 +157,6 @@ using v8::Object; using v8::ObjectTemplate; using v8::Promise; using v8::PromiseHookType; -using v8::PromiseRejectMessage; using v8::PropertyCallbackInfo; using v8::ScriptOrigin; using v8::SealHandleScope; @@ -264,7 +263,7 @@ bool v8_initialized = false; bool linux_at_secure = false; // process-relative uptime base, initialized at start-up -static double prog_start_time; +double prog_start_time; static Mutex node_isolate_mutex; static v8::Isolate* node_isolate; @@ -367,7 +366,7 @@ static struct { static const unsigned kMaxSignal = 32; #endif -static void PrintErrorString(const char* format, ...) { +void PrintErrorString(const char* format, ...) { va_list ap; va_start(ap, format); #ifdef _WIN32 @@ -1277,6 +1276,8 @@ void SetupDomainUse(const FunctionCallbackInfo& args) { env->set_domains_stack_array(args[1].As()); // Do a little housekeeping. + // TODO(jasnell): This should be moved to bootstrapper.cc and the bootstrap + // object at some point, but doing so requires a bit more refactoring. env->process_object()->Delete( env->context(), FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupDomainUse")).FromJust(); @@ -1292,81 +1293,6 @@ void SetupDomainUse(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(Uint32Array::New(array_buffer, 0, fields_count)); } - -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()); - CHECK(args[1]->IsObject()); - - env->set_tick_callback_function(args[0].As()); - - env->SetMethod(args[1].As(), "runMicrotasks", RunMicrotasks); - - // Do a little housekeeping. - env->process_object()->Delete( - env->context(), - FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupNextTick")).FromJust(); - - // Values use to cross communicate with processNextTick. - uint32_t* const fields = env->tick_info()->fields(); - uint32_t const fields_count = env->tick_info()->fields_count(); - - Local array_buffer = - ArrayBuffer::New(env->isolate(), fields, sizeof(*fields) * fields_count); - - args.GetReturnValue().Set(Uint32Array::New(array_buffer, 0, fields_count)); -} - -void PromiseRejectCallback(PromiseRejectMessage message) { - Local promise = message.GetPromise(); - Isolate* isolate = promise->GetIsolate(); - Local value = message.GetValue(); - Local event = Integer::New(isolate, message.GetEvent()); - - Environment* env = Environment::GetCurrent(isolate); - Local callback = env->promise_reject_function(); - - if (value.IsEmpty()) - value = Undefined(isolate); - - Local args[] = { event, promise, value }; - Local process = env->process_object(); - - callback->Call(process, arraysize(args), args); -} - -void SetupPromises(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); - Isolate* isolate = env->isolate(); - - CHECK(args[0]->IsFunction()); - - isolate->SetPromiseRejectCallback(PromiseRejectCallback); - env->set_promise_reject_function(args[0].As()); - - env->process_object()->Delete( - env->context(), - FIXED_ONE_BYTE_STRING(isolate, "_setupPromises")).FromJust(); -} - } // anonymous namespace @@ -2058,12 +1984,12 @@ NO_RETURN void Assert(const char* const (*args)[4]) { } -static void Abort(const FunctionCallbackInfo& args) { +void Abort(const FunctionCallbackInfo& args) { Abort(); } -static void Chdir(const FunctionCallbackInfo& args) { +void Chdir(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); if (args.Length() != 1 || !args[0]->IsString()) { @@ -2078,7 +2004,7 @@ static void Chdir(const FunctionCallbackInfo& args) { } -static void Cwd(const FunctionCallbackInfo& args) { +void Cwd(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); #ifdef _WIN32 /* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */ @@ -2101,7 +2027,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; @@ -2238,31 +2164,31 @@ static gid_t gid_by_name(Isolate* isolate, Local value) { } } -static void GetUid(const FunctionCallbackInfo& args) { +void GetUid(const FunctionCallbackInfo& args) { // uid_t is an uint32_t on all supported platforms. args.GetReturnValue().Set(static_cast(getuid())); } -static void GetGid(const FunctionCallbackInfo& args) { +void GetGid(const FunctionCallbackInfo& args) { // gid_t is an uint32_t on all supported platforms. args.GetReturnValue().Set(static_cast(getgid())); } -static void GetEUid(const FunctionCallbackInfo& args) { +void GetEUid(const FunctionCallbackInfo& args) { // uid_t is an uint32_t on all supported platforms. args.GetReturnValue().Set(static_cast(geteuid())); } -static void GetEGid(const FunctionCallbackInfo& args) { +void GetEGid(const FunctionCallbackInfo& args) { // gid_t is an uint32_t on all supported platforms. args.GetReturnValue().Set(static_cast(getegid())); } -static void SetGid(const FunctionCallbackInfo& args) { +void SetGid(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); if (!args[0]->IsUint32() && !args[0]->IsString()) { @@ -2281,7 +2207,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()) { @@ -2300,7 +2226,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()) { @@ -2319,7 +2245,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()) { @@ -2338,7 +2264,7 @@ static void SetEUid(const FunctionCallbackInfo& args) { } -static void GetGroups(const FunctionCallbackInfo& args) { +void GetGroups(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); int ngroups = getgroups(0, nullptr); @@ -2376,7 +2302,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()) { @@ -2407,7 +2333,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()) { @@ -2487,7 +2413,7 @@ static void Exit(const FunctionCallbackInfo& args) { } -static void Uptime(const FunctionCallbackInfo& args) { +void Uptime(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); double uptime; @@ -2498,7 +2424,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; @@ -2526,7 +2452,7 @@ static void MemoryUsage(const FunctionCallbackInfo& args) { } -static void Kill(const FunctionCallbackInfo& args) { +void Kill(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); if (args.Length() != 2) { @@ -2550,7 +2476,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(); @@ -2569,7 +2495,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. @@ -3688,22 +3614,14 @@ void SetupProcessObject(Environment* env, env->SetMethod(process, "_debugPause", DebugPause); env->SetMethod(process, "_debugEnd", DebugEnd); - env->SetMethod(process, "hrtime", Hrtime); - - env->SetMethod(process, "cpuUsage", CPUUsage); - env->SetMethod(process, "dlopen", DLOpen); env->SetMethod(process, "uptime", Uptime); - env->SetMethod(process, "memoryUsage", MemoryUsage); env->SetMethod(process, "binding", Binding); env->SetMethod(process, "_linkedBinding", LinkedBinding); env->SetMethod(process, "_internalBinding", InternalBinding); - env->SetMethod(process, "_setupProcessObject", SetupProcessObject); - env->SetMethod(process, "_setupNextTick", SetupNextTick); - env->SetMethod(process, "_setupPromises", SetupPromises); env->SetMethod(process, "_setupDomainUse", SetupDomainUse); // pre-set _events object for faster emit checks @@ -3737,7 +3655,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]); @@ -3793,8 +3711,6 @@ void LoadEnvironment(Environment* env) { // thrown during process startup. try_catch.SetVerbose(true); - env->SetMethod(env->process_object(), "_rawDebug", RawDebug); - // Expose the global object as a property on itself // (Allows you to set stuff on `global` from anywhere in JavaScript.) global->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "global"), global); @@ -3806,9 +3722,15 @@ void LoadEnvironment(Environment* env) { // We start the process this way in order to be more modular. Developers // who do not like how bootstrap_node.js sets up the module system but do // like Node's I/O bindings may want to replace 'f' with their own function. - Local arg = env->process_object(); - - auto ret = f->Call(env->context(), Null(env->isolate()), 1, &arg); + Local bootstrapper = Object::New(env->isolate()); + SetupBootstrapObject(env, bootstrapper); + Local args[] = { + env->process_object(), + bootstrapper + }; + auto ret = f->Call(env->context(), + Null(env->isolate()), + arraysize(args), args); // If there was an error during bootstrap then it was either handled by the // FatalException handler or it's unrecoverable (e.g. max call stack // exceeded). Either way, clear the stack so that the AsyncCallbackScope diff --git a/src/node_internals.h b/src/node_internals.h index b2cef8c9abcad5..ff98995a19873c 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -262,6 +262,8 @@ void ProcessEmitWarning(Environment* env, const char* fmt, ...); void FillStatsArray(double* fields, const uv_stat_t* s); +void SetupBootstrapObject(Environment* env, + v8::Local bootstrapper); void SetupProcessObject(Environment* env, int argc, const char* const* argv, @@ -413,6 +415,36 @@ class InternalCallbackScope { #define NODE_MODULE_CONTEXT_AWARE_INTERNAL(modname, regfunc) \ NODE_MODULE_CONTEXT_AWARE_CPP(modname, regfunc, nullptr, NM_F_INTERNAL) +// Functions defined in node.cc that are exposed via the bootstrapper object + +extern double prog_start_time; +void PrintErrorString(const char* format, ...); + +void Abort(const v8::FunctionCallbackInfo& args); +void Chdir(const v8::FunctionCallbackInfo& args); +void CPUUsage(const v8::FunctionCallbackInfo& args); +void Cwd(const v8::FunctionCallbackInfo& args); +void Hrtime(const v8::FunctionCallbackInfo& args); +void Kill(const v8::FunctionCallbackInfo& args); +void MemoryUsage(const v8::FunctionCallbackInfo& args); +void RawDebug(const v8::FunctionCallbackInfo& args); +void Umask(const v8::FunctionCallbackInfo& args); +void Uptime(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); +void GetUid(const v8::FunctionCallbackInfo& args); +void GetGid(const v8::FunctionCallbackInfo& args); +void GetEUid(const v8::FunctionCallbackInfo& args); +void GetEGid(const v8::FunctionCallbackInfo& args); +void GetGroups(const v8::FunctionCallbackInfo& args); +#endif // __POSIX__ && !defined(__ANDROID__) && !defined(__CloudABI__) + } // namespace node