• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "frameworks/base/utils/string_utils.h"
17#include "frameworks/bridge/js_frontend/engine/jsi/ark_js_runtime.h"
18#include "frameworks/bridge/declarative_frontend/engine/jsi/jsi_ref.h"
19#include "frameworks/bridge/declarative_frontend/engine/jsi/jsi_types.h"
20
21namespace OHOS::Ace::Framework {
22
23template<typename T>
24JsiType<T>::JsiType(panda::Local<T> val)
25{
26    if (!val.IsEmpty()) {
27        auto runtime = std::static_pointer_cast<ArkJSRuntime>(JsiDeclarativeEngineInstance::GetCurrentRuntime());
28        handle_ = panda::CopyableGlobal(runtime->GetEcmaVm(), val);
29    }
30}
31
32template<typename T>
33JsiType<T>::JsiType(const EcmaVM *vm, panda::Local<T> val)
34{
35    if (!val.IsEmpty()) {
36        handle_ = panda::CopyableGlobal(vm, val);
37    }
38}
39
40template<typename T>
41template<typename S>
42JsiType<T>::JsiType(panda::Local<S> val)
43{
44    if (!val.IsEmpty()) {
45        auto runtime = std::static_pointer_cast<ArkJSRuntime>(JsiDeclarativeEngineInstance::GetCurrentRuntime());
46        handle_ = panda::CopyableGlobal(runtime->GetEcmaVm(), val);
47    }
48}
49
50template<typename T>
51JsiType<T>::JsiType(const panda::CopyableGlobal<T>& other) : handle_(other)
52{
53}
54
55template<typename T>
56JsiType<T>::JsiType(const JsiType<T>& rhs) : handle_(rhs.handle_)
57{
58}
59
60template<typename T>
61JsiType<T>::JsiType(JsiType<T>&& rhs) : handle_(std::move(rhs.handle_))
62{
63}
64
65template<typename T>
66JsiType<T>& JsiType<T>::operator=(const JsiType<T>& rhs)
67{
68    handle_ = rhs.handle_;
69    return *this;
70}
71
72template<typename T>
73JsiType<T>& JsiType<T>::operator=(JsiType<T>&& rhs)
74{
75    handle_ = std::move(rhs.handle_);
76    return *this;
77}
78
79template<typename T>
80void JsiType<T>::SetWeakCallback(void *ref, panda::WeakRefClearCallBack callback)
81{
82    if (!handle_.IsEmpty()) {
83        handle_.SetWeakCallback(ref, callback, nullptr);
84    }
85}
86
87template<typename T>
88const EcmaVM* JsiType<T>::GetEcmaVM() const
89{
90    return handle_.GetEcmaVM();
91}
92
93template<typename T>
94const panda::CopyableGlobal<T>& JsiType<T>::GetHandle() const
95{
96    return handle_;
97}
98
99template<typename T>
100panda::Local<T> JsiType<T>::GetLocalHandle() const
101{
102    return handle_.ToLocal();
103}
104
105template<typename T>
106bool JsiType<T>::IsEmpty() const
107{
108    return handle_.IsEmpty();
109}
110
111template<typename T>
112bool JsiType<T>::IsWeak() const
113{
114    return handle_.IsWeak();
115}
116
117template<typename T>
118void JsiType<T>::Reset()
119{
120    handle_.Reset();
121}
122
123template<typename T>
124const panda::CopyableGlobal<T>& JsiType<T>::operator->() const
125{
126    return handle_;
127}
128
129template<typename T>
130JsiType<T>::operator panda::CopyableGlobal<T>() const
131{
132    return handle_;
133}
134
135template<typename T>
136template<class... Args>
137JsiType<T> JsiType<T>::New(Args&&... args)
138{
139    auto runtime = std::static_pointer_cast<ArkJSRuntime>(JsiDeclarativeEngineInstance::GetCurrentRuntime());
140    return JsiType<T>(T::New(runtime->GetEcmaVm(), std::forward<Args>(args)...));
141}
142
143template<typename T>
144T JsiValue::ToNumber() const
145{
146    if (ACE_UNLIKELY(SystemProperties::DetectJsObjTypeConvertion() && !IsNumber())) {
147        LOGF_ABORT("bad call to ToNumber.");
148    }
149    return JsiValueConvertor::fromJsiValue<T>(GetEcmaVM(), GetLocalHandle());
150}
151
152template<typename T>
153T* JsiObject::Unwrap() const
154{
155    if (GetHandle()->GetNativePointerFieldCount(GetEcmaVM()) < 1) {
156        return nullptr;
157    }
158    return static_cast<T*>(GetHandle()->GetNativePointerField(GetEcmaVM(), INSTANCE));
159}
160
161template<typename T>
162void JsiObject::Wrap(T* data) const
163{
164    GetHandle()->SetNativePointerField(GetEcmaVM(), INSTANCE, static_cast<void*>(data));
165}
166
167template<typename T>
168void JsiObject::SetProperty(const char* prop, T value) const
169{
170    auto stringRef = panda::StringRef::NewFromUtf8(GetEcmaVM(), prop);
171    GetHandle()->Set(GetEcmaVM(), stringRef, JsiValueConvertor::toJsiValueWithVM<T>(GetEcmaVM(), value));
172}
173
174template<typename T>
175void JsiObject::SetProperty(int32_t propertyIndex, T value) const
176{
177    Local<StringRef> stringRef = panda::ExternalStringCache::GetCachedString(GetEcmaVM(), propertyIndex);
178    GetHandle()->Set(GetEcmaVM(), stringRef, JsiValueConvertor::toJsiValueWithVM<T>(GetEcmaVM(), value));
179}
180
181template<typename T>
182T JsiObject::GetPropertyValue(const char* prop, T defaultValue) const
183{
184    static_assert(!std::is_const_v<T> && !std::is_reference_v<T>,
185        "Cannot convert value to reference or cv-qualified types!");
186
187    const EcmaVM* vm = GetEcmaVM();
188    Local<StringRef> stringRef = panda::StringRef::NewFromUtf8(vm, prop);
189    Local<JSValueRef> valueRef = GetHandle()->Get(vm, stringRef);
190    if constexpr (std::is_same<T, bool>::value) {
191        return valueRef->IsBoolean() ? valueRef->BooleaValue(vm) : defaultValue;
192    } else if constexpr (std::is_arithmetic<T>::value) {
193        return valueRef->IsNumber() ? JsiValueConvertor::fromJsiValue<T>(vm, valueRef) : defaultValue;
194    } else if constexpr (std::is_same_v<T, std::string>) {
195        return valueRef->IsString(vm) ? valueRef->ToString(vm)->ToString(vm) : defaultValue;
196    } else {
197        LOGW("Get property value failed.");
198    }
199    return defaultValue;
200}
201
202template<typename T>
203T JsiObject::GetPropertyValue(int32_t propertyIndex, T defaultValue) const
204{
205    static_assert(!std::is_const_v<T> && !std::is_reference_v<T>,
206        "Cannot convert value to reference or cv-qualified types!");
207
208    const EcmaVM* vm = GetEcmaVM();
209    Local<StringRef> stringRef = panda::ExternalStringCache::GetCachedString(vm, propertyIndex);
210    Local<JSValueRef> valueRef = GetHandle()->Get(vm, stringRef);
211    if constexpr (std::is_same<T, bool>::value) {
212        return valueRef->IsBoolean() ? valueRef->BooleaValue(vm) : defaultValue;
213    } else if constexpr (std::is_arithmetic<T>::value) {
214        return valueRef->IsNumber() ? JsiValueConvertor::fromJsiValue<T>(vm, valueRef) : defaultValue;
215    } else if constexpr (std::is_same_v<T, std::string>) {
216        return valueRef->IsString(vm) ? valueRef->ToString(vm)->ToString(vm) : defaultValue;
217    } else {
218        LOGW("Get property value failed.");
219    }
220    return defaultValue;
221}
222
223template<typename T>
224void JsiCallbackInfo::SetReturnValue(T* instance) const
225{
226    retVal_ = instance;
227}
228
229template<typename T>
230void JsiCallbackInfo::SetReturnValue(JsiRef<T> val) const
231{
232    retVal_ = panda::CopyableGlobal<panda::JSValueRef>(val.Get().GetHandle());
233}
234
235template<typename T>
236T* JsiCallbackInfo::UnwrapArg(size_t index) const
237{
238    auto arg = info_->GetCallArgRef(index);
239    if (arg.IsEmpty() || !arg->IsObject(info_->GetVM())) {
240        return nullptr;
241    }
242    return static_cast<T*>(arg->ToEcmaObject(info_->GetVM())->GetNativePointerField(info_->GetVM(), 0));
243}
244
245template<typename... Args>
246void JsiException::Throw(const char* format, Args... args)
247{
248    const std::string str = StringUtils::FormatString(format, args...);
249    auto runtime = std::static_pointer_cast<ArkJSRuntime>(JsiDeclarativeEngineInstance::GetCurrentRuntime());
250    auto vm = runtime->GetEcmaVm();
251    panda::JSNApi::ThrowException(vm, panda::Exception::Error(vm, panda::StringRef::NewFromUtf8(vm, str.c_str())));
252}
253
254template<typename... Args>
255void JsiException::Throw(int32_t code, const char* format, Args... args)
256{
257    const std::string str = StringUtils::FormatString(format, args...);
258    auto runtime = std::static_pointer_cast<ArkJSRuntime>(JsiDeclarativeEngineInstance::GetCurrentRuntime());
259    auto vm = runtime->GetEcmaVm();
260    LocalScope scope(vm);
261    Local<JSValueRef> error(JSValueRef::Undefined(vm));
262    error = panda::Exception::Error(vm, StringRef::NewFromUtf8(vm, str.c_str()));
263    Local<JSValueRef> codeKey = StringRef::NewFromUtf8(vm, "code");
264    Local<JSValueRef> codeValue = StringRef::NewFromUtf8(vm, std::to_string(code).c_str());
265    Local<ObjectRef> errorObj(error);
266    errorObj->Set(vm, codeKey, codeValue);
267    panda::JSNApi::ThrowException(vm, error);
268}
269
270template<typename... Args>
271void JsiException::ThrowRangeError(const char* format, Args... args)
272{
273    const std::string str = StringUtils::FormatString(format, args...);
274    auto runtime = std::static_pointer_cast<ArkJSRuntime>(JsiDeclarativeEngineInstance::GetCurrentRuntime());
275    auto vm = runtime->GetEcmaVm();
276    panda::JSNApi::ThrowException(vm, panda::Exception::RangeError(vm, panda::StringRef::NewFromUtf8(vm, str.c_str())));
277}
278
279template<typename... Args>
280void JsiException::ThrowReferenceError(const char* format, Args... args)
281{
282    const std::string str = StringUtils::FormatString(format, args...);
283    auto runtime = std::static_pointer_cast<ArkJSRuntime>(JsiDeclarativeEngineInstance::GetCurrentRuntime());
284    auto vm = runtime->GetEcmaVm();
285    panda::JSNApi::ThrowException(
286        vm, panda::Exception::ReferenceError(vm, panda::StringRef::NewFromUtf8(vm, str.c_str())));
287}
288
289template<typename... Args>
290void JsiException::ThrowSyntaxError(const char* format, Args... args)
291{
292    const std::string str = StringUtils::FormatString(format, args...);
293    auto runtime = std::static_pointer_cast<ArkJSRuntime>(JsiDeclarativeEngineInstance::GetCurrentRuntime());
294    auto vm = runtime->GetEcmaVm();
295    panda::JSNApi::ThrowException(
296        vm, panda::Exception::SyntaxError(vm, panda::StringRef::NewFromUtf8(vm, str.c_str())));
297}
298
299template<typename... Args>
300void JsiException::ThrowTypeError(const char* format, Args... args)
301{
302    const std::string str = StringUtils::FormatString(format, args...);
303    auto runtime = std::static_pointer_cast<ArkJSRuntime>(JsiDeclarativeEngineInstance::GetCurrentRuntime());
304    auto vm = runtime->GetEcmaVm();
305    panda::JSNApi::ThrowException(vm, panda::Exception::TypeError(vm, panda::StringRef::NewFromUtf8(vm, str.c_str())));
306}
307
308template<typename... Args>
309void JsiException::ThrowEvalError(const char* format, Args... args)
310{
311    const std::string str = StringUtils::FormatString(format, args...);
312    auto runtime = std::static_pointer_cast<ArkJSRuntime>(JsiDeclarativeEngineInstance::GetCurrentRuntime());
313    auto vm = runtime->GetEcmaVm();
314    panda::JSNApi::ThrowException(vm, panda::Exception::EvalError(vm, panda::StringRef::NewFromUtf8(vm, str.c_str())));
315}
316} // namespace OHOS::Ace::Framework
317