From e5ca62b3a679df83e0a040bd29033353691f532d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=81=E5=AE=B6=E7=86=99?= Date: Tue, 3 Jun 2025 17:37:12 +0800 Subject: [PATCH] Fix Readonly and Required hide function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/IC3JW0 Signed-off-by: 梁家熙 --- ets2panda/checker/ets/utilityTypeHandlers.cpp | 10 ++- ets2panda/checker/types/ets/etsObjectType.cpp | 79 ++++++++++++++++++- ets2panda/checker/types/ets/etsObjectType.h | 11 +++ 3 files changed, 96 insertions(+), 4 deletions(-) diff --git a/ets2panda/checker/ets/utilityTypeHandlers.cpp b/ets2panda/checker/ets/utilityTypeHandlers.cpp index e893a1a951..d2849c5747 100644 --- a/ets2panda/checker/ets/utilityTypeHandlers.cpp +++ b/ets2panda/checker/ets/utilityTypeHandlers.cpp @@ -970,8 +970,9 @@ Type *ETSChecker::GetReadonlyType(Type *type) } if (type->IsETSObjectType()) { - type->AsETSObjectType()->InstanceFields(); auto *clonedType = type->Clone(this)->AsETSObjectType(); + clonedType->AsETSObjectType()->SetNoInstanceMethod(true); + clonedType->AsETSObjectType()->InstanceFields(); MakePropertiesReadonly(clonedType); return clonedType; } @@ -1035,12 +1036,12 @@ Type *ETSChecker::HandleRequiredType(Type *typeToBeRequired) return CreateETSUnionType(std::move(unionTypes)); } + typeToBeRequired = typeToBeRequired->Clone(this); if (typeToBeRequired->IsETSObjectType()) { + typeToBeRequired->AsETSObjectType()->SetNoInstanceMethod(true); typeToBeRequired->AsETSObjectType()->InstanceFields(); // call to instantiate properties } - typeToBeRequired = typeToBeRequired->Clone(this); - MakePropertiesNonNullish(typeToBeRequired->AsETSObjectType()); return typeToBeRequired; @@ -1061,6 +1062,9 @@ void ETSChecker::MakePropertiesNonNullish(ETSObjectType *const classType) if (classType->SuperType() != nullptr) { auto *const superRequired = classType->SuperType()->Clone(this)->AsETSObjectType(); + if (classType->NoInstanceMethod()) { + superRequired->SetNoInstanceMethod(true); + } MakePropertiesNonNullish(superRequired); classType->SetSuperType(superRequired); } diff --git a/ets2panda/checker/types/ets/etsObjectType.cpp b/ets2panda/checker/types/ets/etsObjectType.cpp index e7d2fb4229..6a2f217138 100644 --- a/ets2panda/checker/types/ets/etsObjectType.cpp +++ b/ets2panda/checker/types/ets/etsObjectType.cpp @@ -81,6 +81,24 @@ varbinder::LocalVariable *ETSObjectType::SearchFieldsDecls(util::StringView name return res; } +static bool CheckIfInterfaceNoMethod(const ETSObjectType *type, const varbinder::LocalVariable *var) +{ + // If type is set NoInstanceMethod flag, it must be established from Readonly or Required object + if (!type->NoInstanceMethod() || var == nullptr) { + return false; + } + + // Only filter function types, regular member objects are not filtered + auto *funcType = var->TsType(); + if (funcType == nullptr || !funcType->IsETSFunctionType()) { + return false; + } + + // In interface, memberType will create get and set function. These function are not filtered + return funcType->AsETSFunctionType()->FindGetter() == nullptr && + funcType->AsETSFunctionType()->FindSetter() == nullptr; +} + varbinder::LocalVariable *ETSObjectType::GetProperty(util::StringView name, PropertySearchFlags flags) const { // CC-OFFNXT(G.FMT.14-CPP) project code style @@ -117,7 +135,8 @@ varbinder::LocalVariable *ETSObjectType::GetProperty(util::StringView name, Prop if (((flags & PropertySearchFlags::SEARCH_INSTANCE) != 0 || (flags & PropertySearchFlags::SEARCH_STATIC) == 0) && (flags & PropertySearchFlags::SEARCH_IN_INTERFACES) != 0) { for (auto *interface : interfaces_) { - if (auto res = interface->GetProperty(name, flags); res != nullptr) { + if (auto res = interface->GetProperty(name, flags); + (res != nullptr && !CheckIfInterfaceNoMethod(this, res))) { return res; } } @@ -378,6 +397,9 @@ varbinder::LocalVariable *ETSObjectType::CollectSignaturesForSyntheticType(std:: if ((flags & PropertySearchFlags::SEARCH_IN_INTERFACES) != 0) { for (auto *interface : Interfaces()) { + if (NoInstanceMethod()) { + flags &= ~PropertySearchFlags::SEARCH_INSTANCE_METHOD; + } interface->CollectSignaturesForSyntheticType(signatures, name, flags, overloadDeclarationCall); } } @@ -1107,6 +1129,7 @@ Type *ETSObjectType::Instantiate(ArenaAllocator *const allocator, TypeRelation * copiedType->propertiesInstantiated_ = false; copiedType->relation_ = relation; copiedType->effectiveSubstitution_ = nullptr; + copiedType->SetNoInstanceMethod(NoInstanceMethod()); relation->DecreaseTypeRecursionCount(base); @@ -1236,6 +1259,9 @@ void ETSObjectType::UpdateTypeProperties(PropertyProcesser const &func) SuperType() ->Instantiate(allocator_, relation_, relation_->GetChecker()->GetGlobalTypesHolder()) ->AsETSObjectType(); + if (NoInstanceMethod()) { + superProp->SetNoInstanceMethod(true); + } superProp->UpdateTypeProperties(func); SetSuperType(superProp); } @@ -1385,6 +1411,54 @@ ETSChecker *ETSObjectType::GetETSChecker() return relation_->GetChecker()->AsETSChecker(); } +static bool CheckMethodPropertyMember(const util::StringView &propName, const ir::ScriptFunction *funcDecl) +{ + if (propName.Mutf8().find(compiler::Signatures::PROPERTY, 0) == std::string::npos) { + return false; + } + + if (funcDecl->Id() == nullptr) { + return false; + } + + std::string name = propName.Mutf8().substr(compiler::Signatures::PROPERTY.size()); + return name == funcDecl->Id()->Name().Mutf8(); +} + +static bool ShouldSkipMethodProp(const ETSObjectType *type, const varbinder::LocalVariable *prop) +{ + // If type is set NoInstanceMethod flag, it must be established from Readonly or Required object + // If type is Array, its $_get function should not be skipped, so return false + if (!type->NoInstanceMethod() || type->IsETSResizableArrayType()) { + return false; + } + + // Ensure prop's Declaration is a method and has its function + if (prop == nullptr || prop->Declaration() == nullptr || prop->Declaration()->Node() == nullptr || + !prop->Declaration()->Node()->IsMethodDefinition() || + prop->Declaration()->Node()->AsMethodDefinition()->Function() == nullptr) { + return false; + } + + // In interface, memberType will create get and set function. These function are not filtered + auto *funcDecl = prop->Declaration()->Node()->AsMethodDefinition()->Function(); + if (type->HasObjectFlag(ETSObjectFlags::INTERFACE) && (funcDecl->IsGetter() || funcDecl->IsSetter())) { + return false; + } + + // If object implements interface, properties defined by interface will be parsed into getter and setter functions + // If property's name is "i", the function's name in object is "i" + // We will match the function's name without "" prefix here. If matched, we will not skip this function + for (auto const &[_, p] : type->GetBaseType()->InstanceFields()) { + (void)_; + if (CheckMethodPropertyMember(p->Name(), funcDecl) && (funcDecl->IsGetter() || funcDecl->IsSetter())) { + return false; + } + } + + return true; +} + void ETSObjectType::InstantiateProperties() const { ES2PANDA_ASSERT(relation_ != nullptr); @@ -1422,6 +1496,9 @@ void ETSObjectType::InstantiateProperties() const for (auto const &[_, prop] : baseType_->InstanceMethods()) { (void)_; auto *copiedProp = CopyPropertyWithTypeArguments(prop, relation_, &subst); + if (ShouldSkipMethodProp(this, copiedProp)) { + continue; + } properties_[static_cast(PropertyType::INSTANCE_METHOD)].emplace(prop->Name(), copiedProp); } diff --git a/ets2panda/checker/types/ets/etsObjectType.h b/ets2panda/checker/types/ets/etsObjectType.h index 2f81c4be7c..70039174d9 100644 --- a/ets2panda/checker/types/ets/etsObjectType.h +++ b/ets2panda/checker/types/ets/etsObjectType.h @@ -403,6 +403,16 @@ public: return propertiesInstantiated_; } + void SetNoInstanceMethod(bool noInstanceMethod) + { + noInstanceMethod_ = noInstanceMethod; + } + + bool NoInstanceMethod() const + { + return noInstanceMethod_; + } + protected: virtual ETSFunctionType *CreateMethodTypeForProp(util::StringView name) const; @@ -481,6 +491,7 @@ private: mutable bool propertiesInstantiated_ = false; mutable ArenaVector constructSignatures_; mutable PropertyHolder properties_; + mutable bool noInstanceMethod_ = false; }; } // namespace ark::es2panda::checker -- Gitee