• 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 "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