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 "bindings_implementation.h"
17
18namespace OHOS::Ace::Framework {
19
20template<typename T, template<typename> typename ImplDetail>
21std::unordered_map<int, IFunctionBinding*> JSClassImpl<T, ImplDetail>::functions_;
22template<typename T, template<typename> typename ImplDetail>
23int JSClassImpl<T, ImplDetail>::nextFreeId_ = 0;
24template<typename T, template<typename> typename ImplDetail>
25std::string JSClassImpl<T, ImplDetail>::jsName;
26
27template<typename C, template<typename> typename ImplDetail>
28void JSClassImpl<C, ImplDetail>::Declare(const char* name)
29{
30    jsName = name;
31    ImplDetail<C>::Declare(name);
32}
33
34template<typename C, template<typename> typename ImplDetail>
35template<typename R, typename... Args>
36void JSClassImpl<C, ImplDetail>::Method(const char* name, R (C::*func)(Args...), MethodOptions options)
37{
38    functions_.emplace(nextFreeId_, new FunctionBinding(name, options, func));
39    ImplDetail<C>::Method(name, func, nextFreeId_++);
40}
41
42template<typename C, template<typename> typename ImplDetail>
43template<typename Base, typename R, typename... Args>
44void JSClassImpl<C, ImplDetail>::Method(const char* name, R (Base::*func)(Args...), MethodOptions options)
45{
46    static_assert(std::is_base_of_v<Base, C>, "Trying to bind an unrelated method!");
47    functions_.emplace(nextFreeId_, new FunctionBinding(name, options, func));
48    ImplDetail<C>::Method(name, func, nextFreeId_++);
49}
50
51template<typename C, template<typename> typename ImplDetail>
52template<typename R, typename... Args>
53void JSClassImpl<C, ImplDetail>::StaticMethod(const char* name, R (C::*func)(Args...), MethodOptions options)
54{
55    functions_.emplace(nextFreeId, new FunctionBinding(name, options, func));
56    ImplDetail<C>::StaticMethod(name, func, nextFreeId++);
57}
58
59template<typename C, template<typename> typename ImplDetail>
60template<typename Base, typename R, typename... Args>
61void JSClassImpl<C, ImplDetail>::StaticMethod(const char* name, R (Base::*func)(Args...), MethodOptions options)
62{
63    static_assert(std::is_base_of_v<Base, C>, "Trying to bind an unrelated method!");
64    functions_.emplace(nextFreeId, new FunctionBinding(name, options, func));
65    ImplDetail<C>::StaticMethod(name, func, nextFreeId++);
66}
67
68template<typename C, template<typename> typename ImplDetail>
69template<typename T>
70void JSClassImpl<C, ImplDetail>::CustomMethod(
71    const char* name, typename ImplDetail<C>::template MemberFunctionCallback<T> callback)
72{
73    static_assert(std::is_base_of_v<T, C>, "Trying to bind an unrelated method!");
74    functions_.emplace(nextFreeId_, new FunctionBinding(name, MethodOptions::NONE, callback));
75    ImplDetail<C>::CustomMethod(name, callback, nextFreeId_++);
76}
77
78template<typename C, template<typename> typename ImplDetail>
79void JSClassImpl<C, ImplDetail>::CustomMethod(const char* name, typename ImplDetail<C>::FunctionCallback callback)
80{
81    ImplDetail<C>::CustomMethod(name, callback);
82}
83
84template<typename C, template<typename> typename ImplDetail>
85template<typename T>
86void JSClassImpl<C, ImplDetail>::CustomProperty(
87    const char* name, typename ImplDetail<C>::template MemberFunctionGetCallback<T> getter,
88    typename ImplDetail<C>::template MemberFunctionSetCallback<T> setter)
89{
90    int getFuncId;
91    int setFuncId;
92    static_assert(std::is_base_of_v<T, C>, "Trying to bind an unrelated method!");
93    getFunctions_.emplace(nextFreeId_, new FunctionBinding(name, MethodOptions::NONE, getter));
94    setFunctions_.emplace(nextFreeId_, new FunctionBinding(name, MethodOptions::NONE, setter));
95    functions_.emplace(nextFreeId_, new FunctionBinding(name, MethodOptions::NONE, getter));
96    getFuncId = nextFreeId_++;
97    functions_.emplace(nextFreeId_, new FunctionBinding(name, MethodOptions::NONE, setter));
98    setFuncId = nextFreeId_++;
99    ImplDetail<C>::CustomProperty(name, getter, getFuncId, setFuncId);
100}
101
102template<typename C, template<typename> typename ImplDetail>
103void JSClassImpl<C, ImplDetail>::CustomProperty(const char* name, typename ImplDetail<C>::FunctionGetCallback getter,
104    typename ImplDetail<C>::FunctionSetCallback setter)
105{
106    ImplDetail<C>::CustomProperty(name, getter, setter);
107}
108
109template<typename C, template<typename> typename ImplDetail>
110template<typename T>
111void JSClassImpl<C, ImplDetail>::StaticMethod(
112    const char* name, typename ImplDetail<C>::template MemberFunctionCallback<T> callback)
113{
114    static_assert(std::is_base_of_v<T, C>, "Trying to bind an unrelated method!");
115    functions_.emplace(nextFreeId, new FunctionBinding(name, MethodOptions::NONE, callback));
116    ImplDetail<C>::StaticMethod(name, callback, nextFreeId++);
117}
118
119template<typename C, template<typename> typename ImplDetail>
120void JSClassImpl<C, ImplDetail>::StaticMethod(const char* name, typename ImplDetail<C>::FunctionCallback callback)
121{
122    ImplDetail<C>::StaticMethod(name, callback);
123}
124
125template<typename C, template<typename> typename ImplDetail>
126template<typename T>
127void JSClassImpl<C, ImplDetail>::StaticConstant(const char* name, T value)
128{
129    ImplDetail<C>::StaticConstant(name, value);
130}
131
132template<typename C, template<typename> typename ImplDetail>
133void JSClassImpl<C, ImplDetail>::Bind(
134    typename ImplDetail<C>::BindingTarget bindTarget, typename ImplDetail<C>::FunctionCallback ctor)
135{
136    ImplDetail<C>::Bind(bindTarget, ctor);
137}
138
139template<typename C, template<typename> typename ImplDetail>
140template<typename... Args>
141void JSClassImpl<C, ImplDetail>::Bind(typename ImplDetail<C>::BindingTarget bindTarget)
142{
143    ImplDetail<C>::template Bind<Args...>(bindTarget);
144}
145
146template<typename C, template<typename> typename ImplDetail>
147template<typename Base>
148void JSClassImpl<C, ImplDetail>::Inherit()
149{
150    static_assert(std::is_base_of_v<Base, C>, "Calling Inherit() on unrelated classes!");
151    ImplDetail<C>::template Inherit<Base>();
152}
153
154template<typename C, template<typename> typename ImplDetail>
155template<typename Base>
156void JSClassImpl<C, ImplDetail>::InheritAndBind(
157    typename ImplDetail<C>::BindingTarget bindTarget, ImplDetail<C>::JSFunctionCallback ctor,
158    ImplDetail<C>::JSDestructorCallback dtor, ImplDetail<C>::JSGCMarkCallback gcMark)
159{
160    static_assert(std::is_base_of_v<Base, C>, "Calling Inherit() on unrelated classes!");
161    ImplDetail<C>::template InheritAndBind<Base>(bindTarget, ctor, dtor, gcMark);
162}
163
164template<typename C, template<typename> typename ImplDetail>
165IFunctionBinding* JSClassImpl<C, ImplDetail>::GetFunctionBinding(int id)
166{
167    return functions_[id];
168}
169
170template<typename C, template<typename> typename ImplDetail>
171const char* JSClassImpl<C, ImplDetail>::JSName()
172{
173    return jsName.c_str();
174}
175
176}; // namespace OHOS::Ace::Framework
177