1 /*
2 * Copyright (C) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "strong_ref.h"
17
18 namespace NapiApi {
19
StrongRef(napi_env env,napi_value obj)20 StrongRef::StrongRef(napi_env env, napi_value obj)
21 {
22 if (env && obj) {
23 env_ = env;
24 napi_create_reference(env_, obj, 1, &ref_);
25 }
26 }
27
StrongRef(napi_env env,napi_ref ref)28 StrongRef::StrongRef(napi_env env, napi_ref ref)
29 {
30 if (env && ref) {
31 env_ = env;
32 ref_ = ref;
33 Ref();
34 }
35 }
36
StrongRef(const NapiApi::Object & obj)37 StrongRef::StrongRef(const NapiApi::Object& obj)
38 {
39 if (obj) {
40 env_ = obj.GetEnv();
41 napi_create_reference(env_, obj.ToNapiValue(), 1, &ref_);
42 }
43 }
44
StrongRef(const NapiApi::Value<NapiApi::Object> objValue)45 StrongRef::StrongRef(const NapiApi::Value<NapiApi::Object> objValue)
46 : StrongRef(objValue.GetEnv(), objValue.ToNapiValue())
47 {}
48
StrongRef(const NapiApi::StrongRef & ref)49 StrongRef::StrongRef(const NapiApi::StrongRef& ref)
50 {
51 if (!ref.IsEmpty()) {
52 env_ = ref.env_;
53 ref_ = ref.ref_;
54 Ref();
55 }
56 }
57
StrongRef(NapiApi::StrongRef && ref)58 StrongRef::StrongRef(NapiApi::StrongRef&& ref) noexcept
59 {
60 if (!ref.IsEmpty()) {
61 env_ = ref.env_;
62 ref_ = ref.ref_;
63 ref.env_ = nullptr;
64 ref.ref_ = nullptr;
65 }
66 }
67
operator =(const NapiApi::StrongRef & ref)68 StrongRef& StrongRef::operator=(const NapiApi::StrongRef& ref)
69 {
70 if (&ref != this) {
71 Reset();
72 if (!ref.IsEmpty()) {
73 env_ = ref.env_;
74 ref_ = ref.ref_;
75 Ref();
76 }
77 }
78 return *this;
79 }
80
operator =(NapiApi::StrongRef && ref)81 StrongRef& StrongRef::operator=(NapiApi::StrongRef&& ref) noexcept
82 {
83 if (&ref != this) {
84 Reset();
85 env_ = ref.env_;
86 ref_ = ref.ref_;
87 ref.env_ = nullptr;
88 ref.ref_ = nullptr;
89 }
90 return *this;
91 }
92
~StrongRef()93 StrongRef::~StrongRef()
94 {
95 if (!IsEmpty()) {
96 Reset();
97 }
98 }
99
Reset()100 void StrongRef::Reset()
101 {
102 if (IsEmpty()) {
103 return;
104 }
105 uint32_t cnt;
106 napi_status stat = napi_reference_unref(env_, ref_, &cnt);
107 if (stat != napi_ok) {
108 return;
109 }
110 if (cnt == 0) {
111 // that was the last reference.
112 napi_delete_reference(env_, ref_);
113 }
114 env_ = nullptr;
115 ref_ = nullptr;
116 }
117
IsEmpty() const118 bool StrongRef::IsEmpty() const
119 {
120 return !(env_ && ref_);
121 }
122
GetEnv() const123 napi_env StrongRef::GetEnv() const
124 {
125 return env_;
126 }
127
GetValue() const128 napi_value StrongRef::GetValue() const
129 {
130 if (IsEmpty()) {
131 return {};
132 }
133 napi_value value;
134 napi_get_reference_value(env_, ref_, &value);
135 return value;
136 }
137
GetObject() const138 NapiApi::Object StrongRef::GetObject() const
139 {
140 return NapiApi::Object(env_, (napi_value)GetValue());
141 }
142
GetRefCount() const143 uint32_t StrongRef::GetRefCount() const
144 {
145 // this is racy, but for debug use "fine"
146 if (!IsEmpty()) {
147 uint32_t cnt;
148 napi_reference_ref(env_, ref_, &cnt);
149 napi_reference_unref(env_, ref_, &cnt);
150 return cnt;
151 }
152 return 0;
153 }
154
Ref()155 void StrongRef::Ref()
156 {
157 uint32_t cnt;
158 napi_status stat = napi_reference_ref(env_, ref_, &cnt);
159 }
160
161 } // namespace NapiApi
162