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 "ark_native_engine.h"
17
18 #include "ark_native_reference.h"
19
20 #ifdef ENABLE_CONTAINER_SCOPE
21 #include "core/common/container_scope.h"
22 #endif
23
24 #include "utils/log.h"
25
ArkNativeReference(ArkNativeEngine * engine,NativeValue * value,uint32_t initialRefcount,bool deleteSelf,NativeFinalize callback,void * data,void * hint)26 ArkNativeReference::ArkNativeReference(ArkNativeEngine* engine,
27 NativeValue* value,
28 uint32_t initialRefcount,
29 bool deleteSelf,
30 NativeFinalize callback,
31 void* data,
32 void* hint)
33 : engine_(engine),
34 value_(Global<JSValueRef>(engine->GetEcmaVm(), JSValueRef::Undefined(engine->GetEcmaVm()))),
35 refCount_(initialRefcount),
36 deleteSelf_(deleteSelf),
37 callback_(callback),
38 data_(data),
39 hint_(hint)
40 {
41 Global<JSValueRef> oldValue = *value;
42 auto vm = engine->GetEcmaVm();
43 LocalScope scope(vm);
44 Global<JSValueRef> newValue(vm, oldValue.ToLocal(vm));
45 value_ = newValue;
46 if (initialRefcount == 0) {
47 value_.SetWeakCallback(reinterpret_cast<void*>(this), FirstPassCallBack, SecondPassCallBack);
48 }
49
50 #ifdef ENABLE_CONTAINER_SCOPE
51 scopeId_ = OHOS::Ace::ContainerScope::CurrentId();
52 #endif
53
54 if (deleteSelf) {
55 NativeReferenceManager* referenceManager = engine->GetReferenceManager();
56 if (referenceManager != nullptr) {
57 referenceManager->CreateHandler(this);
58 }
59 }
60 }
61
~ArkNativeReference()62 ArkNativeReference::~ArkNativeReference()
63 {
64 if (deleteSelf_ && engine_->GetReferenceManager()) {
65 engine_->GetReferenceManager()->ReleaseHandler(this);
66 }
67 if (value_.IsEmpty()) {
68 return;
69 }
70 hasDelete_ = true;
71 value_.FreeGlobalHandleAddr();
72 FinalizeCallback();
73 }
74
Ref()75 uint32_t ArkNativeReference::Ref()
76 {
77 ++refCount_;
78 if (refCount_ == 1) {
79 value_.ClearWeak();
80 }
81 return refCount_;
82 }
83
Unref()84 uint32_t ArkNativeReference::Unref()
85 {
86 if (refCount_ == 0) {
87 return refCount_;
88 }
89 --refCount_;
90 if (value_.IsEmpty()) {
91 return refCount_;
92 }
93 if (refCount_ == 0) {
94 value_.SetWeakCallback(reinterpret_cast<void*>(this), FirstPassCallBack, SecondPassCallBack);
95 }
96 return refCount_;
97 }
98
Get()99 NativeValue* ArkNativeReference::Get()
100 {
101 if (value_.IsEmpty()) {
102 return nullptr;
103 }
104 auto vm = engine_->GetEcmaVm();
105 LocalScope scope(vm);
106 Local<JSValueRef> value = value_.ToLocal(vm);
107 #ifdef ENABLE_CONTAINER_SCOPE
108 OHOS::Ace::ContainerScope containerScope(scopeId_);
109 #endif
110 return ArkNativeEngine::ArkValueToNativeValue(engine_, value);
111 }
112
operator NativeValue*()113 ArkNativeReference::operator NativeValue*()
114 {
115 return Get();
116 }
117
GetData()118 void* ArkNativeReference::GetData()
119 {
120 return data_;
121 }
122
FinalizeCallback()123 void ArkNativeReference::FinalizeCallback()
124 {
125 if (callback_ != nullptr) {
126 callback_(engine_, data_, hint_);
127 }
128 callback_ = nullptr;
129 data_ = nullptr;
130 hint_ = nullptr;
131
132 if (deleteSelf_ && !hasDelete_) {
133 delete this;
134 }
135 }
136
FirstPassCallBack(void * ref)137 void ArkNativeReference::FirstPassCallBack(void* ref)
138 {
139 auto that = reinterpret_cast<ArkNativeReference*>(ref);
140 that->value_.FreeGlobalHandleAddr();
141 }
142
SecondPassCallBack(void * ref)143 void ArkNativeReference::SecondPassCallBack(void* ref)
144 {
145 auto that = reinterpret_cast<ArkNativeReference*>(ref);
146 that->FinalizeCallback();
147 }
148