Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: cbf0ef68ade64b72082fcc6de3b06f70db1fa46f
https://github.com/WebKit/WebKit/commit/cbf0ef68ade64b72082fcc6de3b06f70db1fa46f
Author: Richard Robinson <[email protected]>
Date: 2026-08-26 (Wed, 26 Aug 2026)
Changed paths:
M Source/WTF/wtf/CompletionHandler.h
M Source/WTF/wtf/OptionSet.h
M Source/WTF/wtf/module.modulemap
M Source/WebKit/CMakeLists.txt
A Source/WebKit/Shared/WTFCompletionHandler+Extras.swift
M Source/WebKit/UIProcess/WebPageProxy.swift
M Source/WebKit/UIProcess/mac/WKTextSelectionController.swift
M Source/WebKit/WebKit.xcodeproj/project.pbxproj
M Tools/TestWebKitAPI/Configurations/TestWTFLibrary.xcconfig
A Tools/TestWebKitAPI/Helpers/WTFCompletionHandler+Extras.swift
M Tools/TestWebKitAPI/Helpers/cocoa/HTTPServer.swift
M Tools/TestWebKitAPI/TestBundle/TestWebKitAPIBundle-Bridging-Header.h
A Tools/TestWebKitAPI/TestWTFLibrary/SwiftCxxInteropTestbed.cpp
A Tools/TestWebKitAPI/TestWTFLibrary/SwiftCxxInteropTestbed.h
A Tools/TestWebKitAPI/TestWTFLibrary/TestWTFLibrary.swift
A Tools/TestWebKitAPI/TestWTFLibrary/module.modulemap
M Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
R Tools/TestWebKitAPI/Tests/WTF/cocoa/SwiftCxxInteropTestbed.cpp
R Tools/TestWebKitAPI/Tests/WTF/cocoa/SwiftCxxInteropTestbed.h
M Tools/TestWebKitAPI/Tests/WTF/cocoa/SwiftCxxInteropTests.swift
M Tools/TestWebKitAPI/Tests/WebKit/WebPage/JSHandleTests.swift
M Tools/TestWebKitAPI/Tests/WebKit/WebPage/WebPageTests.swift
Log Message:
-----------
[Swift in WebKit] Introduce a bridging mechanism to create
`WTF::CompletionHandler`s in Swift
https://bugs.webkit.org/show_bug.cgi?id=322377
rdar://185660724
Reviewed by Adrian Taylor.
Create an abstraction to allow `WTF::CompletionHandler` types to be properly
constructed in Swift.
This is done by designing a pair of Swift protocols which
`WTF::CompletionHandler` specializations
may conform to: `CxxCompletionHandler` for specializations taking a single
argument, and
`CxxVoidCompletionHandler` for those taking none. Both refine
`CxxCompletionHandlerBase`, which
provides the initializers.
Previously, Swift created these by relying on `WTF::CompletionHandler`'s
Objective-C block
constructor, which was only exposed under `#ifdef __swift__`. That is now
deleted unconditionally,
because implicitly bridging a Swift closure to a block gave no control over the
closure's lifetime
and forced every callsite to spell out a `WTF::ThreadLikeAssertion` by hand. It
was also not cross-platform.
Instead, a Swift closure is now reduced to the C ABI it fundamentally is (a
function pointer, an opaque
context, and a destructor for that context) and `WTF::CompletionHandler` gains
a constructor accepting
exactly that. The context is owned by a `std::unique_ptr<void,
SwiftClosureDestroy>` captured by the
resulting handler, so it is destroyed together with the handler.
On the Swift side, the closure is stored in a class box passed across as a
retained opaque pointer.
The box is deliberately split into a generic `SwiftClosureBox<Argument>` and a
non-generic
`ErasedSwiftClosureBox` base, since a C function pointer cannot be formed from
a closure that
captures generic parameters.
Note that because WTF does not yet support Swift,
`WTFCompletionHandler+Extras.swift` must have a
copy in TestWTFLibrary for now.
The `callAsFunction` protocol requirement is witnessed by the imported C++
`operator()`. This is what
makes the compiler check that the `Argument` associated type matches the
parameter type C++ actually
passes, so a mismatched conformance fails to compile rather than silently
reinterpreting memory.
This abstraction currently does not support completion handlers whose
parameters are noncopyable
types; this will be done in a subsequent change.
It also only supports completion handlers whose parameter list is of arity-0 or
arity-1, and whose
return type is void; supporting arbitrary arity-n parameter lists is not
currently prioritized due
to its infrequent use. Both restrictions are enforced at compile time by
`static_assert`.
Tests: Tools/TestWebKitAPI/Tests/WTF/cocoa/SwiftCxxInteropTests.swift
Tools/TestWebKitAPI/Tests/WebKit/WebPage/JSHandleTests.swift
Tools/TestWebKitAPI/Tests/WebKit/WebPage/WebPageTests.swift
* Source/WTF/wtf/CompletionHandler.h:
(WTF::CompletionHandler<Out):
(WTF::adopt):
(WTF::CompletionHandlerWithFinalizer<Out):
(WTF::Detail::CallableWrapper<CompletionHandler<Out):
Add the `SwiftClosureInvoke` and `SwiftClosureDestroy` aliases describing the C
ABI a Swift closure
reduces to, along with the constructor accepting them. Add an `Argument` alias
for the Swift
protocols to key off of, and `VoidCompletionHandler` / `BoolCompletionHandler`
aliases for the two
specializations common enough to conform out of the box.
Annotate the pointers in this header for nullability, which is required now
that the Swift closure
typedefs introduce nullability into it.
* Source/WTF/wtf/OptionSet.h:
Use a different spelling for the friendship to ConstexprOptionSet to workaround
a compiler bug (rdar://185869726).
* Source/WTF/wtf/module.modulemap:
* Source/WebKit/CMakeLists.txt:
* Source/WebKit/Shared/WTFCompletionHandler+Extras.swift: Added.
(CxxCompletionHandlerBase.init(_:)):
(ErasedSwiftClosureBox.call(with:)):
(SwiftClosureBox.init(_:)):
(SwiftClosureBox.call(with:)):
(CxxCompletionHandler.callAsFunction(_:)):
(CxxVoidCompletionHandler.callAsFunction):
* Source/WebKit/WebKit.xcodeproj/project.pbxproj:
* Source/WebKit/UIProcess/WebPageProxy.swift:
(WebKit.WebPageProxy.selectWithGesture(at:type:state:isInteractingWithFocusedElement:)):
Deleted.
(WebKit.WebPageProxy.selectPosition(at:isInteractingWithFocusedElement:)):
Deleted.
(WebKit.WebPageProxy.selectText(at:by:isInteractingWithFocusedElement:)):
Deleted.
(WebKit.WebPageProxy.updateSelection(withExtentPoint:by:isInteractingWithFocusedElement:source:)):
Deleted.
(WebKit.selectPosition(at:isInteractingWithFocusedElement:)): Deleted.
* Source/WebKit/UIProcess/mac/WKTextSelectionController.swift:
(WKTextSelectionController.reextendSelectionForAutoscrollIfNeeded):
(WKTextSelectionController.moveInsertionCursor(to:placeAtWordBoundary:)):
(WKTextSelectionController.beginRangeSelection(at:with:)):
(WKTextSelectionController.continueRangeSelection(at:)):
Simplify the existing call-sites. These hand-written `async` wrappers existed
only to hide the
boilerplate the block constructor demanded; with the continuation initializer,
the callers can now
wrap the C++ functions directly and the wrappers earn their keep no longer.
* Tools/TestWebKitAPI/Configurations/TestWTFLibrary.xcconfig:
* Tools/TestWebKitAPI/Helpers/WTFCompletionHandler+Extras.swift: Added.
(CxxCompletionHandlerBase.init(_:)):
(ErasedSwiftClosureBox.call(with:)):
(SwiftClosureBox.init(_:)):
(SwiftClosureBox.call(with:)):
(CxxCompletionHandler.callAsFunction(_:)):
(CxxVoidCompletionHandler.callAsFunction):
* Tools/TestWebKitAPI/TestBundle/TestWebKitAPIBundle-Bridging-Header.h:
* Tools/TestWebKitAPI/TestWTFLibrary/TestWTFLibrary.swift: Added.
* Tools/TestWebKitAPI/TestWTFLibrary/module.modulemap: Added.
* Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* Tools/TestWebKitAPI/Helpers/cocoa/HTTPServer.swift:
(HTTPServer.run(_:)):
* Tools/TestWebKitAPI/TestWTFLibrary/SwiftCxxInteropTestbed.h: Renamed from
Tools/TestWebKitAPI/Tests/WTF/cocoa/SwiftCxxInteropTestbed.h.
* Tools/TestWebKitAPI/TestWTFLibrary/SwiftCxxInteropTestbed.cpp: Renamed from
Tools/TestWebKitAPI/Tests/WTF/cocoa/SwiftCxxInteropTestbed.cpp.
(SwiftCxxInteropTestbed::callIntBoolFunction):
(SwiftCxxInteropTestbed::callIntCompletionHandler):
(SwiftCxxInteropTestbed::callVoidCompletionHandler):
(SwiftCxxInteropTestbed::storedIntCompletionHandler):
(SwiftCxxInteropTestbed::storeIntCompletionHandler):
(SwiftCxxInteropTestbed::invokeStoredIntCompletionHandler):
(SwiftCxxInteropTestbed::resetStoredIntCompletionHandler):
* Tools/TestWebKitAPI/Tests/WTF/cocoa/SwiftCxxInteropTests.swift:
(Recorder.values):
(SwiftCxxInteropTests.completionHandlerReceivesItsArgument):
(SwiftCxxInteropTests.wtfCompletionHandlerCanBeInvokedFromSwift):
(SwiftCxxInteropTests.completionHandlerPreservesCapturedState):
(SwiftCxxInteropTests.voidCompletionHandlerCanBeInvokedFromSwift):
(SwiftCxxInteropTests.voidCompletionHandlerWorksWithAContinuation):
(SwiftCxxInteropTests.separateHandlersDoNotShareAContext):
(SwiftCxxInteropTests.contextIsReleasedAfterTheHandlerIsCalled):
(SwiftCxxInteropTests.contextSurvivesUntilTheHandlerIsInvokedLater):
* Tools/TestWebKitAPI/Tests/WebKit/WebPage/JSHandleTests.swift:
* Tools/TestWebKitAPI/Tests/WebKit/WebPage/WebPageTests.swift:
Add tests
* Source/WTF/wtf/OptionSet.h:
Canonical link: https://commits.webkit.org/319901@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications