Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: d9672f0e75352880994a81f213bfd3bd560141b0
https://github.com/WebKit/WebKit/commit/d9672f0e75352880994a81f213bfd3bd560141b0
Author: David Kilzer <[email protected]>
Date: 2025-12-21 (Sun, 21 Dec 2025)
Changed paths:
M Source/WTF/WTF.xcodeproj/project.pbxproj
M Source/WTF/wtf/cf/TypeCastsCF.h
M Source/WTF/wtf/cocoa/TypeCastsCocoa.h
A Source/WTF/wtf/darwin/TypeCastsOSObject.h
M Source/WebCore/platform/network/cf/DNSResolveQueueCFNet.cpp
M Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm
M Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
A Tools/TestWebKitAPI/Tests/WTF/darwin/TypeCastsOSObjectCF.cpp
A Tools/TestWebKitAPI/Tests/WTF/darwin/TypeCastsOSObjectCocoa.mm
A Tools/TestWebKitAPI/Tests/WTF/darwin/TypeCastsOSObjectCocoaARC.mm
Log Message:
-----------
Add checked/dynamic casts for OSObjectPtr
<https://bugs.webkit.org/show_bug.cgi?id=297639>
<rdar://158736926>
Reviewed by Darin Adler.
OSObject types behave like CF objects in C/C++, but they behave like
Cocoa objects in Objective-C/C++, including opting into ARC. Unlike
toll-free bridged types, OSObject CF types and the Cocoa types aren't
defined at the same time, which complicates implementing a shared
solution for both.
For example, an OSObject of type `foo_bar` will be defined like this in
plain C:
struct foo_bar;
typedef struct foo_bar *foo_bar_t;
Note that some implementations (like libdispatch) have separate
definitions for C++ with an "_s" suffix:
typedef struct dispatch_object_s { ... } *dispatch_object_t;
On the other hand, an OSObject of type `foo_bar` will be defined like
this in Objective-C/C++:
@protocol OS_foo_bar <NSObject> @end
typedef NSObject<OS_foo_bar> * __attribute__((objc_independent_class))
foo_bar_t;
OSObject "class" inheritance is implemented in Objective-C/C++ by making
the @protocol inherit from the @protocol of the superclass, or inherit
from NSObject if it's a top-level class. There is no concept of
inheritence in plain C, although libdispatch does provide inheritance of
struct types in C++:
typedef struct dispatch_group_s : public dispatch_object_s {}
*dispatch_group_t;
However, most OSObject types don't implement separate C++ definitions,
so that can't be relied upon to check inheritance. (These C++
definitions are also not available in Objective-C++ sources, so it would
require implementation of two different type checks, which is less than
ideal.)
Instead, to check whether a given object is of a specific OSObject type,
the Objective-C +[Class conformsToProtocol:] method (or
class_conformsToProtocol() in C) may be used. Conveniently, any
OSObject that's currently a plain C/C++ type may be treated as a
CFTypeRef, bridge-cast to `id`, and then used to call either
+conformsToProtocol: or class_conformsToProtocol().
The challenge with implemeting isOSObject<T>() is that an OSObject type,
such as foo_bar_t, is defined differently in plain C++ and
Objective-C++, as noted above.
To make it possible to use a single implementation of isOSObject<T>()
for a type (regardless of the language), OSObjectTypeCastTraits structs
are defined so that `T` is mapped to a common type that's shared between
C++ and Objective-C++.
If `T` is an OSObject of type `foo_bar_t`, the trait is defined like
this in plain C++ (with the typedef resolved to the underlying type):
template<> struct OSObjectTypeCastTraits<struct foo_bar*> { using BaseType =
struct foo_bar*; };
But it is defined like this in Objective-C++:
template<> struct OSObjectTypeCastTraits<NSObject<OS_foo_bar> *> { using
BaseType = struct foo_bar*; };
While redundant for plain C++, this allows us to map `foo_bar_t` to the
same type no matter which language is used at compile time, and thus
only implement isOSObject<>() once per OSObject type:
template<> bool
isOSObject<OSObjectTypeCastTraits<foo_bar_t>::BaseType>(CFTypeRef object) {
Class cls = object_getClass(bridge_id_cast(object));
return class_conformsToProtocol(cls, objc_getProtocol(ProtocolString));
}
The only downside to this approach is that we must embed some knowledge
of the plain C/C++ struct type when constructing OSObjectTypeCastTraits
for Objective-C++, although it's only a pre-declared struct.
* Source/WTF/WTF.xcodeproj/project.pbxproj:
- Add TypeCastsOSObject.h to project.
* Source/WTF/wtf/cf/TypeCastsCF.h:
- Add `using WTF::bridgeCFCast` statement.
- Move `using WTF::bridge_id_cast` statement here from TypeCastsCocoa.h.
(WTF::bridgeCFCast): Add.
- Add convenience function to cast from CFTypeRef to id without
reference churn. Works in both plain C++ and Objective-C++.
(WTF::bridge_id_cast):
- Move from TypeCastsCocoa.h and make work for CF in plain C++.
* Source/WTF/wtf/cocoa/TypeCastsCocoa.h:
- Include <wtf/cf/TypeCastsCF.h> for bridge_id_cast().
- Move `using WTF::bridge_id_cast` statement to TypeCastsCF.h.
* Source/WTF/wtf/darwin/TypeCastsOSObject.h: Add.
(WTF::isOSObject): Add.
(WTF::osObjectCast): Add.
(WTF::dynamicOSObjectCast): Add.
* Source/WebCore/platform/network/cf/DNSResolveQueueCFNet.cpp:
(WebCore::DNSResolveQueueCFNet::performDNSLookup):
- Add dynamic cast.
* Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm:
(extractResolutionReport):
- Add dynamic casts.
* Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
- Add TypeCastsOSObjectCF.cpp, TypeCastsOSObjectCocoa.mm and
TypeCastsOSObjectCocoaARC.mm to the project.
* Tools/TestWebKitAPI/Tests/WTF/darwin/TypeCastsOSObjectCF.cpp: Add.
(TestWebKitAPI::TEST(TypeCastsOSObjectCF, osObjectCast)): Add.
(TestWebKitAPI::TEST(TypeCastsOSObjectCF, dynamicOSObjectCast)): Add.
(TestWebKitAPI::TEST(TypeCastsOSObjectCF, dynamicOSObjectCast_OSObjectPtr)):
Add.
* Tools/TestWebKitAPI/Tests/WTF/darwin/TypeCastsOSObjectCocoa.mm: Add.
(TestWebKitAPI::TEST(TYPE_CASTS_OSOBJECT_PTR_TEST_NAME, osObjectCast_from_id)):
Add.
(TestWebKitAPI::TEST(TYPE_CASTS_OSOBJECT_PTR_TEST_NAME,
dynamicOSObjectCast_from_OSObjectPtr)): Add.
(TestWebKitAPI::TEST(TYPE_CASTS_OSOBJECT_PTR_TEST_NAME,
dynamicOSObjectCast_from_id)): Add.
* Tools/TestWebKitAPI/Tests/WTF/darwin/TypeCastsOSObjectCocoaARC.mm: Add.
Canonical link: https://commits.webkit.org/304847@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications