• 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 #include "native_sendable.h"
17 
18 #include "ark_native_engine.h"
19 #include "native_engine/native_utils.h"
20 
21 using panda::ObjectRef;
22 using panda::StringRef;
23 using panda::SymbolRef;
24 using PropertyAttribute = panda::PropertyAttribute;
25 
CreateSendablePropertiesInfos(napi_env env,const NapiPropertyDescriptor * properties,size_t propertiesLength)26 FunctionRef::SendablePropertiesInfos NativeSendable::CreateSendablePropertiesInfos(
27     napi_env env,
28     const NapiPropertyDescriptor* properties,
29     size_t propertiesLength)
30 {
31     FunctionRef::SendablePropertiesInfos infos;
32 
33     for (size_t i = 0; i < propertiesLength; ++i) {
34         if (properties[i].attributes & NATIVE_STATIC) {
35             InitSendablePropertiesInfo(env, infos.staticPropertiesInfo, properties[i]);
36         } else if (properties[i].attributes & NATIVE_INSTANCE) {
37             InitSendablePropertiesInfo(env, infos.instancePropertiesInfo, properties[i]);
38         } else if (properties[i].attributes & NATIVE_INSTANCE_OBJECT) {
39             InitSendablePropertiesInfo(env, infos.instancePropertiesInfo, properties[i],
40                                        FunctionRef::SendableType::OBJECT);
41         } else if (properties[i].attributes & NATIVE_INSTANCE_GENERIC) {
42             InitSendablePropertiesInfo(env, infos.instancePropertiesInfo, properties[i],
43                                        FunctionRef::SendableType::GENERIC);
44         } else {
45             InitSendablePropertiesInfo(env, infos.nonStaticPropertiesInfo, properties[i]);
46         }
47     }
48 
49     return infos;
50 }
51 
InitSendablePropertiesInfo(napi_env env,FunctionRef::SendablePropertiesInfo & info,NapiPropertyDescriptor propertyDescriptor,FunctionRef::SendableType type)52 void NativeSendable::InitSendablePropertiesInfo(napi_env env,
53                                                 FunctionRef::SendablePropertiesInfo& info,
54                                                 NapiPropertyDescriptor propertyDescriptor,
55                                                 FunctionRef::SendableType type)
56 {
57     auto engine = reinterpret_cast<NativeEngine*>(env);
58     auto vm = engine->GetEcmaVm();
59 
60     bool writable = (propertyDescriptor.attributes & NATIVE_WRITABLE) != 0;
61     bool enumable = (propertyDescriptor.attributes & NATIVE_ENUMERABLE) != 0;
62     bool configable = (propertyDescriptor.attributes & NATIVE_CONFIGURABLE) != 0;
63 
64     Local<StringRef> key;
65     if (propertyDescriptor.utf8name == nullptr) {
66         key = LocalValueFromJsValue(propertyDescriptor.name);
67     } else {
68         key = StringRef::NewFromUtf8(vm, propertyDescriptor.utf8name);
69     }
70     info.keys.push_back(key);
71 
72     if (propertyDescriptor.getter != nullptr || propertyDescriptor.setter != nullptr) {
73         Local<JSValueRef> localGetter = JSValueRef::Undefined(vm);
74         Local<JSValueRef> localSetter = JSValueRef::Undefined(vm);
75 
76         if (propertyDescriptor.getter != nullptr) {
77             localGetter =
78                 NapiNativeCreateSendableFunction(env, "getter", propertyDescriptor.getter, propertyDescriptor.data);
79         }
80         if (propertyDescriptor.setter != nullptr) {
81             localSetter =
82                 NapiNativeCreateSendableFunction(env, "setter", propertyDescriptor.setter, propertyDescriptor.data);
83         }
84 
85         Local<JSValueRef> val = ObjectRef::CreateSendableAccessorData(vm, localGetter, localSetter);
86         info.types.push_back(FunctionRef::SendableType::OBJECT);
87         info.attributes.push_back(PropertyAttribute(val, false, enumable, configable));
88     } else if (propertyDescriptor.method != nullptr) {
89         std::string fullName;
90         if (propertyDescriptor.utf8name != nullptr) {
91             fullName += propertyDescriptor.utf8name;
92         } else {
93             fullName += key->IsString(vm) ? Local<StringRef>(key)->ToString(vm)
94                                           : Local<SymbolRef>(key)->GetDescription(vm)->ToString(vm);
95         }
96 
97         Local<JSValueRef> func =
98             NapiNativeCreateSendableFunction(env, fullName.c_str(), propertyDescriptor.method, propertyDescriptor.data);
99         info.types.push_back(FunctionRef::SendableType::OBJECT);
100         info.attributes.push_back(PropertyAttribute(func, writable, enumable, configable));
101     } else {
102         Local<JSValueRef> val = LocalValueFromJsValue(propertyDescriptor.value);
103         info.types.push_back(type);
104         info.attributes.push_back(PropertyAttribute(val, writable, enumable, configable));
105     }
106 }
107 
NapiNativeCreateSendableFunction(napi_env env,const char * name,NapiNativeCallback cb,void * value)108 Local<JSValueRef> NativeSendable::NapiNativeCreateSendableFunction(napi_env env,
109                                                                    const char* name,
110                                                                    NapiNativeCallback cb,
111                                                                    void* value)
112 {
113     auto engine = reinterpret_cast<NativeEngine*>(env);
114     auto vm = const_cast<EcmaVM*>(engine->GetEcmaVm());
115     NapiFunctionInfo* funcInfo = NapiFunctionInfo::CreateNewInstance();
116     if (funcInfo == nullptr) {
117         HILOG_ERROR("funcInfo is nullptr");
118         return JSValueRef::Undefined(vm);
119     }
120     funcInfo->callback = cb;
121     funcInfo->data = value;
122     funcInfo->isSendable = true;
123 
124     Local<FunctionRef> fn = FunctionRef::NewSendable(vm, ArkNativeFunctionCallBack, CommonDeleter,
125                                                      reinterpret_cast<void*>(funcInfo), true);
126     return fn;
127 }
128 
NapiDefineSendabledProperty(napi_env env,Local<ObjectRef> & obj,NapiPropertyDescriptor & propertyDescriptor,Local<JSValueRef> & propertyName,bool & result)129 void NativeSendable::NapiDefineSendabledProperty(napi_env env,
130                                                  Local<ObjectRef>& obj,
131                                                  NapiPropertyDescriptor& propertyDescriptor,
132                                                  Local<JSValueRef>& propertyName,
133                                                  bool& result)
134 {
135     auto engine = reinterpret_cast<NativeEngine*>(env);
136     auto vm = engine->GetEcmaVm();
137 
138     bool enumable = (propertyDescriptor.attributes & NATIVE_ENUMERABLE) != 0;
139     bool configable = (propertyDescriptor.attributes & NATIVE_CONFIGURABLE) != 0;
140 
141     if (propertyDescriptor.getter != nullptr || propertyDescriptor.setter != nullptr) {
142         Local<JSValueRef> localGetter = JSValueRef::Undefined(vm);
143         Local<JSValueRef> localSetter = JSValueRef::Undefined(vm);
144 
145         if (propertyDescriptor.getter != nullptr) {
146             localGetter =
147                 NapiNativeCreateSendableFunction(env, "getter", propertyDescriptor.getter, propertyDescriptor.data);
148         }
149         if (propertyDescriptor.setter != nullptr) {
150             localSetter =
151                 NapiNativeCreateSendableFunction(env, "setter", propertyDescriptor.setter, propertyDescriptor.data);
152         }
153 
154         PropertyAttribute attr(JSValueRef::Undefined(vm), false, enumable, configable);
155         // note(lzl): SetSendableAccessorProperty?
156         result = obj->SetAccessorProperty(vm, propertyName, localGetter, localSetter, attr);
157     } else if (propertyDescriptor.method != nullptr) {
158         std::string fullName;
159         if (propertyDescriptor.utf8name != nullptr) {
160             fullName += propertyDescriptor.utf8name;
161         } else {
162             fullName += propertyName->IsString(vm) ? Local<StringRef>(propertyName)->ToString(vm)
163                                                    : Local<SymbolRef>(propertyName)->GetDescription(vm)->ToString(vm);
164         }
165 
166         Local<JSValueRef> func =
167             NapiNativeCreateSendableFunction(env, fullName.c_str(), propertyDescriptor.method, propertyDescriptor.data);
168         result = obj->Set(vm, propertyName, func);
169     } else {
170         Local<JSValueRef> val = LocalValueFromJsValue(propertyDescriptor.value);
171         result = obj->Set(vm, propertyName, val);
172     }
173 }
174