diff --git a/src/env.h b/src/env.h index ace6ae6fcbd..0dd6c36c80a 100644 --- a/src/env.h +++ b/src/env.h @@ -252,6 +252,7 @@ namespace node { V(domain_array, v8::Array) \ V(fs_stats_constructor_function, v8::Function) \ V(gc_info_callback_function, v8::Function) \ + V(handle_close_callback, v8::Function) \ V(module_load_list_array, v8::Array) \ V(pipe_constructor_template, v8::FunctionTemplate) \ V(process_object, v8::Object) \ diff --git a/src/handle_wrap.cc b/src/handle_wrap.cc index 68b6ec3cef8..195d24bf2ff 100644 --- a/src/handle_wrap.cc +++ b/src/handle_wrap.cc @@ -32,11 +32,15 @@ namespace node { using v8::Context; +using v8::Function; using v8::FunctionCallbackInfo; using v8::Handle; using v8::HandleScope; using v8::Local; +using v8::Number; using v8::Object; +using v8::TryCatch; +using v8::Undefined; using v8::Value; // defined in node.cc @@ -130,6 +134,19 @@ void HandleWrap::OnClose(uv_handle_t* handle) { object->SetAlignedPointerInInternalField(0, NULL); wrap->persistent().Reset(); + + Local handle_close_callback = env->handle_close_callback(); + if (handle_close_callback.IsEmpty() == false) { + Local arg = Number::New(env->isolate(), + static_cast(wrap->id())); + TryCatch try_catch; + handle_close_callback->Call(Undefined(env->isolate()), 1, &arg); + if (try_catch.HasCaught()) { + FatalException(env->isolate(), try_catch); + UNREACHABLE(); + } + } + delete wrap; } diff --git a/src/node.cc b/src/node.cc index 886e5787eec..32e97c2f721 100644 --- a/src/node.cc +++ b/src/node.cc @@ -2274,6 +2274,27 @@ static void ProcessTitleSetter(Local property, } +static void GetHandleCloseCallback(Local, + const PropertyCallbackInfo& info) { + Environment* env = Environment::GetCurrent(info.GetIsolate()); + HandleScope scope(env->isolate()); + Local handle_close_callback = env->handle_close_callback(); + if (handle_close_callback.IsEmpty()) return; + info.GetReturnValue().Set(handle_close_callback); +} + + + +static void SetHandleCloseCallback(Local, + Local value, + const PropertyCallbackInfo& info) { + Environment* env = Environment::GetCurrent(info.GetIsolate()); + HandleScope scope(env->isolate()); + env->set_handle_close_callback( + value->IsFunction() ? value.As() : Local()); +} + + static void EnvGetter(Local property, const PropertyCallbackInfo& info) { Environment* env = Environment::GetCurrent(info.GetIsolate()); @@ -2600,6 +2621,11 @@ void SetupProcessObject(Environment* env, env->uv_context_id_pointer(), kExternalFloat64Array, 1); READONLY_PROPERTY(process, "_uvContextId", uv_context_id_obj); + process->SetAccessor( + FIXED_ONE_BYTE_STRING(env->isolate(), "_uvHandleCloseCallback"), + GetHandleCloseCallback, + SetHandleCloseCallback); + process->SetAccessor(env->title_string(), ProcessTitleGetter, ProcessTitleSetter);