11cb0ef41Sopenharmony_ci// Copyright Joyent, Inc. and other Node contributors.
21cb0ef41Sopenharmony_ci//
31cb0ef41Sopenharmony_ci// Permission is hereby granted, free of charge, to any person obtaining a
41cb0ef41Sopenharmony_ci// copy of this software and associated documentation files (the
51cb0ef41Sopenharmony_ci// "Software"), to deal in the Software without restriction, including
61cb0ef41Sopenharmony_ci// without limitation the rights to use, copy, modify, merge, publish,
71cb0ef41Sopenharmony_ci// distribute, sublicense, and/or sell copies of the Software, and to permit
81cb0ef41Sopenharmony_ci// persons to whom the Software is furnished to do so, subject to the
91cb0ef41Sopenharmony_ci// following conditions:
101cb0ef41Sopenharmony_ci//
111cb0ef41Sopenharmony_ci// The above copyright notice and this permission notice shall be included
121cb0ef41Sopenharmony_ci// in all copies or substantial portions of the Software.
131cb0ef41Sopenharmony_ci//
141cb0ef41Sopenharmony_ci// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
151cb0ef41Sopenharmony_ci// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
161cb0ef41Sopenharmony_ci// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
171cb0ef41Sopenharmony_ci// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
181cb0ef41Sopenharmony_ci// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
191cb0ef41Sopenharmony_ci// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
201cb0ef41Sopenharmony_ci// USE OR OTHER DEALINGS IN THE SOFTWARE.
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci#include "handle_wrap.h"
231cb0ef41Sopenharmony_ci#include "async_wrap-inl.h"
241cb0ef41Sopenharmony_ci#include "env-inl.h"
251cb0ef41Sopenharmony_ci#include "node_external_reference.h"
261cb0ef41Sopenharmony_ci#include "util-inl.h"
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_cinamespace node {
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ciusing v8::Context;
311cb0ef41Sopenharmony_ciusing v8::FunctionCallbackInfo;
321cb0ef41Sopenharmony_ciusing v8::FunctionTemplate;
331cb0ef41Sopenharmony_ciusing v8::HandleScope;
341cb0ef41Sopenharmony_ciusing v8::Isolate;
351cb0ef41Sopenharmony_ciusing v8::Local;
361cb0ef41Sopenharmony_ciusing v8::Object;
371cb0ef41Sopenharmony_ciusing v8::Value;
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_civoid HandleWrap::Ref(const FunctionCallbackInfo<Value>& args) {
411cb0ef41Sopenharmony_ci  HandleWrap* wrap;
421cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci  if (IsAlive(wrap))
451cb0ef41Sopenharmony_ci    uv_ref(wrap->GetHandle());
461cb0ef41Sopenharmony_ci}
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_civoid HandleWrap::Unref(const FunctionCallbackInfo<Value>& args) {
501cb0ef41Sopenharmony_ci  HandleWrap* wrap;
511cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci  if (IsAlive(wrap))
541cb0ef41Sopenharmony_ci    uv_unref(wrap->GetHandle());
551cb0ef41Sopenharmony_ci}
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_civoid HandleWrap::HasRef(const FunctionCallbackInfo<Value>& args) {
591cb0ef41Sopenharmony_ci  HandleWrap* wrap;
601cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
611cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(HasRef(wrap));
621cb0ef41Sopenharmony_ci}
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_civoid HandleWrap::Close(const FunctionCallbackInfo<Value>& args) {
661cb0ef41Sopenharmony_ci  HandleWrap* wrap;
671cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ci  wrap->Close(args[0]);
701cb0ef41Sopenharmony_ci}
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_civoid HandleWrap::Close(Local<Value> close_callback) {
731cb0ef41Sopenharmony_ci  if (state_ != kInitialized)
741cb0ef41Sopenharmony_ci    return;
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci  uv_close(handle_, OnClose);
771cb0ef41Sopenharmony_ci  state_ = kClosing;
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci  if (!close_callback.IsEmpty() && close_callback->IsFunction() &&
801cb0ef41Sopenharmony_ci      !persistent().IsEmpty()) {
811cb0ef41Sopenharmony_ci    object()->Set(env()->context(),
821cb0ef41Sopenharmony_ci                  env()->handle_onclose_symbol(),
831cb0ef41Sopenharmony_ci                  close_callback).Check();
841cb0ef41Sopenharmony_ci  }
851cb0ef41Sopenharmony_ci}
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_civoid HandleWrap::OnGCCollect() {
891cb0ef41Sopenharmony_ci  // When all references to a HandleWrap are lost and the object is supposed to
901cb0ef41Sopenharmony_ci  // be destroyed, we first call Close() to clean up the underlying libuv
911cb0ef41Sopenharmony_ci  // handle. The OnClose callback then acquires and destroys another reference
921cb0ef41Sopenharmony_ci  // to that object, and when that reference is lost, we perform the default
931cb0ef41Sopenharmony_ci  // action (i.e. destroying `this`).
941cb0ef41Sopenharmony_ci  if (state_ != kClosed) {
951cb0ef41Sopenharmony_ci    Close();
961cb0ef41Sopenharmony_ci  } else {
971cb0ef41Sopenharmony_ci    BaseObject::OnGCCollect();
981cb0ef41Sopenharmony_ci  }
991cb0ef41Sopenharmony_ci}
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_cibool HandleWrap::IsNotIndicativeOfMemoryLeakAtExit() const {
1031cb0ef41Sopenharmony_ci  return IsWeakOrDetached() ||
1041cb0ef41Sopenharmony_ci         !HandleWrap::HasRef(this) ||
1051cb0ef41Sopenharmony_ci         !uv_is_active(GetHandle());
1061cb0ef41Sopenharmony_ci}
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_civoid HandleWrap::MarkAsInitialized() {
1101cb0ef41Sopenharmony_ci  env()->handle_wrap_queue()->PushBack(this);
1111cb0ef41Sopenharmony_ci  state_ = kInitialized;
1121cb0ef41Sopenharmony_ci}
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_civoid HandleWrap::MarkAsUninitialized() {
1161cb0ef41Sopenharmony_ci  handle_wrap_queue_.Remove();
1171cb0ef41Sopenharmony_ci  state_ = kClosed;
1181cb0ef41Sopenharmony_ci}
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci
1211cb0ef41Sopenharmony_ciHandleWrap::HandleWrap(Environment* env,
1221cb0ef41Sopenharmony_ci                       Local<Object> object,
1231cb0ef41Sopenharmony_ci                       uv_handle_t* handle,
1241cb0ef41Sopenharmony_ci                       AsyncWrap::ProviderType provider)
1251cb0ef41Sopenharmony_ci    : AsyncWrap(env, object, provider),
1261cb0ef41Sopenharmony_ci      state_(kInitialized),
1271cb0ef41Sopenharmony_ci      handle_(handle) {
1281cb0ef41Sopenharmony_ci  handle_->data = this;
1291cb0ef41Sopenharmony_ci  HandleScope scope(env->isolate());
1301cb0ef41Sopenharmony_ci  CHECK(env->has_run_bootstrapping_code());
1311cb0ef41Sopenharmony_ci  env->handle_wrap_queue()->PushBack(this);
1321cb0ef41Sopenharmony_ci}
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_civoid HandleWrap::OnClose(uv_handle_t* handle) {
1361cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(handle->data);
1371cb0ef41Sopenharmony_ci  BaseObjectPtr<HandleWrap> wrap { static_cast<HandleWrap*>(handle->data) };
1381cb0ef41Sopenharmony_ci  wrap->Detach();
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_ci  Environment* env = wrap->env();
1411cb0ef41Sopenharmony_ci  HandleScope scope(env->isolate());
1421cb0ef41Sopenharmony_ci  Context::Scope context_scope(env->context());
1431cb0ef41Sopenharmony_ci
1441cb0ef41Sopenharmony_ci  CHECK_EQ(wrap->state_, kClosing);
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci  wrap->state_ = kClosed;
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci  wrap->OnClose();
1491cb0ef41Sopenharmony_ci  wrap->handle_wrap_queue_.Remove();
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci  if (!wrap->persistent().IsEmpty() &&
1521cb0ef41Sopenharmony_ci      wrap->object()->Has(env->context(), env->handle_onclose_symbol())
1531cb0ef41Sopenharmony_ci      .FromMaybe(false)) {
1541cb0ef41Sopenharmony_ci    wrap->MakeCallback(env->handle_onclose_symbol(), 0, nullptr);
1551cb0ef41Sopenharmony_ci  }
1561cb0ef41Sopenharmony_ci}
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ciLocal<FunctionTemplate> HandleWrap::GetConstructorTemplate(Environment* env) {
1591cb0ef41Sopenharmony_ci  Local<FunctionTemplate> tmpl = env->handle_wrap_ctor_template();
1601cb0ef41Sopenharmony_ci  if (tmpl.IsEmpty()) {
1611cb0ef41Sopenharmony_ci    Isolate* isolate = env->isolate();
1621cb0ef41Sopenharmony_ci    tmpl = NewFunctionTemplate(isolate, nullptr);
1631cb0ef41Sopenharmony_ci    tmpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "HandleWrap"));
1641cb0ef41Sopenharmony_ci    tmpl->Inherit(AsyncWrap::GetConstructorTemplate(env));
1651cb0ef41Sopenharmony_ci    SetProtoMethod(isolate, tmpl, "close", HandleWrap::Close);
1661cb0ef41Sopenharmony_ci    SetProtoMethodNoSideEffect(isolate, tmpl, "hasRef", HandleWrap::HasRef);
1671cb0ef41Sopenharmony_ci    SetProtoMethod(isolate, tmpl, "ref", HandleWrap::Ref);
1681cb0ef41Sopenharmony_ci    SetProtoMethod(isolate, tmpl, "unref", HandleWrap::Unref);
1691cb0ef41Sopenharmony_ci    env->set_handle_wrap_ctor_template(tmpl);
1701cb0ef41Sopenharmony_ci  }
1711cb0ef41Sopenharmony_ci  return tmpl;
1721cb0ef41Sopenharmony_ci}
1731cb0ef41Sopenharmony_ci
1741cb0ef41Sopenharmony_civoid HandleWrap::RegisterExternalReferences(
1751cb0ef41Sopenharmony_ci    ExternalReferenceRegistry* registry) {
1761cb0ef41Sopenharmony_ci  registry->Register(HandleWrap::Close);
1771cb0ef41Sopenharmony_ci  registry->Register(HandleWrap::HasRef);
1781cb0ef41Sopenharmony_ci  registry->Register(HandleWrap::Ref);
1791cb0ef41Sopenharmony_ci  registry->Register(HandleWrap::Unref);
1801cb0ef41Sopenharmony_ci}
1811cb0ef41Sopenharmony_ci
1821cb0ef41Sopenharmony_ci}  // namespace node
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_ciNODE_BINDING_EXTERNAL_REFERENCE(handle_wrap,
1851cb0ef41Sopenharmony_ci                                node::HandleWrap::RegisterExternalReferences)
186