Skip to content

Commit 9be8285

Browse files
schmidt-sebastianMichael Lehenbauer
authored and
Michael Lehenbauer
committed
Treat empty maps correctly in Document.get() (#2206)
1 parent 6e377fe commit 9be8285

File tree

4 files changed

+30
-7
lines changed

4 files changed

+30
-7
lines changed

packages/firestore/CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
# Unreleased (1.5.0)
1+
# Unreleased
2+
- [fixed] Fixed a regression that caused queries with nested field filters to
3+
crash the client if the field was not present in the local copy of the
4+
document.
5+
6+
# 1.5.0
27
- [feature] Added a `Firestore.waitForPendingWrites()` method that
38
allows users to wait until all pending writes are acknowledged by the
49
Firestore backend.

packages/firestore/src/model/document.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ export class Document extends MaybeDocument {
120120
data(): ObjectValue {
121121
if (!this.objectValue) {
122122
let result = ObjectValue.EMPTY;
123-
obj.forEach(this.proto!.fields, (key: string, value: api.Value) => {
123+
obj.forEach(this.proto!.fields || {}, (key: string, value: api.Value) => {
124124
result = result.set(new FieldPath([key]), this.converter!(value));
125125
});
126126
this.objectValue = result;
@@ -170,11 +170,11 @@ export class Document extends MaybeDocument {
170170
'Can only call getProtoField() when proto is defined'
171171
);
172172

173-
let protoValue: api.Value | undefined = this.proto!.fields[
174-
path.firstSegment()
175-
];
173+
let protoValue: api.Value | undefined = this.proto!.fields
174+
? this.proto!.fields[path.firstSegment()]
175+
: undefined;
176176
for (let i = 1; i < path.length; ++i) {
177-
if (!protoValue || !protoValue.mapValue) {
177+
if (!protoValue || !protoValue.mapValue || !protoValue.mapValue.fields) {
178178
return undefined;
179179
}
180180
protoValue = protoValue.mapValue.fields[path.get(i)];

packages/firestore/src/protos/firestore_proto_api.d.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222
@typescript-eslint/interface-name-prefix, @typescript-eslint/class-name-casing
2323
*/
2424
export declare type ApiClientHookFactory = any;
25-
export declare type ApiClientObjectMap<T> = any;
2625
export declare type PromiseRequestService = any;
26+
export interface ApiClientObjectMap<T> {
27+
[k: string]: T;
28+
}
2729

2830
export declare type CompositeFilterOp = 'OPERATOR_UNSPECIFIED' | 'AND';
2931
export interface ICompositeFilterOpEnum {

packages/firestore/test/integration/api/query.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -819,4 +819,20 @@ apiDescribe('Queries', (persistence: boolean) => {
819819
}
820820
});
821821
});
822+
823+
it('can use filter with nested field', () => {
824+
// Reproduces https://github.com/firebase/firebase-js-sdk/issues/2204
825+
const testDocs = {
826+
a: {},
827+
b: { map: {} },
828+
c: { map: { nested: {} } },
829+
d: { map: { nested: 'foo' } }
830+
};
831+
832+
return withTestCollection(persistence, testDocs, async coll => {
833+
await coll.get(); // Populate the cache
834+
const snapshot = await coll.where('map.nested', '==', 'foo').get();
835+
expect(toDataArray(snapshot)).to.deep.equal([{ map: { nested: 'foo' } }]);
836+
});
837+
});
822838
});

0 commit comments

Comments
 (0)