@@ -501,7 +501,7 @@ class DocumentReference {
501
501
502
502
let watch = Watch . forDocument ( this ) ;
503
503
504
- return watch . onSnapshot ( ( readTime , docs ) => {
504
+ return watch . onSnapshot ( ( readTime , size , docs ) => {
505
505
for ( let document of docs ( ) ) {
506
506
if ( document . ref . path === this . path ) {
507
507
onNext ( document ) ;
@@ -852,17 +852,20 @@ class QuerySnapshot {
852
852
* @param {Query } query - The originating query.
853
853
* @param {string } readTime - The ISO 8601 time when this query snapshot was
854
854
* current.
855
- *
855
+ * @param { number } size - The number of documents in the result set.
856
856
* @param {function } docs - A callback returning a sorted array of documents
857
857
* matching this query
858
858
* @param {function } changes - A callback returning a sorted array of
859
859
* document change events for this snapshot.
860
860
*/
861
- constructor ( query , readTime , docs , changes ) {
861
+ constructor ( query , readTime , size , docs , changes ) {
862
862
this . _query = query ;
863
863
this . _readTime = readTime ;
864
+ this . _size = size ;
864
865
this . _docs = docs ;
866
+ this . _materializedDocs = null ;
865
867
this . _changes = changes ;
868
+ this . _materializedChanges = null ;
866
869
}
867
870
868
871
/**
@@ -910,6 +913,7 @@ class QuerySnapshot {
910
913
return this . _materializedDocs ;
911
914
}
912
915
this . _materializedDocs = this . _docs ( ) ;
916
+ this . _docs = null ;
913
917
return this . _materializedDocs ;
914
918
}
915
919
@@ -925,6 +929,7 @@ class QuerySnapshot {
925
929
return this . _materializedChanges ;
926
930
}
927
931
this . _materializedChanges = this . _changes ( ) ;
932
+ this . _changes = null ;
928
933
return this . _materializedChanges ;
929
934
}
930
935
@@ -945,7 +950,7 @@ class QuerySnapshot {
945
950
* });
946
951
*/
947
952
get empty ( ) {
948
- return this . docs . length === 0 ;
953
+ return this . _size === 0 ;
949
954
}
950
955
951
956
/**
@@ -963,7 +968,7 @@ class QuerySnapshot {
963
968
* });
964
969
*/
965
970
get size ( ) {
966
- return this . docs . length ;
971
+ return this . _size ;
967
972
}
968
973
969
974
/**
@@ -1025,37 +1030,27 @@ class QuerySnapshot {
1025
1030
return false ;
1026
1031
}
1027
1032
1028
- if ( ! this . _query . isEqual ( other . _query ) ) {
1029
- return false ;
1030
- }
1031
-
1032
- const thisChanges = this . docChanges ;
1033
- const otherChanges = other . docChanges ;
1034
-
1035
- if ( thisChanges . length !== otherChanges . length ) {
1033
+ if ( this . _size !== other . _size ) {
1036
1034
return false ;
1037
1035
}
1038
1036
1039
- for ( let i = 0 ; i < thisChanges . length ; ++ i ) {
1040
- if ( ! thisChanges [ i ] . isEqual ( otherChanges [ i ] ) ) {
1041
- return false ;
1042
- }
1043
- }
1044
-
1045
- const thisDocs = this . docs ;
1046
- const otherDocs = other . docs ;
1047
-
1048
- if ( thisDocs . length !== otherDocs . length ) {
1037
+ if ( ! this . _query . isEqual ( other . _query ) ) {
1049
1038
return false ;
1050
1039
}
1051
1040
1052
- for ( let i = 0 ; i < thisDocs . length ; ++ i ) {
1053
- if ( ! thisDocs [ i ] . isEqual ( otherDocs [ i ] ) ) {
1054
- return false ;
1055
- }
1041
+ if ( this . _materializedChanges ) {
1042
+ // If we have already materialized the document changes, we compare
1043
+ // them first as they are expected to be much smaller.
1044
+ return (
1045
+ isArrayEqual ( this . docChanges , other . docChanges ) &&
1046
+ isArrayEqual ( this . docs , other . docs )
1047
+ ) ;
1056
1048
}
1057
1049
1058
- return true ;
1050
+ return (
1051
+ isArrayEqual ( this . docs , other . docs ) &&
1052
+ isArrayEqual ( this . docChanges , other . docChanges )
1053
+ ) ;
1059
1054
}
1060
1055
}
1061
1056
@@ -1756,7 +1751,6 @@ class Query {
1756
1751
_get ( queryOptions ) {
1757
1752
let self = this ;
1758
1753
let docs = [ ] ;
1759
- let changes = [ ] ;
1760
1754
1761
1755
return new Promise ( ( resolve , reject ) => {
1762
1756
let readTime ;
@@ -1770,19 +1764,27 @@ class Query {
1770
1764
readTime = result . readTime ;
1771
1765
if ( result . document ) {
1772
1766
let document = result . document ;
1773
- changes . push (
1774
- new DocumentChange (
1775
- DocumentChange . ADDED ,
1776
- document ,
1777
- - 1 ,
1778
- docs . length
1779
- )
1780
- ) ;
1781
1767
docs . push ( document ) ;
1782
1768
}
1783
1769
} )
1784
1770
. on ( 'end' , ( ) => {
1785
- resolve ( new QuerySnapshot ( this , readTime , ( ) => docs , ( ) => changes ) ) ;
1771
+ resolve (
1772
+ new QuerySnapshot (
1773
+ this ,
1774
+ readTime ,
1775
+ docs . length ,
1776
+ ( ) => docs ,
1777
+ ( ) => {
1778
+ let changes = [ ] ;
1779
+ for ( let i = 0 ; i < docs . length ; ++ i ) {
1780
+ changes . push (
1781
+ new DocumentChange ( DocumentChange . ADDED , docs [ i ] , - 1 , i )
1782
+ ) ;
1783
+ }
1784
+ return changes ;
1785
+ }
1786
+ )
1787
+ ) ;
1786
1788
} ) ;
1787
1789
} ) ;
1788
1790
}
@@ -1972,8 +1974,8 @@ class Query {
1972
1974
1973
1975
let watch = Watch . forQuery ( this ) ;
1974
1976
1975
- return watch . onSnapshot ( ( readTime , docs , changes ) => {
1976
- onNext ( new QuerySnapshot ( this , readTime , docs , changes ) ) ;
1977
+ return watch . onSnapshot ( ( readTime , size , docs , changes ) => {
1978
+ onNext ( new QuerySnapshot ( this , readTime , docs . length , docs , changes ) ) ;
1977
1979
} , onError ) ;
1978
1980
}
1979
1981
@@ -2236,6 +2238,27 @@ function validateDocumentReference(value) {
2236
2238
throw validate . customObjectError ( value ) ;
2237
2239
}
2238
2240
2241
+ /**
2242
+ * Verifies euqality for an array of objects using the `isEqual` interface.
2243
+ *
2244
+ * @param {Array.<Object> } left Array of objects supporting `isEqual`.
2245
+ * @param {Array.<Object> } right Array of objects supporting `isEqual`.
2246
+ * @return {boolean } True if arrays are equal.
2247
+ */
2248
+ function isArrayEqual ( left , right ) {
2249
+ if ( left . length !== right . length ) {
2250
+ return false ;
2251
+ }
2252
+
2253
+ for ( let i = 0 ; i < left . length ; ++ i ) {
2254
+ if ( ! left [ i ] . isEqual ( right [ i ] ) ) {
2255
+ return false ;
2256
+ }
2257
+ }
2258
+
2259
+ return true ;
2260
+ }
2261
+
2239
2262
module . exports = FirestoreType => {
2240
2263
Firestore = FirestoreType ;
2241
2264
let document = require ( './document' ) ( DocumentReference ) ;
0 commit comments