1 /*
2 * Copyright (c) 2021 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 <cinttypes>
17
18 #include "ark_native_reference.h"
19
20 #include "native_engine/native_api_internal.h"
21 #include "native_engine/native_utils.h"
22
ArkNativeReference(ArkNativeEngine * engine,napi_value value,uint32_t initialRefcount,bool deleteSelf,NapiNativeFinalize napiCallback,void * data,void * hint,bool isAsyncCall,size_t nativeBindingSize)23 ArkNativeReference::ArkNativeReference(ArkNativeEngine* engine,
24 napi_value value,
25 uint32_t initialRefcount,
26 bool deleteSelf,
27 NapiNativeFinalize napiCallback,
28 void* data,
29 void* hint,
30 bool isAsyncCall,
31 size_t nativeBindingSize)
32 : engine_(engine),
33 value_(engine->GetEcmaVm(), LocalValueFromJsValue(value)),
34 refCount_(initialRefcount),
35 deleteSelf_(deleteSelf),
36 isAsyncCall_(isAsyncCall),
37 napiCallback_(napiCallback),
38 data_(data),
39 hint_(hint),
40 nativeBindingSize_(nativeBindingSize)
41 {
42 ArkNativeReferenceConstructor(initialRefcount, deleteSelf);
43 }
44
ArkNativeReference(ArkNativeEngine * engine,Local<JSValueRef> value,uint32_t initialRefcount,bool deleteSelf,NapiNativeFinalize napiCallback,void * data,void * hint,bool isAsyncCall,size_t nativeBindingSize)45 ArkNativeReference::ArkNativeReference(ArkNativeEngine* engine,
46 Local<JSValueRef> value,
47 uint32_t initialRefcount,
48 bool deleteSelf,
49 NapiNativeFinalize napiCallback,
50 void* data,
51 void* hint,
52 bool isAsyncCall,
53 size_t nativeBindingSize)
54 : engine_(engine),
55 value_(engine->GetEcmaVm(), value),
56 refCount_(initialRefcount),
57 deleteSelf_(deleteSelf),
58 isAsyncCall_(isAsyncCall),
59 napiCallback_(napiCallback),
60 data_(data),
61 hint_(hint),
62 nativeBindingSize_(nativeBindingSize)
63 {
64 ArkNativeReferenceConstructor(initialRefcount, deleteSelf);
65 }
66
~ArkNativeReference()67 ArkNativeReference::~ArkNativeReference()
68 {
69 VALID_ENGINE_CHECK(engine_, engine_, engineId_);
70
71 if (deleteSelf_ && engine_->GetReferenceManager()) {
72 engine_->GetReferenceManager()->ReleaseHandler(this);
73 prev_ = nullptr;
74 next_ = nullptr;
75 }
76 if (value_.IsEmpty()) {
77 return;
78 }
79 hasDelete_ = true;
80 value_.FreeGlobalHandleAddr();
81 FinalizeCallback(FinalizerState::DESTRUCTION);
82 }
83
Ref()84 uint32_t ArkNativeReference::Ref()
85 {
86 ++refCount_;
87 if (refCount_ == 1) {
88 value_.ClearWeak();
89 }
90 return refCount_;
91 }
92
Unref()93 uint32_t ArkNativeReference::Unref()
94 {
95 if (refCount_ == 0) {
96 return refCount_;
97 }
98 --refCount_;
99 if (value_.IsEmpty()) {
100 return refCount_;
101 }
102 if (refCount_ == 0) {
103 value_.SetWeakCallback(reinterpret_cast<void*>(this), FreeGlobalCallBack, NativeFinalizeCallBack);
104 }
105 return refCount_;
106 }
107
Get(NativeEngine * engine)108 napi_value ArkNativeReference::Get(NativeEngine* engine)
109 {
110 if (value_.IsEmpty()) {
111 return nullptr;
112 }
113 VALID_ENGINE_CHECK(engine, engine_, engineId_);
114 Local<JSValueRef> value = value_.ToLocal(engine->GetEcmaVm());
115 return JsValueFromLocalValue(value);
116 }
117
Get()118 napi_value ArkNativeReference::Get()
119 {
120 return Get(engine_);
121 }
122
operator napi_value()123 ArkNativeReference::operator napi_value()
124 {
125 return Get(engine_);
126 }
127
GetData()128 void* ArkNativeReference::GetData()
129 {
130 return data_;
131 }
132
FinalizeCallback(FinalizerState state)133 void ArkNativeReference::FinalizeCallback(FinalizerState state)
134 {
135 if (napiCallback_ != nullptr && !engine_->IsInDestructor()) {
136 if (state == FinalizerState::COLLECTION) {
137 if (isAsyncCall_) {
138 std::pair<void*, void*> pair = std::make_pair(data_, hint_);
139 RefAsyncFinalizer asyncFinalizer = std::make_pair(napiCallback_, pair);
140 engine_->GetPendingAsyncFinalizers().emplace_back(asyncFinalizer);
141 } else {
142 std::tuple<NativeEngine*, void*, void*> tuple = std::make_tuple(engine_, data_, hint_);
143 RefFinalizer finalizer = std::make_pair(napiCallback_, tuple);
144 engine_->GetArkFinalizersPack().AddFinalizer(finalizer, nativeBindingSize_);
145 }
146 } else {
147 napiCallback_(reinterpret_cast<napi_env>(engine_), data_, hint_);
148 }
149 }
150 napiCallback_ = nullptr;
151 data_ = nullptr;
152 hint_ = nullptr;
153 finalRun_ = true;
154
155 if (deleteSelf_ && !hasDelete_) {
156 delete this;
157 }
158 }
159
FreeGlobalCallBack(void * ref)160 void ArkNativeReference::FreeGlobalCallBack(void* ref)
161 {
162 auto that = reinterpret_cast<ArkNativeReference*>(ref);
163 that->value_.FreeGlobalHandleAddr();
164 }
165
NativeFinalizeCallBack(void * ref)166 void ArkNativeReference::NativeFinalizeCallBack(void* ref)
167 {
168 auto that = reinterpret_cast<ArkNativeReference*>(ref);
169 that->FinalizeCallback(FinalizerState::COLLECTION);
170 }
171
SetDeleteSelf()172 void ArkNativeReference::SetDeleteSelf()
173 {
174 deleteSelf_ = true;
175 }
176
GetDeleteSelf() const177 bool ArkNativeReference::GetDeleteSelf() const
178 {
179 return deleteSelf_;
180 }
181
GetRefCount()182 uint32_t ArkNativeReference::GetRefCount()
183 {
184 return refCount_;
185 }
186
GetFinalRun()187 bool ArkNativeReference::GetFinalRun()
188 {
189 return finalRun_;
190 }
191
GetNapiValue()192 napi_value ArkNativeReference::GetNapiValue()
193 {
194 return Get();
195 }
196
ResetFinalizer()197 void ArkNativeReference::ResetFinalizer()
198 {
199 napiCallback_ = nullptr;
200 data_ = nullptr;
201 hint_ = nullptr;
202 }