Skip to content

Commit f3ec700

Browse files
committed
Rework FieldMask to use a SortedSet of FieldPaths
Rather than an array. Port of firebase/firebase-android-sdk#137
1 parent c3895ac commit f3ec700

File tree

4 files changed

+28
-17
lines changed

4 files changed

+28
-17
lines changed

packages/firestore/src/api/user_data_converter.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ export class UserDataConverter {
336336
let fieldTransforms: FieldTransform[];
337337

338338
if (!fieldPaths) {
339-
fieldMask = new FieldMask(context.fieldMask);
339+
fieldMask = FieldMask.fromArray(context.fieldMask);
340340
fieldTransforms = context.fieldTransforms;
341341
} else {
342342
const validatedFieldPaths: FieldPath[] = [];
@@ -367,7 +367,7 @@ export class UserDataConverter {
367367
validatedFieldPaths.push(fieldPath);
368368
}
369369

370-
fieldMask = new FieldMask(validatedFieldPaths);
370+
fieldMask = FieldMask.fromArray(validatedFieldPaths);
371371
fieldTransforms = context.fieldTransforms.filter(transform =>
372372
fieldMask.covers(transform.field)
373373
);
@@ -407,7 +407,7 @@ export class UserDataConverter {
407407
}
408408
});
409409

410-
const mask = new FieldMask(fieldMaskPaths);
410+
const mask = FieldMask.fromArray(fieldMaskPaths);
411411
return new ParsedUpdateData(updateData, mask, context.fieldTransforms);
412412
}
413413

@@ -462,7 +462,7 @@ export class UserDataConverter {
462462
}
463463
}
464464

465-
const mask = new FieldMask(fieldMaskPaths);
465+
const mask = FieldMask.fromArray(fieldMaskPaths);
466466
return new ParsedUpdateData(updateData, mask, context.fieldTransforms);
467467
}
468468

packages/firestore/src/model/mutation.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { Timestamp } from '../api/timestamp';
1818
import { SnapshotVersion } from '../core/snapshot_version';
1919
import { assert } from '../util/assert';
2020
import * as misc from '../util/misc';
21+
import { SortedSet } from '../util/sorted_set';
2122

2223
import {
2324
Document,
@@ -41,28 +42,34 @@ import { TransformOperation } from './transform_operation';
4142
* containing foo
4243
*/
4344
export class FieldMask {
44-
constructor(readonly fields: FieldPath[]) {
45+
private constructor(readonly fields: SortedSet<FieldPath>) {
4546
// TODO(dimond): validation of FieldMask
4647
}
4748

49+
static fromArray(fields: FieldPath[]): FieldMask {
50+
let fieldsAsSet = new SortedSet<FieldPath>(FieldPath.comparator);
51+
fields.forEach(fieldPath => (fieldsAsSet = fieldsAsSet.add(fieldPath)));
52+
return new FieldMask(fieldsAsSet);
53+
}
54+
4855
/**
4956
* Verifies that `fieldPath` is included by at least one field in this field
5057
* mask.
5158
*
5259
* This is an O(n) operation, where `n` is the size of the field mask.
5360
*/
5461
covers(fieldPath: FieldPath): boolean {
55-
for (const fieldMaskPath of this.fields) {
62+
let found = false;
63+
this.fields.forEach(fieldMaskPath => {
5664
if (fieldMaskPath.isPrefixOf(fieldPath)) {
57-
return true;
65+
found = true;
5866
}
59-
}
60-
61-
return false;
67+
});
68+
return found;
6269
}
6370

6471
isEqual(other: FieldMask): boolean {
65-
return misc.arrayEquals(this.fields, other.fields);
72+
return this.fields.isEqual(other.fields);
6673
}
6774
}
6875

@@ -448,7 +455,7 @@ export class PatchMutation extends Mutation {
448455
}
449456

450457
private patchObject(data: ObjectValue): ObjectValue {
451-
for (const fieldPath of this.fieldMask.fields) {
458+
this.fieldMask.fields.forEach(fieldPath => {
452459
if (!fieldPath.isEmpty()) {
453460
const newValue = this.data.field(fieldPath);
454461
if (newValue !== undefined) {
@@ -457,7 +464,7 @@ export class PatchMutation extends Mutation {
457464
data = data.delete(fieldPath);
458465
}
459466
}
460-
}
467+
});
461468
return data;
462469
}
463470
}

packages/firestore/src/remote/serializer.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,15 +1304,19 @@ export class JsonProtoSerializer {
13041304
}
13051305

13061306
toDocumentMask(fieldMask: FieldMask): api.DocumentMask {
1307+
const canonicalFields: string[] = [];
1308+
fieldMask.fields.forEach(field =>
1309+
canonicalFields.push(field.canonicalString())
1310+
);
13071311
return {
1308-
fieldPaths: fieldMask.fields.map(field => field.canonicalString())
1312+
fieldPaths: canonicalFields
13091313
};
13101314
}
13111315

13121316
fromDocumentMask(proto: api.DocumentMask): FieldMask {
13131317
const paths = proto.fieldPaths || [];
13141318
const fields = paths.map(path => FieldPath.fromServerFormat(path));
1315-
return new FieldMask(fields);
1319+
return FieldMask.fromArray(fields);
13161320
}
13171321
}
13181322

packages/firestore/test/unit/remote/node/serializer.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ describe('Serializer', () => {
605605
// tslint:disable-next-line:ban TODO(b/34988481): Implement correct escaping
606606
it.skip('converts a weird path', () => {
607607
const expected: api.DocumentMask = { fieldPaths: ['foo.`bar.baz\\qux`'] };
608-
const mask = new FieldMask([
608+
const mask = FieldMask.fromArray([
609609
FieldPath.fromServerFormat('foo.bar\\.baz\\\\qux')
610610
]);
611611
const actual = s.toDocumentMask(mask);
@@ -618,7 +618,7 @@ describe('Serializer', () => {
618618

619619
// tslint:disable-next-line:ban TODO(b/34988481): Implement correct escaping
620620
it.skip('converts a weird path', () => {
621-
const expected = new FieldMask([
621+
const expected = FieldMask.fromArray([
622622
FieldPath.fromServerFormat('foo.bar\\.baz\\\\qux')
623623
]);
624624
const proto: api.DocumentMask = { fieldPaths: ['foo.`bar.baz\\qux`'] };

0 commit comments

Comments
 (0)