Skip to content

Commit 5113cfd

Browse files
authored
[Functions] 'call' API's completion handler should be called on the main thread (#14667)
1 parent cb10f05 commit 5113cfd

File tree

5 files changed

+70
-6
lines changed

5 files changed

+70
-6
lines changed

FirebaseFunctions/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# Unreleased
2+
- [fixed] Fix regression from 11.6.0 where `HTTPSCallable` did not invoke
3+
completion block on main thread (#14653).
4+
15
# 11.10.0
26
- [added] Streaming callable functions are now supported.
37

FirebaseFunctions/Sources/HTTPSCallable.swift

+9-5
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,15 @@ open class HTTPSCallable: NSObject {
7676
/// - data: Parameters to pass to the trigger.
7777
/// - completion: The block to call when the HTTPS request has completed.
7878
@objc(callWithObject:completion:) open func call(_ data: Any? = nil,
79-
completion: @escaping (HTTPSCallableResult?,
79+
completion: @escaping @MainActor (HTTPSCallableResult?,
8080
Error?) -> Void) {
8181
if #available(iOS 13, macCatalyst 13, macOS 10.15, tvOS 13, watchOS 7, *) {
8282
Task {
8383
do {
8484
let result = try await call(data)
85-
completion(result, nil)
85+
await completion(result, nil)
8686
} catch {
87-
completion(nil, error)
87+
await completion(nil, error)
8888
}
8989
}
9090
} else {
@@ -98,9 +98,13 @@ open class HTTPSCallable: NSObject {
9898
) { result in
9999
switch result {
100100
case let .success(callableResult):
101-
completion(callableResult, nil)
101+
DispatchQueue.main.async {
102+
completion(callableResult, nil)
103+
}
102104
case let .failure(error):
103-
completion(nil, error)
105+
DispatchQueue.main.async {
106+
completion(nil, error)
107+
}
104108
}
105109
}
106110
}

FirebaseFunctions/Tests/Integration/IntegrationTests.swift

+32
Original file line numberDiff line numberDiff line change
@@ -867,6 +867,38 @@ class IntegrationTests: XCTestCase {
867867
XCTAssertEqual(response, expected)
868868
}
869869
}
870+
871+
func testFunctionsReturnsOnMainThread() {
872+
let expectation = expectation(description: #function)
873+
functions.httpsCallable(
874+
"scalarTest",
875+
requestAs: Int16.self,
876+
responseAs: Int.self
877+
).call(17) { result in
878+
guard case .success = result else {
879+
return XCTFail("Unexpected failure.")
880+
}
881+
XCTAssert(Thread.isMainThread)
882+
expectation.fulfill()
883+
}
884+
waitForExpectations(timeout: 5)
885+
}
886+
887+
func testFunctionsThrowsOnMainThread() {
888+
let expectation = expectation(description: #function)
889+
functions.httpsCallable(
890+
"httpErrorTest",
891+
requestAs: [Int].self,
892+
responseAs: Int.self
893+
).call([]) { result in
894+
guard case .failure = result else {
895+
return XCTFail("Unexpected failure.")
896+
}
897+
XCTAssert(Thread.isMainThread)
898+
expectation.fulfill()
899+
}
900+
waitForExpectations(timeout: 5)
901+
}
870902
}
871903

872904
// MARK: - Streaming

FirebaseFunctions/Tests/ObjCIntegration/FIRIntegrationTests.m

+24
Original file line numberDiff line numberDiff line change
@@ -290,4 +290,28 @@ - (void)testTimeout {
290290
[self waitForExpectations:@[ expectation ] timeout:10];
291291
}
292292

293+
- (void)testFunctionsReturnsOnMainThread {
294+
XCTestExpectation *expectation = [[XCTestExpectation alloc] init];
295+
FIRHTTPSCallable *function = [_functions HTTPSCallableWithName:@"scalarTest"];
296+
[function callWithObject:@17
297+
completion:^(FIRHTTPSCallableResult *_Nullable result, NSError *_Nullable error) {
298+
XCTAssert(NSThread.isMainThread);
299+
XCTAssertNotNil(result);
300+
[expectation fulfill];
301+
}];
302+
[self waitForExpectations:@[ expectation ] timeout:10];
303+
}
304+
305+
- (void)testFunctionErrorsOnMainThread {
306+
XCTestExpectation *expectation = [[XCTestExpectation alloc] init];
307+
FIRHTTPSCallable *function = [_functions HTTPSCallableWithName:@"httpErrorTest"];
308+
[function callWithObject:@{}
309+
completion:^(FIRHTTPSCallableResult *_Nullable result, NSError *_Nullable error) {
310+
XCTAssert(NSThread.isMainThread);
311+
XCTAssertNotNil(error);
312+
[expectation fulfill];
313+
}];
314+
[self waitForExpectations:@[ expectation ] timeout:10];
315+
}
316+
293317
@end

FirebaseFunctions/Tests/Unit/FunctionsTests.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ class FunctionsTests: XCTestCase {
290290
}
291291

292292
XCTAssertEqual(error as NSError, networkError)
293-
293+
XCTAssert(Thread.isMainThread)
294294
completionExpectation.fulfill()
295295
}
296296

0 commit comments

Comments
 (0)