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