@firebase/firestore 3.4.4-canary.b20cf306a → 3.4.4-canary.bb8f37c3e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/firestore/src/api/credentials.d.ts +1 -0
- package/dist/firestore/src/api/snapshot.d.ts +1 -2
- package/dist/firestore/src/core/target.d.ts +8 -4
- package/dist/firestore/src/lite-api/query.d.ts +2 -2
- package/dist/firestore/src/local/index_manager.d.ts +52 -0
- package/dist/firestore/src/local/indexeddb_index_manager.d.ts +21 -2
- package/dist/firestore/src/local/indexeddb_persistence.d.ts +4 -4
- package/dist/firestore/src/local/indexeddb_remote_document_cache.d.ts +2 -8
- package/dist/firestore/src/local/indexeddb_schema.d.ts +149 -7
- package/dist/firestore/src/local/local_documents_view.d.ts +0 -1
- package/dist/firestore/src/local/local_serializer.d.ts +7 -2
- package/dist/firestore/src/local/memory_index_manager.d.ts +11 -0
- package/dist/firestore/src/local/memory_persistence.d.ts +3 -2
- package/dist/firestore/src/local/memory_remote_document_cache.d.ts +1 -3
- package/dist/firestore/src/local/persistence.d.ts +2 -2
- package/dist/firestore/src/local/remote_document_cache.d.ts +7 -9
- package/dist/firestore/src/local/simple_db.d.ts +1 -0
- package/dist/firestore/src/model/field_index.d.ts +2 -2
- package/dist/firestore/src/model/target_index_matcher.d.ts +70 -0
- package/dist/firestore/test/unit/local/counting_query_engine.d.ts +3 -3
- package/dist/firestore/test/unit/local/persistence_test_helpers.d.ts +1 -0
- package/dist/firestore/test/unit/local/test_index_manager.d.ts +11 -0
- package/dist/firestore/test/unit/local/test_remote_document_cache.d.ts +4 -2
- package/dist/firestore/test/unit/local/test_remote_document_change_buffer.d.ts +1 -1
- package/dist/firestore/test/unit/model/target_index_matcher.test.d.ts +17 -0
- package/dist/firestore/test/util/helpers.d.ts +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.esm2017.js +3373 -3129
- package/dist/index.esm2017.js.map +1 -1
- package/dist/index.esm5.js +3823 -3602
- package/dist/index.esm5.js.map +1 -1
- package/dist/index.node.cjs.js +506 -220
- package/dist/index.node.cjs.js.map +1 -1
- package/dist/index.node.mjs +506 -220
- package/dist/index.node.mjs.map +1 -1
- package/dist/index.rn.js +3623 -3379
- package/dist/index.rn.js.map +1 -1
- package/dist/internal.d.ts +178 -14
- package/dist/lite/firestore/src/api/credentials.d.ts +1 -0
- package/dist/lite/firestore/src/api/snapshot.d.ts +1 -2
- package/dist/lite/firestore/src/core/target.d.ts +8 -4
- package/dist/lite/firestore/src/lite-api/query.d.ts +2 -2
- package/dist/lite/firestore/src/local/index_manager.d.ts +52 -0
- package/dist/lite/firestore/src/local/indexeddb_index_manager.d.ts +21 -2
- package/dist/lite/firestore/src/local/indexeddb_persistence.d.ts +4 -4
- package/dist/lite/firestore/src/local/indexeddb_remote_document_cache.d.ts +2 -8
- package/dist/lite/firestore/src/local/indexeddb_schema.d.ts +149 -7
- package/dist/lite/firestore/src/local/local_documents_view.d.ts +0 -1
- package/dist/lite/firestore/src/local/local_serializer.d.ts +7 -2
- package/dist/lite/firestore/src/local/memory_index_manager.d.ts +11 -0
- package/dist/lite/firestore/src/local/memory_persistence.d.ts +3 -2
- package/dist/lite/firestore/src/local/memory_remote_document_cache.d.ts +1 -3
- package/dist/lite/firestore/src/local/persistence.d.ts +2 -2
- package/dist/lite/firestore/src/local/remote_document_cache.d.ts +7 -9
- package/dist/lite/firestore/src/local/simple_db.d.ts +1 -0
- package/dist/lite/firestore/src/model/field_index.d.ts +2 -2
- package/dist/lite/firestore/src/model/target_index_matcher.d.ts +70 -0
- package/dist/lite/firestore/test/unit/local/counting_query_engine.d.ts +3 -3
- package/dist/lite/firestore/test/unit/local/persistence_test_helpers.d.ts +1 -0
- package/dist/lite/firestore/test/unit/local/test_index_manager.d.ts +11 -0
- package/dist/lite/firestore/test/unit/local/test_remote_document_cache.d.ts +4 -2
- package/dist/lite/firestore/test/unit/local/test_remote_document_change_buffer.d.ts +1 -1
- package/dist/lite/firestore/test/unit/model/target_index_matcher.test.d.ts +17 -0
- package/dist/lite/firestore/test/util/helpers.d.ts +1 -1
- package/dist/lite/index.browser.esm2017.js +1146 -1143
- package/dist/lite/index.browser.esm2017.js.map +1 -1
- package/dist/lite/index.browser.esm5.js +332 -331
- package/dist/lite/index.browser.esm5.js.map +1 -1
- package/dist/lite/index.node.cjs.js +36 -29
- package/dist/lite/index.node.cjs.js.map +1 -1
- package/dist/lite/index.node.mjs +36 -29
- package/dist/lite/index.node.mjs.map +1 -1
- package/dist/lite/index.rn.esm2017.js +301 -298
- package/dist/lite/index.rn.esm2017.js.map +1 -1
- package/dist/lite/internal.d.ts +2 -2
- package/dist/lite/packages/firestore/dist/lite/index.browser.esm2017.d.ts +121 -121
- package/dist/lite/packages/firestore/src/api/credentials.d.ts +1 -0
- package/dist/lite/packages/firestore/src/api/snapshot.d.ts +1 -2
- package/dist/lite/packages/firestore/src/core/target.d.ts +8 -4
- package/dist/lite/packages/firestore/src/lite-api/query.d.ts +2 -2
- package/dist/lite/packages/firestore/src/local/index_manager.d.ts +52 -0
- package/dist/lite/packages/firestore/src/local/indexeddb_index_manager.d.ts +21 -2
- package/dist/lite/packages/firestore/src/local/indexeddb_persistence.d.ts +4 -4
- package/dist/lite/packages/firestore/src/local/indexeddb_remote_document_cache.d.ts +2 -8
- package/dist/lite/packages/firestore/src/local/indexeddb_schema.d.ts +149 -7
- package/dist/lite/packages/firestore/src/local/local_documents_view.d.ts +0 -1
- package/dist/lite/packages/firestore/src/local/local_serializer.d.ts +7 -2
- package/dist/lite/packages/firestore/src/local/memory_index_manager.d.ts +11 -0
- package/dist/lite/packages/firestore/src/local/memory_persistence.d.ts +3 -2
- package/dist/lite/packages/firestore/src/local/memory_remote_document_cache.d.ts +1 -3
- package/dist/lite/packages/firestore/src/local/persistence.d.ts +2 -2
- package/dist/lite/packages/firestore/src/local/remote_document_cache.d.ts +7 -9
- package/dist/lite/packages/firestore/src/local/simple_db.d.ts +1 -0
- package/dist/lite/packages/firestore/src/model/field_index.d.ts +2 -2
- package/dist/lite/packages/firestore/src/model/target_index_matcher.d.ts +70 -0
- package/dist/lite/packages/firestore/test/unit/local/counting_query_engine.d.ts +3 -3
- package/dist/lite/packages/firestore/test/unit/local/persistence_test_helpers.d.ts +1 -0
- package/dist/lite/packages/firestore/test/unit/local/test_index_manager.d.ts +11 -0
- package/dist/lite/packages/firestore/test/unit/local/test_remote_document_cache.d.ts +4 -2
- package/dist/lite/packages/firestore/test/unit/local/test_remote_document_change_buffer.d.ts +1 -1
- package/dist/lite/packages/firestore/test/unit/model/target_index_matcher.test.d.ts +17 -0
- package/dist/lite/packages/firestore/test/util/helpers.d.ts +1 -1
- package/dist/lite/private.d.ts +2 -2
- package/dist/packages/firestore/dist/index.esm2017.d.ts +170 -170
- package/dist/packages/firestore/src/api/credentials.d.ts +1 -0
- package/dist/packages/firestore/src/api/snapshot.d.ts +1 -2
- package/dist/packages/firestore/src/core/target.d.ts +8 -4
- package/dist/packages/firestore/src/lite-api/query.d.ts +2 -2
- package/dist/packages/firestore/src/local/index_manager.d.ts +52 -0
- package/dist/packages/firestore/src/local/indexeddb_index_manager.d.ts +21 -2
- package/dist/packages/firestore/src/local/indexeddb_persistence.d.ts +4 -4
- package/dist/packages/firestore/src/local/indexeddb_remote_document_cache.d.ts +2 -8
- package/dist/packages/firestore/src/local/indexeddb_schema.d.ts +149 -7
- package/dist/packages/firestore/src/local/local_documents_view.d.ts +0 -1
- package/dist/packages/firestore/src/local/local_serializer.d.ts +7 -2
- package/dist/packages/firestore/src/local/memory_index_manager.d.ts +11 -0
- package/dist/packages/firestore/src/local/memory_persistence.d.ts +3 -2
- package/dist/packages/firestore/src/local/memory_remote_document_cache.d.ts +1 -3
- package/dist/packages/firestore/src/local/persistence.d.ts +2 -2
- package/dist/packages/firestore/src/local/remote_document_cache.d.ts +7 -9
- package/dist/packages/firestore/src/local/simple_db.d.ts +1 -0
- package/dist/packages/firestore/src/model/field_index.d.ts +2 -2
- package/dist/packages/firestore/src/model/target_index_matcher.d.ts +70 -0
- package/dist/packages/firestore/test/unit/local/counting_query_engine.d.ts +3 -3
- package/dist/packages/firestore/test/unit/local/persistence_test_helpers.d.ts +1 -0
- package/dist/packages/firestore/test/unit/local/test_index_manager.d.ts +11 -0
- package/dist/packages/firestore/test/unit/local/test_remote_document_cache.d.ts +4 -2
- package/dist/packages/firestore/test/unit/local/test_remote_document_change_buffer.d.ts +1 -1
- package/dist/packages/firestore/test/unit/model/target_index_matcher.test.d.ts +17 -0
- package/dist/packages/firestore/test/util/helpers.d.ts +1 -1
- package/dist/private.d.ts +178 -14
- package/package.json +9 -9
package/dist/index.node.cjs.js
CHANGED
|
@@ -12,7 +12,7 @@ var grpcJs = require('@grpc/grpc-js');
|
|
|
12
12
|
var protoLoader = require('@grpc/proto-loader');
|
|
13
13
|
|
|
14
14
|
const name = "@firebase/firestore";
|
|
15
|
-
const version$1 = "3.4.4-canary.
|
|
15
|
+
const version$1 = "3.4.4-canary.bb8f37c3e";
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* @license
|
|
@@ -65,7 +65,7 @@ User.GOOGLE_CREDENTIALS = new User('google-credentials-uid');
|
|
|
65
65
|
User.FIRST_PARTY = new User('first-party-uid');
|
|
66
66
|
User.MOCK_USER = new User('mock-user');
|
|
67
67
|
|
|
68
|
-
const version = "9.6.
|
|
68
|
+
const version = "9.6.6-canary.bb8f37c3e";
|
|
69
69
|
|
|
70
70
|
/**
|
|
71
71
|
* @license
|
|
@@ -670,13 +670,19 @@ class FirebaseAppCheckTokenProvider {
|
|
|
670
670
|
this.appCheckProvider = appCheckProvider;
|
|
671
671
|
this.forceRefresh = false;
|
|
672
672
|
this.appCheck = null;
|
|
673
|
+
this.latestAppCheckToken = null;
|
|
673
674
|
}
|
|
674
675
|
start(asyncQueue, changeListener) {
|
|
675
676
|
const onTokenChanged = tokenResult => {
|
|
676
677
|
if (tokenResult.error != null) {
|
|
677
678
|
logDebug('FirebaseAppCheckTokenProvider', `Error getting App Check token; using placeholder token instead. Error: ${tokenResult.error.message}`);
|
|
678
679
|
}
|
|
679
|
-
|
|
680
|
+
const tokenUpdated = tokenResult.token !== this.latestAppCheckToken;
|
|
681
|
+
this.latestAppCheckToken = tokenResult.token;
|
|
682
|
+
logDebug('FirebaseAppCheckTokenProvider', `Received ${tokenUpdated ? 'new' : 'existing'} token.`);
|
|
683
|
+
return tokenUpdated
|
|
684
|
+
? changeListener(tokenResult.token)
|
|
685
|
+
: Promise.resolve();
|
|
680
686
|
};
|
|
681
687
|
this.tokenListener = (tokenResult) => {
|
|
682
688
|
asyncQueue.enqueueRetryable(() => onTokenChanged(tokenResult));
|
|
@@ -711,6 +717,7 @@ class FirebaseAppCheckTokenProvider {
|
|
|
711
717
|
return this.appCheck.getToken(forceRefresh).then(tokenResult => {
|
|
712
718
|
if (tokenResult) {
|
|
713
719
|
hardAssert(typeof tokenResult.token === 'string');
|
|
720
|
+
this.latestAppCheckToken = tokenResult.token;
|
|
714
721
|
return new AppCheckToken(tokenResult.token);
|
|
715
722
|
}
|
|
716
723
|
else {
|
|
@@ -1196,23 +1203,6 @@ function decodeResourcePath(path) {
|
|
|
1196
1203
|
}
|
|
1197
1204
|
return new ResourcePath(segments);
|
|
1198
1205
|
}
|
|
1199
|
-
|
|
1200
|
-
/**
|
|
1201
|
-
* @license
|
|
1202
|
-
* Copyright 2017 Google LLC
|
|
1203
|
-
*
|
|
1204
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
1205
|
-
* you may not use this file except in compliance with the License.
|
|
1206
|
-
* You may obtain a copy of the License at
|
|
1207
|
-
*
|
|
1208
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
1209
|
-
*
|
|
1210
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
1211
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
1212
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
1213
|
-
* See the License for the specific language governing permissions and
|
|
1214
|
-
* limitations under the License.
|
|
1215
|
-
*/
|
|
1216
1206
|
/**
|
|
1217
1207
|
* Schema Version for the Web client:
|
|
1218
1208
|
* 1. Initial version including Mutation Queue, Query Cache, and Remote
|
|
@@ -1231,6 +1221,7 @@ function decodeResourcePath(path) {
|
|
|
1231
1221
|
* an auto-incrementing ID. This is required for Index-Free queries.
|
|
1232
1222
|
* 10. Rewrite the canonical IDs to the explicit Protobuf-based format.
|
|
1233
1223
|
* 11. Add bundles and named_queries for bundle support.
|
|
1224
|
+
* 12. Add indexing support.
|
|
1234
1225
|
*/
|
|
1235
1226
|
const SCHEMA_VERSION = 11;
|
|
1236
1227
|
/**
|
|
@@ -1757,9 +1748,7 @@ class DbClientMetadata {
|
|
|
1757
1748
|
DbClientMetadata.store = 'clientMetadata';
|
|
1758
1749
|
/** Keys are automatically assigned via the clientId properties. */
|
|
1759
1750
|
DbClientMetadata.keyPath = 'clientId';
|
|
1760
|
-
/**
|
|
1761
|
-
* A object representing a bundle loaded by the SDK.
|
|
1762
|
-
*/
|
|
1751
|
+
/** An object representing a bundle loaded by the SDK. */
|
|
1763
1752
|
class DbBundle {
|
|
1764
1753
|
constructor(
|
|
1765
1754
|
/** The ID of the loaded bundle. */
|
|
@@ -1776,9 +1765,7 @@ class DbBundle {
|
|
|
1776
1765
|
/** Name of the IndexedDb object store. */
|
|
1777
1766
|
DbBundle.store = 'bundles';
|
|
1778
1767
|
DbBundle.keyPath = 'bundleId';
|
|
1779
|
-
/**
|
|
1780
|
-
* A object representing a named query loaded by the SDK via a bundle.
|
|
1781
|
-
*/
|
|
1768
|
+
/** An object representing a named query loaded by the SDK via a bundle. */
|
|
1782
1769
|
class DbNamedQuery {
|
|
1783
1770
|
constructor(
|
|
1784
1771
|
/** The name of the query. */
|
|
@@ -1795,6 +1782,116 @@ class DbNamedQuery {
|
|
|
1795
1782
|
/** Name of the IndexedDb object store. */
|
|
1796
1783
|
DbNamedQuery.store = 'namedQueries';
|
|
1797
1784
|
DbNamedQuery.keyPath = 'name';
|
|
1785
|
+
/** An object representing the global configuration for a field index. */
|
|
1786
|
+
class DbIndexConfiguration {
|
|
1787
|
+
constructor(
|
|
1788
|
+
/**
|
|
1789
|
+
* The index id for this entry. Undefined for indexes that are not yet
|
|
1790
|
+
* persisted.
|
|
1791
|
+
*/
|
|
1792
|
+
indexId,
|
|
1793
|
+
/** The collection group this index belongs to. */
|
|
1794
|
+
collectionGroup,
|
|
1795
|
+
/** The fields to index for this index. */
|
|
1796
|
+
fields) {
|
|
1797
|
+
this.indexId = indexId;
|
|
1798
|
+
this.collectionGroup = collectionGroup;
|
|
1799
|
+
this.fields = fields;
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
/** Name of the IndexedDb object store. */
|
|
1803
|
+
DbIndexConfiguration.store = 'indexConfiguration';
|
|
1804
|
+
DbIndexConfiguration.keyPath = 'indexId';
|
|
1805
|
+
/**
|
|
1806
|
+
* An index that provides access to the index configurations by collection
|
|
1807
|
+
* group.
|
|
1808
|
+
*
|
|
1809
|
+
* PORTING NOTE: iOS and Android maintain this index in-memory, but this is
|
|
1810
|
+
* not possible here as the Web client supports concurrent access to
|
|
1811
|
+
* persistence via multi-tab.
|
|
1812
|
+
*/
|
|
1813
|
+
DbIndexConfiguration.collectionGroupIndex = 'collectionGroupIndex';
|
|
1814
|
+
DbIndexConfiguration.collectionGroupIndexPath = 'collectionGroup';
|
|
1815
|
+
/**
|
|
1816
|
+
* An object describing how up-to-date the index backfill is for each user and
|
|
1817
|
+
* index.
|
|
1818
|
+
*/
|
|
1819
|
+
class DbIndexState {
|
|
1820
|
+
constructor(
|
|
1821
|
+
/** The index id for this entry. */
|
|
1822
|
+
indexId,
|
|
1823
|
+
/** The user id for this entry. */
|
|
1824
|
+
uid,
|
|
1825
|
+
/**
|
|
1826
|
+
* A number that indicates when the index was last updated (relative to
|
|
1827
|
+
* other indexes).
|
|
1828
|
+
*/
|
|
1829
|
+
sequenceNumber,
|
|
1830
|
+
/**
|
|
1831
|
+
* The latest read time that has been indexed by Firestore for this field
|
|
1832
|
+
* index. Set to `{seconds: 0, nanos: 0}` if no documents have been indexed.
|
|
1833
|
+
*/
|
|
1834
|
+
readTime,
|
|
1835
|
+
/**
|
|
1836
|
+
* The last document that has been indexed for this field index. Empty if
|
|
1837
|
+
* no documents have been indexed.
|
|
1838
|
+
*/
|
|
1839
|
+
documentKey,
|
|
1840
|
+
/**
|
|
1841
|
+
* The largest mutation batch id that has been processed for this index. -1
|
|
1842
|
+
* if no mutations have been indexed.
|
|
1843
|
+
*/
|
|
1844
|
+
largestBatchId) {
|
|
1845
|
+
this.indexId = indexId;
|
|
1846
|
+
this.uid = uid;
|
|
1847
|
+
this.sequenceNumber = sequenceNumber;
|
|
1848
|
+
this.readTime = readTime;
|
|
1849
|
+
this.documentKey = documentKey;
|
|
1850
|
+
this.largestBatchId = largestBatchId;
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
/** Name of the IndexedDb object store. */
|
|
1854
|
+
DbIndexState.store = 'indexState';
|
|
1855
|
+
DbIndexState.keyPath = ['indexId', 'uid'];
|
|
1856
|
+
/**
|
|
1857
|
+
* An index that provides access to documents in a collection sorted by last
|
|
1858
|
+
* update time. Used by the backfiller.
|
|
1859
|
+
*
|
|
1860
|
+
* PORTING NOTE: iOS and Android maintain this index in-memory, but this is
|
|
1861
|
+
* not possible here as the Web client supports concurrent access to
|
|
1862
|
+
* persistence via multi-tab.
|
|
1863
|
+
*/
|
|
1864
|
+
DbIndexState.sequenceNumberIndex = 'sequenceNumberIndex';
|
|
1865
|
+
DbIndexState.sequenceNumberIndexPath = ['uid', 'sequenceNumber'];
|
|
1866
|
+
/** An object that stores the encoded entries for all documents and fields. */
|
|
1867
|
+
class DbIndexEntry {
|
|
1868
|
+
constructor(
|
|
1869
|
+
/** The index id for this entry. */
|
|
1870
|
+
indexId,
|
|
1871
|
+
/** The user id for this entry. */
|
|
1872
|
+
uid,
|
|
1873
|
+
/** The encoded array index value for this entry. */
|
|
1874
|
+
arrayValue,
|
|
1875
|
+
/** The encoded directional value for equality and inequality filters. */
|
|
1876
|
+
directionalValue,
|
|
1877
|
+
/** The document key this entry points to. */
|
|
1878
|
+
documentKey) {
|
|
1879
|
+
this.indexId = indexId;
|
|
1880
|
+
this.uid = uid;
|
|
1881
|
+
this.arrayValue = arrayValue;
|
|
1882
|
+
this.directionalValue = directionalValue;
|
|
1883
|
+
this.documentKey = documentKey;
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
/** Name of the IndexedDb object store. */
|
|
1887
|
+
DbIndexEntry.store = 'indexEntries';
|
|
1888
|
+
DbIndexEntry.keyPath = [
|
|
1889
|
+
'indexId',
|
|
1890
|
+
'uid',
|
|
1891
|
+
'arrayValue',
|
|
1892
|
+
'directionalValue',
|
|
1893
|
+
'documentKey'
|
|
1894
|
+
];
|
|
1798
1895
|
// Visible for testing
|
|
1799
1896
|
const V1_STORES = [
|
|
1800
1897
|
DbMutationQueue.store,
|
|
@@ -1809,7 +1906,6 @@ const V1_STORES = [
|
|
|
1809
1906
|
// V2 is no longer usable (see comment at top of file)
|
|
1810
1907
|
// Visible for testing
|
|
1811
1908
|
const V3_STORES = V1_STORES;
|
|
1812
|
-
// Visible for testing
|
|
1813
1909
|
// Note: DbRemoteDocumentChanges is no longer used and dropped with v9.
|
|
1814
1910
|
const V4_STORES = [...V3_STORES, DbClientMetadata.store];
|
|
1815
1911
|
// V5 does not change the set of stores.
|
|
@@ -1819,12 +1915,24 @@ const V8_STORES = [...V6_STORES, DbCollectionParent.store];
|
|
|
1819
1915
|
// V9 does not change the set of stores.
|
|
1820
1916
|
// V10 does not change the set of stores.
|
|
1821
1917
|
const V11_STORES = [...V8_STORES, DbBundle.store, DbNamedQuery.store];
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1918
|
+
const V12_STORES = [
|
|
1919
|
+
...V11_STORES,
|
|
1920
|
+
DbIndexConfiguration.store,
|
|
1921
|
+
DbIndexState.store,
|
|
1922
|
+
DbIndexEntry.store
|
|
1923
|
+
];
|
|
1924
|
+
/** Returns the object stores for the provided schema. */
|
|
1925
|
+
function getObjectStores(schemaVersion) {
|
|
1926
|
+
if (schemaVersion === 12) {
|
|
1927
|
+
return V12_STORES;
|
|
1928
|
+
}
|
|
1929
|
+
else if (schemaVersion === 11) {
|
|
1930
|
+
return V11_STORES;
|
|
1931
|
+
}
|
|
1932
|
+
else {
|
|
1933
|
+
fail();
|
|
1934
|
+
}
|
|
1935
|
+
}
|
|
1828
1936
|
|
|
1829
1937
|
/**
|
|
1830
1938
|
* @license
|
|
@@ -2121,6 +2229,15 @@ class SimpleDbTransaction {
|
|
|
2121
2229
|
this.transaction.abort();
|
|
2122
2230
|
}
|
|
2123
2231
|
}
|
|
2232
|
+
maybeCommit() {
|
|
2233
|
+
// If the browser supports V3 IndexedDB, we invoke commit() explicitly to
|
|
2234
|
+
// speed up index DB processing if the event loop remains blocks.
|
|
2235
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2236
|
+
const maybeV3IndexedDb = this.transaction;
|
|
2237
|
+
if (!this.aborted && typeof maybeV3IndexedDb.commit === 'function') {
|
|
2238
|
+
maybeV3IndexedDb.commit();
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2124
2241
|
/**
|
|
2125
2242
|
* Returns a SimpleDbStore<KeyType, ValueType> for the specified store. All
|
|
2126
2243
|
* operations performed on the SimpleDbStore happen within the context of this
|
|
@@ -2317,6 +2434,10 @@ class SimpleDb {
|
|
|
2317
2434
|
this.db = await this.ensureDb(action);
|
|
2318
2435
|
const transaction = SimpleDbTransaction.open(this.db, action, readonly ? 'readonly' : 'readwrite', objectStores);
|
|
2319
2436
|
const transactionFnResult = transactionFn(transaction)
|
|
2437
|
+
.next(result => {
|
|
2438
|
+
transaction.maybeCommit();
|
|
2439
|
+
return result;
|
|
2440
|
+
})
|
|
2320
2441
|
.catch(error => {
|
|
2321
2442
|
// Abort the transaction if there was an error.
|
|
2322
2443
|
transaction.abort(error);
|
|
@@ -2489,13 +2610,29 @@ class SimpleDbStore {
|
|
|
2489
2610
|
return wrapRequest(request);
|
|
2490
2611
|
}
|
|
2491
2612
|
loadAll(indexOrRange, range) {
|
|
2492
|
-
const
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
return
|
|
2498
|
-
|
|
2613
|
+
const iterateOptions = this.options(indexOrRange, range);
|
|
2614
|
+
// Use `getAll()` if the browser supports IndexedDB v3, as it is roughly
|
|
2615
|
+
// 20% faster. Unfortunately, getAll() does not support custom indices.
|
|
2616
|
+
if (!iterateOptions.index && typeof this.store.getAll === 'function') {
|
|
2617
|
+
const request = this.store.getAll(iterateOptions.range);
|
|
2618
|
+
return new PersistencePromise((resolve, reject) => {
|
|
2619
|
+
request.onerror = (event) => {
|
|
2620
|
+
reject(event.target.error);
|
|
2621
|
+
};
|
|
2622
|
+
request.onsuccess = (event) => {
|
|
2623
|
+
resolve(event.target.result);
|
|
2624
|
+
};
|
|
2625
|
+
});
|
|
2626
|
+
}
|
|
2627
|
+
else {
|
|
2628
|
+
const cursor = this.cursor(iterateOptions);
|
|
2629
|
+
const results = [];
|
|
2630
|
+
return this.iterateCursor(cursor, (key, value) => {
|
|
2631
|
+
results.push(value);
|
|
2632
|
+
}).next(() => {
|
|
2633
|
+
return results;
|
|
2634
|
+
});
|
|
2635
|
+
}
|
|
2499
2636
|
}
|
|
2500
2637
|
deleteAll(indexOrRange, range) {
|
|
2501
2638
|
logDebug(LOG_TAG$g, 'DELETE ALL', this.store.name);
|
|
@@ -4349,12 +4486,12 @@ class FieldIndex {
|
|
|
4349
4486
|
/** The collection ID this index applies to. */
|
|
4350
4487
|
collectionGroup,
|
|
4351
4488
|
/** The field segments for this index. */
|
|
4352
|
-
|
|
4489
|
+
fields,
|
|
4353
4490
|
/** Shows how up-to-date the index is for the current user. */
|
|
4354
4491
|
indexState) {
|
|
4355
4492
|
this.indexId = indexId;
|
|
4356
4493
|
this.collectionGroup = collectionGroup;
|
|
4357
|
-
this.
|
|
4494
|
+
this.fields = fields;
|
|
4358
4495
|
this.indexState = indexState;
|
|
4359
4496
|
}
|
|
4360
4497
|
}
|
|
@@ -4464,27 +4601,29 @@ function newTarget(path, collectionGroup = null, orderBy = [], filters = [], lim
|
|
|
4464
4601
|
function canonifyTarget(target) {
|
|
4465
4602
|
const targetImpl = debugCast(target);
|
|
4466
4603
|
if (targetImpl.memoizedCanonicalId === null) {
|
|
4467
|
-
let
|
|
4604
|
+
let str = targetImpl.path.canonicalString();
|
|
4468
4605
|
if (targetImpl.collectionGroup !== null) {
|
|
4469
|
-
|
|
4606
|
+
str += '|cg:' + targetImpl.collectionGroup;
|
|
4470
4607
|
}
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4608
|
+
str += '|f:';
|
|
4609
|
+
str += targetImpl.filters.map(f => canonifyFilter(f)).join(',');
|
|
4610
|
+
str += '|ob:';
|
|
4611
|
+
str += targetImpl.orderBy.map(o => canonifyOrderBy(o)).join(',');
|
|
4475
4612
|
if (!isNullOrUndefined(targetImpl.limit)) {
|
|
4476
|
-
|
|
4477
|
-
|
|
4613
|
+
str += '|l:';
|
|
4614
|
+
str += targetImpl.limit;
|
|
4478
4615
|
}
|
|
4479
4616
|
if (targetImpl.startAt) {
|
|
4480
|
-
|
|
4481
|
-
|
|
4617
|
+
str += '|lb:';
|
|
4618
|
+
str += targetImpl.startAt.inclusive ? 'b:' : 'a:';
|
|
4619
|
+
str += targetImpl.startAt.position.map(p => canonicalId(p)).join(',');
|
|
4482
4620
|
}
|
|
4483
4621
|
if (targetImpl.endAt) {
|
|
4484
|
-
|
|
4485
|
-
|
|
4622
|
+
str += '|ub:';
|
|
4623
|
+
str += targetImpl.endAt.inclusive ? 'a:' : 'b:';
|
|
4624
|
+
str += targetImpl.endAt.position.map(p => canonicalId(p)).join(',');
|
|
4486
4625
|
}
|
|
4487
|
-
targetImpl.memoizedCanonicalId =
|
|
4626
|
+
targetImpl.memoizedCanonicalId = str;
|
|
4488
4627
|
}
|
|
4489
4628
|
return targetImpl.memoizedCanonicalId;
|
|
4490
4629
|
}
|
|
@@ -4507,10 +4646,14 @@ function stringifyTarget(target) {
|
|
|
4507
4646
|
.join(', ')}]`;
|
|
4508
4647
|
}
|
|
4509
4648
|
if (target.startAt) {
|
|
4510
|
-
str += ', startAt: '
|
|
4649
|
+
str += ', startAt: ';
|
|
4650
|
+
str += target.startAt.inclusive ? 'b:' : 'a:';
|
|
4651
|
+
str += target.startAt.position.map(p => canonicalId(p)).join(',');
|
|
4511
4652
|
}
|
|
4512
4653
|
if (target.endAt) {
|
|
4513
|
-
str += ', endAt: '
|
|
4654
|
+
str += ', endAt: ';
|
|
4655
|
+
str += target.endAt.inclusive ? 'a:' : 'b:';
|
|
4656
|
+
str += target.endAt.position.map(p => canonicalId(p)).join(',');
|
|
4514
4657
|
}
|
|
4515
4658
|
return `Target(${str})`;
|
|
4516
4659
|
}
|
|
@@ -4733,7 +4876,6 @@ class ArrayContainsAnyFilter extends FieldFilter {
|
|
|
4733
4876
|
return other.arrayValue.values.some(val => arrayValueContains(this.value.arrayValue, val));
|
|
4734
4877
|
}
|
|
4735
4878
|
}
|
|
4736
|
-
// TODO(indexing): Change Bound.before to "inclusive"
|
|
4737
4879
|
/**
|
|
4738
4880
|
* Represents a bound of a query.
|
|
4739
4881
|
*
|
|
@@ -4749,17 +4891,11 @@ class ArrayContainsAnyFilter extends FieldFilter {
|
|
|
4749
4891
|
* just after the provided values.
|
|
4750
4892
|
*/
|
|
4751
4893
|
class Bound {
|
|
4752
|
-
constructor(position,
|
|
4894
|
+
constructor(position, inclusive) {
|
|
4753
4895
|
this.position = position;
|
|
4754
|
-
this.
|
|
4896
|
+
this.inclusive = inclusive;
|
|
4755
4897
|
}
|
|
4756
4898
|
}
|
|
4757
|
-
function canonifyBound(bound) {
|
|
4758
|
-
// TODO(b/29183165): Make this collision robust.
|
|
4759
|
-
return `${bound.before ? 'b' : 'a'}:${bound.position
|
|
4760
|
-
.map(p => canonicalId(p))
|
|
4761
|
-
.join(',')}`;
|
|
4762
|
-
}
|
|
4763
4899
|
/**
|
|
4764
4900
|
* An ordering on a field, in some Direction. Direction defaults to ASCENDING.
|
|
4765
4901
|
*/
|
|
@@ -4779,11 +4915,7 @@ function stringifyOrderBy(orderBy) {
|
|
|
4779
4915
|
function orderByEquals(left, right) {
|
|
4780
4916
|
return left.dir === right.dir && left.field.isEqual(right.field);
|
|
4781
4917
|
}
|
|
4782
|
-
|
|
4783
|
-
* Returns true if a document sorts before a bound using the provided sort
|
|
4784
|
-
* order.
|
|
4785
|
-
*/
|
|
4786
|
-
function sortsBeforeDocument(bound, orderBy, doc) {
|
|
4918
|
+
function boundCompareToDocument(bound, orderBy, doc) {
|
|
4787
4919
|
let comparison = 0;
|
|
4788
4920
|
for (let i = 0; i < bound.position.length; i++) {
|
|
4789
4921
|
const orderByComponent = orderBy[i];
|
|
@@ -4802,7 +4934,23 @@ function sortsBeforeDocument(bound, orderBy, doc) {
|
|
|
4802
4934
|
break;
|
|
4803
4935
|
}
|
|
4804
4936
|
}
|
|
4805
|
-
return
|
|
4937
|
+
return comparison;
|
|
4938
|
+
}
|
|
4939
|
+
/**
|
|
4940
|
+
* Returns true if a document sorts after a bound using the provided sort
|
|
4941
|
+
* order.
|
|
4942
|
+
*/
|
|
4943
|
+
function boundSortsAfterDocument(bound, orderBy, doc) {
|
|
4944
|
+
const comparison = boundCompareToDocument(bound, orderBy, doc);
|
|
4945
|
+
return bound.inclusive ? comparison >= 0 : comparison > 0;
|
|
4946
|
+
}
|
|
4947
|
+
/**
|
|
4948
|
+
* Returns true if a document sorts before a bound using the provided sort
|
|
4949
|
+
* order.
|
|
4950
|
+
*/
|
|
4951
|
+
function boundSortsBeforeDocument(bound, orderBy, doc) {
|
|
4952
|
+
const comparison = boundCompareToDocument(bound, orderBy, doc);
|
|
4953
|
+
return bound.inclusive ? comparison <= 0 : comparison < 0;
|
|
4806
4954
|
}
|
|
4807
4955
|
function boundEquals(left, right) {
|
|
4808
4956
|
if (left === null) {
|
|
@@ -4811,7 +4959,7 @@ function boundEquals(left, right) {
|
|
|
4811
4959
|
else if (right === null) {
|
|
4812
4960
|
return false;
|
|
4813
4961
|
}
|
|
4814
|
-
if (left.
|
|
4962
|
+
if (left.inclusive !== right.inclusive ||
|
|
4815
4963
|
left.position.length !== right.position.length) {
|
|
4816
4964
|
return false;
|
|
4817
4965
|
}
|
|
@@ -5015,10 +5163,10 @@ function queryToTarget(query) {
|
|
|
5015
5163
|
}
|
|
5016
5164
|
// We need to swap the cursors to match the now-flipped query ordering.
|
|
5017
5165
|
const startAt = queryImpl.endAt
|
|
5018
|
-
? new Bound(queryImpl.endAt.position, !queryImpl.endAt.
|
|
5166
|
+
? new Bound(queryImpl.endAt.position, !queryImpl.endAt.inclusive)
|
|
5019
5167
|
: null;
|
|
5020
5168
|
const endAt = queryImpl.startAt
|
|
5021
|
-
? new Bound(queryImpl.startAt.position, !queryImpl.startAt.
|
|
5169
|
+
? new Bound(queryImpl.startAt.position, !queryImpl.startAt.inclusive)
|
|
5022
5170
|
: null;
|
|
5023
5171
|
// Now return as a LimitType.First query.
|
|
5024
5172
|
queryImpl.memoizedTarget = newTarget(queryImpl.path, queryImpl.collectionGroup, orderBys, queryImpl.filters, queryImpl.limit, startAt, endAt);
|
|
@@ -5106,11 +5254,11 @@ function queryMatchesFilters(query, doc) {
|
|
|
5106
5254
|
/** Makes sure a document is within the bounds, if provided. */
|
|
5107
5255
|
function queryMatchesBounds(query, doc) {
|
|
5108
5256
|
if (query.startAt &&
|
|
5109
|
-
!
|
|
5257
|
+
!boundSortsBeforeDocument(query.startAt, queryOrderBy(query), doc)) {
|
|
5110
5258
|
return false;
|
|
5111
5259
|
}
|
|
5112
5260
|
if (query.endAt &&
|
|
5113
|
-
|
|
5261
|
+
!boundSortsAfterDocument(query.endAt, queryOrderBy(query), doc)) {
|
|
5114
5262
|
return false;
|
|
5115
5263
|
}
|
|
5116
5264
|
return true;
|
|
@@ -7989,10 +8137,10 @@ function toQueryTarget(serializer, target) {
|
|
|
7989
8137
|
result.structuredQuery.limit = limit;
|
|
7990
8138
|
}
|
|
7991
8139
|
if (target.startAt) {
|
|
7992
|
-
result.structuredQuery.startAt =
|
|
8140
|
+
result.structuredQuery.startAt = toStartAtCursor(target.startAt);
|
|
7993
8141
|
}
|
|
7994
8142
|
if (target.endAt) {
|
|
7995
|
-
result.structuredQuery.endAt =
|
|
8143
|
+
result.structuredQuery.endAt = toEndAtCursor(target.endAt);
|
|
7996
8144
|
}
|
|
7997
8145
|
return result;
|
|
7998
8146
|
}
|
|
@@ -8025,11 +8173,11 @@ function convertQueryTargetToQuery(target) {
|
|
|
8025
8173
|
}
|
|
8026
8174
|
let startAt = null;
|
|
8027
8175
|
if (query.startAt) {
|
|
8028
|
-
startAt =
|
|
8176
|
+
startAt = fromStartAtCursor(query.startAt);
|
|
8029
8177
|
}
|
|
8030
8178
|
let endAt = null;
|
|
8031
8179
|
if (query.endAt) {
|
|
8032
|
-
endAt =
|
|
8180
|
+
endAt = fromEndAtCursor(query.endAt);
|
|
8033
8181
|
}
|
|
8034
8182
|
return newQuery(path, collectionGroup, orderBy, filterBy, limit, "F" /* First */, startAt, endAt);
|
|
8035
8183
|
}
|
|
@@ -8120,16 +8268,27 @@ function toOrder(orderBys) {
|
|
|
8120
8268
|
function fromOrder(orderBys) {
|
|
8121
8269
|
return orderBys.map(order => fromPropertyOrder(order));
|
|
8122
8270
|
}
|
|
8123
|
-
function
|
|
8271
|
+
function toStartAtCursor(cursor) {
|
|
8124
8272
|
return {
|
|
8125
|
-
before: cursor.
|
|
8273
|
+
before: cursor.inclusive,
|
|
8126
8274
|
values: cursor.position
|
|
8127
8275
|
};
|
|
8128
8276
|
}
|
|
8129
|
-
function
|
|
8130
|
-
|
|
8277
|
+
function toEndAtCursor(cursor) {
|
|
8278
|
+
return {
|
|
8279
|
+
before: !cursor.inclusive,
|
|
8280
|
+
values: cursor.position
|
|
8281
|
+
};
|
|
8282
|
+
}
|
|
8283
|
+
function fromStartAtCursor(cursor) {
|
|
8284
|
+
const inclusive = !!cursor.before;
|
|
8285
|
+
const position = cursor.values || [];
|
|
8286
|
+
return new Bound(position, inclusive);
|
|
8287
|
+
}
|
|
8288
|
+
function fromEndAtCursor(cursor) {
|
|
8289
|
+
const inclusive = !cursor.before;
|
|
8131
8290
|
const position = cursor.values || [];
|
|
8132
|
-
return new Bound(position,
|
|
8291
|
+
return new Bound(position, inclusive);
|
|
8133
8292
|
}
|
|
8134
8293
|
// visible for testing
|
|
8135
8294
|
function toDirection(dir) {
|
|
@@ -8593,6 +8752,19 @@ function fromBundleMetadata(metadata) {
|
|
|
8593
8752
|
version: metadata.version,
|
|
8594
8753
|
createTime: fromVersion(metadata.createTime)
|
|
8595
8754
|
};
|
|
8755
|
+
}
|
|
8756
|
+
function toDbIndexConfiguration(index) {
|
|
8757
|
+
return new DbIndexConfiguration(index.indexId, index.collectionGroup, index.fields.map(s => [s.fieldPath.canonicalString(), s.kind]));
|
|
8758
|
+
}
|
|
8759
|
+
function fromDbIndexConfiguration(index, state) {
|
|
8760
|
+
const decodedState = state
|
|
8761
|
+
? new IndexState(state.sequenceNumber, new IndexOffset(fromDbTimestamp(state.readTime), new DocumentKey(decodeResourcePath(state.documentKey)), state.largestBatchId))
|
|
8762
|
+
: IndexState.empty();
|
|
8763
|
+
const decodedSegments = index.fields.map(([fieldPath, kind]) => new IndexSegment(FieldPath$1.fromServerFormat(fieldPath), kind));
|
|
8764
|
+
return new FieldIndex(index.indexId, index.collectionGroup, decodedSegments, decodedState);
|
|
8765
|
+
}
|
|
8766
|
+
function toDbIndexState(indexId, user, sequenceNumber, offset) {
|
|
8767
|
+
return new DbIndexState(indexId, user.uid || '', sequenceNumber, toDbTimestamp(offset.readTime), encodeResourcePath(offset.documentKey.path), offset.largestBatchId);
|
|
8596
8768
|
}
|
|
8597
8769
|
|
|
8598
8770
|
/**
|
|
@@ -8682,6 +8854,38 @@ class MemoryIndexManager {
|
|
|
8682
8854
|
getCollectionParents(transaction, collectionId) {
|
|
8683
8855
|
return PersistencePromise.resolve(this.collectionParentIndex.getEntries(collectionId));
|
|
8684
8856
|
}
|
|
8857
|
+
addFieldIndex(transaction, index) {
|
|
8858
|
+
// Field indices are not supported with memory persistence.
|
|
8859
|
+
return PersistencePromise.resolve();
|
|
8860
|
+
}
|
|
8861
|
+
deleteFieldIndex(transaction, index) {
|
|
8862
|
+
// Field indices are not supported with memory persistence.
|
|
8863
|
+
return PersistencePromise.resolve();
|
|
8864
|
+
}
|
|
8865
|
+
getDocumentsMatchingTarget(transaction, fieldIndex, target) {
|
|
8866
|
+
// Field indices are not supported with memory persistence.
|
|
8867
|
+
return PersistencePromise.resolve(documentKeySet());
|
|
8868
|
+
}
|
|
8869
|
+
getFieldIndex(transaction, target) {
|
|
8870
|
+
// Field indices are not supported with memory persistence.
|
|
8871
|
+
return PersistencePromise.resolve(null);
|
|
8872
|
+
}
|
|
8873
|
+
getFieldIndexes(transaction, collectionGroup) {
|
|
8874
|
+
// Field indices are not supported with memory persistence.
|
|
8875
|
+
return PersistencePromise.resolve([]);
|
|
8876
|
+
}
|
|
8877
|
+
getNextCollectionGroupToUpdate(transaction) {
|
|
8878
|
+
// Field indices are not supported with memory persistence.
|
|
8879
|
+
return PersistencePromise.resolve(null);
|
|
8880
|
+
}
|
|
8881
|
+
updateCollectionGroup(transaction, collectionGroup, offset) {
|
|
8882
|
+
// Field indices are not supported with memory persistence.
|
|
8883
|
+
return PersistencePromise.resolve();
|
|
8884
|
+
}
|
|
8885
|
+
updateIndexEntries(transaction, documents) {
|
|
8886
|
+
// Field indices are not supported with memory persistence.
|
|
8887
|
+
return PersistencePromise.resolve();
|
|
8888
|
+
}
|
|
8685
8889
|
}
|
|
8686
8890
|
/**
|
|
8687
8891
|
* Internal implementation of the collection-parent index exposed by MemoryIndexManager.
|
|
@@ -8733,17 +8937,22 @@ class MemoryCollectionParentIndex {
|
|
|
8733
8937
|
*/
|
|
8734
8938
|
/**
|
|
8735
8939
|
* A persisted implementation of IndexManager.
|
|
8940
|
+
*
|
|
8941
|
+
* PORTING NOTE: Unlike iOS and Android, the Web SDK does not memoize index
|
|
8942
|
+
* data as it supports multi-tab access.
|
|
8736
8943
|
*/
|
|
8737
8944
|
class IndexedDbIndexManager {
|
|
8738
|
-
constructor() {
|
|
8945
|
+
constructor(user) {
|
|
8946
|
+
this.user = user;
|
|
8739
8947
|
/**
|
|
8740
8948
|
* An in-memory copy of the index entries we've already written since the SDK
|
|
8741
8949
|
* launched. Used to avoid re-writing the same entry repeatedly.
|
|
8742
8950
|
*
|
|
8743
|
-
* This is *NOT* a complete cache of what's in persistence and so can never be
|
|
8744
|
-
* satisfy reads.
|
|
8951
|
+
* This is *NOT* a complete cache of what's in persistence and so can never be
|
|
8952
|
+
* used to satisfy reads.
|
|
8745
8953
|
*/
|
|
8746
8954
|
this.collectionParentsCache = new MemoryCollectionParentIndex();
|
|
8955
|
+
this.uid = user.uid || '';
|
|
8747
8956
|
}
|
|
8748
8957
|
/**
|
|
8749
8958
|
* Adds a new entry to the collection parent index.
|
|
@@ -8790,6 +8999,85 @@ class IndexedDbIndexManager {
|
|
|
8790
8999
|
return parentPaths;
|
|
8791
9000
|
});
|
|
8792
9001
|
}
|
|
9002
|
+
addFieldIndex(transaction, index) {
|
|
9003
|
+
// TODO(indexing): Verify that the auto-incrementing index ID works in
|
|
9004
|
+
// Safari & Firefox.
|
|
9005
|
+
const indexes = indexConfigurationStore(transaction);
|
|
9006
|
+
const dbIndex = toDbIndexConfiguration(index);
|
|
9007
|
+
delete dbIndex.indexId; // `indexId` is auto-populated by IndexedDb
|
|
9008
|
+
return indexes.add(dbIndex).next();
|
|
9009
|
+
}
|
|
9010
|
+
deleteFieldIndex(transaction, index) {
|
|
9011
|
+
const indexes = indexConfigurationStore(transaction);
|
|
9012
|
+
const states = indexStateStore(transaction);
|
|
9013
|
+
const entries = indexEntriesStore(transaction);
|
|
9014
|
+
return indexes
|
|
9015
|
+
.delete(index.indexId)
|
|
9016
|
+
.next(() => states.delete(IDBKeyRange.bound([index.indexId], [index.indexId + 1],
|
|
9017
|
+
/*lowerOpen=*/ false,
|
|
9018
|
+
/*upperOpen=*/ true)))
|
|
9019
|
+
.next(() => entries.delete(IDBKeyRange.bound([index.indexId], [index.indexId + 1],
|
|
9020
|
+
/*lowerOpen=*/ false,
|
|
9021
|
+
/*upperOpen=*/ true)));
|
|
9022
|
+
}
|
|
9023
|
+
getDocumentsMatchingTarget(transaction, fieldIndex, target) {
|
|
9024
|
+
// TODO(indexing): Implement
|
|
9025
|
+
return PersistencePromise.resolve(documentKeySet());
|
|
9026
|
+
}
|
|
9027
|
+
getFieldIndex(transaction, target) {
|
|
9028
|
+
// TODO(indexing): Implement
|
|
9029
|
+
return PersistencePromise.resolve(null);
|
|
9030
|
+
}
|
|
9031
|
+
getFieldIndexes(transaction, collectionGroup) {
|
|
9032
|
+
const indexes = indexConfigurationStore(transaction);
|
|
9033
|
+
const states = indexStateStore(transaction);
|
|
9034
|
+
return (collectionGroup
|
|
9035
|
+
? indexes.loadAll(DbIndexConfiguration.collectionGroupIndex, IDBKeyRange.bound(collectionGroup, collectionGroup))
|
|
9036
|
+
: indexes.loadAll()).next(indexConfigs => {
|
|
9037
|
+
const result = [];
|
|
9038
|
+
return PersistencePromise.forEach(indexConfigs, (indexConfig) => {
|
|
9039
|
+
return states
|
|
9040
|
+
.get([indexConfig.indexId, this.uid])
|
|
9041
|
+
.next(indexState => {
|
|
9042
|
+
result.push(fromDbIndexConfiguration(indexConfig, indexState));
|
|
9043
|
+
});
|
|
9044
|
+
}).next(() => result);
|
|
9045
|
+
});
|
|
9046
|
+
}
|
|
9047
|
+
getNextCollectionGroupToUpdate(transaction) {
|
|
9048
|
+
return this.getFieldIndexes(transaction).next(indexes => {
|
|
9049
|
+
if (indexes.length === 0) {
|
|
9050
|
+
return null;
|
|
9051
|
+
}
|
|
9052
|
+
indexes.sort((l, r) => l.indexState.sequenceNumber - r.indexState.sequenceNumber);
|
|
9053
|
+
return indexes[0].collectionGroup;
|
|
9054
|
+
});
|
|
9055
|
+
}
|
|
9056
|
+
updateCollectionGroup(transaction, collectionGroup, offset) {
|
|
9057
|
+
const indexes = indexConfigurationStore(transaction);
|
|
9058
|
+
const states = indexStateStore(transaction);
|
|
9059
|
+
return this.getNextSequenceNumber(transaction).next(nextSequenceNumber => indexes
|
|
9060
|
+
.loadAll(DbIndexConfiguration.collectionGroupIndex, IDBKeyRange.bound(collectionGroup, collectionGroup))
|
|
9061
|
+
.next(configs => PersistencePromise.forEach(configs, (config) => states.put(toDbIndexState(config.indexId, this.user, nextSequenceNumber, offset)))));
|
|
9062
|
+
}
|
|
9063
|
+
updateIndexEntries(transaction, documents) {
|
|
9064
|
+
// TODO(indexing): Implement
|
|
9065
|
+
return PersistencePromise.resolve();
|
|
9066
|
+
}
|
|
9067
|
+
getNextSequenceNumber(transaction) {
|
|
9068
|
+
let nextSequenceNumber = 1;
|
|
9069
|
+
const states = indexStateStore(transaction);
|
|
9070
|
+
return states
|
|
9071
|
+
.iterate({
|
|
9072
|
+
index: DbIndexState.sequenceNumberIndex,
|
|
9073
|
+
reverse: true,
|
|
9074
|
+
range: IDBKeyRange.upperBound([this.uid, Number.MAX_SAFE_INTEGER])
|
|
9075
|
+
}, (_, state, controller) => {
|
|
9076
|
+
controller.done();
|
|
9077
|
+
nextSequenceNumber = state.sequenceNumber + 1;
|
|
9078
|
+
})
|
|
9079
|
+
.next(() => nextSequenceNumber);
|
|
9080
|
+
}
|
|
8793
9081
|
}
|
|
8794
9082
|
/**
|
|
8795
9083
|
* Helper to get a typed SimpleDbStore for the collectionParents
|
|
@@ -8797,6 +9085,24 @@ class IndexedDbIndexManager {
|
|
|
8797
9085
|
*/
|
|
8798
9086
|
function collectionParentsStore(txn) {
|
|
8799
9087
|
return getStore(txn, DbCollectionParent.store);
|
|
9088
|
+
}
|
|
9089
|
+
/**
|
|
9090
|
+
* Helper to get a typed SimpleDbStore for the index entry object store.
|
|
9091
|
+
*/
|
|
9092
|
+
function indexEntriesStore(txn) {
|
|
9093
|
+
return getStore(txn, DbIndexEntry.store);
|
|
9094
|
+
}
|
|
9095
|
+
/**
|
|
9096
|
+
* Helper to get a typed SimpleDbStore for the index configuration object store.
|
|
9097
|
+
*/
|
|
9098
|
+
function indexConfigurationStore(txn) {
|
|
9099
|
+
return getStore(txn, DbIndexConfiguration.store);
|
|
9100
|
+
}
|
|
9101
|
+
/**
|
|
9102
|
+
* Helper to get a typed SimpleDbStore for the index state object store.
|
|
9103
|
+
*/
|
|
9104
|
+
function indexStateStore(txn) {
|
|
9105
|
+
return getStore(txn, DbIndexState.store);
|
|
8800
9106
|
}
|
|
8801
9107
|
|
|
8802
9108
|
/**
|
|
@@ -10266,12 +10572,10 @@ class RemoteDocumentChangeBuffer {
|
|
|
10266
10572
|
* `newIndexedDbRemoteDocumentCache()`.
|
|
10267
10573
|
*/
|
|
10268
10574
|
class IndexedDbRemoteDocumentCacheImpl {
|
|
10269
|
-
|
|
10270
|
-
* @param serializer - The document serializer.
|
|
10271
|
-
* @param indexManager - The query indexes that need to be maintained.
|
|
10272
|
-
*/
|
|
10273
|
-
constructor(serializer, indexManager) {
|
|
10575
|
+
constructor(serializer) {
|
|
10274
10576
|
this.serializer = serializer;
|
|
10577
|
+
}
|
|
10578
|
+
setIndexManager(indexManager) {
|
|
10275
10579
|
this.indexManager = indexManager;
|
|
10276
10580
|
}
|
|
10277
10581
|
/**
|
|
@@ -10393,21 +10697,21 @@ class IndexedDbRemoteDocumentCacheImpl {
|
|
|
10393
10697
|
}
|
|
10394
10698
|
});
|
|
10395
10699
|
}
|
|
10396
|
-
|
|
10700
|
+
getAll(transaction, collection, sinceReadTime) {
|
|
10397
10701
|
let results = mutableDocumentMap();
|
|
10398
|
-
const immediateChildrenPathLength =
|
|
10702
|
+
const immediateChildrenPathLength = collection.length + 1;
|
|
10399
10703
|
const iterationOptions = {};
|
|
10400
10704
|
if (sinceReadTime.isEqual(SnapshotVersion.min())) {
|
|
10401
10705
|
// Documents are ordered by key, so we can use a prefix scan to narrow
|
|
10402
10706
|
// down the documents we need to match the query against.
|
|
10403
|
-
const startKey =
|
|
10707
|
+
const startKey = collection.toArray();
|
|
10404
10708
|
iterationOptions.range = IDBKeyRange.lowerBound(startKey);
|
|
10405
10709
|
}
|
|
10406
10710
|
else {
|
|
10407
10711
|
// Execute an index-free query and filter by read time. This is safe
|
|
10408
10712
|
// since all document changes to queries that have a
|
|
10409
10713
|
// lastLimboFreeSnapshotVersion (`sinceReadTime`) have a read time set.
|
|
10410
|
-
const collectionKey =
|
|
10714
|
+
const collectionKey = collection.toArray();
|
|
10411
10715
|
const readTimeKey = toDbTimestampKey(sinceReadTime);
|
|
10412
10716
|
iterationOptions.range = IDBKeyRange.lowerBound([collectionKey, readTimeKey],
|
|
10413
10717
|
/* open= */ true);
|
|
@@ -10424,12 +10728,12 @@ class IndexedDbRemoteDocumentCacheImpl {
|
|
|
10424
10728
|
return;
|
|
10425
10729
|
}
|
|
10426
10730
|
const document = this.maybeDecodeDocument(DocumentKey.fromSegments(key), dbRemoteDoc);
|
|
10427
|
-
if (
|
|
10428
|
-
control.done();
|
|
10429
|
-
}
|
|
10430
|
-
else if (queryMatches(query, document)) {
|
|
10731
|
+
if (collection.isPrefixOf(document.key.path)) {
|
|
10431
10732
|
results = results.insert(document.key, document);
|
|
10432
10733
|
}
|
|
10734
|
+
else {
|
|
10735
|
+
control.done();
|
|
10736
|
+
}
|
|
10433
10737
|
})
|
|
10434
10738
|
.next(() => results);
|
|
10435
10739
|
}
|
|
@@ -10467,14 +10771,9 @@ class IndexedDbRemoteDocumentCacheImpl {
|
|
|
10467
10771
|
return MutableDocument.newInvalidDocument(documentKey);
|
|
10468
10772
|
}
|
|
10469
10773
|
}
|
|
10470
|
-
/**
|
|
10471
|
-
|
|
10472
|
-
|
|
10473
|
-
* @param serializer - The document serializer.
|
|
10474
|
-
* @param indexManager - The query indexes that need to be maintained.
|
|
10475
|
-
*/
|
|
10476
|
-
function newIndexedDbRemoteDocumentCache(serializer, indexManager) {
|
|
10477
|
-
return new IndexedDbRemoteDocumentCacheImpl(serializer, indexManager);
|
|
10774
|
+
/** Creates a new IndexedDbRemoteDocumentCache. */
|
|
10775
|
+
function newIndexedDbRemoteDocumentCache(serializer) {
|
|
10776
|
+
return new IndexedDbRemoteDocumentCacheImpl(serializer);
|
|
10478
10777
|
}
|
|
10479
10778
|
/**
|
|
10480
10779
|
* Returns the set of documents that have changed since the specified read
|
|
@@ -10641,9 +10940,6 @@ class SchemaConverter {
|
|
|
10641
10940
|
* and local feature development.
|
|
10642
10941
|
*/
|
|
10643
10942
|
createOrUpgrade(db, txn, fromVersion, toVersion) {
|
|
10644
|
-
hardAssert(fromVersion < toVersion &&
|
|
10645
|
-
fromVersion >= 0 &&
|
|
10646
|
-
toVersion <= SCHEMA_VERSION);
|
|
10647
10943
|
const simpleDbTransaction = new SimpleDbTransaction('createOrUpgrade', txn);
|
|
10648
10944
|
if (fromVersion < 1 && toVersion >= 1) {
|
|
10649
10945
|
createPrimaryClientStore(db);
|
|
@@ -10710,6 +11006,11 @@ class SchemaConverter {
|
|
|
10710
11006
|
createNamedQueriesStore(db);
|
|
10711
11007
|
});
|
|
10712
11008
|
}
|
|
11009
|
+
if (fromVersion < 12 && toVersion >= 12) {
|
|
11010
|
+
p = p.next(() => {
|
|
11011
|
+
createFieldIndex(db);
|
|
11012
|
+
});
|
|
11013
|
+
}
|
|
10713
11014
|
return p;
|
|
10714
11015
|
}
|
|
10715
11016
|
addDocumentGlobal(txn) {
|
|
@@ -10916,6 +11217,20 @@ function createNamedQueriesStore(db) {
|
|
|
10916
11217
|
db.createObjectStore(DbNamedQuery.store, {
|
|
10917
11218
|
keyPath: DbNamedQuery.keyPath
|
|
10918
11219
|
});
|
|
11220
|
+
}
|
|
11221
|
+
function createFieldIndex(db) {
|
|
11222
|
+
const indexConfiguratioStore = db.createObjectStore(DbIndexConfiguration.store, {
|
|
11223
|
+
keyPath: DbIndexConfiguration.keyPath,
|
|
11224
|
+
autoIncrement: true
|
|
11225
|
+
});
|
|
11226
|
+
indexConfiguratioStore.createIndex(DbIndexConfiguration.collectionGroupIndex, DbIndexConfiguration.collectionGroupIndexPath, { unique: false });
|
|
11227
|
+
const indexStateStore = db.createObjectStore(DbIndexState.store, {
|
|
11228
|
+
keyPath: DbIndexState.keyPath
|
|
11229
|
+
});
|
|
11230
|
+
indexStateStore.createIndex(DbIndexState.sequenceNumberIndex, DbIndexState.sequenceNumberIndexPath, { unique: false });
|
|
11231
|
+
db.createObjectStore(DbIndexEntry.store, {
|
|
11232
|
+
keyPath: DbIndexEntry.keyPath
|
|
11233
|
+
});
|
|
10919
11234
|
}
|
|
10920
11235
|
|
|
10921
11236
|
/**
|
|
@@ -11027,7 +11342,7 @@ class IndexedDbPersistence {
|
|
|
11027
11342
|
* If set to true, forcefully obtains database access. Existing tabs will
|
|
11028
11343
|
* no longer be able to access IndexedDB.
|
|
11029
11344
|
*/
|
|
11030
|
-
forceOwningTab) {
|
|
11345
|
+
forceOwningTab, schemaVersion = SCHEMA_VERSION) {
|
|
11031
11346
|
this.allowTabSynchronization = allowTabSynchronization;
|
|
11032
11347
|
this.persistenceKey = persistenceKey;
|
|
11033
11348
|
this.clientId = clientId;
|
|
@@ -11036,6 +11351,7 @@ class IndexedDbPersistence {
|
|
|
11036
11351
|
this.document = document;
|
|
11037
11352
|
this.sequenceNumberSyncer = sequenceNumberSyncer;
|
|
11038
11353
|
this.forceOwningTab = forceOwningTab;
|
|
11354
|
+
this.schemaVersion = schemaVersion;
|
|
11039
11355
|
this.listenSequence = null;
|
|
11040
11356
|
this._started = false;
|
|
11041
11357
|
this.isPrimary = false;
|
|
@@ -11057,10 +11373,9 @@ class IndexedDbPersistence {
|
|
|
11057
11373
|
this.referenceDelegate = new IndexedDbLruDelegateImpl(this, lruParams);
|
|
11058
11374
|
this.dbName = persistenceKey + MAIN_DATABASE;
|
|
11059
11375
|
this.serializer = new LocalSerializer(serializer);
|
|
11060
|
-
this.simpleDb = new SimpleDb(this.dbName,
|
|
11376
|
+
this.simpleDb = new SimpleDb(this.dbName, this.schemaVersion, new SchemaConverter(this.serializer));
|
|
11061
11377
|
this.targetCache = new IndexedDbTargetCache(this.referenceDelegate, this.serializer);
|
|
11062
|
-
this.
|
|
11063
|
-
this.remoteDocumentCache = newIndexedDbRemoteDocumentCache(this.serializer, this.indexManager);
|
|
11378
|
+
this.remoteDocumentCache = newIndexedDbRemoteDocumentCache(this.serializer);
|
|
11064
11379
|
this.bundleCache = new IndexedDbBundleCache();
|
|
11065
11380
|
if (this.window && this.window.localStorage) {
|
|
11066
11381
|
this.webStorage = this.window.localStorage;
|
|
@@ -11396,8 +11711,8 @@ class IndexedDbPersistence {
|
|
|
11396
11711
|
get started() {
|
|
11397
11712
|
return this._started;
|
|
11398
11713
|
}
|
|
11399
|
-
getMutationQueue(user) {
|
|
11400
|
-
return IndexedDbMutationQueue.forUser(user, this.serializer,
|
|
11714
|
+
getMutationQueue(user, indexManager) {
|
|
11715
|
+
return IndexedDbMutationQueue.forUser(user, this.serializer, indexManager, this.referenceDelegate);
|
|
11401
11716
|
}
|
|
11402
11717
|
getTargetCache() {
|
|
11403
11718
|
return this.targetCache;
|
|
@@ -11405,8 +11720,8 @@ class IndexedDbPersistence {
|
|
|
11405
11720
|
getRemoteDocumentCache() {
|
|
11406
11721
|
return this.remoteDocumentCache;
|
|
11407
11722
|
}
|
|
11408
|
-
getIndexManager() {
|
|
11409
|
-
return
|
|
11723
|
+
getIndexManager(user) {
|
|
11724
|
+
return new IndexedDbIndexManager(user);
|
|
11410
11725
|
}
|
|
11411
11726
|
getBundleCache() {
|
|
11412
11727
|
return this.bundleCache;
|
|
@@ -11414,11 +11729,12 @@ class IndexedDbPersistence {
|
|
|
11414
11729
|
runTransaction(action, mode, transactionOperation) {
|
|
11415
11730
|
logDebug(LOG_TAG$d, 'Starting transaction:', action);
|
|
11416
11731
|
const simpleDbMode = mode === 'readonly' ? 'readonly' : 'readwrite';
|
|
11732
|
+
const objectStores = getObjectStores(this.schemaVersion);
|
|
11417
11733
|
let persistenceTransaction;
|
|
11418
11734
|
// Do all transactions as readwrite against all object stores, since we
|
|
11419
11735
|
// are the only reader/writer.
|
|
11420
11736
|
return this.simpleDb
|
|
11421
|
-
.runTransaction(action, simpleDbMode,
|
|
11737
|
+
.runTransaction(action, simpleDbMode, objectStores, simpleDbTxn => {
|
|
11422
11738
|
persistenceTransaction = new IndexedDbTransaction(simpleDbTxn, this.listenSequence
|
|
11423
11739
|
? this.listenSequence.next()
|
|
11424
11740
|
: ListenSequence.INVALID);
|
|
@@ -11790,39 +12106,28 @@ class LocalDocumentsView {
|
|
|
11790
12106
|
getDocumentsMatchingCollectionQuery(transaction, query, sinceReadTime) {
|
|
11791
12107
|
// Query the remote documents and overlay mutations.
|
|
11792
12108
|
let results;
|
|
11793
|
-
let mutationBatches;
|
|
11794
12109
|
return this.remoteDocumentCache
|
|
11795
|
-
.
|
|
12110
|
+
.getAll(transaction, query.path, sinceReadTime)
|
|
11796
12111
|
.next(queryResults => {
|
|
11797
12112
|
results = queryResults;
|
|
11798
12113
|
return this.mutationQueue.getAllMutationBatchesAffectingQuery(transaction, query);
|
|
11799
12114
|
})
|
|
11800
|
-
.next(
|
|
11801
|
-
mutationBatches
|
|
11802
|
-
|
|
11803
|
-
|
|
11804
|
-
|
|
11805
|
-
|
|
11806
|
-
|
|
11807
|
-
|
|
11808
|
-
|
|
11809
|
-
|
|
11810
|
-
|
|
11811
|
-
|
|
11812
|
-
|
|
11813
|
-
let document = results.get(key);
|
|
11814
|
-
if (document == null) {
|
|
11815
|
-
// Create invalid document to apply mutations on top of
|
|
11816
|
-
document = MutableDocument.newInvalidDocument(key);
|
|
11817
|
-
results = results.insert(key, document);
|
|
11818
|
-
}
|
|
11819
|
-
mutationApplyToLocalView(mutation, document, batch.localWriteTime);
|
|
11820
|
-
if (!document.isFoundDocument()) {
|
|
11821
|
-
results = results.remove(key);
|
|
11822
|
-
}
|
|
12115
|
+
.next(mutationBatches => {
|
|
12116
|
+
for (const batch of mutationBatches) {
|
|
12117
|
+
for (const mutation of batch.mutations) {
|
|
12118
|
+
const key = mutation.key;
|
|
12119
|
+
let document = results.get(key);
|
|
12120
|
+
if (document == null) {
|
|
12121
|
+
// Create invalid document to apply mutations on top of
|
|
12122
|
+
document = MutableDocument.newInvalidDocument(key);
|
|
12123
|
+
results = results.insert(key, document);
|
|
12124
|
+
}
|
|
12125
|
+
mutationApplyToLocalView(mutation, document, batch.localWriteTime);
|
|
12126
|
+
if (!document.isFoundDocument()) {
|
|
12127
|
+
results = results.remove(key);
|
|
11823
12128
|
}
|
|
11824
12129
|
}
|
|
11825
|
-
}
|
|
12130
|
+
}
|
|
11826
12131
|
})
|
|
11827
12132
|
.next(() => {
|
|
11828
12133
|
// Finally, filter out any documents that don't actually match
|
|
@@ -11835,29 +12140,6 @@ class LocalDocumentsView {
|
|
|
11835
12140
|
return results;
|
|
11836
12141
|
});
|
|
11837
12142
|
}
|
|
11838
|
-
addMissingBaseDocuments(transaction, matchingMutationBatches, existingDocuments) {
|
|
11839
|
-
let missingBaseDocEntriesForPatching = documentKeySet();
|
|
11840
|
-
for (const batch of matchingMutationBatches) {
|
|
11841
|
-
for (const mutation of batch.mutations) {
|
|
11842
|
-
if (mutation instanceof PatchMutation &&
|
|
11843
|
-
existingDocuments.get(mutation.key) === null) {
|
|
11844
|
-
missingBaseDocEntriesForPatching =
|
|
11845
|
-
missingBaseDocEntriesForPatching.add(mutation.key);
|
|
11846
|
-
}
|
|
11847
|
-
}
|
|
11848
|
-
}
|
|
11849
|
-
let mergedDocuments = existingDocuments;
|
|
11850
|
-
return this.remoteDocumentCache
|
|
11851
|
-
.getEntries(transaction, missingBaseDocEntriesForPatching)
|
|
11852
|
-
.next(missingBaseDocs => {
|
|
11853
|
-
missingBaseDocs.forEach((key, doc) => {
|
|
11854
|
-
if (doc.isFoundDocument()) {
|
|
11855
|
-
mergedDocuments = mergedDocuments.insert(key, doc);
|
|
11856
|
-
}
|
|
11857
|
-
});
|
|
11858
|
-
return mergedDocuments;
|
|
11859
|
-
});
|
|
11860
|
-
}
|
|
11861
12143
|
}
|
|
11862
12144
|
|
|
11863
12145
|
/**
|
|
@@ -11916,11 +12198,18 @@ class LocalStoreImpl {
|
|
|
11916
12198
|
* PORTING NOTE: This is only used for multi-tab synchronization.
|
|
11917
12199
|
*/
|
|
11918
12200
|
this.lastDocumentChangeReadTime = SnapshotVersion.min();
|
|
11919
|
-
this.mutationQueue = persistence.getMutationQueue(initialUser);
|
|
11920
12201
|
this.remoteDocuments = persistence.getRemoteDocumentCache();
|
|
11921
12202
|
this.targetCache = persistence.getTargetCache();
|
|
11922
|
-
this.localDocuments = new LocalDocumentsView(this.remoteDocuments, this.mutationQueue, this.persistence.getIndexManager());
|
|
11923
12203
|
this.bundleCache = persistence.getBundleCache();
|
|
12204
|
+
this.initializeUserComponents(initialUser);
|
|
12205
|
+
}
|
|
12206
|
+
initializeUserComponents(user) {
|
|
12207
|
+
// TODO(indexing): Add spec tests that test these components change after a
|
|
12208
|
+
// user change
|
|
12209
|
+
this.indexManager = this.persistence.getIndexManager(user);
|
|
12210
|
+
this.mutationQueue = this.persistence.getMutationQueue(user, this.indexManager);
|
|
12211
|
+
this.localDocuments = new LocalDocumentsView(this.remoteDocuments, this.mutationQueue, this.indexManager);
|
|
12212
|
+
this.remoteDocuments.setIndexManager(this.indexManager);
|
|
11924
12213
|
this.queryEngine.setLocalDocumentsView(this.localDocuments);
|
|
11925
12214
|
}
|
|
11926
12215
|
collectGarbage(garbageCollector) {
|
|
@@ -11942,8 +12231,6 @@ persistence, queryEngine, initialUser, serializer) {
|
|
|
11942
12231
|
// change.
|
|
11943
12232
|
async function localStoreHandleUserChange(localStore, user) {
|
|
11944
12233
|
const localStoreImpl = debugCast(localStore);
|
|
11945
|
-
let newMutationQueue = localStoreImpl.mutationQueue;
|
|
11946
|
-
let newLocalDocuments = localStoreImpl.localDocuments;
|
|
11947
12234
|
const result = await localStoreImpl.persistence.runTransaction('Handle user change', 'readonly', txn => {
|
|
11948
12235
|
// Swap out the mutation queue, grabbing the pending mutation batches
|
|
11949
12236
|
// before and after.
|
|
@@ -11952,11 +12239,8 @@ async function localStoreHandleUserChange(localStore, user) {
|
|
|
11952
12239
|
.getAllMutationBatches(txn)
|
|
11953
12240
|
.next(promisedOldBatches => {
|
|
11954
12241
|
oldBatches = promisedOldBatches;
|
|
11955
|
-
|
|
11956
|
-
|
|
11957
|
-
// MutationQueue.
|
|
11958
|
-
newLocalDocuments = new LocalDocumentsView(localStoreImpl.remoteDocuments, newMutationQueue, localStoreImpl.persistence.getIndexManager());
|
|
11959
|
-
return newMutationQueue.getAllMutationBatches(txn);
|
|
12242
|
+
localStoreImpl.initializeUserComponents(user);
|
|
12243
|
+
return localStoreImpl.mutationQueue.getAllMutationBatches(txn);
|
|
11960
12244
|
})
|
|
11961
12245
|
.next(newBatches => {
|
|
11962
12246
|
const removedBatchIds = [];
|
|
@@ -11977,7 +12261,7 @@ async function localStoreHandleUserChange(localStore, user) {
|
|
|
11977
12261
|
}
|
|
11978
12262
|
// Return the set of all (potentially) changed documents and the list
|
|
11979
12263
|
// of mutation batch IDs that were affected by change.
|
|
11980
|
-
return
|
|
12264
|
+
return localStoreImpl.localDocuments
|
|
11981
12265
|
.getDocuments(txn, changedKeys)
|
|
11982
12266
|
.next(affectedDocuments => {
|
|
11983
12267
|
return {
|
|
@@ -11988,9 +12272,6 @@ async function localStoreHandleUserChange(localStore, user) {
|
|
|
11988
12272
|
});
|
|
11989
12273
|
});
|
|
11990
12274
|
});
|
|
11991
|
-
localStoreImpl.mutationQueue = newMutationQueue;
|
|
11992
|
-
localStoreImpl.localDocuments = newLocalDocuments;
|
|
11993
|
-
localStoreImpl.queryEngine.setLocalDocumentsView(localStoreImpl.localDocuments);
|
|
11994
12275
|
return result;
|
|
11995
12276
|
}
|
|
11996
12277
|
/* Accepts locally generated Mutations and commit them to storage. */
|
|
@@ -13056,14 +13337,16 @@ class MemoryRemoteDocumentCacheImpl {
|
|
|
13056
13337
|
* expected to just return 0 to avoid unnecessarily doing the work of
|
|
13057
13338
|
* calculating the size.
|
|
13058
13339
|
*/
|
|
13059
|
-
constructor(
|
|
13060
|
-
this.indexManager = indexManager;
|
|
13340
|
+
constructor(sizer) {
|
|
13061
13341
|
this.sizer = sizer;
|
|
13062
13342
|
/** Underlying cache of documents and their read times. */
|
|
13063
13343
|
this.docs = documentEntryMap();
|
|
13064
13344
|
/** Size of all cached documents. */
|
|
13065
13345
|
this.size = 0;
|
|
13066
13346
|
}
|
|
13347
|
+
setIndexManager(indexManager) {
|
|
13348
|
+
this.indexManager = indexManager;
|
|
13349
|
+
}
|
|
13067
13350
|
/**
|
|
13068
13351
|
* Adds the supplied entry to the cache and updates the cache size as appropriate.
|
|
13069
13352
|
*
|
|
@@ -13111,21 +13394,22 @@ class MemoryRemoteDocumentCacheImpl {
|
|
|
13111
13394
|
});
|
|
13112
13395
|
return PersistencePromise.resolve(results);
|
|
13113
13396
|
}
|
|
13114
|
-
|
|
13397
|
+
getAll(transaction, collectionPath, sinceReadTime) {
|
|
13115
13398
|
let results = mutableDocumentMap();
|
|
13116
13399
|
// Documents are ordered by key, so we can use a prefix scan to narrow down
|
|
13117
13400
|
// the documents we need to match the query against.
|
|
13118
|
-
const prefix = new DocumentKey(
|
|
13401
|
+
const prefix = new DocumentKey(collectionPath.child(''));
|
|
13119
13402
|
const iterator = this.docs.getIteratorFrom(prefix);
|
|
13120
13403
|
while (iterator.hasNext()) {
|
|
13121
13404
|
const { key, value: { document } } = iterator.getNext();
|
|
13122
|
-
if (!
|
|
13405
|
+
if (!collectionPath.isPrefixOf(key.path)) {
|
|
13123
13406
|
break;
|
|
13124
13407
|
}
|
|
13125
|
-
if (
|
|
13408
|
+
if (key.path.length > collectionPath.length + 1) {
|
|
13409
|
+
// Exclude entries from subcollections.
|
|
13126
13410
|
continue;
|
|
13127
13411
|
}
|
|
13128
|
-
if (
|
|
13412
|
+
if (document.readTime.compareTo(sinceReadTime) <= 0) {
|
|
13129
13413
|
continue;
|
|
13130
13414
|
}
|
|
13131
13415
|
results = results.insert(document.key, document.mutableCopy());
|
|
@@ -13147,13 +13431,12 @@ class MemoryRemoteDocumentCacheImpl {
|
|
|
13147
13431
|
/**
|
|
13148
13432
|
* Creates a new memory-only RemoteDocumentCache.
|
|
13149
13433
|
*
|
|
13150
|
-
* @param indexManager - A class that manages collection group indices.
|
|
13151
13434
|
* @param sizer - Used to assess the size of a document. For eager GC, this is
|
|
13152
13435
|
* expected to just return 0 to avoid unnecessarily doing the work of
|
|
13153
13436
|
* calculating the size.
|
|
13154
13437
|
*/
|
|
13155
|
-
function newMemoryRemoteDocumentCache(
|
|
13156
|
-
return new MemoryRemoteDocumentCacheImpl(
|
|
13438
|
+
function newMemoryRemoteDocumentCache(sizer) {
|
|
13439
|
+
return new MemoryRemoteDocumentCacheImpl(sizer);
|
|
13157
13440
|
}
|
|
13158
13441
|
/**
|
|
13159
13442
|
* Handles the details of adding and updating documents in the MemoryRemoteDocumentCache.
|
|
@@ -13354,7 +13637,7 @@ class MemoryPersistence {
|
|
|
13354
13637
|
this.targetCache = new MemoryTargetCache(this);
|
|
13355
13638
|
const sizer = (doc) => this.referenceDelegate.documentSize(doc);
|
|
13356
13639
|
this.indexManager = new MemoryIndexManager();
|
|
13357
|
-
this.remoteDocumentCache = newMemoryRemoteDocumentCache(
|
|
13640
|
+
this.remoteDocumentCache = newMemoryRemoteDocumentCache(sizer);
|
|
13358
13641
|
this.serializer = new LocalSerializer(serializer);
|
|
13359
13642
|
this.bundleCache = new MemoryBundleCache(this.serializer);
|
|
13360
13643
|
}
|
|
@@ -13375,13 +13658,15 @@ class MemoryPersistence {
|
|
|
13375
13658
|
setNetworkEnabled() {
|
|
13376
13659
|
// No op.
|
|
13377
13660
|
}
|
|
13378
|
-
getIndexManager() {
|
|
13661
|
+
getIndexManager(user) {
|
|
13662
|
+
// We do not currently support indices for memory persistence, so we can
|
|
13663
|
+
// return the same shared instance of the memory index manager.
|
|
13379
13664
|
return this.indexManager;
|
|
13380
13665
|
}
|
|
13381
|
-
getMutationQueue(user) {
|
|
13666
|
+
getMutationQueue(user, indexManager) {
|
|
13382
13667
|
let queue = this.mutationQueues[user.toKey()];
|
|
13383
13668
|
if (!queue) {
|
|
13384
|
-
queue = new MemoryMutationQueue(
|
|
13669
|
+
queue = new MemoryMutationQueue(indexManager, this.referenceDelegate);
|
|
13385
13670
|
this.mutationQueues[user.toKey()] = queue;
|
|
13386
13671
|
}
|
|
13387
13672
|
return queue;
|
|
@@ -20344,12 +20629,12 @@ async function syncEngineListen(syncEngine, query) {
|
|
|
20344
20629
|
}
|
|
20345
20630
|
else {
|
|
20346
20631
|
const targetData = await localStoreAllocateTarget(syncEngineImpl.localStore, queryToTarget(query));
|
|
20347
|
-
const status = syncEngineImpl.sharedClientState.addLocalQueryTarget(targetData.targetId);
|
|
20348
|
-
targetId = targetData.targetId;
|
|
20349
|
-
viewSnapshot = await initializeViewAndComputeSnapshot(syncEngineImpl, query, targetId, status === 'current');
|
|
20350
20632
|
if (syncEngineImpl.isPrimaryClient) {
|
|
20351
20633
|
remoteStoreListen(syncEngineImpl.remoteStore, targetData);
|
|
20352
20634
|
}
|
|
20635
|
+
const status = syncEngineImpl.sharedClientState.addLocalQueryTarget(targetData.targetId);
|
|
20636
|
+
targetId = targetData.targetId;
|
|
20637
|
+
viewSnapshot = await initializeViewAndComputeSnapshot(syncEngineImpl, query, targetId, status === 'current');
|
|
20353
20638
|
}
|
|
20354
20639
|
return viewSnapshot;
|
|
20355
20640
|
}
|
|
@@ -24857,8 +25142,7 @@ class DocumentSnapshot extends DocumentSnapshot$1 {
|
|
|
24857
25142
|
this.metadata = metadata;
|
|
24858
25143
|
}
|
|
24859
25144
|
/**
|
|
24860
|
-
*
|
|
24861
|
-
* exists. True if the document exists.
|
|
25145
|
+
* Returns whether or not the data exists. True if the document exists.
|
|
24862
25146
|
*/
|
|
24863
25147
|
exists() {
|
|
24864
25148
|
return super.exists();
|
|
@@ -25232,51 +25516,53 @@ function limitToLast(limit) {
|
|
|
25232
25516
|
return new QueryLimitConstraint('limitToLast', limit, "L" /* Last */);
|
|
25233
25517
|
}
|
|
25234
25518
|
class QueryStartAtConstraint extends QueryConstraint {
|
|
25235
|
-
constructor(type, _docOrFields,
|
|
25519
|
+
constructor(type, _docOrFields, _inclusive) {
|
|
25236
25520
|
super();
|
|
25237
25521
|
this.type = type;
|
|
25238
25522
|
this._docOrFields = _docOrFields;
|
|
25239
|
-
this.
|
|
25523
|
+
this._inclusive = _inclusive;
|
|
25240
25524
|
}
|
|
25241
25525
|
_apply(query) {
|
|
25242
|
-
const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this.
|
|
25526
|
+
const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this._inclusive);
|
|
25243
25527
|
return new Query(query.firestore, query.converter, queryWithStartAt(query._query, bound));
|
|
25244
25528
|
}
|
|
25245
25529
|
}
|
|
25246
25530
|
function startAt(...docOrFields) {
|
|
25247
|
-
return new QueryStartAtConstraint('startAt', docOrFields,
|
|
25531
|
+
return new QueryStartAtConstraint('startAt', docOrFields,
|
|
25532
|
+
/*inclusive=*/ true);
|
|
25248
25533
|
}
|
|
25249
25534
|
function startAfter(...docOrFields) {
|
|
25250
25535
|
return new QueryStartAtConstraint('startAfter', docOrFields,
|
|
25251
|
-
/*
|
|
25536
|
+
/*inclusive=*/ false);
|
|
25252
25537
|
}
|
|
25253
25538
|
class QueryEndAtConstraint extends QueryConstraint {
|
|
25254
|
-
constructor(type, _docOrFields,
|
|
25539
|
+
constructor(type, _docOrFields, _inclusive) {
|
|
25255
25540
|
super();
|
|
25256
25541
|
this.type = type;
|
|
25257
25542
|
this._docOrFields = _docOrFields;
|
|
25258
|
-
this.
|
|
25543
|
+
this._inclusive = _inclusive;
|
|
25259
25544
|
}
|
|
25260
25545
|
_apply(query) {
|
|
25261
|
-
const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this.
|
|
25546
|
+
const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this._inclusive);
|
|
25262
25547
|
return new Query(query.firestore, query.converter, queryWithEndAt(query._query, bound));
|
|
25263
25548
|
}
|
|
25264
25549
|
}
|
|
25265
25550
|
function endBefore(...docOrFields) {
|
|
25266
|
-
return new QueryEndAtConstraint('endBefore', docOrFields,
|
|
25551
|
+
return new QueryEndAtConstraint('endBefore', docOrFields,
|
|
25552
|
+
/*inclusive=*/ false);
|
|
25267
25553
|
}
|
|
25268
25554
|
function endAt(...docOrFields) {
|
|
25269
|
-
return new QueryEndAtConstraint('endAt', docOrFields, /*
|
|
25555
|
+
return new QueryEndAtConstraint('endAt', docOrFields, /*inclusive=*/ true);
|
|
25270
25556
|
}
|
|
25271
25557
|
/** Helper function to create a bound from a document or fields */
|
|
25272
|
-
function newQueryBoundFromDocOrFields(query, methodName, docOrFields,
|
|
25558
|
+
function newQueryBoundFromDocOrFields(query, methodName, docOrFields, inclusive) {
|
|
25273
25559
|
docOrFields[0] = util$1.getModularInstance(docOrFields[0]);
|
|
25274
25560
|
if (docOrFields[0] instanceof DocumentSnapshot$1) {
|
|
25275
|
-
return newQueryBoundFromDocument(query._query, query.firestore._databaseId, methodName, docOrFields[0]._document,
|
|
25561
|
+
return newQueryBoundFromDocument(query._query, query.firestore._databaseId, methodName, docOrFields[0]._document, inclusive);
|
|
25276
25562
|
}
|
|
25277
25563
|
else {
|
|
25278
25564
|
const reader = newUserDataReader(query.firestore);
|
|
25279
|
-
return newQueryBoundFromFields(query._query, query.firestore._databaseId, reader, methodName, docOrFields,
|
|
25565
|
+
return newQueryBoundFromFields(query._query, query.firestore._databaseId, reader, methodName, docOrFields, inclusive);
|
|
25280
25566
|
}
|
|
25281
25567
|
}
|
|
25282
25568
|
function newQueryFilter(query, methodName, dataReader, databaseId, fieldPath, op, value) {
|
|
@@ -25334,7 +25620,7 @@ function newQueryOrderBy(query, fieldPath, direction) {
|
|
|
25334
25620
|
* of the query or if any of the fields in the order by are an uncommitted
|
|
25335
25621
|
* server timestamp.
|
|
25336
25622
|
*/
|
|
25337
|
-
function newQueryBoundFromDocument(query, databaseId, methodName, doc,
|
|
25623
|
+
function newQueryBoundFromDocument(query, databaseId, methodName, doc, inclusive) {
|
|
25338
25624
|
if (!doc) {
|
|
25339
25625
|
throw new FirestoreError(Code.NOT_FOUND, `Can't use a DocumentSnapshot that doesn't exist for ` +
|
|
25340
25626
|
`${methodName}().`);
|
|
@@ -25371,12 +25657,12 @@ function newQueryBoundFromDocument(query, databaseId, methodName, doc, before) {
|
|
|
25371
25657
|
}
|
|
25372
25658
|
}
|
|
25373
25659
|
}
|
|
25374
|
-
return new Bound(components,
|
|
25660
|
+
return new Bound(components, inclusive);
|
|
25375
25661
|
}
|
|
25376
25662
|
/**
|
|
25377
25663
|
* Converts a list of field values to a `Bound` for the given query.
|
|
25378
25664
|
*/
|
|
25379
|
-
function newQueryBoundFromFields(query, databaseId, dataReader, methodName, values,
|
|
25665
|
+
function newQueryBoundFromFields(query, databaseId, dataReader, methodName, values, inclusive) {
|
|
25380
25666
|
// Use explicit order by's because it has to match the query the user made
|
|
25381
25667
|
const orderBy = query.explicitOrderBy;
|
|
25382
25668
|
if (values.length > orderBy.length) {
|
|
@@ -25413,7 +25699,7 @@ function newQueryBoundFromFields(query, databaseId, dataReader, methodName, valu
|
|
|
25413
25699
|
components.push(wrapped);
|
|
25414
25700
|
}
|
|
25415
25701
|
}
|
|
25416
|
-
return new Bound(components,
|
|
25702
|
+
return new Bound(components, inclusive);
|
|
25417
25703
|
}
|
|
25418
25704
|
/**
|
|
25419
25705
|
* Parses the given `documentIdValue` into a `ReferenceValue`, throwing
|