Skip to content

Commit 25ed060

Browse files
committed
Add missing weak specifiers
1 parent 7453895 commit 25ed060

File tree

8 files changed

+61
-20
lines changed

8 files changed

+61
-20
lines changed

FirebaseFunctions/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# 10.10.0
2+
- [fixed] Fixed potential memory leak of Functions instances. (#11248)
3+
14
# 10.0.0
25
- [fixed] Remove unnecessary and unused `encoder` and `decoder` parameters from
36
`public func call(_ data: Request) async throws -> Response` API. (#9891)

FirebaseFunctions/Sources/Internal/FunctionsComponent.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ protocol FunctionsProvider {
3636
// MARK: - Private Variables
3737

3838
/// The app associated with all functions instances in this container.
39-
private let app: FirebaseApp
39+
private weak var app: FirebaseApp?
4040

4141
/// A map of active instances, grouped by app. Keys are FirebaseApp names and values are arrays
4242
/// containing all instances of Functions associated with the given app.

FirebaseFunctions/Tests/Unit/FunctionsTests.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,4 +167,22 @@ class FunctionsTests: XCTestCase {
167167
}
168168
waitForExpectations(timeout: 1.5)
169169
}
170+
171+
/// Test that Functions instances get deallocated.
172+
func testFunctionsLifecycle() throws {
173+
weak var weakApp: FirebaseApp?
174+
weak var weakFunctions: Functions?
175+
try autoreleasepool {
176+
let options = FirebaseOptions(googleAppID: "0:0000000000000:ios:0000000000000000",
177+
gcmSenderID: "00000000000000000-00000000000-000000000")
178+
options.projectID = "myProjectID"
179+
let app1 = FirebaseApp(instanceWithName: "transitory app", options: options)
180+
weakApp = try XCTUnwrap(app1)
181+
let functions = Functions(app: app1, region: "transitory-region", customDomain: nil)
182+
weakFunctions = functions
183+
XCTAssertNotNil(weakFunctions)
184+
}
185+
XCTAssertNil(weakApp)
186+
XCTAssertNil(weakFunctions)
187+
}
170188
}

FirebaseFunctions/Tests/Unit/SerializerTests.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ class SerializerTests: XCTestCase {
198198
1 as Int32,
199199
"two",
200200
[3 as Int32, ["@type": "type.googleapis.com/google.protobuf.Int64Value",
201-
"value": "9876543210"]],
201+
"value": "9876543210"]] as [Any],
202202
] as NSArray
203203
XCTAssertEqual(input, try serializer.encode(input) as? NSArray)
204204
}
@@ -209,23 +209,23 @@ class SerializerTests: XCTestCase {
209209
1 as Int64,
210210
"two",
211211
[3 as Int32, ["@type": "type.googleapis.com/google.protobuf.Int64Value",
212-
"value": "9876543210"]],
212+
"value": "9876543210"]] as [Any],
213213
] as NSArray
214-
let expected = [1 as Int64, "two", [3 as Int32, 9_876_543_210 as Int64]] as NSArray
214+
let expected = [1 as Int64, "two", [3 as Int32, 9_876_543_210 as Int64] as [Any]] as NSArray
215215
XCTAssertEqual(expected, try serializer.decode(input) as? NSArray)
216216
}
217217

218218
func testEncodeMap() {
219219
let input = [
220220
"foo": 1 as Int32,
221221
"bar": "hello",
222-
"baz": [3 as Int32, 9_876_543_210 as Int64],
222+
"baz": [3 as Int32, 9_876_543_210 as Int64] as [Any],
223223
] as NSDictionary
224224
let expected = [
225225
"foo": 1,
226226
"bar": "hello",
227227
"baz": [3, ["@type": "type.googleapis.com/google.protobuf.Int64Value",
228-
"value": "9876543210"]],
228+
"value": "9876543210"]] as [Any],
229229
] as NSDictionary
230230
let serializer = FUNSerializer()
231231
XCTAssertEqual(expected, try serializer.encode(input) as? NSDictionary)

FirebaseStorage/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# 10.10.0
2+
- [fixed] Fixed potential memory leak of Storage instances. (#11248)
3+
14
# 10.7.0
25
- [added] Provide server errors via the `NSUnderlyingErrorKey`.
36

FirebaseStorage/Sources/Storage.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ import FirebaseAuthInterop
7070
@objc(storageForApp:) open class func storage(app: FirebaseApp) -> Storage {
7171
let provider = ComponentType<StorageProvider>.instance(for: StorageProvider.self,
7272
in: app.container)
73-
return provider.storage(for: Storage.bucket(for: app))
73+
return provider.storage(for: Storage.bucket(for: app), app: app)
7474
}
7575

7676
/**
@@ -85,7 +85,7 @@ import FirebaseAuthInterop
8585
open class func storage(app: FirebaseApp, url: String) -> Storage {
8686
let provider = ComponentType<StorageProvider>.instance(for: StorageProvider.self,
8787
in: app.container)
88-
return provider.storage(for: Storage.bucket(for: app, urlString: url))
88+
return provider.storage(for: Storage.bucket(for: app, urlString: url), app: app)
8989
}
9090

9191
/**

FirebaseStorage/Sources/StorageComponent.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ import FirebaseCore
2222

2323
@objc(FIRStorageProvider)
2424
protocol StorageProvider {
25-
@objc func storage(for bucket: String) -> Storage
25+
@objc func storage(for bucket: String, app: FirebaseApp) -> Storage
2626
}
2727

2828
@objc(FIRStorageComponent) class StorageComponent: NSObject, Library, StorageProvider {
2929
// MARK: - Private Variables
3030

3131
/// The app associated with all Storage instances in this container.
32-
private let app: FirebaseApp
32+
private weak var app: FirebaseApp?
3333

3434
/// A map of active instances, grouped by app. Keys are FirebaseApp names and values are arrays
3535
/// containing all instances of Storage associated with the given app.
@@ -63,7 +63,7 @@ protocol StorageProvider {
6363

6464
// MARK: - StorageProvider conformance
6565

66-
func storage(for bucket: String) -> Storage {
66+
func storage(for bucket: String, app: FirebaseApp) -> Storage {
6767
os_unfair_lock_lock(&instancesLock)
6868

6969
// Unlock before the function returns.

FirebaseStorage/Tests/Unit/StorageComponentTests.swift

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@ class StorageComponentTests: StorageTestHelpers {
3434

3535
/// Tests that a Storage instance can be created properly by the StorageComponent.
3636
func testStorageInstanceCreation() throws {
37-
let component = StorageComponent(app: StorageComponentTests.app)
38-
let storage = component.storage(for: "someBucket")
37+
let app = try XCTUnwrap(StorageComponentTests.app)
38+
let component = StorageComponent(app: app)
39+
let storage = component.storage(for: "someBucket", app: app)
3940
XCTAssertNotNil(storage)
4041
}
4142

@@ -61,26 +62,42 @@ class StorageComponentTests: StorageTestHelpers {
6162

6263
/// Tests that instances of Storage created are different.
6364
func testMultipleStorageInstancesCreated() throws {
65+
let app = try XCTUnwrap(StorageComponentTests.app)
6466
let registrants = NSMutableSet(array: [StorageComponent.self])
65-
let container = FirebaseComponentContainer(
66-
app: StorageComponentTests.app,
67-
registrants: registrants
68-
)
67+
let container = FirebaseComponentContainer(app: app, registrants: registrants)
6968

7069
let provider = ComponentType<StorageProvider>.instance(for: StorageProvider.self,
7170
in: container)
7271
XCTAssertNotNil(provider)
7372

74-
let storage1 = provider.storage(for: "randomBucket")
75-
let storage2 = provider.storage(for: "randomBucket")
73+
let storage1 = provider.storage(for: "randomBucket", app: app)
74+
let storage2 = provider.storage(for: "randomBucket", app: app)
7675
XCTAssertNotNil(storage1)
7776

7877
// Ensure they're the same instance.
7978
XCTAssert(storage1 === storage2)
8079

81-
let storage3 = provider.storage(for: "differentBucket")
80+
let storage3 = provider.storage(for: "differentBucket", app: app)
8281
XCTAssertNotNil(storage3)
8382

8483
XCTAssert(storage1 !== storage3)
8584
}
85+
86+
/// Test that Storage instances get deallocated.
87+
func testStorageLifecycle() throws {
88+
weak var weakApp: FirebaseApp?
89+
weak var weakStorage: Storage?
90+
try autoreleasepool {
91+
let options = FirebaseOptions(googleAppID: "0:0000000000000:ios:0000000000000000",
92+
gcmSenderID: "00000000000000000-00000000000-000000000")
93+
options.projectID = "myProjectID"
94+
let app1 = FirebaseApp(instanceWithName: "transitory app", options: options)
95+
weakApp = try XCTUnwrap(app1)
96+
let storage = Storage(app: app1, bucket: "transitory bucket")
97+
weakStorage = storage
98+
XCTAssertNotNil(weakStorage)
99+
}
100+
XCTAssertNil(weakApp)
101+
XCTAssertNil(weakStorage)
102+
}
86103
}

0 commit comments

Comments
 (0)