diff --git a/runtime/src/main/cpp/ObjCExport.mm b/runtime/src/main/cpp/ObjCExport.mm index 95e5792ac49..517077bfa6f 100644 --- a/runtime/src/main/cpp/ObjCExport.mm +++ b/runtime/src/main/cpp/ObjCExport.mm @@ -673,17 +673,34 @@ static void addDefinedSelectors(Class clazz, KStdUnorderedSet& result) { static KStdVector getProtocolsAsInterfaces(Class clazz) { KStdVector result; + KStdUnorderedSet handledProtocols; + KStdVector protocolsToHandle; - unsigned int protocolCount; - Protocol** protocols = class_copyProtocolList(clazz, &protocolCount); - if (protocols == nullptr) return result; - - for (int i = 0; i < protocolCount; ++i) { - Protocol* protocol = protocols[i]; - const ObjCTypeAdapter* typeAdapter = findProtocolAdapter(protocol); - if (typeAdapter != nullptr) result.push_back(typeAdapter->kotlinTypeInfo); + { + unsigned int protocolCount; + Protocol** protocols = class_copyProtocolList(clazz, &protocolCount); + if (protocols != nullptr) { + protocolsToHandle.insert(protocolsToHandle.end(), protocols, protocols + protocolCount); + free(protocols); + } + } + + while (!protocolsToHandle.empty()) { + Protocol* proto = protocolsToHandle[protocolsToHandle.size() - 1]; + protocolsToHandle.pop_back(); + + if (handledProtocols.insert(proto).second) { + const ObjCTypeAdapter* typeAdapter = findProtocolAdapter(proto); + if (typeAdapter != nullptr) result.push_back(typeAdapter->kotlinTypeInfo); + + unsigned int protocolCount; + Protocol** protocols = protocol_copyProtocolList(proto, &protocolCount); + if (protocols != nullptr) { + protocolsToHandle.insert(protocolsToHandle.end(), protocols, protocols + protocolCount); + free(protocols); + } + } } - if (protocols != nullptr) free(protocols); return result; }