Skip to content

Commit 3a769aa

Browse files
Don't drop empty object during merge
1 parent 2b87644 commit 3a769aa

File tree

8 files changed

+71
-43
lines changed

8 files changed

+71
-43
lines changed

Firestore/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
- [changed] Changed `get()` to only make 1 attempt to reach the backend before
55
returning cached data, potentially reducing delays while offline. Previously
66
it would make 2 attempts, to work around a backend bug.
7+
- [fixed] Fixed an issue that caused us to drop empty objects from calls to
8+
`setData(..., merge:true)`.
79

810
# v0.13.3
911
- [changed] Internal improvements.

Firestore/Example/App/GoogleService-Info.plist

Lines changed: 0 additions & 28 deletions
This file was deleted.

Firestore/Example/Firestore.xcodeproj/project.pbxproj

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,6 @@
123123
54A0353020A3B3D8003E0143 /* statusor_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54A0352D20A3B3D7003E0143 /* statusor_test.cc */; };
124124
54A0353520A3D8CB003E0143 /* iterator_adaptors_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54A0353420A3D8CB003E0143 /* iterator_adaptors_test.cc */; };
125125
54C2294F1FECABAE007D065B /* log_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54C2294E1FECABAE007D065B /* log_test.cc */; };
126-
54D400D42148BACE001D2BCC /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 54D400D32148BACE001D2BCC /* GoogleService-Info.plist */; };
127126
54DA12A61F315EE100DD57A1 /* collection_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 54DA129C1F315EE100DD57A1 /* collection_spec_test.json */; };
128127
54DA12A71F315EE100DD57A1 /* existence_filter_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 54DA129D1F315EE100DD57A1 /* existence_filter_spec_test.json */; };
129128
54DA12A81F315EE100DD57A1 /* limbo_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 54DA129E1F315EE100DD57A1 /* limbo_spec_test.json */; };
@@ -217,7 +216,10 @@
217216
C80B10E79CDD7EF7843C321E /* type_traits_apple_test.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2A0CF41BA5AED6049B0BEB2C /* type_traits_apple_test.mm */; };
218217
C8D3CE2343E53223E6487F2C /* Pods_Firestore_Example_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5918805E993304321A05E82B /* Pods_Firestore_Example_iOS.framework */; };
219218
CA989C0E6020C372A62B7062 /* testutil.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54A0352820A3B3BD003E0143 /* testutil.cc */; };
219+
D5B2529BEB307D0725979F62 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = D5B259789B257368234FA2F6 /* GoogleService-Info.plist */; };
220220
D5B25CBF07F65E885C9D68AB /* perf_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = D5B2593BCB52957D62F1C9D3 /* perf_spec_test.json */; };
221+
D5B25DDFD27670BEA5AD70EE /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = D5B259789B257368234FA2F6 /* GoogleService-Info.plist */; };
222+
D5B25EE88A01AC7768B6D98F /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = D5B259789B257368234FA2F6 /* GoogleService-Info.plist */; };
221223
D94A1862B8FB778225DB54A1 /* filesystem_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = F51859B394D01C0C507282F1 /* filesystem_test.cc */; };
222224
DD5976A45071455FF3FE74B8 /* string_win_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 79507DF8378D3C42F5B36268 /* string_win_test.cc */; };
223225
DE03B2D41F2149D600A30B9C /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F5AF195388D20070C39A /* XCTest.framework */; };
@@ -408,7 +410,6 @@
408410
54C2294E1FECABAE007D065B /* log_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = log_test.cc; sourceTree = "<group>"; };
409411
54C9EDF12040E16300A969CD /* Firestore_SwiftTests_iOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Firestore_SwiftTests_iOS.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
410412
54C9EDF52040E16300A969CD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
411-
54D400D32148BACE001D2BCC /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "App/GoogleService-Info.plist"; sourceTree = SOURCE_ROOT; };
412413
54DA129C1F315EE100DD57A1 /* collection_spec_test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = collection_spec_test.json; sourceTree = "<group>"; };
413414
54DA129D1F315EE100DD57A1 /* existence_filter_spec_test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = existence_filter_spec_test.json; sourceTree = "<group>"; };
414415
54DA129E1F315EE100DD57A1 /* limbo_spec_test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = limbo_spec_test.json; sourceTree = "<group>"; };
@@ -532,6 +533,7 @@
532533
BB92EB03E3F92485023F64ED /* Pods_Firestore_Example_iOS_Firestore_SwiftTests_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Example_iOS_Firestore_SwiftTests_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
533534
D3CC3DC5338DCAF43A211155 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; };
534535
D5B2593BCB52957D62F1C9D3 /* perf_spec_test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = perf_spec_test.json; sourceTree = "<group>"; };
536+
D5B259789B257368234FA2F6 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.info; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
535537
DE03B2E91F2149D600A30B9C /* Firestore_IntegrationTests_iOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Firestore_IntegrationTests_iOS.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
536538
DE03B3621F215E1600A30B9C /* CAcert.pem */ = {isa = PBXFileReference; lastKnownFileType = text; path = CAcert.pem; sourceTree = "<group>"; };
537539
DE0761F61F2FE68D003233AF /* BasicCompileTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BasicCompileTests.swift; sourceTree = "<group>"; };
@@ -625,7 +627,7 @@
625627
isa = PBXGroup;
626628
children = (
627629
6003F593195388D20070C39A /* iOS */,
628-
54D400D32148BACE001D2BCC /* GoogleService-Info.plist */,
630+
D5B259789B257368234FA2F6 /* GoogleService-Info.plist */,
629631
);
630632
path = App;
631633
sourceTree = "<group>";
@@ -1440,11 +1442,11 @@
14401442
isa = PBXResourcesBuildPhase;
14411443
buildActionMask = 2147483647;
14421444
files = (
1443-
54D400D42148BACE001D2BCC /* GoogleService-Info.plist in Resources */,
14441445
6003F5A9195388D20070C39A /* Images.xcassets in Resources */,
14451446
873B8AEB1B1F5CCA007FD442 /* Main.storyboard in Resources */,
14461447
71719F9F1E33DC2100824A3D /* LaunchScreen.storyboard in Resources */,
14471448
6003F598195388D20070C39A /* InfoPlist.strings in Resources */,
1449+
D5B25DDFD27670BEA5AD70EE /* GoogleService-Info.plist in Resources */,
14481450
);
14491451
runOnlyForDeploymentPostprocessing = 0;
14501452
};
@@ -1465,6 +1467,7 @@
14651467
3B843E4C1F3A182900548890 /* remote_store_spec_test.json in Resources */,
14661468
54DA12AE1F315EE100DD57A1 /* resume_token_spec_test.json in Resources */,
14671469
54DA12AF1F315EE100DD57A1 /* write_spec_test.json in Resources */,
1470+
D5B2529BEB307D0725979F62 /* GoogleService-Info.plist in Resources */,
14681471
);
14691472
runOnlyForDeploymentPostprocessing = 0;
14701473
};
@@ -1482,6 +1485,7 @@
14821485
files = (
14831486
DE03B3631F215E1A00A30B9C /* CAcert.pem in Resources */,
14841487
DE03B2DD1F2149D600A30B9C /* InfoPlist.strings in Resources */,
1488+
D5B25EE88A01AC7768B6D98F /* GoogleService-Info.plist in Resources */,
14851489
);
14861490
runOnlyForDeploymentPostprocessing = 0;
14871491
};

Firestore/Example/Tests/Integration/API/FIRDatabaseTests.mm

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#import <XCTest/XCTest.h>
2020

21+
#import "Firestore/Example/Tests/Util/FSTEventAccumulator.h"
2122
#import "Firestore/Example/Tests/Util/FSTIntegrationTestCase.h"
2223
#import "Firestore/Source/API/FIRFirestore+Internal.h"
2324
#import "Firestore/Source/Core/FSTFirestoreClient.h"
@@ -155,6 +156,31 @@ - (void)testCanMergeDataWithAnExistingDocumentUsingSet {
155156
XCTAssertEqualObjects(document.data, finalData);
156157
}
157158

159+
- (void)testCanMergeEmptyObject {
160+
FIRDocumentReference *doc = [[self.db collectionWithPath:@"rooms"] documentWithAutoID];
161+
162+
FSTEventAccumulator *accumulator = [FSTEventAccumulator accumulatorForTest:self];
163+
id<FIRListenerRegistration> listenerRegistration =
164+
[doc addSnapshotListener:[accumulator valueEventHandler]];
165+
166+
[self writeDocumentRef:doc data:@{}];
167+
FIRDocumentSnapshot *snapshot = [accumulator awaitEventWithName:@"Snapshot"];
168+
XCTAssertEqualObjects(snapshot.data, @{});
169+
170+
[self mergeDocumentRef:doc data:@{@"a" : @{}} fields:@[ @"a" ]];
171+
snapshot = [accumulator awaitEventWithName:@"Snapshot"];
172+
XCTAssertEqualObjects(snapshot.data, @{@"a" : @{}});
173+
174+
[self mergeDocumentRef:doc data:@{@"b" : @{}}];
175+
snapshot = [accumulator awaitEventWithName:@"Snapshot"];
176+
XCTAssertEqualObjects(snapshot.data, (@{@"a" : @{}, @"b" : @{}}));
177+
178+
snapshot = [self readDocumentForRef:doc source:FIRFirestoreSourceServer];
179+
XCTAssertEqualObjects(snapshot.data, (@{@"a" : @{}, @"b" : @{}}));
180+
181+
[listenerRegistration remove];
182+
}
183+
158184
- (void)testCanMergeServerTimestamps {
159185
FIRDocumentReference *doc = [[self.db collectionWithPath:@"rooms"] documentWithAutoID];
160186

Firestore/Example/Tests/Util/FSTIntegrationTestCase.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ extern "C" {
9090

9191
- (void)mergeDocumentRef:(FIRDocumentReference *)ref data:(NSDictionary<NSString *, id> *)data;
9292

93+
- (void)mergeDocumentRef:(FIRDocumentReference *)ref
94+
data:(NSDictionary<NSString *, id> *)data
95+
fields:(NSArray<id> *)fields;
96+
9397
- (void)disableNetwork;
9498

9599
- (void)enableNetwork;

Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,15 @@ - (void)mergeDocumentRef:(FIRDocumentReference *)ref data:(NSDictionary<NSString
331331
[self awaitExpectations];
332332
}
333333

334+
- (void)mergeDocumentRef:(FIRDocumentReference *)ref
335+
data:(NSDictionary<NSString *, id> *)data
336+
fields:(NSArray<id> *)fields {
337+
[ref setData:data
338+
mergeFields:fields
339+
completion:[self completionForExpectationWithName:@"setDataWithMerge"]];
340+
[self awaitExpectations];
341+
}
342+
334343
- (void)disableNetwork {
335344
[self.db.client
336345
disableNetworkWithCompletion:[self completionForExpectationWithName:@"Disable Network."]];

Firestore/Source/API/FSTUserDataConverter.mm

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -257,13 +257,22 @@ - (nullable FSTFieldValue *)parseData:(id)input context:(ParseContext &&)context
257257
- (FSTFieldValue *)parseDictionary:(NSDictionary *)dict context:(ParseContext &&)context {
258258
NSMutableDictionary<NSString *, FSTFieldValue *> *result =
259259
[NSMutableDictionary dictionaryWithCapacity:dict.count];
260-
[dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL *stop) {
261-
FSTFieldValue *_Nullable parsedValue =
262-
[self parseData:value context:context.ChildContext(util::MakeString(key))];
263-
if (parsedValue) {
264-
result[key] = parsedValue;
260+
261+
if ([dict count] == 0) {
262+
const FieldPath *path = context.path();
263+
if (path && !path->empty()) {
264+
context.AddToFieldMask(*path);
265265
}
266-
}];
266+
return [FSTObjectValue objectValue];
267+
} else {
268+
[dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL *stop) {
269+
FSTFieldValue *_Nullable parsedValue =
270+
[self parseData:value context:context.ChildContext(util::MakeString(key))];
271+
if (parsedValue) {
272+
result[key] = parsedValue;
273+
}
274+
}];
275+
}
267276
return [[FSTObjectValue alloc] initWithDictionary:result];
268277
}
269278

Firestore/Source/Model/FSTMutation.mm

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -271,11 +271,13 @@ - (nullable FSTMaybeDocument *)applyTo:(nullable FSTMaybeDocument *)maybeDoc
271271
- (FSTObjectValue *)patchObjectValue:(FSTObjectValue *)objectValue {
272272
FSTObjectValue *result = objectValue;
273273
for (const FieldPath &fieldPath : self.fieldMask) {
274-
FSTFieldValue *newValue = [self.value valueForPath:fieldPath];
275-
if (newValue) {
276-
result = [result objectBySettingValue:newValue forPath:fieldPath];
277-
} else {
278-
result = [result objectByDeletingPath:fieldPath];
274+
if (!fieldPath.empty()) {
275+
FSTFieldValue *newValue = [self.value valueForPath:fieldPath];
276+
if (newValue) {
277+
result = [result objectBySettingValue:newValue forPath:fieldPath];
278+
} else {
279+
result = [result objectByDeletingPath:fieldPath];
280+
}
279281
}
280282
}
281283
return result;

0 commit comments

Comments
 (0)