From b72ec23201227391f796868a5d36debbe2a882aa Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Thu, 17 Jan 2019 03:00:55 +0800 Subject: [PATCH] src: move public C++ APIs into src/api/*.cc This patch moves most of the public C++ APIs into src/api/*.cc so that it's easier to tell that we need to be careful about the compatibility of these code. Some APIs, like `node::LoadEnvironmet()`, `node::Start()` and `node::Init()` still stay in `node.cc` because they are still very specific to our use cases and do not work quite well yet for embedders anyway - we could not even manage to write cctest for them at the moment. PR-URL: https://github.com/nodejs/node/pull/25541 Reviewed-By: Gus Caplan --- node.gyp | 10 +- src/{callback_scope.cc => api/callback.cc} | 0 src/{node_encoding.cc => api/encoding.cc} | 0 src/api/environment.cc | 214 ++++++++++ src/{ => api}/exceptions.cc | 14 + src/api/hooks.cc | 149 +++++++ src/api/utils.cc | 170 ++++++++ src/async_wrap.cc | 65 --- src/node.cc | 456 +-------------------- src/node_errors.cc | 13 - src/node_internals.h | 1 + 11 files changed, 557 insertions(+), 535 deletions(-) rename src/{callback_scope.cc => api/callback.cc} (100%) rename src/{node_encoding.cc => api/encoding.cc} (100%) create mode 100644 src/api/environment.cc rename src/{ => api}/exceptions.cc (92%) create mode 100644 src/api/hooks.cc create mode 100644 src/api/utils.cc diff --git a/node.gyp b/node.gyp index 1eceb2c6361143..81a0ade8f7ac83 100644 --- a/node.gyp +++ b/node.gyp @@ -365,14 +365,19 @@ 'dependencies': [ 'deps/histogram/histogram.gyp:histogram' ], 'sources': [ + 'src/api/callback.cc', + 'src/api/encoding.cc', + 'src/api/environment.cc', + 'src/api/exceptions.cc', + 'src/api/hooks.cc', + 'src/api/utils.cc', + 'src/async_wrap.cc', - 'src/callback_scope.cc', 'src/cares_wrap.cc', 'src/connect_wrap.cc', 'src/connection_wrap.cc', 'src/debug_utils.cc', 'src/env.cc', - 'src/exceptions.cc', 'src/fs_event_wrap.cc', 'src/handle_wrap.cc', 'src/heap_utils.cc', @@ -392,7 +397,6 @@ 'src/node_contextify.cc', 'src/node_credentials.cc', 'src/node_domain.cc', - 'src/node_encoding.cc', 'src/node_env_var.cc', 'src/node_errors.cc', 'src/node_file.cc', diff --git a/src/callback_scope.cc b/src/api/callback.cc similarity index 100% rename from src/callback_scope.cc rename to src/api/callback.cc diff --git a/src/node_encoding.cc b/src/api/encoding.cc similarity index 100% rename from src/node_encoding.cc rename to src/api/encoding.cc diff --git a/src/api/environment.cc b/src/api/environment.cc new file mode 100644 index 00000000000000..9480fb2b96144c --- /dev/null +++ b/src/api/environment.cc @@ -0,0 +1,214 @@ +#include "env.h" +#include "node.h" +#include "node_context_data.h" +#include "node_errors.h" +#include "node_internals.h" +#include "node_native_module.h" +#include "node_platform.h" +#include "node_process.h" +#include "node_v8_platform-inl.h" +#include "uv.h" + +namespace node { +using v8::Context; +using v8::Function; +using v8::HandleScope; +using v8::Isolate; +using v8::Local; +using v8::MaybeLocal; +using v8::Message; +using v8::MicrotasksPolicy; +using v8::ObjectTemplate; +using v8::String; +using v8::Value; + +static bool AllowWasmCodeGenerationCallback(Local context, + Local) { + Local wasm_code_gen = + context->GetEmbedderData(ContextEmbedderIndex::kAllowWasmCodeGeneration); + return wasm_code_gen->IsUndefined() || wasm_code_gen->IsTrue(); +} + +static bool ShouldAbortOnUncaughtException(Isolate* isolate) { + HandleScope scope(isolate); + Environment* env = Environment::GetCurrent(isolate); + return env != nullptr && env->should_abort_on_uncaught_toggle()[0] && + !env->inside_should_not_abort_on_uncaught_scope(); +} + +static void OnMessage(Local message, Local error) { + Isolate* isolate = message->GetIsolate(); + switch (message->ErrorLevel()) { + case Isolate::MessageErrorLevel::kMessageWarning: { + Environment* env = Environment::GetCurrent(isolate); + if (!env) { + break; + } + Utf8Value filename(isolate, message->GetScriptOrigin().ResourceName()); + // (filename):(line) (message) + std::stringstream warning; + warning << *filename; + warning << ":"; + warning << message->GetLineNumber(env->context()).FromMaybe(-1); + warning << " "; + v8::String::Utf8Value msg(isolate, message->Get()); + warning << *msg; + USE(ProcessEmitWarningGeneric(env, warning.str().c_str(), "V8")); + break; + } + case Isolate::MessageErrorLevel::kMessageError: + FatalException(isolate, error, message); + break; + } +} + +void* ArrayBufferAllocator::Allocate(size_t size) { + if (zero_fill_field_ || per_process::cli_options->zero_fill_all_buffers) + return UncheckedCalloc(size); + else + return UncheckedMalloc(size); +} + +ArrayBufferAllocator* CreateArrayBufferAllocator() { + return new ArrayBufferAllocator(); +} + +void FreeArrayBufferAllocator(ArrayBufferAllocator* allocator) { + delete allocator; +} + +Isolate* NewIsolate(ArrayBufferAllocator* allocator, uv_loop_t* event_loop) { + Isolate::CreateParams params; + params.array_buffer_allocator = allocator; +#ifdef NODE_ENABLE_VTUNE_PROFILING + params.code_event_handler = vTune::GetVtuneCodeEventHandler(); +#endif + + Isolate* isolate = Isolate::Allocate(); + if (isolate == nullptr) return nullptr; + + // Register the isolate on the platform before the isolate gets initialized, + // so that the isolate can access the platform during initialization. + per_process::v8_platform.Platform()->RegisterIsolate(isolate, event_loop); + Isolate::Initialize(isolate, params); + + isolate->AddMessageListenerWithErrorLevel( + OnMessage, + Isolate::MessageErrorLevel::kMessageError | + Isolate::MessageErrorLevel::kMessageWarning); + isolate->SetAbortOnUncaughtExceptionCallback(ShouldAbortOnUncaughtException); + isolate->SetMicrotasksPolicy(MicrotasksPolicy::kExplicit); + isolate->SetFatalErrorHandler(OnFatalError); + isolate->SetAllowWasmCodeGenerationCallback(AllowWasmCodeGenerationCallback); + v8::CpuProfiler::UseDetailedSourcePositionsForProfiling(isolate); + + return isolate; +} + +IsolateData* CreateIsolateData(Isolate* isolate, + uv_loop_t* loop, + MultiIsolatePlatform* platform, + ArrayBufferAllocator* allocator) { + return new IsolateData( + isolate, + loop, + platform, + allocator != nullptr ? allocator->zero_fill_field() : nullptr); +} + +void FreeIsolateData(IsolateData* isolate_data) { + delete isolate_data; +} + +Environment* CreateEnvironment(IsolateData* isolate_data, + Local context, + int argc, + const char* const* argv, + int exec_argc, + const char* const* exec_argv) { + Isolate* isolate = context->GetIsolate(); + HandleScope handle_scope(isolate); + Context::Scope context_scope(context); + // TODO(addaleax): This is a much better place for parsing per-Environment + // options than the global parse call. + std::vector args(argv, argv + argc); + std::vector exec_args(exec_argv, exec_argv + exec_argc); + Environment* env = new Environment(isolate_data, context); + env->Start(per_process::v8_is_profiling); + env->ProcessCliArgs(args, exec_args); + return env; +} + +void FreeEnvironment(Environment* env) { + env->RunCleanup(); + delete env; +} + +Environment* GetCurrentEnvironment(Local context) { + return Environment::GetCurrent(context); +} + +MultiIsolatePlatform* GetMainThreadMultiIsolatePlatform() { + return per_process::v8_platform.Platform(); +} + +MultiIsolatePlatform* CreatePlatform( + int thread_pool_size, + node::tracing::TracingController* tracing_controller) { + return new NodePlatform(thread_pool_size, tracing_controller); +} + +MultiIsolatePlatform* InitializeV8Platform(int thread_pool_size) { + per_process::v8_platform.Initialize(thread_pool_size); + return per_process::v8_platform.Platform(); +} + +void FreePlatform(MultiIsolatePlatform* platform) { + delete platform; +} + +Local NewContext(Isolate* isolate, + Local object_template) { + auto context = Context::New(isolate, nullptr, object_template); + if (context.IsEmpty()) return context; + HandleScope handle_scope(isolate); + + context->SetEmbedderData(ContextEmbedderIndex::kAllowWasmCodeGeneration, + True(isolate)); + + { + // Run lib/internal/per_context.js + Context::Scope context_scope(context); + + std::vector> parameters = { + FIXED_ONE_BYTE_STRING(isolate, "global")}; + Local arguments[] = {context->Global()}; + MaybeLocal maybe_fn = + per_process::native_module_loader.LookupAndCompile( + context, "internal/per_context", ¶meters, nullptr); + if (maybe_fn.IsEmpty()) { + return Local(); + } + Local fn = maybe_fn.ToLocalChecked(); + MaybeLocal result = + fn->Call(context, Undefined(isolate), arraysize(arguments), arguments); + // Execution failed during context creation. + // TODO(joyeecheung): deprecate this signature and return a MaybeLocal. + if (result.IsEmpty()) { + return Local(); + } + } + + return context; +} + +uv_loop_t* GetCurrentEventLoop(Isolate* isolate) { + HandleScope handle_scope(isolate); + Local context = isolate->GetCurrentContext(); + if (context.IsEmpty()) return nullptr; + Environment* env = Environment::GetCurrent(context); + if (env == nullptr) return nullptr; + return env->event_loop(); +} + +} // namespace node diff --git a/src/exceptions.cc b/src/api/exceptions.cc similarity index 92% rename from src/exceptions.cc rename to src/api/exceptions.cc index d5c05fdf420926..4d1cca8b6512b4 100644 --- a/src/exceptions.cc +++ b/src/api/exceptions.cc @@ -12,6 +12,7 @@ namespace node { using v8::Exception; +using v8::HandleScope; using v8::Integer; using v8::Isolate; using v8::Local; @@ -228,4 +229,17 @@ Local WinapiErrnoException(Isolate* isolate, } #endif +void FatalException(Isolate* isolate, const v8::TryCatch& try_catch) { + // If we try to print out a termination exception, we'd just get 'null', + // so just crashing here with that information seems like a better idea, + // and in particular it seems like we should handle terminations at the call + // site for this function rather than by printing them out somewhere. + CHECK(!try_catch.HasTerminated()); + + HandleScope scope(isolate); + if (!try_catch.IsVerbose()) { + FatalException(isolate, try_catch.Exception(), try_catch.Message()); + } +} + } // namespace node diff --git a/src/api/hooks.cc b/src/api/hooks.cc new file mode 100644 index 00000000000000..b54292638ddf95 --- /dev/null +++ b/src/api/hooks.cc @@ -0,0 +1,149 @@ +#include "env-inl.h" +#include "node.h" +#include "node_process.h" +#include "async_wrap.h" + +namespace node { + +using v8::Context; +using v8::HandleScope; +using v8::Integer; +using v8::Isolate; +using v8::Local; +using v8::Object; +using v8::String; +using v8::Value; +using v8::NewStringType; + +void RunAtExit(Environment* env) { + env->RunAtExitCallbacks(); +} + +void AtExit(void (*cb)(void* arg), void* arg) { + auto env = Environment::GetThreadLocalEnv(); + AtExit(env, cb, arg); +} + +void AtExit(Environment* env, void (*cb)(void* arg), void* arg) { + CHECK_NOT_NULL(env); + env->AtExit(cb, arg); +} + +void EmitBeforeExit(Environment* env) { + HandleScope handle_scope(env->isolate()); + Context::Scope context_scope(env->context()); + Local exit_code = env->process_object() + ->Get(env->context(), env->exit_code_string()) + .ToLocalChecked() + ->ToInteger(env->context()) + .ToLocalChecked(); + ProcessEmit(env, "beforeExit", exit_code).ToLocalChecked(); +} + +int EmitExit(Environment* env) { + // process.emit('exit') + HandleScope handle_scope(env->isolate()); + Context::Scope context_scope(env->context()); + Local process_object = env->process_object(); + process_object + ->Set(env->context(), + FIXED_ONE_BYTE_STRING(env->isolate(), "_exiting"), + True(env->isolate())) + .FromJust(); + + Local exit_code = env->exit_code_string(); + int code = process_object->Get(env->context(), exit_code) + .ToLocalChecked() + ->Int32Value(env->context()) + .ToChecked(); + ProcessEmit(env, "exit", Integer::New(env->isolate(), code)); + + // Reload exit code, it may be changed by `emit('exit')` + return process_object->Get(env->context(), exit_code) + .ToLocalChecked() + ->Int32Value(env->context()) + .ToChecked(); +} + +void AddPromiseHook(Isolate* isolate, promise_hook_func fn, void* arg) { + Environment* env = Environment::GetCurrent(isolate); + CHECK_NOT_NULL(env); + env->AddPromiseHook(fn, arg); +} + +void AddEnvironmentCleanupHook(Isolate* isolate, + void (*fun)(void* arg), + void* arg) { + Environment* env = Environment::GetCurrent(isolate); + CHECK_NOT_NULL(env); + env->AddCleanupHook(fun, arg); +} + +void RemoveEnvironmentCleanupHook(Isolate* isolate, + void (*fun)(void* arg), + void* arg) { + Environment* env = Environment::GetCurrent(isolate); + CHECK_NOT_NULL(env); + env->RemoveCleanupHook(fun, arg); +} + +async_id AsyncHooksGetExecutionAsyncId(Isolate* isolate) { + // Environment::GetCurrent() allocates a Local<> handle. + HandleScope handle_scope(isolate); + Environment* env = Environment::GetCurrent(isolate); + if (env == nullptr) return -1; + return env->execution_async_id(); +} + +async_id AsyncHooksGetTriggerAsyncId(Isolate* isolate) { + // Environment::GetCurrent() allocates a Local<> handle. + HandleScope handle_scope(isolate); + Environment* env = Environment::GetCurrent(isolate); + if (env == nullptr) return -1; + return env->trigger_async_id(); +} + + +async_context EmitAsyncInit(Isolate* isolate, + Local resource, + const char* name, + async_id trigger_async_id) { + HandleScope handle_scope(isolate); + Local type = + String::NewFromUtf8(isolate, name, NewStringType::kInternalized) + .ToLocalChecked(); + return EmitAsyncInit(isolate, resource, type, trigger_async_id); +} + +async_context EmitAsyncInit(Isolate* isolate, + Local resource, + Local name, + async_id trigger_async_id) { + HandleScope handle_scope(isolate); + Environment* env = Environment::GetCurrent(isolate); + CHECK_NOT_NULL(env); + + // Initialize async context struct + if (trigger_async_id == -1) + trigger_async_id = env->get_default_trigger_async_id(); + + async_context context = { + env->new_async_id(), // async_id_ + trigger_async_id // trigger_async_id_ + }; + + // Run init hooks + AsyncWrap::EmitAsyncInit(env, resource, name, context.async_id, + context.trigger_async_id); + + return context; +} + +void EmitAsyncDestroy(Isolate* isolate, async_context asyncContext) { + // Environment::GetCurrent() allocates a Local<> handle. + HandleScope handle_scope(isolate); + AsyncWrap::EmitDestroy( + Environment::GetCurrent(isolate), asyncContext.async_id); +} + +} // namespace node diff --git a/src/api/utils.cc b/src/api/utils.cc new file mode 100644 index 00000000000000..e6993f33b00647 --- /dev/null +++ b/src/api/utils.cc @@ -0,0 +1,170 @@ +#include "node.h" +#include "node_internals.h" + +#include + +namespace node { + +const char* signo_string(int signo) { +#define SIGNO_CASE(e) \ + case e: \ + return #e; + switch (signo) { +#ifdef SIGHUP + SIGNO_CASE(SIGHUP); +#endif + +#ifdef SIGINT + SIGNO_CASE(SIGINT); +#endif + +#ifdef SIGQUIT + SIGNO_CASE(SIGQUIT); +#endif + +#ifdef SIGILL + SIGNO_CASE(SIGILL); +#endif + +#ifdef SIGTRAP + SIGNO_CASE(SIGTRAP); +#endif + +#ifdef SIGABRT + SIGNO_CASE(SIGABRT); +#endif + +#ifdef SIGIOT +#if SIGABRT != SIGIOT + SIGNO_CASE(SIGIOT); +#endif +#endif + +#ifdef SIGBUS + SIGNO_CASE(SIGBUS); +#endif + +#ifdef SIGFPE + SIGNO_CASE(SIGFPE); +#endif + +#ifdef SIGKILL + SIGNO_CASE(SIGKILL); +#endif + +#ifdef SIGUSR1 + SIGNO_CASE(SIGUSR1); +#endif + +#ifdef SIGSEGV + SIGNO_CASE(SIGSEGV); +#endif + +#ifdef SIGUSR2 + SIGNO_CASE(SIGUSR2); +#endif + +#ifdef SIGPIPE + SIGNO_CASE(SIGPIPE); +#endif + +#ifdef SIGALRM + SIGNO_CASE(SIGALRM); +#endif + + SIGNO_CASE(SIGTERM); + +#ifdef SIGCHLD + SIGNO_CASE(SIGCHLD); +#endif + +#ifdef SIGSTKFLT + SIGNO_CASE(SIGSTKFLT); +#endif + +#ifdef SIGCONT + SIGNO_CASE(SIGCONT); +#endif + +#ifdef SIGSTOP + SIGNO_CASE(SIGSTOP); +#endif + +#ifdef SIGTSTP + SIGNO_CASE(SIGTSTP); +#endif + +#ifdef SIGBREAK + SIGNO_CASE(SIGBREAK); +#endif + +#ifdef SIGTTIN + SIGNO_CASE(SIGTTIN); +#endif + +#ifdef SIGTTOU + SIGNO_CASE(SIGTTOU); +#endif + +#ifdef SIGURG + SIGNO_CASE(SIGURG); +#endif + +#ifdef SIGXCPU + SIGNO_CASE(SIGXCPU); +#endif + +#ifdef SIGXFSZ + SIGNO_CASE(SIGXFSZ); +#endif + +#ifdef SIGVTALRM + SIGNO_CASE(SIGVTALRM); +#endif + +#ifdef SIGPROF + SIGNO_CASE(SIGPROF); +#endif + +#ifdef SIGWINCH + SIGNO_CASE(SIGWINCH); +#endif + +#ifdef SIGIO + SIGNO_CASE(SIGIO); +#endif + +#ifdef SIGPOLL +#if SIGPOLL != SIGIO + SIGNO_CASE(SIGPOLL); +#endif +#endif + +#ifdef SIGLOST +#if SIGLOST != SIGABRT + SIGNO_CASE(SIGLOST); +#endif +#endif + +#ifdef SIGPWR +#if SIGPWR != SIGLOST + SIGNO_CASE(SIGPWR); +#endif +#endif + +#ifdef SIGINFO +#if !defined(SIGPWR) || SIGINFO != SIGPWR + SIGNO_CASE(SIGINFO); +#endif +#endif + +#ifdef SIGSYS + SIGNO_CASE(SIGSYS); +#endif + + default: + return ""; + } +} + +} // namespace node diff --git a/src/async_wrap.cc b/src/async_wrap.cc index 9798fc0de8471f..4550312abd1b02 100644 --- a/src/async_wrap.cc +++ b/src/async_wrap.cc @@ -39,7 +39,6 @@ using v8::Integer; using v8::Isolate; using v8::Local; using v8::MaybeLocal; -using v8::NewStringType; using v8::Number; using v8::Object; using v8::ObjectTemplate; @@ -700,70 +699,6 @@ MaybeLocal AsyncWrap::MakeCallback(const Local cb, return ret; } - -/* Public C++ embedder API */ - - -async_id AsyncHooksGetExecutionAsyncId(Isolate* isolate) { - // Environment::GetCurrent() allocates a Local<> handle. - HandleScope handle_scope(isolate); - Environment* env = Environment::GetCurrent(isolate); - if (env == nullptr) return -1; - return env->execution_async_id(); -} - - -async_id AsyncHooksGetTriggerAsyncId(Isolate* isolate) { - // Environment::GetCurrent() allocates a Local<> handle. - HandleScope handle_scope(isolate); - Environment* env = Environment::GetCurrent(isolate); - if (env == nullptr) return -1; - return env->trigger_async_id(); -} - - -async_context EmitAsyncInit(Isolate* isolate, - Local resource, - const char* name, - async_id trigger_async_id) { - HandleScope handle_scope(isolate); - Local type = - String::NewFromUtf8(isolate, name, NewStringType::kInternalized) - .ToLocalChecked(); - return EmitAsyncInit(isolate, resource, type, trigger_async_id); -} - -async_context EmitAsyncInit(Isolate* isolate, - Local resource, - Local name, - async_id trigger_async_id) { - HandleScope handle_scope(isolate); - Environment* env = Environment::GetCurrent(isolate); - CHECK_NOT_NULL(env); - - // Initialize async context struct - if (trigger_async_id == -1) - trigger_async_id = env->get_default_trigger_async_id(); - - async_context context = { - env->new_async_id(), // async_id_ - trigger_async_id // trigger_async_id_ - }; - - // Run init hooks - AsyncWrap::EmitAsyncInit(env, resource, name, context.async_id, - context.trigger_async_id); - - return context; -} - -void EmitAsyncDestroy(Isolate* isolate, async_context asyncContext) { - // Environment::GetCurrent() allocates a Local<> handle. - HandleScope handle_scope(isolate); - AsyncWrap::EmitDestroy( - Environment::GetCurrent(isolate), asyncContext.async_id); -} - std::string AsyncWrap::MemoryInfoName() const { return provider_names[provider_type()]; } diff --git a/src/node.cc b/src/node.cc index b9f4403829963f..745ed83917885e 100644 --- a/src/node.cc +++ b/src/node.cc @@ -119,32 +119,21 @@ using v8::Function; using v8::FunctionCallbackInfo; using v8::HandleScope; using v8::Int32; -using v8::Integer; using v8::Isolate; using v8::Just; using v8::Local; using v8::Locker; using v8::Maybe; using v8::MaybeLocal; -using v8::Message; -using v8::MicrotasksPolicy; using v8::Object; -using v8::ObjectTemplate; using v8::Script; -using v8::ScriptOrigin; using v8::SealHandleScope; using v8::String; -using v8::TracingController; using v8::Undefined; using v8::V8; using v8::Value; namespace per_process { -// Tells whether --prof is passed. -// TODO(joyeecheung): move env->options()->prof_process to -// per_process::cli_options.prof_process and use that instead. -static bool v8_is_profiling = false; - // TODO(joyeecheung): these are no longer necessary. Remove them. // See: https://github.com/nodejs/node/pull/25302#discussion_r244924196 // Isolate on the main thread @@ -163,6 +152,8 @@ bool v8_initialized = false; // node_internals.h // process-relative uptime base, initialized at start-up double prog_start_time; +// Tells whether --prof is passed. +bool v8_is_profiling = false; // node_v8_platform-inl.h struct V8Platform v8_platform; @@ -172,209 +163,6 @@ struct V8Platform v8_platform; static const unsigned kMaxSignal = 32; #endif -const char* signo_string(int signo) { -#define SIGNO_CASE(e) case e: return #e; - switch (signo) { -#ifdef SIGHUP - SIGNO_CASE(SIGHUP); -#endif - -#ifdef SIGINT - SIGNO_CASE(SIGINT); -#endif - -#ifdef SIGQUIT - SIGNO_CASE(SIGQUIT); -#endif - -#ifdef SIGILL - SIGNO_CASE(SIGILL); -#endif - -#ifdef SIGTRAP - SIGNO_CASE(SIGTRAP); -#endif - -#ifdef SIGABRT - SIGNO_CASE(SIGABRT); -#endif - -#ifdef SIGIOT -# if SIGABRT != SIGIOT - SIGNO_CASE(SIGIOT); -# endif -#endif - -#ifdef SIGBUS - SIGNO_CASE(SIGBUS); -#endif - -#ifdef SIGFPE - SIGNO_CASE(SIGFPE); -#endif - -#ifdef SIGKILL - SIGNO_CASE(SIGKILL); -#endif - -#ifdef SIGUSR1 - SIGNO_CASE(SIGUSR1); -#endif - -#ifdef SIGSEGV - SIGNO_CASE(SIGSEGV); -#endif - -#ifdef SIGUSR2 - SIGNO_CASE(SIGUSR2); -#endif - -#ifdef SIGPIPE - SIGNO_CASE(SIGPIPE); -#endif - -#ifdef SIGALRM - SIGNO_CASE(SIGALRM); -#endif - - SIGNO_CASE(SIGTERM); - -#ifdef SIGCHLD - SIGNO_CASE(SIGCHLD); -#endif - -#ifdef SIGSTKFLT - SIGNO_CASE(SIGSTKFLT); -#endif - - -#ifdef SIGCONT - SIGNO_CASE(SIGCONT); -#endif - -#ifdef SIGSTOP - SIGNO_CASE(SIGSTOP); -#endif - -#ifdef SIGTSTP - SIGNO_CASE(SIGTSTP); -#endif - -#ifdef SIGBREAK - SIGNO_CASE(SIGBREAK); -#endif - -#ifdef SIGTTIN - SIGNO_CASE(SIGTTIN); -#endif - -#ifdef SIGTTOU - SIGNO_CASE(SIGTTOU); -#endif - -#ifdef SIGURG - SIGNO_CASE(SIGURG); -#endif - -#ifdef SIGXCPU - SIGNO_CASE(SIGXCPU); -#endif - -#ifdef SIGXFSZ - SIGNO_CASE(SIGXFSZ); -#endif - -#ifdef SIGVTALRM - SIGNO_CASE(SIGVTALRM); -#endif - -#ifdef SIGPROF - SIGNO_CASE(SIGPROF); -#endif - -#ifdef SIGWINCH - SIGNO_CASE(SIGWINCH); -#endif - -#ifdef SIGIO - SIGNO_CASE(SIGIO); -#endif - -#ifdef SIGPOLL -# if SIGPOLL != SIGIO - SIGNO_CASE(SIGPOLL); -# endif -#endif - -#ifdef SIGLOST -# if SIGLOST != SIGABRT - SIGNO_CASE(SIGLOST); -# endif -#endif - -#ifdef SIGPWR -# if SIGPWR != SIGLOST - SIGNO_CASE(SIGPWR); -# endif -#endif - -#ifdef SIGINFO -# if !defined(SIGPWR) || SIGINFO != SIGPWR - SIGNO_CASE(SIGINFO); -# endif -#endif - -#ifdef SIGSYS - SIGNO_CASE(SIGSYS); -#endif - - default: return ""; - } -} - -void* ArrayBufferAllocator::Allocate(size_t size) { - if (zero_fill_field_ || per_process::cli_options->zero_fill_all_buffers) - return UncheckedCalloc(size); - else - return UncheckedMalloc(size); -} - -namespace { - -bool ShouldAbortOnUncaughtException(Isolate* isolate) { - HandleScope scope(isolate); - Environment* env = Environment::GetCurrent(isolate); - return env != nullptr && - env->should_abort_on_uncaught_toggle()[0] && - !env->inside_should_not_abort_on_uncaught_scope(); -} - -} // anonymous namespace - - -void AddPromiseHook(Isolate* isolate, promise_hook_func fn, void* arg) { - Environment* env = Environment::GetCurrent(isolate); - CHECK_NOT_NULL(env); - env->AddPromiseHook(fn, arg); -} - -void AddEnvironmentCleanupHook(Isolate* isolate, - void (*fun)(void* arg), - void* arg) { - Environment* env = Environment::GetCurrent(isolate); - CHECK_NOT_NULL(env); - env->AddCleanupHook(fun, arg); -} - - -void RemoveEnvironmentCleanupHook(Isolate* isolate, - void (*fun)(void* arg), - void* arg) { - Environment* env = Environment::GetCurrent(isolate); - CHECK_NOT_NULL(env); - env->RemoveCleanupHook(fun, arg); -} - static void WaitForInspectorDisconnect(Environment* env) { #if HAVE_INSPECTOR if (env->inspector_agent()->IsActive()) { @@ -402,33 +190,6 @@ void Exit(const FunctionCallbackInfo& args) { env->Exit(code); } -static void OnMessage(Local message, Local error) { - Isolate* isolate = message->GetIsolate(); - switch (message->ErrorLevel()) { - case Isolate::MessageErrorLevel::kMessageWarning: { - Environment* env = Environment::GetCurrent(isolate); - if (!env) { - break; - } - Utf8Value filename(isolate, - message->GetScriptOrigin().ResourceName()); - // (filename):(line) (message) - std::stringstream warning; - warning << *filename; - warning << ":"; - warning << message->GetLineNumber(env->context()).FromMaybe(-1); - warning << " "; - v8::String::Utf8Value msg(isolate, message->Get()); - warning << *msg; - USE(ProcessEmitWarningGeneric(env, warning.str().c_str(), "V8")); - break; - } - case Isolate::MessageErrorLevel::kMessageError: - FatalException(isolate, error, message); - break; - } -} - void SignalExit(int signo) { uv_tty_reset_mode(); #ifdef __FreeBSD__ @@ -969,35 +730,6 @@ void Init(int* argc, argv[i] = strdup(argv_[i].c_str()); } -void RunAtExit(Environment* env) { - env->RunAtExitCallbacks(); -} - - -uv_loop_t* GetCurrentEventLoop(Isolate* isolate) { - HandleScope handle_scope(isolate); - Local context = isolate->GetCurrentContext(); - if (context.IsEmpty()) - return nullptr; - Environment* env = Environment::GetCurrent(context); - if (env == nullptr) - return nullptr; - return env->event_loop(); -} - - -void AtExit(void (*cb)(void* arg), void* arg) { - auto env = Environment::GetThreadLocalEnv(); - AtExit(env, cb, arg); -} - - -void AtExit(Environment* env, void (*cb)(void* arg), void* arg) { - CHECK_NOT_NULL(env); - env->AtExit(cb, arg); -} - - void RunBeforeExit(Environment* env) { env->RunBeforeExitCallbacks(); @@ -1005,155 +737,6 @@ void RunBeforeExit(Environment* env) { EmitBeforeExit(env); } - -void EmitBeforeExit(Environment* env) { - HandleScope handle_scope(env->isolate()); - Context::Scope context_scope(env->context()); - Local exit_code = env->process_object() - ->Get(env->context(), env->exit_code_string()) - .ToLocalChecked() - ->ToInteger(env->context()) - .ToLocalChecked(); - ProcessEmit(env, "beforeExit", exit_code).ToLocalChecked(); -} - -int EmitExit(Environment* env) { - // process.emit('exit') - HandleScope handle_scope(env->isolate()); - Context::Scope context_scope(env->context()); - Local process_object = env->process_object(); - process_object->Set(env->context(), - FIXED_ONE_BYTE_STRING(env->isolate(), "_exiting"), - True(env->isolate())).FromJust(); - - Local exit_code = env->exit_code_string(); - int code = process_object->Get(env->context(), exit_code).ToLocalChecked() - ->Int32Value(env->context()).ToChecked(); - ProcessEmit(env, "exit", Integer::New(env->isolate(), code)); - - // Reload exit code, it may be changed by `emit('exit')` - return process_object->Get(env->context(), exit_code).ToLocalChecked() - ->Int32Value(env->context()).ToChecked(); -} - - -ArrayBufferAllocator* CreateArrayBufferAllocator() { - return new ArrayBufferAllocator(); -} - - -void FreeArrayBufferAllocator(ArrayBufferAllocator* allocator) { - delete allocator; -} - - -IsolateData* CreateIsolateData( - Isolate* isolate, - uv_loop_t* loop, - MultiIsolatePlatform* platform, - ArrayBufferAllocator* allocator) { - return new IsolateData( - isolate, - loop, - platform, - allocator != nullptr ? allocator->zero_fill_field() : nullptr); -} - - -void FreeIsolateData(IsolateData* isolate_data) { - delete isolate_data; -} - - -Environment* CreateEnvironment(IsolateData* isolate_data, - Local context, - int argc, - const char* const* argv, - int exec_argc, - const char* const* exec_argv) { - Isolate* isolate = context->GetIsolate(); - HandleScope handle_scope(isolate); - Context::Scope context_scope(context); - // TODO(addaleax): This is a much better place for parsing per-Environment - // options than the global parse call. - std::vector args(argv, argv + argc); - std::vector exec_args(exec_argv, exec_argv + exec_argc); - Environment* env = new Environment(isolate_data, context); - env->Start(per_process::v8_is_profiling); - env->ProcessCliArgs(args, exec_args); - return env; -} - - -void FreeEnvironment(Environment* env) { - env->RunCleanup(); - delete env; -} - - -Environment* GetCurrentEnvironment(Local context) { - return Environment::GetCurrent(context); -} - - -MultiIsolatePlatform* GetMainThreadMultiIsolatePlatform() { - return per_process::v8_platform.Platform(); -} - - -MultiIsolatePlatform* CreatePlatform( - int thread_pool_size, - node::tracing::TracingController* tracing_controller) { - return new NodePlatform(thread_pool_size, tracing_controller); -} - - -MultiIsolatePlatform* InitializeV8Platform(int thread_pool_size) { - per_process::v8_platform.Initialize(thread_pool_size); - return per_process::v8_platform.Platform(); -} - - -void FreePlatform(MultiIsolatePlatform* platform) { - delete platform; -} - -Local NewContext(Isolate* isolate, - Local object_template) { - Local context = Context::New(isolate, nullptr, object_template); - if (context.IsEmpty()) return context; - HandleScope handle_scope(isolate); - - context->SetEmbedderData( - ContextEmbedderIndex::kAllowWasmCodeGeneration, True(isolate)); - - { - // Run lib/internal/per_context.js - Context::Scope context_scope(context); - - std::vector> parameters = { - FIXED_ONE_BYTE_STRING(isolate, "global")}; - Local arguments[] = {context->Global()}; - MaybeLocal maybe_fn = - per_process::native_module_loader.LookupAndCompile( - context, "internal/per_context", ¶meters, nullptr); - if (maybe_fn.IsEmpty()) { - return Local(); - } - Local fn = maybe_fn.ToLocalChecked(); - MaybeLocal result = - fn->Call(context, Undefined(isolate), arraysize(arguments), arguments); - // Execution failed during context creation. - // TODO(joyeecheung): deprecate this signature and return a MaybeLocal. - if (result.IsEmpty()) { - return Local(); - } - } - - return context; -} - - inline int Start(Isolate* isolate, IsolateData* isolate_data, const std::vector& args, const std::vector& exec_args) { @@ -1235,41 +818,6 @@ inline int Start(Isolate* isolate, IsolateData* isolate_data, return exit_code; } -bool AllowWasmCodeGenerationCallback( - Local context, Local) { - Local wasm_code_gen = - context->GetEmbedderData(ContextEmbedderIndex::kAllowWasmCodeGeneration); - return wasm_code_gen->IsUndefined() || wasm_code_gen->IsTrue(); -} - -Isolate* NewIsolate(ArrayBufferAllocator* allocator, uv_loop_t* event_loop) { - Isolate::CreateParams params; - params.array_buffer_allocator = allocator; -#ifdef NODE_ENABLE_VTUNE_PROFILING - params.code_event_handler = vTune::GetVtuneCodeEventHandler(); -#endif - - Isolate* isolate = Isolate::Allocate(); - if (isolate == nullptr) - return nullptr; - - // Register the isolate on the platform before the isolate gets initialized, - // so that the isolate can access the platform during initialization. - per_process::v8_platform.Platform()->RegisterIsolate(isolate, event_loop); - Isolate::Initialize(isolate, params); - - isolate->AddMessageListenerWithErrorLevel(OnMessage, - Isolate::MessageErrorLevel::kMessageError | - Isolate::MessageErrorLevel::kMessageWarning); - isolate->SetAbortOnUncaughtExceptionCallback(ShouldAbortOnUncaughtException); - isolate->SetMicrotasksPolicy(MicrotasksPolicy::kExplicit); - isolate->SetFatalErrorHandler(OnFatalError); - isolate->SetAllowWasmCodeGenerationCallback(AllowWasmCodeGenerationCallback); - v8::CpuProfiler::UseDetailedSourcePositionsForProfiling(isolate); - - return isolate; -} - inline int Start(uv_loop_t* event_loop, const std::vector& args, const std::vector& exec_args) { diff --git a/src/node_errors.cc b/src/node_errors.cc index 8fb0e0122f542d..42e19f690514ff 100644 --- a/src/node_errors.cc +++ b/src/node_errors.cc @@ -758,19 +758,6 @@ void FatalException(Isolate* isolate, } } -void FatalException(Isolate* isolate, const v8::TryCatch& try_catch) { - // If we try to print out a termination exception, we'd just get 'null', - // so just crashing here with that information seems like a better idea, - // and in particular it seems like we should handle terminations at the call - // site for this function rather than by printing them out somewhere. - CHECK(!try_catch.HasTerminated()); - - HandleScope scope(isolate); - if (!try_catch.IsVerbose()) { - FatalException(isolate, try_catch.Exception(), try_catch.Message()); - } -} - void FatalException(const FunctionCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); Environment* env = Environment::GetCurrent(isolate); diff --git a/src/node_internals.h b/src/node_internals.h index d972e2e5bd5916..b34e6f90e7d28c 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -56,6 +56,7 @@ class NativeModuleLoader; namespace per_process { extern Mutex env_var_mutex; extern double prog_start_time; +extern bool v8_is_profiling; } // namespace per_process // Forward declaration