/* * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "ecmascript/jsnapi_sendable.h" #include "ecmascript/ecma_vm.h" #include "ecmascript/global_env.h" #include "ecmascript/napi/jsnapi_helper.h" #include "ecmascript/object_factory.h" #include "ecmascript/tagged_dictionary.h" #include "js_function.h" namespace panda::ecmascript { JSNapiSendable::JSNapiSendable(JSThread *thread, FunctionRef::SendablePropertiesInfos &infos, Local &name) { InitStaticDescription(thread, staticDescs_, name); InitNonStaticDescription(thread, nonStaticDescs_); InitInstanceDescription(thread, instanceDescs_); InitWithPropertiesInfo(thread, infos.staticPropertiesInfo, staticDescs_); InitWithPropertiesInfo(thread, infos.nonStaticPropertiesInfo, nonStaticDescs_); InitWithPropertiesInfo(thread, infos.instancePropertiesInfo, instanceDescs_); } void JSNapiSendable::SetSConstructor(JSHandle constructor) { nonStaticDescs_[0].SetValue(JSHandle::Cast(constructor)); } void JSNapiSendable::InitStaticDescription(JSThread *thread, std::vector &descs, Local &name) { const GlobalEnvConstants *globalConst = thread->GlobalConstants(); JSHandle nameKey = globalConst->GetHandledNameString(); PropertyDescriptor nameDesc(thread, false, false, false); nameDesc.SetKey(nameKey); nameDesc.SetSharedFieldType(SharedFieldType::STRING); nameDesc.SetValue(JSNApiHelper::ToJSHandle(name)); descs.push_back(nameDesc); JSHandle prototypeKey = globalConst->GetHandledPrototypeString(); PropertyDescriptor prototypeDesc(thread, false, false, false); prototypeDesc.SetKey(prototypeKey); prototypeDesc.SetSharedFieldType(SharedFieldType::SENDABLE); prototypeDesc.SetValue(globalConst->GetHandledNull()); descs.push_back(prototypeDesc); } void JSNapiSendable::InitNonStaticDescription(JSThread *thread, std::vector &descs) { const GlobalEnvConstants *globalConst = thread->GlobalConstants(); JSHandle constructorKey = globalConst->GetHandledConstructorString(); PropertyDescriptor constructorDesc(thread, false, false, false); constructorDesc.SetKey(constructorKey); constructorDesc.SetSharedFieldType(SharedFieldType::SENDABLE); constructorDesc.SetValue(globalConst->GetHandledNull()); descs.push_back(constructorDesc); } void JSNapiSendable::InitInstanceDescription(JSThread *thread, std::vector &descs) { const GlobalEnvConstants *globalConst = thread->GlobalConstants(); JSHandle napiWrapperKey = globalConst->GetHandledNapiWrapperString(); PropertyDescriptor napiWrapperDesc(thread, true, false, false); napiWrapperDesc.SetKey(napiWrapperKey); napiWrapperDesc.SetSharedFieldType(SharedFieldType::SENDABLE); napiWrapperDesc.SetValue(globalConst->GetHandledNull()); descs.push_back(napiWrapperDesc); } void JSNapiSendable::InitWithPropertiesInfo(JSThread *thread, FunctionRef::SendablePropertiesInfo &info, std::vector &descs) { EcmaVM *vm = thread->GetEcmaVM(); auto length = info.keys.size(); for (size_t i = 0; i < length; ++i) { PropertyDescriptor desc(thread, info.attributes[i].IsWritable(), info.attributes[i].IsEnumerable(), info.attributes[i].IsConfigurable()); desc.SetKey(JSNApiHelper::ToJSHandle(info.keys[i])); auto type = GetSharedFieldType(thread, info.types[i], info.attributes[i].GetValue(vm)); desc.SetSharedFieldType(type); desc.SetValue(JSNApiHelper::ToJSHandle(info.attributes[i].GetValue(vm))); descs.push_back(desc); } InitInstanceDescription(thread, descs); } SharedFieldType JSNapiSendable::GetSharedFieldType(JSThread *thread, FunctionRef::SendableType type, Local value) { switch (type) { case FunctionRef::SendableType::OBJECT: return SharedFieldType::SENDABLE; case FunctionRef::SendableType::GENERIC: return SharedFieldType::GENERIC; case FunctionRef::SendableType::NONE: { auto valueHandle = JSNApiHelper::ToJSHandle(value); if (valueHandle->IsUndefined()) { return SharedFieldType::NONE; } if (valueHandle->IsNull()) { // fixme: SharedFieldType::NULL ? return SharedFieldType::SENDABLE; } if (valueHandle->IsNumber()) { return SharedFieldType::NUMBER; } if (valueHandle->IsString()) { return SharedFieldType::STRING; } if (valueHandle->IsBoolean()) { return SharedFieldType::BOOLEAN; } if (valueHandle->IsJSShared()) { return SharedFieldType::SENDABLE; } if (valueHandle->IsBigInt()) { return SharedFieldType::BIG_INT; } THROW_TYPE_ERROR_AND_RETURN(thread, "Unknown SharedFieldType", SharedFieldType::NONE); } default: THROW_TYPE_ERROR_AND_RETURN(thread, "Unknown SharedFieldType", SharedFieldType::NONE); } } } // namespace panda::ecmascript