- Revision
- 267352
- Author
- [email protected]
- Date
- 2020-09-21 12:17:04 -0700 (Mon, 21 Sep 2020)
Log Message
WKWebView Swift overlay has mis-annotated nullability for evaluateJavaScript
<http://webkit.org/b/216198>
<rdar://problem/68035950>
Reviewed by Darin Adler.
Due to a mistranslation of evaluateJavaScript, we are vending an API which does not expect
to receive nil as a valid result value. This change fixes the crash, but does not yet fix
the API to have the correct signature. That will come in a later patch.
To fix the crash, we need to produce a valid Result<Any, Error> to pass back to clients.
Fortunately, instead of inventing something clever, we can just use nil. It's valid to box
optional values into Any, and clients can technically retrieve them with the right dynamic cast
as well. Since client code must be using dynamic casting to convert the result Any to a usable
type, and because in the case where we now return a new value at runtime we would have previously
crashed, this shouldn't have any binary compatibility impact either.
To better validate these changes, I also add new unit tests for the conversion of _javascript_
results into Swift values, including a test for the deprecated API.
* SwiftOverlay/SwiftOverlay/ObjectiveCBlockConversions.swift: Added. For clarity I'm factoring
helper methods into a single namespace, as it also makes a nice place to document their expectations.
(ObjectiveCBlockConversion.exclusive.exclusive(_:)): This is renamed from the free function,
makeResultHandler(_:). It still has the same fatalError (now precondition) as before, but
hopefully a better name to clarify that it expects exactly-one value.
(ObjectiveCBlockConversions.boxingNilAsAnyForCompatibility(_:)): This is a variant of exclusive(_:)
that makes the tradeoff of boxing any nil values as Any to avoid crashing. This is still safe,
since as mentioned our clients will need to cast the value they recieve to do anything with it,
and since the deprecated API expects `Any`, no one could have been successfully comparing it
to `nil` today anyways.
* SwiftOverlay/Tests/_javascript_ToSwiftTypeConversions.swift: Added.
(_javascript_ToSwiftConversions.setUp): Construct a new web view, and add it to a window so that it is
in an expected state. I'm using about:blank as the URL, since page content doesn't matter for
these tests and I want the web content to be ready immediately.
(_javascript_ToSwiftConversions.tearDown): Just perform some window cleanup.
(_javascript_ToSwiftConversions.evaluateJavaScript(_:andExpect:)): Helper method to evaluate script and
check its result. I'm using String.debugDescription because it escapes quotes and special characters
which makes the readout easier to parse.
(_javascript_ToSwiftConversions.testNull): _javascript_'s null is actually mapped to NSNull, not nil.
(_javascript_ToSwiftConversions.testInteger): Some standard type coercion tests. The underlying value for
all number types should be NSNumber, so this is actually check against a float or integer type
without issue.
(_javascript_ToSwiftConversions.testDecimal): Ditto.
(_javascript_ToSwiftConversions.testBoolean): Ditto.
(_javascript_ToSwiftConversions.testString): Ditto.
(_javascript_ToSwiftConversions.testArray): Ditto.
(_javascript_ToSwiftConversions.testDictionary): Ditto, only you can't evaluate an object literal directly
so I need to store it in a temporary location first.
(_javascript_ToSwiftConversions.testUndefined): Test our boxing of nil. The exact value matters less than
not crashing at all.
* SwiftOverlay/WebKitSwiftOverlay.xcodeproj/project.pbxproj: Added new files to project. I kept the
new test file and helper files within the SwiftOverlay group, because they do not contribute any API.
* UIProcess/API/Cocoa/WebKitSwiftOverlay.swift:
(WKWebView.callAsyncJavaScript(_:arguments:in:in:completionHandler:)): Switch to a conversion which does
not trap on nil.
(WKWebView.createPDF(_:completionHandler:)): Updated to use new helper method name.
(WKWebView.createWebArchiveData(_:)): Ditto.
(WKWebView.evaluateJavaScript(_:in:in:completionHandler:Error:)): See above.
(makeResultHandler(_:): This has been subsumed by ObjCBlockConversions.
Modified Paths
Added Paths
Diff
Modified: trunk/Source/WebKit/ChangeLog (267351 => 267352)
--- trunk/Source/WebKit/ChangeLog 2020-09-21 19:00:46 UTC (rev 267351)
+++ trunk/Source/WebKit/ChangeLog 2020-09-21 19:17:04 UTC (rev 267352)
@@ -1,3 +1,68 @@
+2020-09-21 James Savage <[email protected]>
+
+ WKWebView Swift overlay has mis-annotated nullability for evaluateJavaScript
+ <http://webkit.org/b/216198>
+ <rdar://problem/68035950>
+
+ Reviewed by Darin Adler.
+
+ Due to a mistranslation of evaluateJavaScript, we are vending an API which does not expect
+ to receive nil as a valid result value. This change fixes the crash, but does not yet fix
+ the API to have the correct signature. That will come in a later patch.
+
+ To fix the crash, we need to produce a valid Result<Any, Error> to pass back to clients.
+ Fortunately, instead of inventing something clever, we can just use nil. It's valid to box
+ optional values into Any, and clients can technically retrieve them with the right dynamic cast
+ as well. Since client code must be using dynamic casting to convert the result Any to a usable
+ type, and because in the case where we now return a new value at runtime we would have previously
+ crashed, this shouldn't have any binary compatibility impact either.
+
+ To better validate these changes, I also add new unit tests for the conversion of _javascript_
+ results into Swift values, including a test for the deprecated API.
+
+ * SwiftOverlay/SwiftOverlay/ObjectiveCBlockConversions.swift: Added. For clarity I'm factoring
+ helper methods into a single namespace, as it also makes a nice place to document their expectations.
+ (ObjectiveCBlockConversion.exclusive.exclusive(_:)): This is renamed from the free function,
+ makeResultHandler(_:). It still has the same fatalError (now precondition) as before, but
+ hopefully a better name to clarify that it expects exactly-one value.
+ (ObjectiveCBlockConversions.boxingNilAsAnyForCompatibility(_:)): This is a variant of exclusive(_:)
+ that makes the tradeoff of boxing any nil values as Any to avoid crashing. This is still safe,
+ since as mentioned our clients will need to cast the value they recieve to do anything with it,
+ and since the deprecated API expects `Any`, no one could have been successfully comparing it
+ to `nil` today anyways.
+
+ * SwiftOverlay/Tests/_javascript_ToSwiftTypeConversions.swift: Added.
+ (_javascript_ToSwiftConversions.setUp): Construct a new web view, and add it to a window so that it is
+ in an expected state. I'm using about:blank as the URL, since page content doesn't matter for
+ these tests and I want the web content to be ready immediately.
+ (_javascript_ToSwiftConversions.tearDown): Just perform some window cleanup.
+ (_javascript_ToSwiftConversions.evaluateJavaScript(_:andExpect:)): Helper method to evaluate script and
+ check its result. I'm using String.debugDescription because it escapes quotes and special characters
+ which makes the readout easier to parse.
+ (_javascript_ToSwiftConversions.testNull): _javascript_'s null is actually mapped to NSNull, not nil.
+ (_javascript_ToSwiftConversions.testInteger): Some standard type coercion tests. The underlying value for
+ all number types should be NSNumber, so this is actually check against a float or integer type
+ without issue.
+ (_javascript_ToSwiftConversions.testDecimal): Ditto.
+ (_javascript_ToSwiftConversions.testBoolean): Ditto.
+ (_javascript_ToSwiftConversions.testString): Ditto.
+ (_javascript_ToSwiftConversions.testArray): Ditto.
+ (_javascript_ToSwiftConversions.testDictionary): Ditto, only you can't evaluate an object literal directly
+ so I need to store it in a temporary location first.
+ (_javascript_ToSwiftConversions.testUndefined): Test our boxing of nil. The exact value matters less than
+ not crashing at all.
+
+ * SwiftOverlay/WebKitSwiftOverlay.xcodeproj/project.pbxproj: Added new files to project. I kept the
+ new test file and helper files within the SwiftOverlay group, because they do not contribute any API.
+
+ * UIProcess/API/Cocoa/WebKitSwiftOverlay.swift:
+ (WKWebView.callAsyncJavaScript(_:arguments:in:in:completionHandler:)): Switch to a conversion which does
+ not trap on nil.
+ (WKWebView.createPDF(_:completionHandler:)): Updated to use new helper method name.
+ (WKWebView.createWebArchiveData(_:)): Ditto.
+ (WKWebView.evaluateJavaScript(_:in:in:completionHandler:Error:)): See above.
+ (makeResultHandler(_:): This has been subsumed by ObjCBlockConversions.
+
2020-09-21 Kate Cheney <[email protected]>
Allow about:blank subframe loads for non app-bound top frames
Added: trunk/Source/WebKit/SwiftOverlay/SwiftOverlay/ObjectiveCBlockConversions.swift (0 => 267352)
--- trunk/Source/WebKit/SwiftOverlay/SwiftOverlay/ObjectiveCBlockConversions.swift (rev 0)
+++ trunk/Source/WebKit/SwiftOverlay/SwiftOverlay/ObjectiveCBlockConversions.swift 2020-09-21 19:17:04 UTC (rev 267352)
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/// A family of conversions for translating between Swift blocks expecting a `Result<V, Error>` and
+/// Objective-C callbacks of the form `(T?, Error?)`.
+///
+/// Depending on the semantics of the Objective-C API, only one of these conversions is appropriate.
+/// - If the Objective-C block expects to be called with exactly one non-null argument, use the
+/// `exclusive(_:)` conversion.
+/// - If the Objective-C block can be called with one or zero non-null arguments, use the
+/// `treatNilAsSuccess` conversion.
+/// - If the Objective-C block can be called with two non-null values, it is ineligible for
+/// conversion to a `Result`.
+/// - `boxingNilAsAnyForCompatibility` exists as a workaround for http://webkit.org/b/216198, and
+/// should not be used by new code.
+enum ObjCBlockConversion {
+ /// Converts a block from `(Result<Value, Error>) -> Void` to `(Value?, Error?) -> Void`.
+ ///
+ /// The result block must be called with exactly one non-null argument. If both arguments are
+ /// non-null then `handler` will be called with `.success(T)`. If both arguments are `nil`
+ /// the conversion will trap.
+ static func exclusive<Value>(_ handler: @escaping (Result<Value, Error>) -> Void) -> (Value?, Error?) -> Void {
+ return { value, error in
+ if let value = value {
+ handler(.success(value))
+ } else if let error = error {
+ handler(.failure(error))
+ } else {
+ preconditionFailure("Bug in WebKit: Received neither result or failure.")
+ }
+ }
+ }
+
+ /// Converts a block from `(Result<Value?, Error>) -> Void` to `(Value?, Error) -> Void`.
+ ///
+ /// This performs the same conversion as `Self.exclusive(_:)`, but if the result block is called
+ /// with `(nil, nil)` then `handler` is called with `.success(nil)`.
+ static func treatNilAsSuccess<Value>(_ handler: @escaping (Result<Value?, Error>) -> Void) -> (Value?, Error?) -> Void {
+ return { value, error in
+ if let error = error {
+ handler(.failure(error))
+ } else {
+ handler(.success(value))
+ }
+ }
+ }
+
+ /// Converts a block from `(Result<Value, Error>) -> Void` to `(Value?, Error) -> Void`.
+ ///
+ /// This performs the same conversion as `Self.exclusive(_:)`, but if the result block is called
+ /// with `(nil, nil)` then `handler` is called with `.success(Optional<Any>.none as Any)`. This
+ /// is a compatibility behavior for http://webkit.org/b/216198, and should not be adopted by
+ /// new code.
+ static func boxingNilAsAnyForCompatibility(_ handler: @escaping (Result<Any, Error>) -> Void) -> (Any?, Error?) -> Void {
+ return { value, error in
+ if let error = error {
+ handler(.failure(error))
+ } else if let success = value {
+ handler(.success(success))
+ } else {
+ handler(.success(Optional<Any>.none as Any))
+ }
+ }
+ }
+}
Added: trunk/Source/WebKit/SwiftOverlay/Tests/_javascript_ToSwiftTypeConversions.swift (0 => 267352)
--- trunk/Source/WebKit/SwiftOverlay/Tests/_javascript_ToSwiftTypeConversions.swift (rev 0)
+++ trunk/Source/WebKit/SwiftOverlay/Tests/_javascript_ToSwiftTypeConversions.swift 2020-09-21 19:17:04 UTC (rev 267352)
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import XCTest
+import WebKit
+
+final class _javascript_ToSwiftConversions : XCTestCase {
+ #if os(macOS)
+ let window = NSWindow()
+ #elseif os(iOS)
+ let window = UIWindow()
+ #endif
+
+ let webView = WKWebView(frame: CGRect(x: 0, y: 0, width: 320, height: 480))
+
+ override func setUp() {
+ #if os(macOS)
+ window.contentView?.addSubview(webView)
+ #else
+ window.isHidden = false
+ window.addSubview(webView)
+ #endif
+
+ webView.load(URLRequest(url: URL(string: "about:blank")!))
+ }
+
+ override func tearDown() {
+ #if os(macOS)
+ window.orderOut(nil)
+ #else
+ window.isHidden = true
+ #endif
+ }
+
+ func evaluateJavaScript<T : Equatable>(_ _javascript_: String, andExpect expectedValue: T) {
+ let evaluationExpectation = self.expectation(description: "Evaluation of \(_javascript_.debugDescription)")
+ webView.evaluateJavaScript(_javascript_, in: nil, in: .defaultClient) { result in
+ do {
+ let actualValue = try result.get() as? T
+ XCTAssertEqual(actualValue, expectedValue)
+ evaluationExpectation.fulfill()
+ } catch {
+ XCTFail("Evaluating \(_javascript_.debugDescription) failed with error: \(error)")
+ }
+ }
+
+ wait(for: [evaluationExpectation], timeout: 30)
+ }
+
+ func testNull() {
+ evaluateJavaScript("null", andExpect: NSNull())
+ }
+
+ func testInteger() {
+ evaluateJavaScript("12", andExpect: 12 as Int)
+ }
+
+ func testDecimal() {
+ evaluateJavaScript("12.0", andExpect: 12 as Float)
+ }
+
+ func testBoolean() {
+ evaluateJavaScript("true", andExpect: true)
+ evaluateJavaScript("false", andExpect: false)
+ }
+
+ func testString() {
+ evaluateJavaScript(#""Hello, world!""#, andExpect: "Hello, world!")
+ }
+
+ func testArray() {
+ // This uses [AnyHashable], instead of [Any], so we can perform an equality check for testing.
+ evaluateJavaScript(#"[ 1, 2, "cat" ]"#, andExpect: [1, 2, "cat"] as [AnyHashable])
+ }
+
+ func testDictionary() {
+ // This uses [AnyHashable:AnyHashable], instead of [AnyHashable:Any], so we can perform an
+ // equality check for testing. An object’s keys are always converted to strings, so even
+ // though we input `1:` we expect `"1":` back.
+ let result: [AnyHashable:AnyHashable] = ["1": 2, "cat": "dog"]
+ evaluateJavaScript(#"const value = { 1: 2, "cat": "dog" }; value"#, andExpect: result)
+ }
+
+ func testUndefined() {
+ let evaluationExpectation = self.expectation(description: "Evaluation of \"undefined\" using deprecated API")
+ webView.evaluateJavaScript("undefined", in: nil, in: .defaultClient) { (result: Result<Any, Error>) in
+ do {
+ let value = try result.get()
+ if let optionalValue = value as? Any?, optionalValue == nil {
+ evaluationExpectation.fulfill()
+ } else {
+ XCTFail("Value did not contain nil")
+ }
+ } catch {
+ XCTFail("Evaluating \"undefined\" failed with error: \(error)")
+ }
+ }
+
+ wait(for: [evaluationExpectation], timeout: 30)
+ }
+}
Modified: trunk/Source/WebKit/SwiftOverlay/WebKitSwiftOverlay.xcodeproj/project.pbxproj (267351 => 267352)
--- trunk/Source/WebKit/SwiftOverlay/WebKitSwiftOverlay.xcodeproj/project.pbxproj 2020-09-21 19:00:46 UTC (rev 267351)
+++ trunk/Source/WebKit/SwiftOverlay/WebKitSwiftOverlay.xcodeproj/project.pbxproj 2020-09-21 19:17:04 UTC (rev 267352)
@@ -13,6 +13,10 @@
B3A5D39023F78F5400B17727 /* WebKitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3A5D38823F78F5400B17727 /* WebKitTests.swift */; };
B3A5D39223F790DB00B17727 /* WebKitSwiftOverlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3A5D39123F790DB00B17727 /* WebKitSwiftOverlay.swift */; };
B3A5D39323F790DB00B17727 /* WebKitSwiftOverlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3A5D39123F790DB00B17727 /* WebKitSwiftOverlay.swift */; };
+ B3B8FECC250090B1006172CA /* _javascript_ToSwiftTypeConversions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3B8FECB250090B1006172CA /* _javascript_ToSwiftTypeConversions.swift */; };
+ B3B8FECD250090B1006172CA /* _javascript_ToSwiftTypeConversions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3B8FECB250090B1006172CA /* _javascript_ToSwiftTypeConversions.swift */; };
+ B3B8FEEF2502BAA0006172CA /* ObjectiveCBlockConversions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3B8FEEE2502BAA0006172CA /* ObjectiveCBlockConversions.swift */; };
+ B3B8FEF02502BAA0006172CA /* ObjectiveCBlockConversions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3B8FEEE2502BAA0006172CA /* ObjectiveCBlockConversions.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -46,6 +50,8 @@
B3A5D39823F790E100B17727 /* WebKitSwiftOverlayTests.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = WebKitSwiftOverlayTests.xcconfig; sourceTree = "<group>"; };
B3A5D39923F790E100B17727 /* install-swiftmodules.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "install-swiftmodules.sh"; sourceTree = "<group>"; };
B3A5D39A23F790E700B17727 /* WebKitSwiftOverlayTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "WebKitSwiftOverlayTests-Info.plist"; sourceTree = "<group>"; };
+ B3B8FECB250090B1006172CA /* _javascript_ToSwiftTypeConversions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _javascript_ToSwiftTypeConversions.swift; sourceTree = "<group>"; };
+ B3B8FEEE2502BAA0006172CA /* ObjectiveCBlockConversions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObjectiveCBlockConversions.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -86,6 +92,7 @@
isa = PBXGroup;
children = (
B3A5D39923F790E100B17727 /* install-swiftmodules.sh */,
+ B3B8FEEE2502BAA0006172CA /* ObjectiveCBlockConversions.swift */,
B3A5D39123F790DB00B17727 /* WebKitSwiftOverlay.swift */,
);
name = "Swift Overlay";
@@ -102,6 +109,7 @@
7D20070822F4EB72008DF640 /* Tests */ = {
isa = PBXGroup;
children = (
+ B3B8FECB250090B1006172CA /* _javascript_ToSwiftTypeConversions.swift */,
B3A5D39A23F790E700B17727 /* WebKitSwiftOverlayTests-Info.plist */,
B3A5D38823F78F5400B17727 /* WebKitTests.swift */,
);
@@ -344,6 +352,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ B3B8FEEF2502BAA0006172CA /* ObjectiveCBlockConversions.swift in Sources */,
B3A5D39223F790DB00B17727 /* WebKitSwiftOverlay.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -352,6 +361,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ B3B8FEF02502BAA0006172CA /* ObjectiveCBlockConversions.swift in Sources */,
B3A5D39323F790DB00B17727 /* WebKitSwiftOverlay.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -360,6 +370,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ B3B8FECC250090B1006172CA /* _javascript_ToSwiftTypeConversions.swift in Sources */,
B3A5D38F23F78F5400B17727 /* WebKitTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -368,6 +379,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ B3B8FECD250090B1006172CA /* _javascript_ToSwiftTypeConversions.swift in Sources */,
B3A5D39023F78F5400B17727 /* WebKitTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WebKitSwiftOverlay.swift (267351 => 267352)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/WebKitSwiftOverlay.swift 2020-09-21 19:00:46 UTC (rev 267351)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WebKitSwiftOverlay.swift 2020-09-21 19:17:04 UTC (rev 267352)
@@ -36,19 +36,19 @@
@available(iOS 14.0, macOS 10.16, *)
extension WKWebView {
public func callAsyncJavaScript(_ functionBody: String, arguments: [String:Any] = [:], in frame: WKFrameInfo? = nil, in contentWorld: WKContentWorld, completionHandler: ((Result<Any, Error>) -> Void)? = nil) {
- __callAsyncJavaScript(functionBody, arguments: arguments, inFrame: frame, in: contentWorld, completionHandler: completionHandler.map(makeResultHandler))
+ __callAsyncJavaScript(functionBody, arguments: arguments, inFrame: frame, in: contentWorld, completionHandler: completionHandler.map(ObjCBlockConversion.boxingNilAsAnyForCompatibility))
}
public func createPDF(configuration: WKPDFConfiguration = .init(), completionHandler: @escaping (Result<Data, Error>) -> Void) {
- __createPDF(with: configuration, completionHandler: makeResultHandler(completionHandler))
+ __createPDF(with: configuration, completionHandler: ObjCBlockConversion.exclusive(completionHandler))
}
public func createWebArchiveData(completionHandler: @escaping (Result<Data, Error>) -> Void) {
- __createWebArchiveData(completionHandler: makeResultHandler(completionHandler))
+ __createWebArchiveData(completionHandler: ObjCBlockConversion.exclusive(completionHandler))
}
public func evaluateJavaScript(_ _javascript_: String, in frame: WKFrameInfo? = nil, in contentWorld: WKContentWorld, completionHandler: ((Result<Any, Error>) -> Void)? = nil) {
- __evaluateJavaScript(_javascript_, inFrame: frame, in: contentWorld, completionHandler: completionHandler.map(makeResultHandler))
+ __evaluateJavaScript(_javascript_, inFrame: frame, in: contentWorld, completionHandler: completionHandler.map(ObjCBlockConversion.boxingNilAsAnyForCompatibility))
}
public func find(_ string: String, configuration: WKFindConfiguration = .init(), completionHandler: @escaping (WKFindResult) -> Void) {
@@ -55,15 +55,3 @@
__find(string, with: configuration, completionHandler: completionHandler)
}
}
-
-func makeResultHandler<Success, Failure>(_ handler: @escaping (Result<Success, Failure>) -> Void) -> (Success?, Failure?) -> Void {
- return { success, failure in
- if let success = success {
- handler(.success(success))
- } else if let failure = failure {
- handler(.failure(failure))
- } else {
- fatalError("Bug in WebKit: Received neither result or failure.")
- }
- }
-}