• 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>
33template<typename S>
34JsiType<T>::JsiType(panda::Local<S> val)
35{
36    if (!val.IsEmpty()) {
37        auto runtime = std::static_pointer_cast<ArkJSRuntime>(JsiDeclarativeEngineInstance::GetCurrentRuntime());
38        handle_ = panda::CopyableGlobal(runtime->GetEcmaVm(), val);
39    }
40}
41
42template<typename T>
43JsiType<T>::JsiType(const panda::CopyableGlobal<T>& other) : handle_(other)
44{
45}
46
47template<typename T>
48JsiType<T>::JsiType(const JsiType<T>& rhs) : handle_(rhs.handle_)
49{
50}
51
52template<typename T>
53JsiType<T>::JsiType(JsiType<T>&& rhs) : handle_(std::move(rhs.handle_))
54{
55}
56
57template<typename T>
58JsiType<T>& JsiType<T>::operator=(const JsiType<T>& rhs)
59{
60    handle_ = rhs.handle_;
61    return *this;
62}
63
64template<typename T>
65JsiType<T>& JsiType<T>::operator=(JsiType<T>&& rhs)
66{
67    handle_ = std::move(rhs.handle_);
68    return *this;
69}
70
71template<typename T>
72void JsiType<T>::SetWeakCallback(void *ref, panda::WeakRefClearCallBack callback)
73{
74    if (!handle_.IsEmpty()) {
75        handle_.SetWeakCallback(ref, callback, nullptr);
76    }
77}
78
79template<typename T>
80const EcmaVM* JsiType<T>::GetEcmaVM() const
81{
82    return handle_.GetEcmaVM();
83}
84
85template<typename T>
86const panda::CopyableGlobal<T>& JsiType<T>::GetHandle() const
87{
88    return handle_;
89}
90
91template<typename T>
92panda::Local<T> JsiType<T>::GetLocalHandle() const
93{
94    return handle_.ToLocal();
95}
96
97template<typename T>
98bool JsiType<T>::IsEmpty() const
99{
100    return handle_.IsEmpty();
101}
102
103template<typename T>
104bool JsiType<T>::IsWeak() const
105{
106    return handle_.IsWeak();
107}
108
109template<typename T>
110void JsiType<T>::Reset()
111{
112    handle_.Reset();
113}
114
115template<typename T>
116const panda::CopyableGlobal<T>& JsiType<T>::operator->() const
117{
118    return handle_;
119}
120
121template<typename T>
122JsiType<T>::operator panda::CopyableGlobal<T>() const
123{
124    return handle_;
125}
126
127template<typename T>
128template<class... Args>
129JsiType<T> JsiType<T>::New(Args&&... args)
130{
131    auto runtime = std::static_pointer_cast<ArkJSRuntime>(JsiDeclarativeEngineInstance::GetCurrentRuntime());
132    return JsiType<T>(T::New(runtime->GetEcmaVm(), std::forward<Args>(args)...));
133}
134
135template<typename T>
136T JsiValue::ToNumber() const
137{
138    return JsiValueConvertor::fromJsiValue<T>(GetEcmaVM(), GetLocalHandle());
139}
140
141template<typename T>
142T* JsiObject::Unwrap() const
143{
144    if (GetHandle()->GetNativePointerFieldCount() < 1) {
145        return nullptr;
146    }
147    return static_cast<T*>(GetHandle()->GetNativePointerField(INSTANCE));
148}
149
150template<typename T>
151void JsiObject::Wrap(T* data) const
152{
153    GetHandle()->SetNativePointerField(GetEcmaVM(), INSTANCE, static_cast<void*>(data));
154}
155
156template<typename T>
157void JsiObject::SetProperty(const char* prop, T value) const
158{
159    auto stringRef = panda::StringRef::NewFromUtf8(GetEcmaVM(), prop);
160    GetHandle()->Set(GetEcmaVM(), stringRef, JsiValueConvertor::toJsiValueWithVM<T>(GetEcmaVM(), value));
161}
162
163template<typename T>
164T JsiObject::GetPropertyValue(const char* prop, T defaultValue) const
165{
166    static_assert(!std::is_const_v<T> && !std::is_reference_v<T>,
167        "Cannot convert value to reference or cv-qualified types!");
168
169    const EcmaVM* vm = GetEcmaVM();
170    Local<StringRef> stringRef = panda::StringRef::NewFromUtf8(vm, prop);
171    Local<JSValueRef> valueRef = GetHandle()->Get(vm, stringRef);
172    if constexpr (std::is_same<T, bool>::value) {
173        return valueRef->IsBoolean() ? valueRef->BooleaValue() : defaultValue;
174    } else if constexpr (std::is_arithmetic<T>::value) {
175        return valueRef->IsNumber() ? JsiValueConvertor::fromJsiValue<T>(vm, valueRef) : defaultValue;
176    } else if constexpr (std::is_same_v<T, std::string>) {
177        return valueRef->IsString() ? valueRef->ToString(vm)->ToString() : defaultValue;
178    } else {
179        LOGW("Get property value failed.");
180    }
181    return defaultValue;
182}
183
184template<typename T>
185void JsiCallbackInfo::SetReturnValue(T* instance) const
186{
187    retVal_ = instance;
188}
189
190template<typename T>
191void JsiCallbackInfo::SetReturnValue(JsiRef<T> val) const
192{
193    retVal_ = panda::CopyableGlobal<panda::JSValueRef>(val.Get().GetHandle());
194}
195
196template<typename... Args>
197void JsiException::Throw(const char* format, Args... args)
198{
199    const std::string str = StringUtils::FormatString(format, args...);
200    auto runtime = std::static_pointer_cast<ArkJSRuntime>(JsiDeclarativeEngineInstance::GetCurrentRuntime());
201    auto vm = runtime->GetEcmaVm();
202    panda::JSNApi::ThrowException(vm, panda::Exception::Error(vm, panda::StringRef::NewFromUtf8(vm, str.c_str())));
203}
204
205template<typename... Args>
206void JsiException::Throw(int32_t code, const char* format, Args... args)
207{
208    const std::string str = StringUtils::FormatString(format, args...);
209    auto runtime = std::static_pointer_cast<ArkJSRuntime>(JsiDeclarativeEngineInstance::GetCurrentRuntime());
210    auto vm = runtime->GetEcmaVm();
211    LocalScope scope(vm);
212    Local<JSValueRef> error(JSValueRef::Undefined(vm));
213    error = panda::Exception::Error(vm, StringRef::NewFromUtf8(vm, str.c_str()));
214    Local<JSValueRef> codeKey = StringRef::NewFromUtf8(vm, "code");
215    Local<JSValueRef> codeValue = StringRef::NewFromUtf8(vm, std::to_string(code).c_str());
216    Local<ObjectRef> errorObj(error);
217    errorObj->Set(vm, codeKey, codeValue);
218    panda::JSNApi::ThrowException(vm, error);
219}
220
221template<typename... Args>
222void JsiException::ThrowRangeError(const char* format, Args... args)
223{
224    const std::string str = StringUtils::FormatString(format, args...);
225    auto runtime = std::static_pointer_cast<ArkJSRuntime>(JsiDeclarativeEngineInstance::GetCurrentRuntime());
226    auto vm = runtime->GetEcmaVm();
227    panda::JSNApi::ThrowException(vm, panda::Exception::RangeError(vm, panda::StringRef::NewFromUtf8(vm, str.c_str())));
228}
229
230template<typename... Args>
231void JsiException::ThrowReferenceError(const char* format, Args... args)
232{
233    const std::string str = StringUtils::FormatString(format, args...);
234    auto runtime = std::static_pointer_cast<ArkJSRuntime>(JsiDeclarativeEngineInstance::GetCurrentRuntime());
235    auto vm = runtime->GetEcmaVm();
236    panda::JSNApi::ThrowException(
237        vm, panda::Exception::ReferenceError(vm, panda::StringRef::NewFromUtf8(vm, str.c_str())));
238}
239
240template<typename... Args>
241void JsiException::ThrowSyntaxError(const char* format, Args... args)
242{
243    const std::string str = StringUtils::FormatString(format, args...);
244    auto runtime = std::static_pointer_cast<ArkJSRuntime>(JsiDeclarativeEngineInstance::GetCurrentRuntime());
245    auto vm = runtime->GetEcmaVm();
246    panda::JSNApi::ThrowException(
247        vm, panda::Exception::SyntaxError(vm, panda::StringRef::NewFromUtf8(vm, str.c_str())));
248}
249
250template<typename... Args>
251void JsiException::ThrowTypeError(const char* format, Args... args)
252{
253    const std::string str = StringUtils::FormatString(format, args...);
254    auto runtime = std::static_pointer_cast<ArkJSRuntime>(JsiDeclarativeEngineInstance::GetCurrentRuntime());
255    auto vm = runtime->GetEcmaVm();
256    panda::JSNApi::ThrowException(vm, panda::Exception::TypeError(vm, panda::StringRef::NewFromUtf8(vm, str.c_str())));
257}
258
259template<typename... Args>
260void JsiException::ThrowEvalError(const char* format, Args... args)
261{
262    const std::string str = StringUtils::FormatString(format, args...);
263    auto runtime = std::static_pointer_cast<ArkJSRuntime>(JsiDeclarativeEngineInstance::GetCurrentRuntime());
264    auto vm = runtime->GetEcmaVm();
265    panda::JSNApi::ThrowException(vm, panda::Exception::EvalError(vm, panda::StringRef::NewFromUtf8(vm, str.c_str())));
266}
267} // namespace OHOS::Ace::Framework
268