Skip to content

Commit

Permalink
Tree-shakeable Bound (#3250)
Browse files Browse the repository at this point in the history
  • Loading branch information
schmidt-sebastian authored Jun 22, 2020
1 parent 23e8971 commit 992e638
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 94 deletions.
50 changes: 39 additions & 11 deletions packages/firestore/lite/test/dependencies.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,10 @@
"assertUint8ArrayAvailable",
"binaryStringFromUint8Array",
"blobEquals",
"boundEquals",
"canonicalId",
"canonifyArray",
"canonifyBound",
"canonifyByteString",
"canonifyGeoPoint",
"canonifyMap",
Expand Down Expand Up @@ -151,6 +153,8 @@
"primitiveComparator",
"refValue",
"registerFirestore",
"sortsBeforeDocument",
"stringifyTarget",
"targetEquals",
"timestampEquals",
"toBytes",
Expand Down Expand Up @@ -238,7 +242,7 @@
],
"variables": []
},
"sizeInBytes": 97396
"sizeInBytes": 97991
},
"DocumentReference": {
"dependencies": {
Expand Down Expand Up @@ -774,7 +778,7 @@
],
"variables": []
},
"sizeInBytes": 88429
"sizeInBytes": 87202
},
"QueryDocumentSnapshot": {
"dependencies": {
Expand Down Expand Up @@ -1274,8 +1278,10 @@
"assertUint8ArrayAvailable",
"binaryStringFromUint8Array",
"blobEquals",
"boundEquals",
"canonicalId",
"canonifyArray",
"canonifyBound",
"canonifyByteString",
"canonifyGeoPoint",
"canonifyMap",
Expand Down Expand Up @@ -1363,6 +1369,8 @@
"refValue",
"registerFirestore",
"serverTimestamp",
"sortsBeforeDocument",
"stringifyTarget",
"targetEquals",
"timestampEquals",
"toBytes",
Expand Down Expand Up @@ -1466,7 +1474,7 @@
],
"variables": []
},
"sizeInBytes": 107674
"sizeInBytes": 108269
},
"arrayRemove": {
"dependencies": {
Expand Down Expand Up @@ -1697,8 +1705,10 @@
"assertUint8ArrayAvailable",
"binaryStringFromUint8Array",
"blobEquals",
"boundEquals",
"canonicalId",
"canonifyArray",
"canonifyBound",
"canonifyByteString",
"canonifyGeoPoint",
"canonifyMap",
Expand Down Expand Up @@ -1778,6 +1788,8 @@
"primitiveComparator",
"refValue",
"registerFirestore",
"sortsBeforeDocument",
"stringifyTarget",
"targetEquals",
"timestampEquals",
"toBytes",
Expand Down Expand Up @@ -1866,7 +1878,7 @@
],
"variables": []
},
"sizeInBytes": 98024
"sizeInBytes": 98619
},
"collectionGroup": {
"dependencies": {
Expand All @@ -1877,8 +1889,10 @@
"assertUint8ArrayAvailable",
"binaryStringFromUint8Array",
"blobEquals",
"boundEquals",
"canonicalId",
"canonifyArray",
"canonifyBound",
"canonifyByteString",
"canonifyGeoPoint",
"canonifyMap",
Expand Down Expand Up @@ -1958,6 +1972,8 @@
"primitiveComparator",
"refValue",
"registerFirestore",
"sortsBeforeDocument",
"stringifyTarget",
"targetEquals",
"timestampEquals",
"toBytes",
Expand Down Expand Up @@ -2044,7 +2060,7 @@
],
"variables": []
},
"sizeInBytes": 97455
"sizeInBytes": 98050
},
"deleteDoc": {
"dependencies": {
Expand Down Expand Up @@ -2235,8 +2251,10 @@
"assertUint8ArrayAvailable",
"binaryStringFromUint8Array",
"blobEquals",
"boundEquals",
"canonicalId",
"canonifyArray",
"canonifyBound",
"canonifyByteString",
"canonifyGeoPoint",
"canonifyMap",
Expand Down Expand Up @@ -2317,6 +2335,8 @@
"randomBytes",
"refValue",
"registerFirestore",
"sortsBeforeDocument",
"stringifyTarget",
"targetEquals",
"timestampEquals",
"toBytes",
Expand Down Expand Up @@ -2406,7 +2426,7 @@
],
"variables": []
},
"sizeInBytes": 98845
"sizeInBytes": 99440
},
"documentId": {
"dependencies": {
Expand Down Expand Up @@ -2828,7 +2848,7 @@
],
"variables": []
},
"sizeInBytes": 94239
"sizeInBytes": 93121
},
"increment": {
"dependencies": {
Expand Down Expand Up @@ -3005,8 +3025,10 @@
"assertUint8ArrayAvailable",
"binaryStringFromUint8Array",
"blobEquals",
"boundEquals",
"canonicalId",
"canonifyArray",
"canonifyBound",
"canonifyByteString",
"canonifyGeoPoint",
"canonifyMap",
Expand Down Expand Up @@ -3086,6 +3108,8 @@
"primitiveComparator",
"refValue",
"registerFirestore",
"sortsBeforeDocument",
"stringifyTarget",
"targetEquals",
"timestampEquals",
"toBytes",
Expand Down Expand Up @@ -3173,7 +3197,7 @@
],
"variables": []
},
"sizeInBytes": 97739
"sizeInBytes": 98334
},
"queryEqual": {
"dependencies": {
Expand Down Expand Up @@ -3342,7 +3366,7 @@
],
"variables": []
},
"sizeInBytes": 88633
"sizeInBytes": 87406
},
"refEqual": {
"dependencies": {
Expand All @@ -3353,8 +3377,10 @@
"assertUint8ArrayAvailable",
"binaryStringFromUint8Array",
"blobEquals",
"boundEquals",
"canonicalId",
"canonifyArray",
"canonifyBound",
"canonifyByteString",
"canonifyGeoPoint",
"canonifyMap",
Expand Down Expand Up @@ -3434,6 +3460,8 @@
"refEqual",
"refValue",
"registerFirestore",
"sortsBeforeDocument",
"stringifyTarget",
"targetEquals",
"timestampEquals",
"toBytes",
Expand Down Expand Up @@ -3521,7 +3549,7 @@
],
"variables": []
},
"sizeInBytes": 97681
"sizeInBytes": 98276
},
"runTransaction": {
"dependencies": {
Expand Down Expand Up @@ -4142,7 +4170,7 @@
],
"variables": []
},
"sizeInBytes": 89366
"sizeInBytes": 88139
},
"terminate": {
"dependencies": {
Expand Down
129 changes: 68 additions & 61 deletions packages/firestore/src/core/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -452,10 +452,10 @@ export class Query {
* Makes sure a document is within the bounds, if provided.
*/
private matchesBounds(doc: Document): boolean {
if (this.startAt && !this.startAt.sortsBeforeDocument(this.orderBy, doc)) {
if (this.startAt && !sortsBeforeDocument(this.startAt, this.orderBy, doc)) {
return false;
}
if (this.endAt && this.endAt.sortsBeforeDocument(this.orderBy, doc)) {
if (this.endAt && sortsBeforeDocument(this.endAt, this.orderBy, doc)) {
return false;
}
return true;
Expand Down Expand Up @@ -732,73 +732,80 @@ export const enum Direction {
*/
export class Bound {
constructor(readonly position: api.Value[], readonly before: boolean) {}
}

canonicalId(): string {
// TODO(b/29183165): Make this collision robust.
return `${this.before ? 'b' : 'a'}:${this.position
.map(p => canonicalId(p))
.join(',')}`;
}
export function canonifyBound(bound: Bound): string {
// TODO(b/29183165): Make this collision robust.
return `${bound.before ? 'b' : 'a'}:${bound.position
.map(p => canonicalId(p))
.join(',')}`;
}

/**
* Returns true if a document sorts before a bound using the provided sort
* order.
*/
sortsBeforeDocument(orderBy: OrderBy[], doc: Document): boolean {
debugAssert(
this.position.length <= orderBy.length,
"Bound has more components than query's orderBy"
);
let comparison = 0;
for (let i = 0; i < this.position.length; i++) {
const orderByComponent = orderBy[i];
const component = this.position[i];
if (orderByComponent.field.isKeyField()) {
debugAssert(
isReferenceValue(component),
'Bound has a non-key value where the key path is being used.'
);
comparison = DocumentKey.comparator(
DocumentKey.fromName(component.referenceValue),
doc.key
);
} else {
const docValue = doc.field(orderByComponent.field);
debugAssert(
docValue !== null,
'Field should exist since document matched the orderBy already.'
);
comparison = valueCompare(component, docValue);
}
if (orderByComponent.dir === Direction.DESCENDING) {
comparison = comparison * -1;
}
if (comparison !== 0) {
break;
}
/**
* Returns true if a document sorts before a bound using the provided sort
* order.
*/
export function sortsBeforeDocument(
bound: Bound,
orderBy: OrderBy[],
doc: Document
): boolean {
debugAssert(
bound.position.length <= orderBy.length,
"Bound has more components than query's orderBy"
);
let comparison = 0;
for (let i = 0; i < bound.position.length; i++) {
const orderByComponent = orderBy[i];
const component = bound.position[i];
if (orderByComponent.field.isKeyField()) {
debugAssert(
isReferenceValue(component),
'Bound has a non-key value where the key path is being used.'
);
comparison = DocumentKey.comparator(
DocumentKey.fromName(component.referenceValue),
doc.key
);
} else {
const docValue = doc.field(orderByComponent.field);
debugAssert(
docValue !== null,
'Field should exist since document matched the orderBy already.'
);
comparison = valueCompare(component, docValue);
}
if (orderByComponent.dir === Direction.DESCENDING) {
comparison = comparison * -1;
}
if (comparison !== 0) {
break;
}
return this.before ? comparison <= 0 : comparison < 0;
}
return bound.before ? comparison <= 0 : comparison < 0;
}

isEqual(other: Bound | null): boolean {
if (other === null) {
return false;
}
if (
this.before !== other.before ||
this.position.length !== other.position.length
) {
export function boundEquals(left: Bound | null, right: Bound | null): boolean {
if (left === null) {
return right === null;
} else if (right === null) {
return false;
}

if (
left.before !== right.before ||
left.position.length !== right.position.length
) {
return false;
}
for (let i = 0; i < left.position.length; i++) {
const leftPosition = left.position[i];
const rightPosition = right.position[i];
if (!valueEquals(leftPosition, rightPosition)) {
return false;
}
for (let i = 0; i < this.position.length; i++) {
const thisPosition = this.position[i];
const otherPosition = other.position[i];
if (!valueEquals(thisPosition, otherPosition)) {
return false;
}
}
return true;
}
return true;
}

/**
Expand Down
Loading

0 comments on commit 992e638

Please sign in to comment.