• 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 
16 #ifndef OHOS_RENDER_3D_NAPI_API
17 #define OHOS_RENDER_3D_NAPI_API
18 #define NAPI_VERSION 8
19 
20 #ifdef __OHOS_PLATFORM__
21 #include "napi/native_api.h"
22 #else
23 #include <node_api.h>
24 #endif
25 
26 #include <meta/interface/intf_object.h>
27 
28 #include <base/containers/string.h>
29 #include <base/containers/unique_ptr.h>
30 #include <base/containers/vector.h>
31 
32 #define LOG_F(...)
33 
34 namespace NapiApi {
35 template<typename type>
36 bool ValidateType(napi_valuetype jstype, bool isArray);
37 
38 template<typename type>
39 class Value {
40     napi_env env_ { nullptr };
41     napi_value value_ { nullptr };
42 
43 public:
44     using Type = type;
45     Value() = default;
Value(napi_env env,Type v)46     Value(napi_env env, Type v)
47     {
48         Init(env, v);
49     }
50 
51     void Init(napi_env env, Type v);
52 
Value(napi_env env,napi_value v)53     Value(napi_env env, napi_value v) : env_(env)
54     {
55         if ((env == nullptr) || (v == nullptr)) {
56             return;
57         }
58         // validate type
59         napi_valuetype jstype;
60         napi_status status = napi_invalid_arg;
61         status = napi_typeof(env_, v, &jstype);
62         if (status != napi_ok) {
63             // okay then failed.
64             return;
65         }
66         bool isArray = false;
67         napi_is_array(env_, v, &isArray);
68 
69         if (ValidateType<type>(jstype, isArray)) {
70             value_ = v;
71         }
72     }
IsValid()73     bool IsValid()
74     {
75         return (env_ && value_);
76     }
77     type valueOrDefault(const type defaultValue = {});
type()78     operator type()
79     {
80         return valueOrDefault();
81     }
GetEnv()82     napi_env GetEnv() const
83     {
84         return env_;
85     }
86 
napi_value()87     operator napi_value() const
88     {
89         return value_;
90     }
91 };
92 class Function;
93 
94 template<typename... Types>
95 class FunctionContext {
96     napi_value jsThis { nullptr };
97     void* data_ { nullptr };
98     const size_t argc { sizeof...(Types) };
99     napi_value args[sizeof...(Types) + 1] {};
100     napi_env env_ { nullptr };
101     napi_callback_info info_ { nullptr };
102     size_t argCount_ { 0 };
103 
104 public:
105     template<typename First, typename... Rest>
validate(size_t index)106     inline bool validate(size_t index)
107     {
108         napi_valuetype jstype;
109         napi_status status = napi_invalid_arg;
110         status = napi_typeof(env_, args[index], &jstype);
111         bool isArray = false;
112         napi_is_array(env_, args[index], &isArray);
113 
114         bool ret = ValidateType<First>(jstype, isArray);
115         if (ret) {
116             if constexpr (sizeof...(Rest) == 0) {
117                 return true;
118             }
119             if constexpr (sizeof...(Rest) > 0) {
120                 return validate<Rest...>(index + 1);
121             }
122         }
123         return false;
124     }
125     template<typename... ot>
FunctionContext(FunctionContext<ot...> other)126     FunctionContext(FunctionContext<ot...> other) : FunctionContext(other.GetEnv(), other.GetInfo())
127     {}
FunctionContext(const napi_env env,const napi_callback_info info)128     FunctionContext(const napi_env env, const napi_callback_info info)
129     {
130         if ((!env) || (!info)) {
131             return;
132         }
133         napi_status status;
134         if constexpr (sizeof...(Types) == 0) {
135             // dont care about args now. or void args
136             env_ = env;
137             info_ = info;
138             status = napi_get_cb_info(env, info, &argCount_, nullptr, &jsThis, &data_);
139         }
140         if constexpr (sizeof...(Types) > 0) {
141             // check arg count first
142             status = napi_get_cb_info(env, info, &argCount_, nullptr, nullptr, nullptr);
143             if (argc != argCount_) {
144                 // non matching arg count. fail
145                 return;
146             }
147 
148             status = napi_get_cb_info(env, info, &argCount_, args, &jsThis, &data_);
149             env_ = env;
150             if (!validate<Types...>(0)) {
151                 // non matching types in context!
152                 env_ = {};
153                 return;
154             }
155             // Okay valid.
156             info_ = info;
157         }
158     }
159     operator bool()
160     {
161         return (env_ && info_);
162     }
GetData()163     void* GetData() const
164     {
165         return data_;
166     }
napi_env()167     operator napi_env() const
168     {
169         return env_;
170     }
GetEnv()171     napi_env GetEnv() const
172     {
173         return env_;
174     }
GetInfo()175     napi_callback_info GetInfo() const
176     {
177         return info_;
178     }
179 
This()180     napi_value This()
181     {
182         return jsThis;
183     }
value(size_t index)184     napi_value value(size_t index)
185     {
186         if (index < argc) {
187             return args[index];
188         }
189         return nullptr;
190     }
191 
192     template<size_t I, typename T, typename... TypesI>
193     struct GetTypeImpl {
194         using type = typename GetTypeImpl<I - 1, TypesI...>::type;
195     };
196     template<typename T, typename... TypesI>
197     struct GetTypeImpl<0, T, TypesI...> {
198         using type = T;
199     };
200 
201     template<size_t index>
202     auto Arg()
203     {
204         if constexpr (sizeof...(Types) > 0) {
205             if constexpr (index < sizeof...(Types)) {
206                 return Value<typename GetTypeImpl<index, Types...>::type> { env_, args[index] };
207             }
208             if constexpr (index >= sizeof...(Types)) {
209                 static_assert(index < sizeof...(Types), "Index out of range !");
210                 return Value<void*>((napi_env) nullptr, (void*)nullptr);
211             }
212         }
213         if constexpr (sizeof...(Types) == 0) {
214             return;
215         }
216     }
217 
218     size_t ArgCount() const
219     {
220         return argCount_;
221     }
222 
223     // these could be forwarder to env..
224     napi_value GetUndefined()
225     {
226         if (!env_) {
227             return {};
228         }
229         napi_value undefined;
230         napi_get_undefined(env_, &undefined);
231         return undefined;
232     }
233     napi_value GetNull()
234     {
235         if (!env_) {
236             return {};
237         }
238         napi_value null;
239         napi_get_null(env_, &null);
240         return null;
241     }
242     napi_value GetBoolean(bool value)
243     {
244         if (!env_) {
245             return {};
246         }
247         napi_value val;
248         napi_get_boolean(env_, value, &val);
249         return val;
250     }
251 };
252 
253 class Object {
254     napi_env env_ { nullptr };
255     napi_value object_ { nullptr };
256 
257 public:
258     Object() = default;
259     Object(Function ctor);
260     Object(Function ctor, size_t argc, napi_value args[]);
261     Object(napi_env env) : env_(env)
262     {
263         napi_create_object(env, &object_);
264     }
265     Object(napi_env env, napi_value v) : env_(env), object_(v)
266     {
267         napi_valuetype jstype;
268         napi_typeof(env_, v, &jstype);
269         if (jstype != napi_object) {
270             // value was not an object!
271             env_ = nullptr;
272             object_ = nullptr;
273         }
274     }
275 
276     template<class T>
277     T* Native()
278     {
279         T* me = nullptr;
280         napi_unwrap(env_, object_, (void**)&me);
281         return me;
282     }
283     void Set(const BASE_NS::string_view name, napi_value value)
284     {
285         // could check if it is declared. and optionally add it. (now it just adds it if not declared)
286         napi_set_named_property(env_, object_, BASE_NS::string(name).c_str(), value);
287     }
288     void Set(const BASE_NS::string_view name, BASE_NS::string_view v)
289     {
290         napi_value value;
291         napi_status status = napi_create_string_utf8(env_, v.data(), v.length(), &value);
292         status = napi_set_named_property(env_, object_, BASE_NS::string(name).c_str(), value);
293     }
294     napi_value Get(const BASE_NS::string_view name)
295     {
296         napi_status status;
297         napi_value res;
298         status = napi_get_named_property(env_, object_, BASE_NS::string(name).c_str(), &res);
299         if (!res) {
300             return nullptr;
301         }
302         napi_valuetype jstype;
303         napi_typeof(env_, res, &jstype);
304         if (jstype == napi_null) {
305             return nullptr;
306         }
307         if (jstype == napi_undefined) {
308             return nullptr;
309         }
310         return res;
311     }
312     template<typename t>
313     Value<t> Get(const BASE_NS::string_view name)
314     {
315         return Value<t>(env_, Get(name));
316     }
317     operator napi_value() const
318     {
319         return object_;
320     }
321 
322     napi_env GetEnv() const
323     {
324         return env_;
325     }
326 };
327 
328 class Array {
329     napi_env env_ { nullptr };
330     napi_value array_ { nullptr };
331 
332 public:
333     Array() = default;
334     Array(napi_env env, size_t count) : env_(env)
335     {
336         napi_create_array_with_length(env, count, &array_);
337     }
338     Array(napi_env env, napi_value v)
339     {
340         napi_valuetype jstype;
341         napi_typeof(env, v, &jstype);
342         if (jstype != napi_object) {
343             return;
344         }
345         bool isArray = false;
346         napi_is_array(env, v, &isArray);
347         if (!isArray) {
348             return;
349         }
350         env_ = env;
351         array_ = v;
352     }
353 
354     operator napi_value() const
355     {
356         return array_;
357     }
358 
359     napi_env GetEnv() const
360     {
361         return env_;
362     }
363 
364     size_t Count() const
365     {
366         uint32_t size;
367         napi_get_array_length(env_, array_, &size);
368         return size;
369     }
370     void Set_value(size_t index, napi_value v) const
371     {
372         napi_set_element(env_, array_, index, v);
373     }
374 
375     napi_value Get_value(size_t index) const
376     {
377         napi_value result;
378         napi_get_element(env_, array_, index, &result);
379         return result;
380     }
381     napi_valuetype Type(size_t index) const
382     {
383         napi_value element;
384         napi_get_element(env_, array_, index, &element);
385         napi_valuetype jstype;
386         napi_status status = napi_invalid_arg;
387         status = napi_typeof(env_, element, &jstype);
388         return jstype;
389     }
390     template<typename T>
391     Value<T> Get(size_t index) const
392     {
393         return Value<T> { env_, Get_value(index) };
394     }
395     template<typename T>
396     void Set(size_t index, T t) const
397     {
398         Set_value(index, Value<T>(env_, t));
399     }
400 };
401 
402 class Function {
403     napi_env env_ { nullptr };
404     napi_value func_ { nullptr };
405 
406 public:
407     Function() = default;
408     Function(napi_env env, napi_value v) : env_(env), func_(v)
409     {
410         napi_valuetype jstype;
411         napi_typeof(env_, v, &jstype);
412         if (jstype != napi_function) {
413             // value was not an object!
414             env_ = nullptr;
415             func_ = nullptr;
416         }
417     }
418     operator napi_value() const
419     {
420         return func_;
421     }
422 
423     napi_env GetEnv() const
424     {
425         return env_;
426     }
427     napi_value Invoke(NapiApi::Object thisJS, size_t argc = 0, napi_value* argv = nullptr) const
428     {
429         napi_value res;
430         napi_call_function(env_, thisJS, func_, argc, argv, &res);
431         return res;
432     }
433 };
434 
435 class MyInstanceState {
436     napi_ref ref_;
437     napi_env env_;
438 
439 public:
440     MyInstanceState(napi_env env, napi_value obj) : env_(env)
441     {
442         napi_create_reference(env_, obj, 1, &ref_);
443     }
444     MyInstanceState(NapiApi::Object obj)
445     {
446         env_ = obj.GetEnv();
447         napi_create_reference(env_, obj, 1, &ref_);
448     }
449     ~MyInstanceState()
450     {
451         uint32_t res;
452         napi_reference_unref(env_, ref_, &res);
453     }
454     napi_value getRef()
455     {
456         napi_value tmp;
457         napi_get_reference_value(env_, ref_, &tmp);
458         return tmp;
459     }
460 
461     void StoreCtor(BASE_NS::string_view name, napi_value ctor)
462     {
463         NapiApi::Object exp(env_, getRef());
464         exp.Set(name, ctor);
465     }
466     napi_value FetchCtor(BASE_NS::string_view name)
467     {
468         NapiApi::Object exp(env_, getRef());
469         return exp.Get(name);
470     }
471 };
472 template<typename type>
473 bool ValidateType(napi_valuetype jstype, bool isArray)
474 {
475     /*
476       napi_undefined,
477       napi_null,
478       napi_symbol,
479       napi_function,
480       napi_external,
481       napi_bigint,
482     */
483 
484     if constexpr (BASE_NS::is_same_v<type, BASE_NS::string>) {
485         if (jstype == napi_string) {
486             return true;
487         }
488     }
489     if constexpr (BASE_NS::is_same_v<type, bool>) {
490         if (jstype == napi_boolean) {
491             return true;
492         }
493     }
494     // yup..
495     if constexpr (BASE_NS::is_same_v<type, float>) {
496         if (jstype == napi_number) {
497             return true;
498         }
499     }
500     if constexpr (BASE_NS::is_same_v<type, double>) {
501         if (jstype == napi_number) {
502             return true;
503         }
504     }
505     if constexpr (BASE_NS::is_same_v<type, uint32_t>) {
506         if (jstype == napi_number) {
507             return true;
508         }
509     }
510     if constexpr (BASE_NS::is_same_v<type, int32_t>) {
511         if (jstype == napi_number) {
512             return true;
513         }
514     }
515     if constexpr (BASE_NS::is_same_v<type, int64_t>) {
516         if (jstype == napi_number) {
517             return true;
518         }
519     }
520     if constexpr (BASE_NS::is_same_v<type, uint64_t>) {
521         if (jstype == napi_number) {
522             return true;
523         }
524     }
525     if constexpr (BASE_NS::is_same_v<type, NapiApi::Object>) {
526         if (jstype == napi_object) {
527             return true;
528         }
529         // allow undefined and null also
530         if (jstype == napi_undefined) {
531             return true;
532         }
533         if (jstype == napi_null) {
534             return true;
535         }
536     }
537     if constexpr (BASE_NS::is_same_v<type, NapiApi::Array>) {
538         if (jstype == napi_object) {
539             return isArray;
540         }
541     }
542     if constexpr (BASE_NS::is_same_v<type, NapiApi::Function>) {
543         if (jstype == napi_function) {
544             return true;
545         }
546     }
547     return false;
548 }
549 
550 template<typename type>
551 type NapiApi::Value<type>::valueOrDefault(const type defaultValue)
552 {
553     if (!value_) {
554         return defaultValue;
555     }
556     napi_status status = napi_invalid_arg;
557     type value {};
558     if constexpr (BASE_NS::is_same_v<type, BASE_NS::string>) {
559         size_t length;
560         status = napi_get_value_string_utf8(env_, value_, nullptr, 0, &length);
561         if (status != napi_ok) {
562             // return default if failed.
563             return defaultValue;
564         }
565         value.reserve(length + 1);
566         value.resize(length);
567         status = napi_get_value_string_utf8(env_, value_, value.data(), length + 1, &length);
568     }
569     if constexpr (BASE_NS::is_same_v<type, bool>) {
570         status = napi_get_value_bool(env_, value_, &value);
571     }
572     if constexpr (BASE_NS::is_same_v<type, float>) {
573         double tmp;
574         status = napi_get_value_double(env_, value_, &tmp);
575         value = tmp;
576     }
577     if constexpr (BASE_NS::is_same_v<type, double>) {
578         status = napi_get_value_double(env_, value_, &value);
579     }
580     if constexpr (BASE_NS::is_same_v<type, uint32_t>) {
581         status = napi_get_value_uint32(env_, value_, &value);
582     }
583     if constexpr (BASE_NS::is_same_v<type, int32_t>) {
584         status = napi_get_value_int32(env_, value_, &value);
585     }
586     if constexpr (BASE_NS::is_same_v<type, int64_t>) {
587         status = napi_get_value_int64(env_, value_, &value);
588     }
589     if constexpr (BASE_NS::is_same_v<type, uint64_t>) {
590         int64_t tmp;
591         status = napi_get_value_int64(env_, value_, &tmp);
592         value = static_cast<uint64_t>(tmp);
593     }
594     if constexpr (BASE_NS::is_same_v<type, NapiApi::Object>) {
595         status = napi_ok;
596         value = NapiApi::Object(env_, value_);
597     }
598     if constexpr (BASE_NS::is_same_v<type, NapiApi::Function>) {
599         status = napi_ok;
600         value = NapiApi::Function(env_, value_);
601     }
602     if constexpr (BASE_NS::is_same_v<type, NapiApi::Array>) {
603         status = napi_ok;
604         value = NapiApi::Array(env_, value_);
605     }
606     if (status != napi_ok) {
607         // return default if failed.
608         return defaultValue;
609     }
610     return value;
611 }
612 
613 inline Object::Object(Function ctor)
614 {
615     env_ = ctor.GetEnv();
616     napi_new_instance(env_, ctor, 0, nullptr, &object_);
617 }
618 
619 inline Object::Object(Function ctor, size_t argc, napi_value args[])
620 {
621     env_ = ctor.GetEnv();
622     napi_new_instance(env_, ctor, argc, args, &object_);
623 }
624 
625 template<typename Object, napi_value (Object::*F)(NapiApi::FunctionContext<>&)>
626 static inline napi_value Getter(napi_env env, napi_callback_info info)
627 {
628     NapiApi::FunctionContext fc(env, info);
629     if (fc) {
630         NapiApi::Object me(env, fc.This());
631         if (me) {
632             if (auto scj = me.Native<Object>()) {
633                 if (auto ret = (scj->*F)(fc)) {
634                     return ret;
635                 }
636             }
637         }
638     }
639     napi_value undefineVar;
640     napi_get_undefined(env, &undefineVar);
641     return undefineVar;
642 };
643 
644 template<typename Type, typename Object, void (Object::*F)(NapiApi::FunctionContext<Type>&)>
645 static inline napi_value Setter(napi_env env, napi_callback_info info)
646 {
647     NapiApi::FunctionContext<Type> fc(env, info);
648     if (fc) {
649         NapiApi::Object me(env, fc.This());
650         if (me) {
651             if (auto scj = me.Native<Object>()) {
652                 (scj->*F)(fc);
653             }
654         }
655     }
656     napi_value undefineVar;
657     napi_get_undefined(env, &undefineVar);
658     return undefineVar;
659 };
660 
661 template<typename FC, typename Object, napi_value (Object::*F)(FC&)>
662 static inline napi_value MethodI(napi_env env, napi_callback_info info)
663 {
664     FC fc(env, info);
665     if (fc) {
666         NapiApi::Object me(env, fc.This());
667         if (me) {
668             if (auto scj = me.Native<Object>()) {
669                 return (scj->*F)(fc);
670             }
671         }
672     }
673     napi_value undefineVar;
674     napi_get_undefined(env, &undefineVar);
675     return undefineVar;
676 };
677 
678 template<typename FC, typename Object, napi_value (Object::*F)(FC&)>
679 static inline napi_property_descriptor Method(
680     const char* const name, napi_property_attributes flags = napi_default_method)
681 {
682     return napi_property_descriptor { name, nullptr, MethodI<FC, Object, F>, nullptr, nullptr, nullptr, flags,
683         nullptr };
684 }
685 
686 template<typename Type, typename Object, void (Object::*F2)(NapiApi::FunctionContext<Type>&)>
687 static inline napi_property_descriptor SetProperty(
688     const char* const name, napi_property_attributes flags = napi_default_jsproperty)
689 {
690     static_assert(F2 != nullptr);
691     return napi_property_descriptor { name, nullptr, nullptr, nullptr, Setter<Type, Object, F2>, nullptr, flags,
692         nullptr };
693 }
694 
695 template<typename Type, typename Object, napi_value (Object::*F)(NapiApi::FunctionContext<>&)>
696 static inline napi_property_descriptor GetProperty(
697     const char* const name, napi_property_attributes flags = napi_default_jsproperty)
698 {
699     static_assert(F != nullptr);
700     return napi_property_descriptor { name, nullptr, nullptr, Getter<Object, F>, nullptr, nullptr, flags, nullptr };
701 }
702 
703 template<typename Type, typename Object, napi_value (Object::*F)(NapiApi::FunctionContext<>&),
704     void (Object::*F2)(NapiApi::FunctionContext<Type>&)>
705 static inline napi_property_descriptor GetSetProperty(
706     const char* const name, napi_property_attributes flags = napi_default_jsproperty)
707 {
708     static_assert(F != nullptr);
709     static_assert(F2 != nullptr);
710     return napi_property_descriptor { name, nullptr, nullptr, Getter<Object, F>, Setter<Type, Object, F2>, nullptr,
711         flags, nullptr };
712 }
713 class WeakRef {
714     napi_env env_ { nullptr };
715     napi_ref ref_ { nullptr };
716 
717 public:
718     WeakRef() = default;
719     WeakRef(NapiApi::WeakRef&& ref) noexcept
720     {
721         env_ = ref.env_;
722         ref_ = ref.ref_;
723         ref.env_ = nullptr;
724         ref.ref_ = nullptr;
725     }
726 
727     WeakRef(const NapiApi::WeakRef& ref)
728     {
729         if (!ref.IsEmpty()) {
730             napi_status stat;
731             env_ = ref.env_;
732             stat = napi_create_reference(env_, ref.GetValue(), 0, &ref_);
733         }
734     }
735     NapiApi::WeakRef operator=(NapiApi::WeakRef&& ref) noexcept
736     {
737         env_ = ref.env_;
738         ref_ = ref.ref_;
739         ref.env_ = nullptr;
740         ref.ref_ = nullptr;
741         return *this;
742     }
743     NapiApi::WeakRef operator=(const NapiApi::WeakRef& ref)
744     {
745         if (&ref != this) {
746             if (!ref.IsEmpty()) {
747                 napi_status stat;
748                 // unh just create a new one..
749                 env_ = ref.env_;
750                 stat = napi_create_reference(env_, ref.GetValue(), 0, &ref_);
751             }
752         }
753         return *this;
754     }
755     WeakRef(NapiApi::Object obj)
756     {
757         env_ = obj.GetEnv();
758         napi_create_reference(env_, obj, 0, &ref_);
759     }
760     WeakRef(napi_env env, napi_value obj)
761     {
762         env_ = env;
763         napi_create_reference(env_, obj, 0, &ref_);
764     }
765     ~WeakRef()
766     {
767         Reset();
768     }
769     bool IsEmpty() const
770     {
771         if (env_ && ref_) {
772             // possibly actually check the ref?
773             return false;
774         }
775         return true;
776     }
777     NapiApi::Object GetObject()
778     {
779         if (env_ && ref_) {
780             napi_value value;
781             napi_get_reference_value(env_, ref_, &value);
782             return NapiApi::Object(env_, value);
783         }
784         return {};
785     }
786     napi_env GetEnv()
787     {
788         return env_;
789     }
790     napi_value GetValue() const
791     {
792         if (env_ && ref_) {
793             napi_value value;
794             napi_get_reference_value(env_, ref_, &value);
795             return value;
796         }
797         return {};
798     }
799     void Reset()
800     {
801         if (env_ && ref_) {
802             napi_delete_reference(env_, ref_);
803         }
804         env_ = nullptr;
805         ref_ = nullptr;
806     }
807 };
808 
809 class StrongRef {
810     napi_env env_ { nullptr };
811     napi_ref ref_ { nullptr };
812 
813 public:
814     StrongRef() = default;
815     StrongRef(NapiApi::StrongRef&& ref) noexcept
816     {
817         env_ = ref.env_;
818         ref_ = ref.ref_;
819         ref.env_ = nullptr;
820         ref.ref_ = nullptr;
821     }
822 
823     StrongRef(const NapiApi::StrongRef& ref)
824     {
825         if (!ref.IsEmpty()) {
826             napi_status stat;
827             env_ = ref.env_;
828 
829             // unh just create a new one..
830             stat = napi_create_reference(env_, ref.GetValue(), 1, &ref_);
831         }
832     }
833     NapiApi::StrongRef operator=(NapiApi::StrongRef&& ref) noexcept
834     {
835         env_ = ref.env_;
836         ref_ = ref.ref_;
837         ref.env_ = nullptr;
838         ref.ref_ = nullptr;
839         return *this;
840     }
841     NapiApi::StrongRef operator=(const NapiApi::StrongRef& ref)
842     {
843         if (&ref != this) {
844             if (!ref.IsEmpty()) {
845                 napi_status stat;
846                 // unh just create a new one..
847                 env_ = ref.env_;
848                 stat = napi_create_reference(env_, ref.GetValue(), 1, &ref_);
849             }
850         }
851         return *this;
852     }
853     StrongRef(NapiApi::Object obj)
854     {
855         env_ = obj.GetEnv();
856         napi_create_reference(env_, obj, 1, &ref_);
857     }
858     StrongRef(napi_env env, napi_value obj)
859     {
860         env_ = env;
861         napi_create_reference(env_, obj, 1, &ref_);
862     }
863     ~StrongRef()
864     {
865         Reset();
866     }
867     bool IsEmpty() const
868     {
869         if (env_ && ref_) {
870             // possibly actually check the ref?
871             return false;
872         }
873         return true;
874     }
875     NapiApi::Object GetObject()
876     {
877         if (env_ && ref_) {
878             napi_value value;
879             napi_get_reference_value(env_, ref_, &value);
880             return NapiApi::Object(env_, value);
881         }
882         return {};
883     }
884     napi_env GetEnv()
885     {
886         return env_;
887     }
888     napi_value GetValue() const
889     {
890         if (env_ && ref_) {
891             napi_value value;
892             napi_get_reference_value(env_, ref_, &value);
893             return value;
894         }
895         return {};
896     }
897     void Reset()
898     {
899         if (env_ && ref_) {
900             napi_delete_reference(env_, ref_);
901         }
902         env_ = nullptr;
903         ref_ = nullptr;
904     }
905 };
906 
907 template<typename T>
908 void Value<T>::Init(napi_env env, Type v)
909 {
910     if (env == nullptr) {
911         return;
912     }
913     env_ = env;
914     if constexpr (BASE_NS::is_same_v<Type, float>) {
915         napi_create_double(env_, v, &value_);
916     }
917     if constexpr (BASE_NS::is_same_v<Type, double>) {
918         napi_create_double(env_, v, &value_);
919     }
920     if constexpr (BASE_NS::is_same_v<Type, uint32_t>) {
921         napi_create_uint32(env_, v, &value_);
922     }
923     if constexpr (BASE_NS::is_same_v<Type, int32_t>) {
924         napi_create_int32(env_, v, &value_);
925     }
926     if constexpr (BASE_NS::is_same_v<Type, int64_t>) {
927         napi_create_int64(env_, v, &value_);
928     }
929     if constexpr (BASE_NS::is_same_v<Type, uint64_t>) {
930         int64_t tmp = static_cast<int64_t>(v);
931         napi_create_int64(env_, tmp, &value_);
932     }
933     if constexpr (BASE_NS::is_same_v<Type, NapiApi::Object>) {
934         value_ = v;
935     }
936 }
937 
938 } // namespace NapiApi
939 NapiApi::Object FetchJsObj(const META_NS::IObject::Ptr& obj);
940 template<typename t>
941 NapiApi::Object FetchJsObj(const t& obj)
942 {
943     return FetchJsObj(interface_pointer_cast<META_NS::IObject>(obj));
944 }
945 // creates a new reference to jsobj. returns napi_value from reference.
946 NapiApi::Object StoreJsObj(const META_NS::IObject::Ptr& obj, NapiApi::Object jsobj);
947 NapiApi::Function GetJSConstructor(napi_env env, const BASE_NS::string_view jsName);
948 
949 // extracts the uri from "string" or "Resource"
950 BASE_NS::string FetchResourceOrUri(napi_env e, napi_value arg);
951 BASE_NS::string FetchResourceOrUri(NapiApi::FunctionContext<>& ctx);
952 
953 // Instance data
954 napi_status SetInstanceData(napi_env env, void* data, napi_finalize finalizeCb, void* finalizeHint);
955 napi_status GetInstanceData(napi_env env, void** data);
956 
957 // little helper macros
958 
959 // declare NAPI_API_JS_NAME ...
960 #define NAPI_API_xs(s) NAPI_API_s(s)
961 #define NAPI_API_s(s) #s
962 #define NAPI_API_xcn(s) NAPI_API_cn(s)
963 #define NAPI_API_cn(s) s##JS
964 #define NAPI_API_JS_NAME_STRING NAPI_API_xs(NAPI_API_JS_NAME)
965 #define NAPI_API_CLASS_NAME NAPI_API_xcn(NAPI_API_JS_NAME)
966 
967 #define DeclareGet(type, name, getter) \
968     node_props.push_back(NapiApi::GetProperty<type, NAPI_API_CLASS_NAME, &NAPI_API_CLASS_NAME::getter>(name));
969 #define DeclareSet(type, name, setter) \
970     node_props.push_back(NapiApi::SetProperty<type, NAPI_API_CLASS_NAME, &NAPI_API_CLASS_NAME::setter>(name));
971 #define DeclareGetSet(type, name, getter, setter)                                                         \
972     node_props.push_back(NapiApi::GetSetProperty<type, NAPI_API_CLASS_NAME, &NAPI_API_CLASS_NAME::getter, \
973         &NAPI_API_CLASS_NAME::setter>(name));
974 #define DeclareMethod(name, function, ...)                                                                           \
975     node_props.push_back(                                                                                            \
976         NapiApi::Method<NapiApi::FunctionContext<__VA_ARGS__>, NAPI_API_CLASS_NAME, &NAPI_API_CLASS_NAME::function>( \
977             name));
978 #define DeclareClass()                                                                                      \
979     {                                                                                                       \
980         napi_value func;                                                                                    \
981         auto status = napi_define_class(env, NAPI_API_JS_NAME_STRING, NAPI_AUTO_LENGTH,                     \
982             BaseObject::ctor<NAPI_API_CLASS_NAME>(), nullptr, node_props.size(), node_props.data(), &func); \
983         NapiApi::MyInstanceState* mis;                                                                      \
984         GetInstanceData(env, (void**)&mis);                                                                 \
985         mis->StoreCtor(NAPI_API_JS_NAME_STRING, func);                                                      \
986     }
987 
988 #endif // OHOS_RENDER_3D_NAPI_API
989 
990