Skip to content

Commit

Permalink
src: move public C++ APIs into src/api/*.cc
Browse files Browse the repository at this point in the history
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: #25541
Reviewed-By: Gus Caplan <[email protected]>
  • Loading branch information
joyeecheung authored and targos committed Feb 10, 2019
1 parent 0a154ff commit b72ec23
Show file tree
Hide file tree
Showing 11 changed files with 557 additions and 535 deletions.
10 changes: 7 additions & 3 deletions node.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -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',
Expand Down
File renamed without changes.
File renamed without changes.
214 changes: 214 additions & 0 deletions src/api/environment.cc
Original file line number Diff line number Diff line change
@@ -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
14 changes: 14 additions & 0 deletions src/exceptions.cc → src/api/exceptions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace node {

using v8::Exception;
using v8::HandleScope;
using v8::Integer;
using v8::Isolate;
using v8::Local;
Expand Down Expand Up @@ -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
Loading

0 comments on commit b72ec23

Please sign in to comment.