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:
Joyee Cheung 2019-01-17 03:00:55 +08:00
parent 99c3243b22
commit ca9e24e8b4
No known key found for this signature in database
GPG Key ID: 92B78A53C8303B8D
11 changed files with 557 additions and 535 deletions

View File

@ -363,14 +363,19 @@
],
'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',
@ -390,7 +395,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',

214
src/api/environment.cc Normal file
View 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", &parameters, 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

View File

@ -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<Value> 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

149
src/api/hooks.cc Normal file
View 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
View 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

View File

@ -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;
@ -688,70 +687,6 @@ MaybeLocal<Value> AsyncWrap::MakeCallback(const Local<Function> 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<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 {
return provider_names[provider_type()];
}

View File

@ -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<Value>& args) {
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) {
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> 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<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", &parameters, 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,
const std::vector<std::string>& args,
const std::vector<std::string>& exec_args) {
@ -1235,41 +818,6 @@ inline int Start(Isolate* isolate, IsolateData* isolate_data,
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,
const std::vector<std::string>& args,
const std::vector<std::string>& exec_args) {

View File

@ -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) {
Isolate* isolate = args.GetIsolate();
Environment* env = Environment::GetCurrent(isolate);

View File

@ -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