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 <me@gus.host>
This commit is contained in:
parent
99c3243b22
commit
ca9e24e8b4
10
node.gyp
10
node.gyp
@ -363,14 +363,19 @@
|
|||||||
],
|
],
|
||||||
|
|
||||||
'sources': [
|
'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/async_wrap.cc',
|
||||||
'src/callback_scope.cc',
|
|
||||||
'src/cares_wrap.cc',
|
'src/cares_wrap.cc',
|
||||||
'src/connect_wrap.cc',
|
'src/connect_wrap.cc',
|
||||||
'src/connection_wrap.cc',
|
'src/connection_wrap.cc',
|
||||||
'src/debug_utils.cc',
|
'src/debug_utils.cc',
|
||||||
'src/env.cc',
|
'src/env.cc',
|
||||||
'src/exceptions.cc',
|
|
||||||
'src/fs_event_wrap.cc',
|
'src/fs_event_wrap.cc',
|
||||||
'src/handle_wrap.cc',
|
'src/handle_wrap.cc',
|
||||||
'src/heap_utils.cc',
|
'src/heap_utils.cc',
|
||||||
@ -390,7 +395,6 @@
|
|||||||
'src/node_contextify.cc',
|
'src/node_contextify.cc',
|
||||||
'src/node_credentials.cc',
|
'src/node_credentials.cc',
|
||||||
'src/node_domain.cc',
|
'src/node_domain.cc',
|
||||||
'src/node_encoding.cc',
|
|
||||||
'src/node_env_var.cc',
|
'src/node_env_var.cc',
|
||||||
'src/node_errors.cc',
|
'src/node_errors.cc',
|
||||||
'src/node_file.cc',
|
'src/node_file.cc',
|
||||||
|
214
src/api/environment.cc
Normal file
214
src/api/environment.cc
Normal file
@ -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> context,
|
||||||
|
Local<String>) {
|
||||||
|
Local<Value> 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> message, Local<Value> 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> 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<std::string> args(argv, argv + argc);
|
||||||
|
std::vector<std::string> 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> 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<Context> NewContext(Isolate* isolate,
|
||||||
|
Local<ObjectTemplate> 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<Local<String>> parameters = {
|
||||||
|
FIXED_ONE_BYTE_STRING(isolate, "global")};
|
||||||
|
Local<Value> arguments[] = {context->Global()};
|
||||||
|
MaybeLocal<Function> maybe_fn =
|
||||||
|
per_process::native_module_loader.LookupAndCompile(
|
||||||
|
context, "internal/per_context", ¶meters, nullptr);
|
||||||
|
if (maybe_fn.IsEmpty()) {
|
||||||
|
return Local<Context>();
|
||||||
|
}
|
||||||
|
Local<Function> fn = maybe_fn.ToLocalChecked();
|
||||||
|
MaybeLocal<Value> 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<Context>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
uv_loop_t* GetCurrentEventLoop(Isolate* isolate) {
|
||||||
|
HandleScope handle_scope(isolate);
|
||||||
|
Local<Context> context = isolate->GetCurrentContext();
|
||||||
|
if (context.IsEmpty()) return nullptr;
|
||||||
|
Environment* env = Environment::GetCurrent(context);
|
||||||
|
if (env == nullptr) return nullptr;
|
||||||
|
return env->event_loop();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace node
|
@ -12,6 +12,7 @@
|
|||||||
namespace node {
|
namespace node {
|
||||||
|
|
||||||
using v8::Exception;
|
using v8::Exception;
|
||||||
|
using v8::HandleScope;
|
||||||
using v8::Integer;
|
using v8::Integer;
|
||||||
using v8::Isolate;
|
using v8::Isolate;
|
||||||
using v8::Local;
|
using v8::Local;
|
||||||
@ -228,4 +229,17 @@ Local<Value> WinapiErrnoException(Isolate* isolate,
|
|||||||
}
|
}
|
||||||
#endif
|
#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
|
} // namespace node
|
149
src/api/hooks.cc
Normal file
149
src/api/hooks.cc
Normal file
@ -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<Value> 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<Object> process_object = env->process_object();
|
||||||
|
process_object
|
||||||
|
->Set(env->context(),
|
||||||
|
FIXED_ONE_BYTE_STRING(env->isolate(), "_exiting"),
|
||||||
|
True(env->isolate()))
|
||||||
|
.FromJust();
|
||||||
|
|
||||||
|
Local<String> 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<Object> resource,
|
||||||
|
const char* name,
|
||||||
|
async_id trigger_async_id) {
|
||||||
|
HandleScope handle_scope(isolate);
|
||||||
|
Local<String> type =
|
||||||
|
String::NewFromUtf8(isolate, name, NewStringType::kInternalized)
|
||||||
|
.ToLocalChecked();
|
||||||
|
return EmitAsyncInit(isolate, resource, type, trigger_async_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
async_context EmitAsyncInit(Isolate* isolate,
|
||||||
|
Local<Object> resource,
|
||||||
|
Local<String> 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
|
170
src/api/utils.cc
Normal file
170
src/api/utils.cc
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
#include "node.h"
|
||||||
|
#include "node_internals.h"
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
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
|
@ -39,7 +39,6 @@ using v8::Integer;
|
|||||||
using v8::Isolate;
|
using v8::Isolate;
|
||||||
using v8::Local;
|
using v8::Local;
|
||||||
using v8::MaybeLocal;
|
using v8::MaybeLocal;
|
||||||
using v8::NewStringType;
|
|
||||||
using v8::Number;
|
using v8::Number;
|
||||||
using v8::Object;
|
using v8::Object;
|
||||||
using v8::ObjectTemplate;
|
using v8::ObjectTemplate;
|
||||||
@ -688,70 +687,6 @@ MaybeLocal<Value> AsyncWrap::MakeCallback(const Local<Function> cb,
|
|||||||
return ret;
|
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<Object> resource,
|
|
||||||
const char* name,
|
|
||||||
async_id trigger_async_id) {
|
|
||||||
HandleScope handle_scope(isolate);
|
|
||||||
Local<String> type =
|
|
||||||
String::NewFromUtf8(isolate, name, NewStringType::kInternalized)
|
|
||||||
.ToLocalChecked();
|
|
||||||
return EmitAsyncInit(isolate, resource, type, trigger_async_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
async_context EmitAsyncInit(Isolate* isolate,
|
|
||||||
Local<Object> resource,
|
|
||||||
Local<String> 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 {
|
std::string AsyncWrap::MemoryInfoName() const {
|
||||||
return provider_names[provider_type()];
|
return provider_names[provider_type()];
|
||||||
}
|
}
|
||||||
|
456
src/node.cc
456
src/node.cc
@ -119,32 +119,21 @@ using v8::Function;
|
|||||||
using v8::FunctionCallbackInfo;
|
using v8::FunctionCallbackInfo;
|
||||||
using v8::HandleScope;
|
using v8::HandleScope;
|
||||||
using v8::Int32;
|
using v8::Int32;
|
||||||
using v8::Integer;
|
|
||||||
using v8::Isolate;
|
using v8::Isolate;
|
||||||
using v8::Just;
|
using v8::Just;
|
||||||
using v8::Local;
|
using v8::Local;
|
||||||
using v8::Locker;
|
using v8::Locker;
|
||||||
using v8::Maybe;
|
using v8::Maybe;
|
||||||
using v8::MaybeLocal;
|
using v8::MaybeLocal;
|
||||||
using v8::Message;
|
|
||||||
using v8::MicrotasksPolicy;
|
|
||||||
using v8::Object;
|
using v8::Object;
|
||||||
using v8::ObjectTemplate;
|
|
||||||
using v8::Script;
|
using v8::Script;
|
||||||
using v8::ScriptOrigin;
|
|
||||||
using v8::SealHandleScope;
|
using v8::SealHandleScope;
|
||||||
using v8::String;
|
using v8::String;
|
||||||
using v8::TracingController;
|
|
||||||
using v8::Undefined;
|
using v8::Undefined;
|
||||||
using v8::V8;
|
using v8::V8;
|
||||||
using v8::Value;
|
using v8::Value;
|
||||||
|
|
||||||
namespace per_process {
|
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.
|
// TODO(joyeecheung): these are no longer necessary. Remove them.
|
||||||
// See: https://github.com/nodejs/node/pull/25302#discussion_r244924196
|
// See: https://github.com/nodejs/node/pull/25302#discussion_r244924196
|
||||||
// Isolate on the main thread
|
// Isolate on the main thread
|
||||||
@ -163,6 +152,8 @@ bool v8_initialized = false;
|
|||||||
// node_internals.h
|
// node_internals.h
|
||||||
// process-relative uptime base, initialized at start-up
|
// process-relative uptime base, initialized at start-up
|
||||||
double prog_start_time;
|
double prog_start_time;
|
||||||
|
// Tells whether --prof is passed.
|
||||||
|
bool v8_is_profiling = false;
|
||||||
|
|
||||||
// node_v8_platform-inl.h
|
// node_v8_platform-inl.h
|
||||||
struct V8Platform v8_platform;
|
struct V8Platform v8_platform;
|
||||||
@ -172,209 +163,6 @@ struct V8Platform v8_platform;
|
|||||||
static const unsigned kMaxSignal = 32;
|
static const unsigned kMaxSignal = 32;
|
||||||
#endif
|
#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) {
|
static void WaitForInspectorDisconnect(Environment* env) {
|
||||||
#if HAVE_INSPECTOR
|
#if HAVE_INSPECTOR
|
||||||
if (env->inspector_agent()->IsActive()) {
|
if (env->inspector_agent()->IsActive()) {
|
||||||
@ -402,33 +190,6 @@ void Exit(const FunctionCallbackInfo<Value>& args) {
|
|||||||
env->Exit(code);
|
env->Exit(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OnMessage(Local<Message> message, Local<Value> 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) {
|
void SignalExit(int signo) {
|
||||||
uv_tty_reset_mode();
|
uv_tty_reset_mode();
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
@ -969,35 +730,6 @@ void Init(int* argc,
|
|||||||
argv[i] = strdup(argv_[i].c_str());
|
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> 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) {
|
void RunBeforeExit(Environment* env) {
|
||||||
env->RunBeforeExitCallbacks();
|
env->RunBeforeExitCallbacks();
|
||||||
|
|
||||||
@ -1005,155 +737,6 @@ void RunBeforeExit(Environment* env) {
|
|||||||
EmitBeforeExit(env);
|
EmitBeforeExit(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void EmitBeforeExit(Environment* env) {
|
|
||||||
HandleScope handle_scope(env->isolate());
|
|
||||||
Context::Scope context_scope(env->context());
|
|
||||||
Local<Value> 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<Object> process_object = env->process_object();
|
|
||||||
process_object->Set(env->context(),
|
|
||||||
FIXED_ONE_BYTE_STRING(env->isolate(), "_exiting"),
|
|
||||||
True(env->isolate())).FromJust();
|
|
||||||
|
|
||||||
Local<String> 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> 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<std::string> args(argv, argv + argc);
|
|
||||||
std::vector<std::string> 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> 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<Context> NewContext(Isolate* isolate,
|
|
||||||
Local<ObjectTemplate> object_template) {
|
|
||||||
Local<Context> 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<Local<String>> parameters = {
|
|
||||||
FIXED_ONE_BYTE_STRING(isolate, "global")};
|
|
||||||
Local<Value> arguments[] = {context->Global()};
|
|
||||||
MaybeLocal<Function> maybe_fn =
|
|
||||||
per_process::native_module_loader.LookupAndCompile(
|
|
||||||
context, "internal/per_context", ¶meters, nullptr);
|
|
||||||
if (maybe_fn.IsEmpty()) {
|
|
||||||
return Local<Context>();
|
|
||||||
}
|
|
||||||
Local<Function> fn = maybe_fn.ToLocalChecked();
|
|
||||||
MaybeLocal<Value> 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<Context>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline int Start(Isolate* isolate, IsolateData* isolate_data,
|
inline int Start(Isolate* isolate, IsolateData* isolate_data,
|
||||||
const std::vector<std::string>& args,
|
const std::vector<std::string>& args,
|
||||||
const std::vector<std::string>& exec_args) {
|
const std::vector<std::string>& exec_args) {
|
||||||
@ -1235,41 +818,6 @@ inline int Start(Isolate* isolate, IsolateData* isolate_data,
|
|||||||
return exit_code;
|
return exit_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AllowWasmCodeGenerationCallback(
|
|
||||||
Local<Context> context, Local<String>) {
|
|
||||||
Local<Value> 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,
|
inline int Start(uv_loop_t* event_loop,
|
||||||
const std::vector<std::string>& args,
|
const std::vector<std::string>& args,
|
||||||
const std::vector<std::string>& exec_args) {
|
const std::vector<std::string>& exec_args) {
|
||||||
|
@ -763,19 +763,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<Value>& args) {
|
void FatalException(const FunctionCallbackInfo<Value>& args) {
|
||||||
Isolate* isolate = args.GetIsolate();
|
Isolate* isolate = args.GetIsolate();
|
||||||
Environment* env = Environment::GetCurrent(isolate);
|
Environment* env = Environment::GetCurrent(isolate);
|
||||||
|
@ -56,6 +56,7 @@ class NativeModuleLoader;
|
|||||||
namespace per_process {
|
namespace per_process {
|
||||||
extern Mutex env_var_mutex;
|
extern Mutex env_var_mutex;
|
||||||
extern double prog_start_time;
|
extern double prog_start_time;
|
||||||
|
extern bool v8_is_profiling;
|
||||||
} // namespace per_process
|
} // namespace per_process
|
||||||
|
|
||||||
// Forward declaration
|
// Forward declaration
|
||||||
|
Loading…
x
Reference in New Issue
Block a user