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

Reply via email to