#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