133eb0b6dSopenharmony_ci/* 233eb0b6dSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 333eb0b6dSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 433eb0b6dSopenharmony_ci * you may not use this file except in compliance with the License. 533eb0b6dSopenharmony_ci * You may obtain a copy of the License at 633eb0b6dSopenharmony_ci * 733eb0b6dSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 833eb0b6dSopenharmony_ci * 933eb0b6dSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1033eb0b6dSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1133eb0b6dSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1233eb0b6dSopenharmony_ci * See the License for the specific language governing permissions and 1333eb0b6dSopenharmony_ci * limitations under the License. 1433eb0b6dSopenharmony_ci */ 1533eb0b6dSopenharmony_ci 1633eb0b6dSopenharmony_ci#include "native_sendable.h" 1733eb0b6dSopenharmony_ci 1833eb0b6dSopenharmony_ci#include "ark_native_engine.h" 1933eb0b6dSopenharmony_ci#include "native_engine/native_utils.h" 2033eb0b6dSopenharmony_ci 2133eb0b6dSopenharmony_ciusing panda::ObjectRef; 2233eb0b6dSopenharmony_ciusing panda::StringRef; 2333eb0b6dSopenharmony_ciusing panda::SymbolRef; 2433eb0b6dSopenharmony_ci 2533eb0b6dSopenharmony_ciFunctionRef::SendablePropertiesInfos NativeSendable::CreateSendablePropertiesInfos( 2633eb0b6dSopenharmony_ci napi_env env, 2733eb0b6dSopenharmony_ci const NapiPropertyDescriptor* properties, 2833eb0b6dSopenharmony_ci size_t propertiesLength) 2933eb0b6dSopenharmony_ci{ 3033eb0b6dSopenharmony_ci FunctionRef::SendablePropertiesInfos infos; 3133eb0b6dSopenharmony_ci 3233eb0b6dSopenharmony_ci for (size_t i = 0; i < propertiesLength; ++i) { 3333eb0b6dSopenharmony_ci if (properties[i].attributes & NATIVE_STATIC) { 3433eb0b6dSopenharmony_ci InitSendablePropertiesInfo(env, infos.staticPropertiesInfo, properties[i]); 3533eb0b6dSopenharmony_ci } else if (properties[i].attributes & NATIVE_INSTANCE) { 3633eb0b6dSopenharmony_ci InitSendablePropertiesInfo(env, infos.instancePropertiesInfo, properties[i]); 3733eb0b6dSopenharmony_ci } else if (properties[i].attributes & NATIVE_INSTANCE_OBJECT) { 3833eb0b6dSopenharmony_ci InitSendablePropertiesInfo(env, infos.instancePropertiesInfo, properties[i], 3933eb0b6dSopenharmony_ci FunctionRef::SendableType::OBJECT); 4033eb0b6dSopenharmony_ci } else if (properties[i].attributes & NATIVE_INSTANCE_GENERIC) { 4133eb0b6dSopenharmony_ci InitSendablePropertiesInfo(env, infos.instancePropertiesInfo, properties[i], 4233eb0b6dSopenharmony_ci FunctionRef::SendableType::GENERIC); 4333eb0b6dSopenharmony_ci } else { 4433eb0b6dSopenharmony_ci InitSendablePropertiesInfo(env, infos.nonStaticPropertiesInfo, properties[i]); 4533eb0b6dSopenharmony_ci } 4633eb0b6dSopenharmony_ci } 4733eb0b6dSopenharmony_ci 4833eb0b6dSopenharmony_ci return infos; 4933eb0b6dSopenharmony_ci} 5033eb0b6dSopenharmony_ci 5133eb0b6dSopenharmony_civoid NativeSendable::InitSendablePropertiesInfo(napi_env env, 5233eb0b6dSopenharmony_ci FunctionRef::SendablePropertiesInfo& info, 5333eb0b6dSopenharmony_ci NapiPropertyDescriptor propertyDescriptor, 5433eb0b6dSopenharmony_ci FunctionRef::SendableType type) 5533eb0b6dSopenharmony_ci{ 5633eb0b6dSopenharmony_ci auto engine = reinterpret_cast<NativeEngine*>(env); 5733eb0b6dSopenharmony_ci auto vm = engine->GetEcmaVm(); 5833eb0b6dSopenharmony_ci 5933eb0b6dSopenharmony_ci bool writable = (propertyDescriptor.attributes & NATIVE_WRITABLE) != 0; 6033eb0b6dSopenharmony_ci bool enumable = (propertyDescriptor.attributes & NATIVE_ENUMERABLE) != 0; 6133eb0b6dSopenharmony_ci bool configable = (propertyDescriptor.attributes & NATIVE_CONFIGURABLE) != 0; 6233eb0b6dSopenharmony_ci 6333eb0b6dSopenharmony_ci Local<StringRef> key; 6433eb0b6dSopenharmony_ci if (propertyDescriptor.utf8name == nullptr) { 6533eb0b6dSopenharmony_ci key = LocalValueFromJsValue(propertyDescriptor.name); 6633eb0b6dSopenharmony_ci } else { 6733eb0b6dSopenharmony_ci key = StringRef::NewFromUtf8(vm, propertyDescriptor.utf8name); 6833eb0b6dSopenharmony_ci } 6933eb0b6dSopenharmony_ci info.keys.push_back(key); 7033eb0b6dSopenharmony_ci 7133eb0b6dSopenharmony_ci if (propertyDescriptor.getter != nullptr || propertyDescriptor.setter != nullptr) { 7233eb0b6dSopenharmony_ci Local<JSValueRef> localGetter = JSValueRef::Undefined(vm); 7333eb0b6dSopenharmony_ci Local<JSValueRef> localSetter = JSValueRef::Undefined(vm); 7433eb0b6dSopenharmony_ci 7533eb0b6dSopenharmony_ci if (propertyDescriptor.getter != nullptr) { 7633eb0b6dSopenharmony_ci localGetter = 7733eb0b6dSopenharmony_ci NapiNativeCreateSendableFunction(env, "getter", propertyDescriptor.getter, propertyDescriptor.data); 7833eb0b6dSopenharmony_ci } 7933eb0b6dSopenharmony_ci if (propertyDescriptor.setter != nullptr) { 8033eb0b6dSopenharmony_ci localSetter = 8133eb0b6dSopenharmony_ci NapiNativeCreateSendableFunction(env, "setter", propertyDescriptor.setter, propertyDescriptor.data); 8233eb0b6dSopenharmony_ci } 8333eb0b6dSopenharmony_ci 8433eb0b6dSopenharmony_ci Local<JSValueRef> val = ObjectRef::CreateSendableAccessorData(vm, localGetter, localSetter); 8533eb0b6dSopenharmony_ci info.types.push_back(FunctionRef::SendableType::OBJECT); 8633eb0b6dSopenharmony_ci info.attributes.push_back(PropertyAttribute(val, false, enumable, configable)); 8733eb0b6dSopenharmony_ci } else if (propertyDescriptor.method != nullptr) { 8833eb0b6dSopenharmony_ci std::string fullName; 8933eb0b6dSopenharmony_ci if (propertyDescriptor.utf8name != nullptr) { 9033eb0b6dSopenharmony_ci fullName += propertyDescriptor.utf8name; 9133eb0b6dSopenharmony_ci } else { 9233eb0b6dSopenharmony_ci fullName += key->IsString(vm) ? Local<StringRef>(key)->ToString(vm) 9333eb0b6dSopenharmony_ci : Local<SymbolRef>(key)->GetDescription(vm)->ToString(vm); 9433eb0b6dSopenharmony_ci } 9533eb0b6dSopenharmony_ci 9633eb0b6dSopenharmony_ci Local<JSValueRef> func = 9733eb0b6dSopenharmony_ci NapiNativeCreateSendableFunction(env, fullName.c_str(), propertyDescriptor.method, propertyDescriptor.data); 9833eb0b6dSopenharmony_ci info.types.push_back(FunctionRef::SendableType::OBJECT); 9933eb0b6dSopenharmony_ci info.attributes.push_back(PropertyAttribute(func, writable, enumable, configable)); 10033eb0b6dSopenharmony_ci } else { 10133eb0b6dSopenharmony_ci Local<JSValueRef> val = LocalValueFromJsValue(propertyDescriptor.value); 10233eb0b6dSopenharmony_ci info.types.push_back(type); 10333eb0b6dSopenharmony_ci info.attributes.push_back(PropertyAttribute(val, writable, enumable, configable)); 10433eb0b6dSopenharmony_ci } 10533eb0b6dSopenharmony_ci} 10633eb0b6dSopenharmony_ci 10733eb0b6dSopenharmony_ciLocal<JSValueRef> NativeSendable::NapiNativeCreateSendableFunction(napi_env env, 10833eb0b6dSopenharmony_ci const char* name, 10933eb0b6dSopenharmony_ci NapiNativeCallback cb, 11033eb0b6dSopenharmony_ci void* value) 11133eb0b6dSopenharmony_ci{ 11233eb0b6dSopenharmony_ci auto engine = reinterpret_cast<NativeEngine*>(env); 11333eb0b6dSopenharmony_ci auto vm = const_cast<EcmaVM*>(engine->GetEcmaVm()); 11433eb0b6dSopenharmony_ci NapiFunctionInfo* funcInfo = NapiFunctionInfo::CreateNewInstance(); 11533eb0b6dSopenharmony_ci if (funcInfo == nullptr) { 11633eb0b6dSopenharmony_ci HILOG_ERROR("funcInfo is nullptr"); 11733eb0b6dSopenharmony_ci return JSValueRef::Undefined(vm); 11833eb0b6dSopenharmony_ci } 11933eb0b6dSopenharmony_ci funcInfo->callback = cb; 12033eb0b6dSopenharmony_ci funcInfo->data = value; 12133eb0b6dSopenharmony_ci 12233eb0b6dSopenharmony_ci Local<FunctionRef> fn = FunctionRef::NewSendable( 12333eb0b6dSopenharmony_ci vm, ArkNativeFunctionCallBack, 12433eb0b6dSopenharmony_ci [](void* env, void* externalPointer, void* data) { 12533eb0b6dSopenharmony_ci auto info = reinterpret_cast<NapiFunctionInfo*>(data); 12633eb0b6dSopenharmony_ci if (info != nullptr) { 12733eb0b6dSopenharmony_ci delete info; 12833eb0b6dSopenharmony_ci } 12933eb0b6dSopenharmony_ci }, 13033eb0b6dSopenharmony_ci reinterpret_cast<void*>(funcInfo), true); 13133eb0b6dSopenharmony_ci return fn; 13233eb0b6dSopenharmony_ci} 13333eb0b6dSopenharmony_ci 13433eb0b6dSopenharmony_civoid NativeSendable::NapiDefineSendabledProperty(napi_env env, 13533eb0b6dSopenharmony_ci Local<ObjectRef>& obj, 13633eb0b6dSopenharmony_ci NapiPropertyDescriptor& propertyDescriptor, 13733eb0b6dSopenharmony_ci Local<JSValueRef>& propertyName, 13833eb0b6dSopenharmony_ci bool& result) 13933eb0b6dSopenharmony_ci{ 14033eb0b6dSopenharmony_ci auto engine = reinterpret_cast<NativeEngine*>(env); 14133eb0b6dSopenharmony_ci auto vm = engine->GetEcmaVm(); 14233eb0b6dSopenharmony_ci 14333eb0b6dSopenharmony_ci bool enumable = (propertyDescriptor.attributes & NATIVE_ENUMERABLE) != 0; 14433eb0b6dSopenharmony_ci bool configable = (propertyDescriptor.attributes & NATIVE_CONFIGURABLE) != 0; 14533eb0b6dSopenharmony_ci 14633eb0b6dSopenharmony_ci if (propertyDescriptor.getter != nullptr || propertyDescriptor.setter != nullptr) { 14733eb0b6dSopenharmony_ci Local<JSValueRef> localGetter = JSValueRef::Undefined(vm); 14833eb0b6dSopenharmony_ci Local<JSValueRef> localSetter = JSValueRef::Undefined(vm); 14933eb0b6dSopenharmony_ci 15033eb0b6dSopenharmony_ci if (propertyDescriptor.getter != nullptr) { 15133eb0b6dSopenharmony_ci localGetter = 15233eb0b6dSopenharmony_ci NapiNativeCreateSendableFunction(env, "getter", propertyDescriptor.getter, propertyDescriptor.data); 15333eb0b6dSopenharmony_ci } 15433eb0b6dSopenharmony_ci if (propertyDescriptor.setter != nullptr) { 15533eb0b6dSopenharmony_ci localSetter = 15633eb0b6dSopenharmony_ci NapiNativeCreateSendableFunction(env, "setter", propertyDescriptor.setter, propertyDescriptor.data); 15733eb0b6dSopenharmony_ci } 15833eb0b6dSopenharmony_ci 15933eb0b6dSopenharmony_ci PropertyAttribute attr(JSValueRef::Undefined(vm), false, enumable, configable); 16033eb0b6dSopenharmony_ci // note(lzl): SetSendableAccessorProperty? 16133eb0b6dSopenharmony_ci result = obj->SetAccessorProperty(vm, propertyName, localGetter, localSetter, attr); 16233eb0b6dSopenharmony_ci } else if (propertyDescriptor.method != nullptr) { 16333eb0b6dSopenharmony_ci std::string fullName; 16433eb0b6dSopenharmony_ci if (propertyDescriptor.utf8name != nullptr) { 16533eb0b6dSopenharmony_ci fullName += propertyDescriptor.utf8name; 16633eb0b6dSopenharmony_ci } else { 16733eb0b6dSopenharmony_ci fullName += propertyName->IsString(vm) ? Local<StringRef>(propertyName)->ToString(vm) 16833eb0b6dSopenharmony_ci : Local<SymbolRef>(propertyName)->GetDescription(vm)->ToString(vm); 16933eb0b6dSopenharmony_ci } 17033eb0b6dSopenharmony_ci 17133eb0b6dSopenharmony_ci Local<JSValueRef> func = 17233eb0b6dSopenharmony_ci NapiNativeCreateSendableFunction(env, fullName.c_str(), propertyDescriptor.method, propertyDescriptor.data); 17333eb0b6dSopenharmony_ci result = obj->Set(vm, propertyName, func); 17433eb0b6dSopenharmony_ci } else { 17533eb0b6dSopenharmony_ci Local<JSValueRef> val = LocalValueFromJsValue(propertyDescriptor.value); 17633eb0b6dSopenharmony_ci result = obj->Set(vm, propertyName, val); 17733eb0b6dSopenharmony_ci } 17833eb0b6dSopenharmony_ci} 179