1 /*
2 * Copyright (C) 2025 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 "TrueRootObject.h"
17
18 #include <napi_api.h>
19
20 #include "BaseObjectJS.h"
21
TrueRootObject(napi_env env,napi_callback_info info)22 TrueRootObject::TrueRootObject(napi_env env, napi_callback_info info)
23 {
24 if (auto getOnlyFirstArg = NapiApi::FunctionContext<NapiApi::Object>(env, info, NapiApi::ArgCount::PARTIAL)) {
25 auto firstArg = NapiApi::Object { getOnlyFirstArg.Arg<0>() };
26 ExtractNativeObject(firstArg);
27 }
28 }
29
IsStrong() const30 bool TrueRootObject::IsStrong() const
31 {
32 return obj_ != nullptr;
33 }
34
GetNativeObject() const35 META_NS::IObject::Ptr TrueRootObject::GetNativeObject() const
36 {
37 if (obj_) {
38 return obj_;
39 }
40 return objW_.lock();
41 }
42
SetNativeObject(META_NS::IObject::Ptr real,PtrType ptrType)43 void TrueRootObject::SetNativeObject(META_NS::IObject::Ptr real, PtrType ptrType)
44 {
45 if (ptrType == PtrType::STRONG) {
46 obj_ = real;
47 objW_ = nullptr;
48 } else {
49 obj_ = nullptr;
50 objW_ = real;
51 }
52 }
53
UnsetNativeObject()54 void TrueRootObject::UnsetNativeObject()
55 {
56 obj_ = nullptr;
57 objW_ = nullptr;
58 }
59
Finalize(napi_env env)60 void TrueRootObject::Finalize(napi_env env)
61 {
62 // Synchronously destroy the lume object in engine thread.. (only for strong refs.)
63 if (obj_) {
64 ExecSyncTask([obj = BASE_NS::move(obj_)]() { return META_NS::IAny::Ptr {}; });
65 }
66 // and reset the weak ref too. (which may be null anyway)
67 objW_.reset();
68 }
69
destroy(TrueRootObject * object)70 void TrueRootObject::destroy(TrueRootObject* object)
71 {
72 delete object;
73 }
74
ExtractNativeObject(NapiApi::Object & resourceParam)75 void TrueRootObject::ExtractNativeObject(NapiApi::Object& resourceParam)
76 {
77 const auto env = resourceParam.GetEnv();
78 const auto nativeObjStash = resourceParam.Get("NativeObject");
79 auto ptrTypeJs = resourceParam.Get<uint32_t>("NativeObjectPtrType");
80 if (!nativeObjStash || !ptrTypeJs.IsValid()) {
81 // Okay, not created via injecting a native object.
82 return;
83 }
84
85 napi_value undefined;
86 napi_get_undefined(env, &undefined);
87 resourceParam.Set("NativeObject", undefined);
88 resourceParam.Set("NativeObjectPtrType", undefined);
89
90 META_NS::IObject::Ptr metaPtr;
91 InjectedNativeObject* ptr { nullptr };
92 napi_get_value_external(env, nativeObjStash, (void**)&ptr);
93 if (ptr == nullptr || !(metaPtr = ptr->Reset())) {
94 LOG_E("Unable to wrap a native object with TrueRootObject: Native object was null");
95 assert(false);
96 return;
97 }
98 SetNativeObject(metaPtr, static_cast<PtrType>(ptrTypeJs.valueOrDefault()));
99 }
100
101 // TrueRootObject stores the pointer to native. Pass the pointer and strength info over there.
InjectNativeObject(napi_env env,const META_NS::IObject::Ptr & obj,PtrType ptrType,NapiApi::JsFuncArgs & args)102 void TrueRootObject::InjectNativeObject(
103 napi_env env, const META_NS::IObject::Ptr& obj, PtrType ptrType, NapiApi::JsFuncArgs& args)
104 {
105 if (args.argc == 0) {
106 LOG_E("Empty arg list given for native object injection");
107 assert(false);
108 return;
109 }
110 const auto tmpPtr = new TrueRootObject::InjectedNativeObject(obj);
111 const auto deleteTmpPtr = [](napi_env env, void* obj, void* finalize_info) {
112 delete (TrueRootObject::InjectedNativeObject*)obj;
113 };
114 napi_value nativeObjStash;
115 napi_status status = napi_create_external(env, (void*)tmpPtr, deleteTmpPtr, nullptr, &nativeObjStash);
116 if (status != napi_ok) {
117 LOG_E("napi_create_external failed");
118 delete tmpPtr;
119 }
120
121 NapiApi::Object resourceParam(env, args.argv[0]);
122 resourceParam.Set("NativeObject", nativeObjStash);
123 resourceParam.Set("NativeObjectPtrType", NapiApi::Env { env }.GetNumber(static_cast<uint32_t>(ptrType)));
124 }
125
InjectedNativeObject(const META_NS::IObject::Ptr & obj)126 TrueRootObject::InjectedNativeObject::InjectedNativeObject(const META_NS::IObject::Ptr& obj)
127 {
128 object_ = obj;
129 }
Reset()130 META_NS::IObject::Ptr TrueRootObject::InjectedNativeObject::Reset()
131 {
132 return BASE_NS::move(object_);
133 }
134