Skip to content

[Functions] Remove completion-handler based internal logic #15058

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 0 additions & 24 deletions FirebaseFunctions/Sources/Functions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -438,30 +438,6 @@ enum FunctionsConstants {
}
}

func callFunction(at url: URL,
withObject data: Any?,
options: HTTPSCallableOptions?,
timeout: TimeInterval,
completion: @escaping @MainActor (Result<HTTPSCallableResult, Error>) -> Void) {
// Get context first.
contextProvider.getContext(options: options) { context, error in
// Note: context is always non-nil since some checks could succeed, we're only failing if
// there's an error.
if let error {
DispatchQueue.main.async {
completion(.failure(error))
}
} else {
self.callFunction(url: url,
withObject: data,
options: options,
timeout: timeout,
context: context,
completion: completion)
}
}
}

private func callFunction(url: URL,
withObject data: Any?,
options: HTTPSCallableOptions?,
Expand Down
34 changes: 6 additions & 28 deletions FirebaseFunctions/Sources/HTTPSCallable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -184,34 +184,12 @@ private extension HTTPSCallable {
func call(_ data: sending Any? = nil,
completion: @escaping @MainActor (HTTPSCallableResult?, Error?) -> Void) {
let data = (data as? SendableWrapper)?.value ?? data
if #available(iOS 13, macCatalyst 13, macOS 10.15, tvOS 13, watchOS 7, *) {
Task {
do {
let result = try await call(data)
await completion(result, nil)
} catch {
await completion(nil, error)
}
}
} else {
// This isn’t expected to ever be called because Functions
// doesn’t officially support the older platforms.
functions.callFunction(
at: url,
withObject: data,
options: options,
timeout: timeoutInterval
) { result in
switch result {
case let .success(callableResult):
DispatchQueue.main.async {
completion(callableResult, nil)
}
case let .failure(error):
DispatchQueue.main.async {
completion(nil, error)
}
}
Task {
do {
let result = try await call(data)
await completion(result, nil)
} catch {
await completion(nil, error)
}
}
}
Expand Down
52 changes: 0 additions & 52 deletions FirebaseFunctions/Sources/Internal/FunctionsContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,56 +82,4 @@ struct FunctionsContextProvider: Sendable {
}
}
}

func getContext(options: HTTPSCallableOptions? = nil,
_ completion: @escaping ((FunctionsContext, Error?) -> Void)) {
let dispatchGroup = DispatchGroup()

var authToken: String?
var appCheckToken: String?
var error: Error?
var limitedUseAppCheckToken: String?

if let auth {
dispatchGroup.enter()

auth.getToken(forcingRefresh: false) { token, authError in
authToken = token
error = authError
dispatchGroup.leave()
}
}

if let appCheck {
dispatchGroup.enter()

if options?.requireLimitedUseAppCheckTokens == true {
// `getLimitedUseToken(completion:)` is an optional protocol method.
// If it’s not implemented, we still need to leave the dispatch group.
if let limitedUseTokenClosure = appCheck.getLimitedUseToken {
limitedUseTokenClosure { tokenResult in
// In the case of an error, the token will be the placeholder token.
limitedUseAppCheckToken = tokenResult.token
dispatchGroup.leave()
}
} else {
dispatchGroup.leave()
}
} else {
appCheck.getToken(forcingRefresh: false) { tokenResult in
// In the case of an error, the token will be the placeholder token.
appCheckToken = tokenResult.token
dispatchGroup.leave()
}
}
}

dispatchGroup.notify(queue: .main) {
let context = FunctionsContext(authToken: authToken,
fcmToken: self.messaging?.fcmToken,
appCheckToken: appCheckToken,
limitedUseAppCheckToken: limitedUseAppCheckToken)
completion(context, error)
}
}
}
19 changes: 0 additions & 19 deletions FirebaseFunctions/Tests/CombineUnit/HTTPSCallableTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,25 +40,6 @@ class MockFunctions: Functions, @unchecked Sendable {
return try mockCallFunction()
}

override func callFunction(at url: URL,
withObject data: Any?,
options: HTTPSCallableOptions?,
timeout: TimeInterval,
completion: @escaping @MainActor
(Result<HTTPSCallableResult, any Error>) -> Void) {
do {
try verifyParameters?(url, data, timeout)
let result = try mockCallFunction()
DispatchQueue.main.async {
completion(.success(result))
}
} catch {
DispatchQueue.main.async {
completion(.failure(error))
}
}
}

init(mockCallFunction: @escaping () throws -> HTTPSCallableResult) {
self.mockCallFunction = mockCallFunction
super.init(
Expand Down
Loading
Loading