• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 #ifndef BASE_OBJECT_JS_H
16 #define BASE_OBJECT_JS_H
17 #include <meta/api/make_callback.h>
18 #include <meta/interface/intf_object.h>
19 #include <meta/interface/intf_task_queue_registry.h>
20 #include <napi_api.h>
21 #include <scene/interface/intf_scene.h>
22 
23 #include "TrueRootObject.h"
24 
25 // tasks execute in the engine/render thread.
26 static constexpr BASE_NS::Uid ENGINE_THREAD { "2070e705-d061-40e4-bfb7-90fad2c280af" };
27 
28 // tasks execute in the javascript mainthread. *NOT IMPLEMENTED*
29 static constexpr BASE_NS::Uid JS_THREAD { "b2e8cef3-453a-4651-b564-5190f8b5190d" };
30 
31 class BaseObject : public TrueRootObject {
32 protected:
33     bool disposed_ { false };
~BaseObject()34     virtual ~BaseObject() {}
BaseObject(napi_env env,napi_callback_info info)35     BaseObject(napi_env env, napi_callback_info info) : TrueRootObject(env, info)
36     {
37         napi_value thisVar = nullptr;
38         napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
39         auto DTOR = [](napi_env env, void* nativeObject, void* finalize) {
40             TrueRootObject* ptr = static_cast<TrueRootObject*>(nativeObject);
41             ptr->Finalize(env);
42             TrueRootObject::destroy(ptr);
43         };
44         napi_wrap(env, thisVar, reinterpret_cast<void*>((TrueRootObject*)this), DTOR, nullptr, nullptr);
45     }
46     template<typename Object>
ctor()47     static inline napi_callback ctor()
48     {
49         napi_callback ctor = [](napi_env env, napi_callback_info info) -> napi_value {
50             napi_value thisVar = nullptr;
51             // fetch the "this" from javascript.
52             napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
53             // The BaseObject constructor actually handles wrapping..
54             auto r = BASE_NS::make_unique<Object>(env, info);
55             r.release();
56             return thisVar;
57         };
58         return ctor;
59     }
60 };
61 
62 template<typename Object, napi_value (Object::*F)(NapiApi::FunctionContext<>&)>
TROGetter(napi_env env,napi_callback_info info)63 static inline napi_value TROGetter(napi_env env, napi_callback_info info)
64 {
65     NapiApi::FunctionContext fc(env, info);
66     if (fc) {
67         if (TrueRootObject* instance = fc.This().GetRoot()) {
68             if (Object* impl = (Object*)instance->GetInstanceImpl(Object::ID)) {
69                 return (impl->*F)(fc);
70             }
71         };
72     }
73     return fc.GetUndefined();
74 }
75 template<typename Type, typename Object, void (Object::*F)(NapiApi::FunctionContext<Type>&)>
TROSetter(napi_env env,napi_callback_info info)76 static inline napi_value TROSetter(napi_env env, napi_callback_info info)
77 {
78     NapiApi::FunctionContext<Type> fc(env, info);
79     if (fc) {
80         if (TrueRootObject* instance = fc.This().GetRoot()) {
81             if (Object* impl = (Object*)instance->GetInstanceImpl(Object::ID)) {
82                 (impl->*F)(fc);
83             }
84         }
85     }
86     return fc.GetUndefined();
87 };
88 
89 template<typename Type, typename Object, void (Object::*F2)(NapiApi::FunctionContext<Type>&)>
90 static inline napi_property_descriptor TROSetProperty(
91     const char* const name, napi_property_attributes flags = napi_default_jsproperty)
92 {
93     static_assert(F2 != nullptr);
94     return napi_property_descriptor { name, nullptr, nullptr, nullptr, TROSetter<Type, Object, F2>, nullptr, flags,
95         nullptr };
96 }
97 
98 template<typename Type, typename Object, napi_value (Object::*F)(NapiApi::FunctionContext<>&)>
99 static inline napi_property_descriptor TROGetProperty(
100     const char* const name, napi_property_attributes flags = napi_default_jsproperty)
101 {
102     static_assert(F != nullptr);
103     return napi_property_descriptor { name, nullptr, nullptr, TROGetter<Object, F>, nullptr, nullptr, flags, nullptr };
104 }
105 
106 template<typename Type, typename Object, napi_value (Object::*F)(NapiApi::FunctionContext<>&),
107     void (Object::*F2)(NapiApi::FunctionContext<Type>&)>
108 static inline napi_property_descriptor TROGetSetProperty(
109     const char* const name, napi_property_attributes flags = napi_default_jsproperty)
110 {
111     static_assert(F != nullptr);
112     static_assert(F2 != nullptr);
113     return napi_property_descriptor { name, nullptr, nullptr, TROGetter<Object, F>, TROSetter<Type, Object, F2>,
114         nullptr, flags, nullptr };
115 }
116 
117 template<typename FC, typename Object, napi_value (Object::*F)(FC&)>
TROMethod(napi_env env,napi_callback_info info)118 napi_value TROMethod(napi_env env, napi_callback_info info)
119 {
120     FC fc(env, info);
121     if (fc) {
122         if (TrueRootObject* instance = fc.This().GetRoot()) {
123             if (Object* impl = (Object*)instance->GetInstanceImpl(Object::ID)) {
124                 return (impl->*F)(fc);
125             }
126         }
127     }
128     return fc.GetUndefined();
129 }
130 
131 template<typename FC, typename Object, napi_value (Object::*F)(FC&)>
132 inline napi_property_descriptor MakeTROMethod(
133     const char* const name, napi_property_attributes flags = napi_default_method)
134 {
135     return napi_property_descriptor { name, nullptr, TROMethod<FC, Object, F>, nullptr, nullptr, nullptr, flags,
136         nullptr };
137 }
138 
139 //  Create a javascript object that wraps specified IObject.
140 //  uses the classid of obj to create correct wrapper.
141 //  (if the wrapper already exists, returns a new reference to the wrapper)
142 NapiApi::Object CreateFromNativeInstance(napi_env env, const META_NS::IObject::Ptr& obj, PtrType ptrType,
143     const NapiApi::JsFuncArgs& args, BASE_NS::string_view pname = "_JSW");
144 
145 NapiApi::Object CreateFromNativeInstance(napi_env env, const BASE_NS::string& name, const META_NS::IObject::Ptr& obj,
146     PtrType ptrType, const NapiApi::JsFuncArgs& args, BASE_NS::string_view pname = "_JSW");
147 
148 template<typename ObjectPtr>
149 NapiApi::Object CreateFromNativeInstance(napi_env env, const ObjectPtr& obj, PtrType ptrType,
150     const NapiApi::JsFuncArgs& args, BASE_NS::string_view pname = "_JSW")
151 {
152     const auto iobj = interface_pointer_cast<META_NS::IObject>(obj);
153     return CreateFromNativeInstance(env, iobj, ptrType, args, pname);
154 }
155 
156 template<typename ObjectPtr>
157 NapiApi::Object CreateFromNativeInstance(napi_env env, const BASE_NS::string& name, const ObjectPtr& obj,
158     PtrType ptrType, const NapiApi::JsFuncArgs& args, BASE_NS::string_view pname = "_JSW")
159 {
160     const auto iobj = interface_pointer_cast<META_NS::IObject>(obj);
161     return CreateFromNativeInstance(env, name, iobj, ptrType, args, pname);
162 }
163 
164 // run synchronous task in specific tq.
165 template<typename func>
ExecSyncTask(const META_NS::ITaskQueue::Ptr tq,func && fun)166 META_NS::IAny::Ptr ExecSyncTask(const META_NS::ITaskQueue::Ptr tq, func&& fun)
167 {
168     return tq
169         ->AddWaitableTask(BASE_NS::move(META_NS::MakeCallback<META_NS::ITaskQueueWaitableTask>(BASE_NS::move(fun))))
170         ->GetResult();
171 }
172 
173 // run task synchronously in engine thread.
174 template<typename func>
ExecSyncTask(func && fun)175 META_NS::IAny::Ptr ExecSyncTask(func&& fun)
176 {
177     return ExecSyncTask(META_NS::GetTaskQueueRegistry().GetTaskQueue(ENGINE_THREAD), BASE_NS::move(fun));
178 }
179 
180 #endif
181