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