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