diff options
author | James M Snell <jasnell@gmail.com> | 2018-05-23 15:04:23 -0700 |
---|---|---|
committer | James M Snell <jasnell@gmail.com> | 2018-05-31 14:05:53 -0700 |
commit | cb3d049badb772fc1ea7051540d50c89f73e36dd (patch) | |
tree | 4650b56af19be6f85b0c3e063c9cea35b8549dbf /src | |
parent | dcecfb75080dc98176119a81f0afca5805649e75 (diff) | |
download | android-node-v8-cb3d049badb772fc1ea7051540d50c89f73e36dd.tar.gz android-node-v8-cb3d049badb772fc1ea7051540d50c89f73e36dd.tar.bz2 android-node-v8-cb3d049badb772fc1ea7051540d50c89f73e36dd.zip |
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>
Diffstat (limited to 'src')
-rw-r--r-- | src/bootstrapper.cc | 133 | ||||
-rw-r--r-- | src/node.cc | 138 | ||||
-rw-r--r-- | src/node_internals.h | 20 |
3 files changed, 168 insertions, 123 deletions
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc new file mode 100644 index 0000000000..6c7c1af3e3 --- /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<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 diff --git a/src/node.cc b/src/node.cc index 4d8464b9f5..bf3aae2d35 100644 --- a/src/node.cc +++ b/src/node.cc @@ -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, diff --git a/src/node_internals.h b/src/node_internals.h index 1ba56458b1..3014a0e5f7 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -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, |