| #include "env-inl.h" |
| #include "node_internals.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) { |
| env->RunBeforeExitCallbacks(); |
| |
| 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())) |
| .Check(); |
| |
| 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 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* env = Environment::GetCurrent(isolate); |
| if (env == nullptr) return -1; |
| return env->execution_async_id(); |
| } |
| |
| async_id AsyncHooksGetTriggerAsyncId(Isolate* 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) { |
| DebugSealHandleScope 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) { |
| EmitAsyncDestroy(Environment::GetCurrent(isolate), asyncContext); |
| } |
| |
| void EmitAsyncDestroy(Environment* env, async_context asyncContext) { |
| AsyncWrap::EmitDestroy(env, asyncContext.async_id); |
| } |
| |
| } // namespace node |