Skip to content

Commit 39e1eeb

Browse files
Don't drop empty object during merge
1 parent 2b87644 commit 39e1eeb

File tree

6 files changed

+63
-11
lines changed

6 files changed

+63
-11
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/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)