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 "bridge/declarative_frontend/jsview/js_view_common_def.h" 17 18#include <string> 19#include <type_traits> 20 21#include "base/geometry/dimension.h" 22#include "base/log/log.h" 23#include "bridge/declarative_frontend/view_stack_processor.h" 24#include "bridge/declarative_frontend/jsview/js_view_abstract.h" 25#include "core/common/resource/resource_object.h" 26#include "core/components/common/properties/color.h" 27 28namespace OHOS::Ace::Framework { 29 30template<class T> 31JSRef<JSVal> ConvertToJSValue(T&& value) 32{ 33 using ValueType = std::remove_cv_t<std::remove_reference_t<T>>; 34 if constexpr (std::is_arithmetic_v<ValueType> || std::is_same_v<ValueType, std::string> || 35 std::is_same_v<ValueType, std::u16string>) { 36 return JSRef<JSVal>::Make(ToJSValue(std::forward<T>(value))); 37 } else if constexpr (std::is_enum_v<ValueType>) { 38 return JSRef<JSVal>::Make(ToJSValue(static_cast<std::make_signed_t<ValueType>>(value))); 39 } else if constexpr (std::is_same_v<ValueType, Dimension> || std::is_same_v<ValueType, CalcDimension>) { 40 if (value.Unit() == DimensionUnit::VP) { 41 return JSRef<JSVal>::Make(ToJSValue(value.Value())); 42 } else { 43 LOGE("Failed to convert to JS value with dimension which it not using 'VP' unit"); 44 return JSRef<JSVal>(); 45 } 46 } else { 47 LOGE("Failed to convert to JS value"); 48 return JSRef<JSVal>(); 49 } 50} 51 52template<class T> 53void ConvertToJSValuesImpl(std::vector<JSRef<JSVal>>& result, T&& value) 54{ 55 result.emplace_back(ConvertToJSValue(std::forward<T>(value))); 56} 57 58template<class T, class V, class... Args> 59void ConvertToJSValuesImpl(std::vector<JSRef<JSVal>>& result, T&& value, V&& nextValue, Args&&... args) 60{ 61 result.emplace_back(ConvertToJSValue(std::forward<T>(value))); 62 ConvertToJSValuesImpl(result, std::forward<V>(nextValue), std::forward<Args>(args)...); 63} 64 65template<class... Args> 66std::vector<JSRef<JSVal>> ConvertToJSValues(Args... args) 67{ 68 std::vector<JSRef<JSVal>> result; 69 ConvertToJSValuesImpl(result, args...); 70 return result; 71} 72 73template<class T> 74bool ConvertFromJSValueNG(const JSRef<JSVal>& jsValue, T& result) 75{ 76 RefPtr<ResourceObject> resObj; 77 return ConvertFromJSValueNG(jsValue, result, resObj); 78} 79 80template<class T> 81bool ConvertFromJSValueNG(const JSRef<JSVal>& jsValue, T& result, RefPtr<ResourceObject>& resObj) 82{ 83 if constexpr (std::is_same_v<T, bool>) { 84 if (jsValue->IsBoolean()) { 85 result = jsValue->ToBoolean(); 86 return true; 87 } 88 result = false; 89 } else if constexpr (std::is_integral_v<T> || std::is_floating_point_v<T>) { 90 double value; 91 if (JSViewAbstract::ParseJsDouble(jsValue, value, resObj)) { 92 result = static_cast<T>(value); 93 return true; 94 } 95 result = 0; 96 } else if constexpr (std::is_same_v<T, std::string>) { 97 if (jsValue->IsString()) { 98 result = jsValue->ToString(); 99 return true; 100 } 101 } else if constexpr (std::is_same_v<T, Dimension>) { 102 CalcDimension calc; 103 bool ret = JSViewAbstract::ParseJsDimensionVpNG(jsValue, calc, resObj); 104 result = calc; 105 return ret; 106 } else if constexpr (std::is_same_v<T, CalcDimension>) { 107 return JSViewAbstract::ParseJsDimensionVpNG(jsValue, result, resObj); 108 } else if constexpr (std::is_same_v<T, NG::CalcLength>) { 109 return JSViewAbstract::ParseJsLengthVpNG(jsValue, result, resObj); 110 } else if constexpr (std::is_same_v<T, Color>) { 111 return JSViewAbstract::ParseJsColor(jsValue, result, resObj); 112 } 113 return false; 114} 115 116template<class T> 117bool ConvertFromJSValue(const JSRef<JSVal>& jsValue, T& result) 118{ 119 RefPtr<ResourceObject> resObj; 120 return ConvertFromJSValue(jsValue, result, resObj); 121} 122 123template<class T> 124bool ConvertFromJSValue(const JSRef<JSVal>& jsValue, T& result, RefPtr<ResourceObject>& resObj) 125{ 126 if constexpr (std::is_same_v<T, bool>) { 127 if (jsValue->IsBoolean()) { 128 result = jsValue->ToBoolean(); 129 return true; 130 } 131 result = false; 132 } else if constexpr (std::is_integral_v<T> || std::is_floating_point_v<T>) { 133 double value; 134 if (JSViewAbstract::ParseJsDouble(jsValue, value, resObj)) { 135 result = static_cast<T>(value); 136 return true; 137 } 138 result = 0; 139 } else if constexpr (std::is_same_v<T, std::string>) { 140 if (jsValue->IsString()) { 141 result = jsValue->ToString(); 142 return true; 143 } 144 } else if constexpr (std::is_same_v<T, Dimension>) { 145 CalcDimension calc; 146 bool ret = JSViewAbstract::ParseJsDimensionVp(jsValue, calc, resObj); 147 result = calc; 148 return ret; 149 } else if constexpr (std::is_same_v<T, CalcDimension>) { 150 return JSViewAbstract::ParseJsDimensionVp(jsValue, result, resObj); 151 } else if constexpr (std::is_same_v<T, Color>) { 152 return JSViewAbstract::ParseJsColor(jsValue, result, resObj); 153 } 154 return false; 155} 156 157template<class T, size_t N> 158bool ConvertFromJSValue(const JSRef<JSVal>& jsValue, const T (&enumValues)[N], T& result) 159{ 160 int32_t value = 0; 161 if (!ConvertFromJSValue(jsValue, value) || value < 0 || static_cast<size_t>(value) >= N) { 162 return false; 163 } 164 result = enumValues[value]; 165 return true; 166} 167 168template<class T> 169T FastConvertFromJSValue(const JSRef<JSVal>& jsValue) 170{ 171 T result; 172 if (!ConvertFromJSValue(jsValue, result)) { 173 LOGE("Failed to convert from JS value"); 174 } 175 return result; 176} 177 178template<class C, class V, class T, size_t N> 179void JSViewSetProperty(void (C::*setMethod)(V), int32_t param, const T (&enumValues)[N], T defValue) 180{ 181#ifndef NG_BUILD 182 auto component = AceType::DynamicCast<C>(ViewStackProcessor::GetInstance()->GetMainComponent()); 183 if (!component) { 184 LOGW("Failed to get '%{public}s' in view stack", AceType::TypeName<C>()); 185 return; 186 } 187 T value = defValue; 188 if (param >= 0 && static_cast<size_t>(param) < N) { 189 value = enumValues[param]; 190 } 191 ((*component).*setMethod)(value); 192#else 193 LOGE("do not support JSViewSetProperty in new pipeline"); 194#endif 195} 196 197template<class C, class V, class T> 198void JSViewSetProperty(void (C::*setMethod)(V), T&& param) 199{ 200#ifndef NG_BUILD 201 auto component = AceType::DynamicCast<C>(ViewStackProcessor::GetInstance()->GetMainComponent()); 202 if (!component) { 203 LOGW("Failed to get '%{public}s' in view stack", AceType::TypeName<C>()); 204 return; 205 } 206 ((*component).*setMethod)(std::forward<T>(param)); 207#else 208 LOGE("do not support JSViewSetProperty in new pipeline"); 209#endif 210} 211 212template<class C, class F> 213bool JSViewBindEvent( 214 void (C::*setMethod)(std::function<F>&&), const JSExecutionContext& context, const JSRef<JSVal>& jsValue) 215{ 216#ifndef NG_BUILD 217 if (!jsValue->IsFunction()) { 218 LOGW("Argument is not a function object"); 219 return false; 220 } 221 auto component = AceType::DynamicCast<C>(ViewStackProcessor::GetInstance()->GetMainComponent()); 222 if (!component) { 223 LOGW("Failed to get '%{public}s' in view stack", AceType::TypeName<C>()); 224 return false; 225 } 226 ((*component).*setMethod)(JsEventCallback<F>(context, JSRef<JSFunc>::Cast(jsValue))); 227 return true; 228#else 229 LOGE("do not support JSViewBindEvent in new pipeline"); 230 return false; 231#endif 232} 233 234template<class C, class F> 235bool JSViewBindEvent(void (C::*setMethod)(std::function<F>&&), const JSCallbackInfo& args) 236{ 237 if (args.Length() < 1) { 238 LOGW("Must contain at least 1 argument"); 239 return false; 240 } 241 return JSViewBindEvent(setMethod, args.GetExecutionContext(), args[0]); 242} 243 244} // namespace OHOS::Ace::Framework 245