Skip to content
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

[v11] Simplify Component System Usage #13047

Merged
merged 5 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from 4 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
7 changes: 4 additions & 3 deletions FirebaseCore/Sources/FIRApp.m
Original file line number Diff line number Diff line change
Expand Up @@ -825,12 +825,10 @@ + (void)registerSwiftComponents {
SEL componentsToRegisterSEL = @selector(componentsToRegister);
// Dictionary of class names that conform to `FIRLibrary` and their user agents. These should only
// be SDKs that are written in Swift but still visible to ObjC.
// This is only necessary for products that need to do work at launch during configuration.
NSDictionary<NSString *, NSString *> *swiftComponents = @{
@"FIRSessions" : @"fire-ses",
@"FIRAuthComponent" : @"fire-auth",
@"FIRFunctionsComponent" : @"fire-fun",
@"FIRStorageComponent" : @"fire-str",
@"FIRVertexAIComponent" : @"fire-vertex",
};
for (NSString *className in swiftComponents.allKeys) {
Class klass = NSClassFromString(className);
Expand All @@ -845,6 +843,9 @@ + (void)registerSwiftComponents {
@"FIRCombineFirestoreLibrary" : @"comb-firestore",
@"FIRCombineFunctionsLibrary" : @"comb-functions",
@"FIRCombineStorageLibrary" : @"comb-storage",
@"FIRFunctions" : @"fire-fun",
@"FIRStorage" : @"fire-str",
@"FIRVertexAIComponent" : @"fire-vertex",
};
for (NSString *className in swiftLibraries.allKeys) {
Class klass = NSClassFromString(className);
Expand Down
42 changes: 34 additions & 8 deletions FirebaseFunctions/Sources/Functions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ enum FunctionsConstants {
/// A factory for getting the metadata to include with function calls.
private let contextProvider: FunctionsContextProvider

/// A map of active instances, grouped by app. Keys are FirebaseApp names and values are arrays
/// containing all instances of Functions associated with the given app.
private static var instances: [String: [Functions]] = [:]

/// Lock to manage access to the instances array to avoid race conditions.
private static var instancesLock: os_unfair_lock = .init()

/// The custom domain to use for all functions references (optional).
let customDomain: String?

Expand Down Expand Up @@ -294,13 +301,33 @@ enum FunctionsConstants {
/// compatibility.
private class func functions(app: FirebaseApp?, region: String,
customDomain: String?) -> Functions {
precondition(app != nil,
"`FirebaseApp.configure()` needs to be called before using Functions.")
let provider = app!.container.instance(for: FunctionsProvider.self) as? FunctionsProvider
return provider!.functions(for: app!,
region: region,
customDomain: customDomain,
type: self)
guard let app else {
fatalError("`FirebaseApp.configure()` needs to be called before using Functions.")
}
os_unfair_lock_lock(&instancesLock)

// Unlock before the function returns.
defer { os_unfair_lock_unlock(&instancesLock) }

if let associatedInstances = instances[app.name] {
for instance in associatedInstances {
// Domains may be nil, so handle with care.
var equalDomains = false
if let instanceCustomDomain = instance.customDomain {
equalDomains = instanceCustomDomain == customDomain
} else {
equalDomains = customDomain == nil
}
// Check if it's a match.
if instance.region == region, equalDomains {
return instance
}
}
}
let newInstance = Functions(app: app, region: region, customDomain: customDomain)
let existingInstances = instances[app.name, default: []]
instances[app.name] = existingInstances + [newInstance]
return newInstance
}

@objc init(projectID: String,
Expand Down Expand Up @@ -335,7 +362,6 @@ enum FunctionsConstants {
fatalError("Firebase Functions requires the projectID to be set in the App's Options.")
}
self.init(projectID: projectID,

region: region,
customDomain: customDomain,
auth: auth,
Expand Down
109 changes: 0 additions & 109 deletions FirebaseFunctions/Sources/Internal/FunctionsComponent.swift

This file was deleted.

30 changes: 21 additions & 9 deletions FirebaseStorage/Sources/Storage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,7 @@ import FirebaseCore
/// - Parameter app: The custom `FirebaseApp` used for initialization.
/// - Returns: A `Storage` instance, configured with the custom `FirebaseApp`.
@objc(storageForApp:) open class func storage(app: FirebaseApp) -> Storage {
guard let provider = ComponentType<StorageProvider>.instance(for: StorageProvider.self,
in: app.container) else {
fatalError("No \(StorageProvider.self) instance found for Firebase app: \(app.name)")
}
return provider.storage(for: Storage.bucket(for: app))
return storage(app: app, bucket: Storage.bucket(for: app))
}

/// Creates an instance of `Storage`, configured with a custom `FirebaseApp` and a custom storage
Expand All @@ -77,11 +73,19 @@ import FirebaseCore
/// URL.
@objc(storageForApp:URL:)
open class func storage(app: FirebaseApp, url: String) -> Storage {
guard let provider = ComponentType<StorageProvider>.instance(for: StorageProvider.self,
in: app.container) else {
fatalError("No \(StorageProvider.self) instance found for Firebase app: \(app.name)")
return storage(app: app, bucket: Storage.bucket(for: app, urlString: url))
}

private class func storage(app: FirebaseApp, bucket: String) -> Storage {
os_unfair_lock_lock(&instancesLock)
defer { os_unfair_lock_unlock(&instancesLock) }

if let instance = instances[bucket] {
return instance
}
return provider.storage(for: Storage.bucket(for: app, urlString: url))
let newInstance = FirebaseStorage.Storage(app: app, bucket: bucket)
instances[bucket] = newInstance
return newInstance
}

/// The `FirebaseApp` associated with this Storage instance.
Expand Down Expand Up @@ -342,6 +346,14 @@ import FirebaseCore
private let appCheck: AppCheckInterop?
private let storageBucket: String
private var usesEmulator: Bool = false

/// A map of active instances, grouped by app. Keys are FirebaseApp names and values are arrays
/// containing all instances of Storage associated with the given app.
private static var instances: [String: Storage] = [:]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found a small inconsistency between the comment and the code:

/// values are arrays containing all instances of Storage associated with the given app.

but

values are not arrays

private static var instances: [String: Storage] = [:]

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed comment in #13055


/// Lock to manage access to the instances array to avoid race conditions.
private static var instancesLock: os_unfair_lock = .init()

var host: String
var scheme: String
var port: Int
Expand Down
80 changes: 0 additions & 80 deletions FirebaseStorage/Sources/StorageComponent.swift

This file was deleted.

Loading
Loading