summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJames M Snell <jasnell@gmail.com>2018-05-23 15:04:23 -0700
committerJames M Snell <jasnell@gmail.com>2018-05-31 14:05:53 -0700
commitcb3d049badb772fc1ea7051540d50c89f73e36dd (patch)
tree4650b56af19be6f85b0c3e063c9cea35b8549dbf /src
parentdcecfb75080dc98176119a81f0afca5805649e75 (diff)
downloadandroid-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.cc133
-rw-r--r--src/node.cc138
-rw-r--r--src/node_internals.h20
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,