@firebase/firestore 3.4.4-canary.2dd99ae2d → 3.4.4-canary.3e9f3e253
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/document_overlay_cache.d.ts +72 -0
- package/dist/firestore/src/local/index_manager.d.ts +52 -0
- package/dist/firestore/src/local/indexeddb_document_overlay_cache.d.ts +45 -0
- package/dist/firestore/src/local/indexeddb_index_manager.d.ts +21 -2
- package/dist/firestore/src/local/indexeddb_persistence.d.ts +6 -4
- package/dist/firestore/src/local/indexeddb_remote_document_cache.d.ts +2 -8
- package/dist/firestore/src/local/indexeddb_schema.d.ts +193 -7
- package/dist/firestore/src/local/local_documents_view.d.ts +0 -1
- package/dist/firestore/src/local/local_serializer.d.ts +18 -2
- package/dist/firestore/src/local/memory_document_overlay_cache.d.ts +37 -0
- package/dist/firestore/src/local/memory_index_manager.d.ts +11 -0
- package/dist/firestore/src/local/memory_persistence.d.ts +6 -2
- package/dist/firestore/src/local/memory_remote_document_cache.d.ts +1 -3
- package/dist/firestore/src/local/persistence.d.ts +8 -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/document_key.d.ts +4 -0
- package/dist/firestore/src/model/field_index.d.ts +2 -2
- package/dist/firestore/src/model/overlay.d.ts +32 -0
- 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/document_overlay_cache.test.d.ts +1 -0
- package/dist/firestore/test/unit/local/persistence_test_helpers.d.ts +1 -0
- package/dist/firestore/test/unit/local/test_document_overlay_cache.d.ts +38 -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 +3864 -3349
- package/dist/index.esm2017.js.map +1 -1
- package/dist/index.esm5.js +3879 -3455
- package/dist/index.esm5.js.map +1 -1
- package/dist/index.node.cjs.js +878 -221
- package/dist/index.node.cjs.js.map +1 -1
- package/dist/index.node.mjs +878 -221
- package/dist/index.node.mjs.map +1 -1
- package/dist/index.rn.js +3973 -3458
- package/dist/index.rn.js.map +1 -1
- package/dist/internal.d.ts +252 -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/document_overlay_cache.d.ts +72 -0
- package/dist/lite/firestore/src/local/index_manager.d.ts +52 -0
- package/dist/lite/firestore/src/local/indexeddb_document_overlay_cache.d.ts +45 -0
- package/dist/lite/firestore/src/local/indexeddb_index_manager.d.ts +21 -2
- package/dist/lite/firestore/src/local/indexeddb_persistence.d.ts +6 -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 +193 -7
- package/dist/lite/firestore/src/local/local_documents_view.d.ts +0 -1
- package/dist/lite/firestore/src/local/local_serializer.d.ts +18 -2
- package/dist/lite/firestore/src/local/memory_document_overlay_cache.d.ts +37 -0
- package/dist/lite/firestore/src/local/memory_index_manager.d.ts +11 -0
- package/dist/lite/firestore/src/local/memory_persistence.d.ts +6 -2
- package/dist/lite/firestore/src/local/memory_remote_document_cache.d.ts +1 -3
- package/dist/lite/firestore/src/local/persistence.d.ts +8 -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/document_key.d.ts +4 -0
- package/dist/lite/firestore/src/model/field_index.d.ts +2 -2
- package/dist/lite/firestore/src/model/overlay.d.ts +32 -0
- 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/document_overlay_cache.test.d.ts +1 -0
- package/dist/lite/firestore/test/unit/local/persistence_test_helpers.d.ts +1 -0
- package/dist/lite/firestore/test/unit/local/test_document_overlay_cache.d.ts +38 -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 +1152 -1143
- package/dist/lite/index.browser.esm2017.js.map +1 -1
- package/dist/lite/index.browser.esm5.js +348 -341
- package/dist/lite/index.browser.esm5.js.map +1 -1
- package/dist/lite/index.node.cjs.js +44 -29
- package/dist/lite/index.node.cjs.js.map +1 -1
- package/dist/lite/index.node.mjs +44 -29
- package/dist/lite/index.node.mjs.map +1 -1
- package/dist/lite/index.rn.esm2017.js +1180 -1171
- package/dist/lite/index.rn.esm2017.js.map +1 -1
- package/dist/lite/internal.d.ts +6 -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/document_overlay_cache.d.ts +72 -0
- package/dist/lite/packages/firestore/src/local/index_manager.d.ts +52 -0
- package/dist/lite/packages/firestore/src/local/indexeddb_document_overlay_cache.d.ts +45 -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 +6 -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 +193 -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 +18 -2
- package/dist/lite/packages/firestore/src/local/memory_document_overlay_cache.d.ts +37 -0
- 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 +6 -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 +8 -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/document_key.d.ts +4 -0
- package/dist/lite/packages/firestore/src/model/field_index.d.ts +2 -2
- package/dist/lite/packages/firestore/src/model/overlay.d.ts +32 -0
- 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/document_overlay_cache.test.d.ts +1 -0
- package/dist/lite/packages/firestore/test/unit/local/persistence_test_helpers.d.ts +1 -0
- package/dist/lite/packages/firestore/test/unit/local/test_document_overlay_cache.d.ts +38 -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 +181 -179
- 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/document_overlay_cache.d.ts +72 -0
- package/dist/packages/firestore/src/local/index_manager.d.ts +52 -0
- package/dist/packages/firestore/src/local/indexeddb_document_overlay_cache.d.ts +45 -0
- package/dist/packages/firestore/src/local/indexeddb_index_manager.d.ts +21 -2
- package/dist/packages/firestore/src/local/indexeddb_persistence.d.ts +6 -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 +193 -7
- package/dist/packages/firestore/src/local/local_documents_view.d.ts +0 -1
- package/dist/packages/firestore/src/local/local_serializer.d.ts +18 -2
- package/dist/packages/firestore/src/local/memory_document_overlay_cache.d.ts +37 -0
- package/dist/packages/firestore/src/local/memory_index_manager.d.ts +11 -0
- package/dist/packages/firestore/src/local/memory_persistence.d.ts +6 -2
- package/dist/packages/firestore/src/local/memory_remote_document_cache.d.ts +1 -3
- package/dist/packages/firestore/src/local/persistence.d.ts +8 -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/document_key.d.ts +4 -0
- package/dist/packages/firestore/src/model/field_index.d.ts +2 -2
- package/dist/packages/firestore/src/model/overlay.d.ts +32 -0
- 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/document_overlay_cache.test.d.ts +1 -0
- package/dist/packages/firestore/test/unit/local/persistence_test_helpers.d.ts +1 -0
- package/dist/packages/firestore/test/unit/local/test_document_overlay_cache.d.ts +38 -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 +248 -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.3e9f3e253";
|
|
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.3e9f3e253";
|
|
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,8 +1221,10 @@ 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 document overlays.
|
|
1225
|
+
* 13. Add indexing support.
|
|
1234
1226
|
*/
|
|
1235
|
-
const SCHEMA_VERSION =
|
|
1227
|
+
const SCHEMA_VERSION = 12;
|
|
1236
1228
|
/**
|
|
1237
1229
|
* Wrapper class to store timestamps (seconds and nanos) in IndexedDb objects.
|
|
1238
1230
|
*/
|
|
@@ -1757,9 +1749,7 @@ class DbClientMetadata {
|
|
|
1757
1749
|
DbClientMetadata.store = 'clientMetadata';
|
|
1758
1750
|
/** Keys are automatically assigned via the clientId properties. */
|
|
1759
1751
|
DbClientMetadata.keyPath = 'clientId';
|
|
1760
|
-
/**
|
|
1761
|
-
* A object representing a bundle loaded by the SDK.
|
|
1762
|
-
*/
|
|
1752
|
+
/** An object representing a bundle loaded by the SDK. */
|
|
1763
1753
|
class DbBundle {
|
|
1764
1754
|
constructor(
|
|
1765
1755
|
/** The ID of the loaded bundle. */
|
|
@@ -1776,9 +1766,7 @@ class DbBundle {
|
|
|
1776
1766
|
/** Name of the IndexedDb object store. */
|
|
1777
1767
|
DbBundle.store = 'bundles';
|
|
1778
1768
|
DbBundle.keyPath = 'bundleId';
|
|
1779
|
-
/**
|
|
1780
|
-
* A object representing a named query loaded by the SDK via a bundle.
|
|
1781
|
-
*/
|
|
1769
|
+
/** An object representing a named query loaded by the SDK via a bundle. */
|
|
1782
1770
|
class DbNamedQuery {
|
|
1783
1771
|
constructor(
|
|
1784
1772
|
/** The name of the query. */
|
|
@@ -1795,6 +1783,156 @@ class DbNamedQuery {
|
|
|
1795
1783
|
/** Name of the IndexedDb object store. */
|
|
1796
1784
|
DbNamedQuery.store = 'namedQueries';
|
|
1797
1785
|
DbNamedQuery.keyPath = 'name';
|
|
1786
|
+
/** An object representing the global configuration for a field index. */
|
|
1787
|
+
class DbIndexConfiguration {
|
|
1788
|
+
constructor(
|
|
1789
|
+
/**
|
|
1790
|
+
* The index id for this entry. Undefined for indexes that are not yet
|
|
1791
|
+
* persisted.
|
|
1792
|
+
*/
|
|
1793
|
+
indexId,
|
|
1794
|
+
/** The collection group this index belongs to. */
|
|
1795
|
+
collectionGroup,
|
|
1796
|
+
/** The fields to index for this index. */
|
|
1797
|
+
fields) {
|
|
1798
|
+
this.indexId = indexId;
|
|
1799
|
+
this.collectionGroup = collectionGroup;
|
|
1800
|
+
this.fields = fields;
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
/** Name of the IndexedDb object store. */
|
|
1804
|
+
DbIndexConfiguration.store = 'indexConfiguration';
|
|
1805
|
+
DbIndexConfiguration.keyPath = 'indexId';
|
|
1806
|
+
/**
|
|
1807
|
+
* An index that provides access to the index configurations by collection
|
|
1808
|
+
* group.
|
|
1809
|
+
*
|
|
1810
|
+
* PORTING NOTE: iOS and Android maintain this index in-memory, but this is
|
|
1811
|
+
* not possible here as the Web client supports concurrent access to
|
|
1812
|
+
* persistence via multi-tab.
|
|
1813
|
+
*/
|
|
1814
|
+
DbIndexConfiguration.collectionGroupIndex = 'collectionGroupIndex';
|
|
1815
|
+
DbIndexConfiguration.collectionGroupIndexPath = 'collectionGroup';
|
|
1816
|
+
/**
|
|
1817
|
+
* An object describing how up-to-date the index backfill is for each user and
|
|
1818
|
+
* index.
|
|
1819
|
+
*/
|
|
1820
|
+
class DbIndexState {
|
|
1821
|
+
constructor(
|
|
1822
|
+
/** The index id for this entry. */
|
|
1823
|
+
indexId,
|
|
1824
|
+
/** The user id for this entry. */
|
|
1825
|
+
uid,
|
|
1826
|
+
/**
|
|
1827
|
+
* A number that indicates when the index was last updated (relative to
|
|
1828
|
+
* other indexes).
|
|
1829
|
+
*/
|
|
1830
|
+
sequenceNumber,
|
|
1831
|
+
/**
|
|
1832
|
+
* The latest read time that has been indexed by Firestore for this field
|
|
1833
|
+
* index. Set to `{seconds: 0, nanos: 0}` if no documents have been indexed.
|
|
1834
|
+
*/
|
|
1835
|
+
readTime,
|
|
1836
|
+
/**
|
|
1837
|
+
* The last document that has been indexed for this field index. Empty if
|
|
1838
|
+
* no documents have been indexed.
|
|
1839
|
+
*/
|
|
1840
|
+
documentKey,
|
|
1841
|
+
/**
|
|
1842
|
+
* The largest mutation batch id that has been processed for this index. -1
|
|
1843
|
+
* if no mutations have been indexed.
|
|
1844
|
+
*/
|
|
1845
|
+
largestBatchId) {
|
|
1846
|
+
this.indexId = indexId;
|
|
1847
|
+
this.uid = uid;
|
|
1848
|
+
this.sequenceNumber = sequenceNumber;
|
|
1849
|
+
this.readTime = readTime;
|
|
1850
|
+
this.documentKey = documentKey;
|
|
1851
|
+
this.largestBatchId = largestBatchId;
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
/** Name of the IndexedDb object store. */
|
|
1855
|
+
DbIndexState.store = 'indexState';
|
|
1856
|
+
DbIndexState.keyPath = ['indexId', 'uid'];
|
|
1857
|
+
/**
|
|
1858
|
+
* An index that provides access to documents in a collection sorted by last
|
|
1859
|
+
* update time. Used by the backfiller.
|
|
1860
|
+
*
|
|
1861
|
+
* PORTING NOTE: iOS and Android maintain this index in-memory, but this is
|
|
1862
|
+
* not possible here as the Web client supports concurrent access to
|
|
1863
|
+
* persistence via multi-tab.
|
|
1864
|
+
*/
|
|
1865
|
+
DbIndexState.sequenceNumberIndex = 'sequenceNumberIndex';
|
|
1866
|
+
DbIndexState.sequenceNumberIndexPath = ['uid', 'sequenceNumber'];
|
|
1867
|
+
/** An object that stores the encoded entries for all documents and fields. */
|
|
1868
|
+
class DbIndexEntry {
|
|
1869
|
+
constructor(
|
|
1870
|
+
/** The index id for this entry. */
|
|
1871
|
+
indexId,
|
|
1872
|
+
/** The user id for this entry. */
|
|
1873
|
+
uid,
|
|
1874
|
+
/** The encoded array index value for this entry. */
|
|
1875
|
+
arrayValue,
|
|
1876
|
+
/** The encoded directional value for equality and inequality filters. */
|
|
1877
|
+
directionalValue,
|
|
1878
|
+
/** The document key this entry points to. */
|
|
1879
|
+
documentKey) {
|
|
1880
|
+
this.indexId = indexId;
|
|
1881
|
+
this.uid = uid;
|
|
1882
|
+
this.arrayValue = arrayValue;
|
|
1883
|
+
this.directionalValue = directionalValue;
|
|
1884
|
+
this.documentKey = documentKey;
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
/** Name of the IndexedDb object store. */
|
|
1888
|
+
DbIndexEntry.store = 'indexEntries';
|
|
1889
|
+
DbIndexEntry.keyPath = [
|
|
1890
|
+
'indexId',
|
|
1891
|
+
'uid',
|
|
1892
|
+
'arrayValue',
|
|
1893
|
+
'directionalValue',
|
|
1894
|
+
'documentKey'
|
|
1895
|
+
];
|
|
1896
|
+
/**
|
|
1897
|
+
* An object representing a document overlay.
|
|
1898
|
+
*/
|
|
1899
|
+
class DbDocumentOverlay {
|
|
1900
|
+
constructor(
|
|
1901
|
+
/** The user ID to whom this overlay belongs. */
|
|
1902
|
+
userId,
|
|
1903
|
+
/** The path to the collection that contains the document. */
|
|
1904
|
+
collectionPath,
|
|
1905
|
+
/** The ID (key) of the document within the collection. */
|
|
1906
|
+
documentId,
|
|
1907
|
+
/** The collection group to which the document belongs. */
|
|
1908
|
+
collectionGroup,
|
|
1909
|
+
/** The largest batch ID that's been applied for this overlay. */
|
|
1910
|
+
largestBatchId,
|
|
1911
|
+
/** The overlay mutation. */
|
|
1912
|
+
overlayMutation) {
|
|
1913
|
+
this.userId = userId;
|
|
1914
|
+
this.collectionPath = collectionPath;
|
|
1915
|
+
this.documentId = documentId;
|
|
1916
|
+
this.collectionGroup = collectionGroup;
|
|
1917
|
+
this.largestBatchId = largestBatchId;
|
|
1918
|
+
this.overlayMutation = overlayMutation;
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
/** Name of the IndexedDb object store. */
|
|
1922
|
+
DbDocumentOverlay.store = 'documentOverlays';
|
|
1923
|
+
DbDocumentOverlay.keyPath = ['userId', 'collectionPath', 'documentId'];
|
|
1924
|
+
DbDocumentOverlay.collectionPathOverlayIndex = 'collectionPathOverlayIndex';
|
|
1925
|
+
DbDocumentOverlay.collectionPathOverlayIndexPath = [
|
|
1926
|
+
'userId',
|
|
1927
|
+
'collectionPath',
|
|
1928
|
+
'largestBatchId'
|
|
1929
|
+
];
|
|
1930
|
+
DbDocumentOverlay.collectionGroupOverlayIndex = 'collectionGroupOverlayIndex';
|
|
1931
|
+
DbDocumentOverlay.collectionGroupOverlayIndexPath = [
|
|
1932
|
+
'userId',
|
|
1933
|
+
'collectionGroup',
|
|
1934
|
+
'largestBatchId'
|
|
1935
|
+
];
|
|
1798
1936
|
// Visible for testing
|
|
1799
1937
|
const V1_STORES = [
|
|
1800
1938
|
DbMutationQueue.store,
|
|
@@ -1809,7 +1947,6 @@ const V1_STORES = [
|
|
|
1809
1947
|
// V2 is no longer usable (see comment at top of file)
|
|
1810
1948
|
// Visible for testing
|
|
1811
1949
|
const V3_STORES = V1_STORES;
|
|
1812
|
-
// Visible for testing
|
|
1813
1950
|
// Note: DbRemoteDocumentChanges is no longer used and dropped with v9.
|
|
1814
1951
|
const V4_STORES = [...V3_STORES, DbClientMetadata.store];
|
|
1815
1952
|
// V5 does not change the set of stores.
|
|
@@ -1819,12 +1956,28 @@ const V8_STORES = [...V6_STORES, DbCollectionParent.store];
|
|
|
1819
1956
|
// V9 does not change the set of stores.
|
|
1820
1957
|
// V10 does not change the set of stores.
|
|
1821
1958
|
const V11_STORES = [...V8_STORES, DbBundle.store, DbNamedQuery.store];
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1959
|
+
const V12_STORES = [...V11_STORES, DbDocumentOverlay.store];
|
|
1960
|
+
const V13_STORES = [
|
|
1961
|
+
...V12_STORES,
|
|
1962
|
+
DbIndexConfiguration.store,
|
|
1963
|
+
DbIndexState.store,
|
|
1964
|
+
DbIndexEntry.store
|
|
1965
|
+
];
|
|
1966
|
+
/** Returns the object stores for the provided schema. */
|
|
1967
|
+
function getObjectStores(schemaVersion) {
|
|
1968
|
+
if (schemaVersion === 13) {
|
|
1969
|
+
return V13_STORES;
|
|
1970
|
+
}
|
|
1971
|
+
else if (schemaVersion === 12) {
|
|
1972
|
+
return V12_STORES;
|
|
1973
|
+
}
|
|
1974
|
+
else if (schemaVersion === 11) {
|
|
1975
|
+
return V11_STORES;
|
|
1976
|
+
}
|
|
1977
|
+
else {
|
|
1978
|
+
fail();
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1828
1981
|
|
|
1829
1982
|
/**
|
|
1830
1983
|
* @license
|
|
@@ -2121,6 +2274,15 @@ class SimpleDbTransaction {
|
|
|
2121
2274
|
this.transaction.abort();
|
|
2122
2275
|
}
|
|
2123
2276
|
}
|
|
2277
|
+
maybeCommit() {
|
|
2278
|
+
// If the browser supports V3 IndexedDB, we invoke commit() explicitly to
|
|
2279
|
+
// speed up index DB processing if the event loop remains blocks.
|
|
2280
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2281
|
+
const maybeV3IndexedDb = this.transaction;
|
|
2282
|
+
if (!this.aborted && typeof maybeV3IndexedDb.commit === 'function') {
|
|
2283
|
+
maybeV3IndexedDb.commit();
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2124
2286
|
/**
|
|
2125
2287
|
* Returns a SimpleDbStore<KeyType, ValueType> for the specified store. All
|
|
2126
2288
|
* operations performed on the SimpleDbStore happen within the context of this
|
|
@@ -2317,6 +2479,10 @@ class SimpleDb {
|
|
|
2317
2479
|
this.db = await this.ensureDb(action);
|
|
2318
2480
|
const transaction = SimpleDbTransaction.open(this.db, action, readonly ? 'readonly' : 'readwrite', objectStores);
|
|
2319
2481
|
const transactionFnResult = transactionFn(transaction)
|
|
2482
|
+
.next(result => {
|
|
2483
|
+
transaction.maybeCommit();
|
|
2484
|
+
return result;
|
|
2485
|
+
})
|
|
2320
2486
|
.catch(error => {
|
|
2321
2487
|
// Abort the transaction if there was an error.
|
|
2322
2488
|
transaction.abort(error);
|
|
@@ -2489,13 +2655,29 @@ class SimpleDbStore {
|
|
|
2489
2655
|
return wrapRequest(request);
|
|
2490
2656
|
}
|
|
2491
2657
|
loadAll(indexOrRange, range) {
|
|
2492
|
-
const
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
return
|
|
2498
|
-
|
|
2658
|
+
const iterateOptions = this.options(indexOrRange, range);
|
|
2659
|
+
// Use `getAll()` if the browser supports IndexedDB v3, as it is roughly
|
|
2660
|
+
// 20% faster. Unfortunately, getAll() does not support custom indices.
|
|
2661
|
+
if (!iterateOptions.index && typeof this.store.getAll === 'function') {
|
|
2662
|
+
const request = this.store.getAll(iterateOptions.range);
|
|
2663
|
+
return new PersistencePromise((resolve, reject) => {
|
|
2664
|
+
request.onerror = (event) => {
|
|
2665
|
+
reject(event.target.error);
|
|
2666
|
+
};
|
|
2667
|
+
request.onsuccess = (event) => {
|
|
2668
|
+
resolve(event.target.result);
|
|
2669
|
+
};
|
|
2670
|
+
});
|
|
2671
|
+
}
|
|
2672
|
+
else {
|
|
2673
|
+
const cursor = this.cursor(iterateOptions);
|
|
2674
|
+
const results = [];
|
|
2675
|
+
return this.iterateCursor(cursor, (key, value) => {
|
|
2676
|
+
results.push(value);
|
|
2677
|
+
}).next(() => {
|
|
2678
|
+
return results;
|
|
2679
|
+
});
|
|
2680
|
+
}
|
|
2499
2681
|
}
|
|
2500
2682
|
deleteAll(indexOrRange, range) {
|
|
2501
2683
|
logDebug(LOG_TAG$g, 'DELETE ALL', this.store.name);
|
|
@@ -3526,6 +3708,14 @@ class DocumentKey {
|
|
|
3526
3708
|
return (this.path.length >= 2 &&
|
|
3527
3709
|
this.path.get(this.path.length - 2) === collectionId);
|
|
3528
3710
|
}
|
|
3711
|
+
/** Returns the collection group (i.e. the name of the parent collection) for this key. */
|
|
3712
|
+
getCollectionGroup() {
|
|
3713
|
+
return this.path.get(this.path.length - 2);
|
|
3714
|
+
}
|
|
3715
|
+
/** Returns the fully qualified path to the parent collection. */
|
|
3716
|
+
getCollectionPath() {
|
|
3717
|
+
return this.path.popLast();
|
|
3718
|
+
}
|
|
3529
3719
|
isEqual(other) {
|
|
3530
3720
|
return (other !== null && ResourcePath.comparator(this.path, other.path) === 0);
|
|
3531
3721
|
}
|
|
@@ -4349,12 +4539,12 @@ class FieldIndex {
|
|
|
4349
4539
|
/** The collection ID this index applies to. */
|
|
4350
4540
|
collectionGroup,
|
|
4351
4541
|
/** The field segments for this index. */
|
|
4352
|
-
|
|
4542
|
+
fields,
|
|
4353
4543
|
/** Shows how up-to-date the index is for the current user. */
|
|
4354
4544
|
indexState) {
|
|
4355
4545
|
this.indexId = indexId;
|
|
4356
4546
|
this.collectionGroup = collectionGroup;
|
|
4357
|
-
this.
|
|
4547
|
+
this.fields = fields;
|
|
4358
4548
|
this.indexState = indexState;
|
|
4359
4549
|
}
|
|
4360
4550
|
}
|
|
@@ -4464,27 +4654,29 @@ function newTarget(path, collectionGroup = null, orderBy = [], filters = [], lim
|
|
|
4464
4654
|
function canonifyTarget(target) {
|
|
4465
4655
|
const targetImpl = debugCast(target);
|
|
4466
4656
|
if (targetImpl.memoizedCanonicalId === null) {
|
|
4467
|
-
let
|
|
4657
|
+
let str = targetImpl.path.canonicalString();
|
|
4468
4658
|
if (targetImpl.collectionGroup !== null) {
|
|
4469
|
-
|
|
4659
|
+
str += '|cg:' + targetImpl.collectionGroup;
|
|
4470
4660
|
}
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4661
|
+
str += '|f:';
|
|
4662
|
+
str += targetImpl.filters.map(f => canonifyFilter(f)).join(',');
|
|
4663
|
+
str += '|ob:';
|
|
4664
|
+
str += targetImpl.orderBy.map(o => canonifyOrderBy(o)).join(',');
|
|
4475
4665
|
if (!isNullOrUndefined(targetImpl.limit)) {
|
|
4476
|
-
|
|
4477
|
-
|
|
4666
|
+
str += '|l:';
|
|
4667
|
+
str += targetImpl.limit;
|
|
4478
4668
|
}
|
|
4479
4669
|
if (targetImpl.startAt) {
|
|
4480
|
-
|
|
4481
|
-
|
|
4670
|
+
str += '|lb:';
|
|
4671
|
+
str += targetImpl.startAt.inclusive ? 'b:' : 'a:';
|
|
4672
|
+
str += targetImpl.startAt.position.map(p => canonicalId(p)).join(',');
|
|
4482
4673
|
}
|
|
4483
4674
|
if (targetImpl.endAt) {
|
|
4484
|
-
|
|
4485
|
-
|
|
4675
|
+
str += '|ub:';
|
|
4676
|
+
str += targetImpl.endAt.inclusive ? 'a:' : 'b:';
|
|
4677
|
+
str += targetImpl.endAt.position.map(p => canonicalId(p)).join(',');
|
|
4486
4678
|
}
|
|
4487
|
-
targetImpl.memoizedCanonicalId =
|
|
4679
|
+
targetImpl.memoizedCanonicalId = str;
|
|
4488
4680
|
}
|
|
4489
4681
|
return targetImpl.memoizedCanonicalId;
|
|
4490
4682
|
}
|
|
@@ -4507,10 +4699,14 @@ function stringifyTarget(target) {
|
|
|
4507
4699
|
.join(', ')}]`;
|
|
4508
4700
|
}
|
|
4509
4701
|
if (target.startAt) {
|
|
4510
|
-
str += ', startAt: '
|
|
4702
|
+
str += ', startAt: ';
|
|
4703
|
+
str += target.startAt.inclusive ? 'b:' : 'a:';
|
|
4704
|
+
str += target.startAt.position.map(p => canonicalId(p)).join(',');
|
|
4511
4705
|
}
|
|
4512
4706
|
if (target.endAt) {
|
|
4513
|
-
str += ', endAt: '
|
|
4707
|
+
str += ', endAt: ';
|
|
4708
|
+
str += target.endAt.inclusive ? 'a:' : 'b:';
|
|
4709
|
+
str += target.endAt.position.map(p => canonicalId(p)).join(',');
|
|
4514
4710
|
}
|
|
4515
4711
|
return `Target(${str})`;
|
|
4516
4712
|
}
|
|
@@ -4733,7 +4929,6 @@ class ArrayContainsAnyFilter extends FieldFilter {
|
|
|
4733
4929
|
return other.arrayValue.values.some(val => arrayValueContains(this.value.arrayValue, val));
|
|
4734
4930
|
}
|
|
4735
4931
|
}
|
|
4736
|
-
// TODO(indexing): Change Bound.before to "inclusive"
|
|
4737
4932
|
/**
|
|
4738
4933
|
* Represents a bound of a query.
|
|
4739
4934
|
*
|
|
@@ -4749,17 +4944,11 @@ class ArrayContainsAnyFilter extends FieldFilter {
|
|
|
4749
4944
|
* just after the provided values.
|
|
4750
4945
|
*/
|
|
4751
4946
|
class Bound {
|
|
4752
|
-
constructor(position,
|
|
4947
|
+
constructor(position, inclusive) {
|
|
4753
4948
|
this.position = position;
|
|
4754
|
-
this.
|
|
4949
|
+
this.inclusive = inclusive;
|
|
4755
4950
|
}
|
|
4756
4951
|
}
|
|
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
4952
|
/**
|
|
4764
4953
|
* An ordering on a field, in some Direction. Direction defaults to ASCENDING.
|
|
4765
4954
|
*/
|
|
@@ -4779,11 +4968,7 @@ function stringifyOrderBy(orderBy) {
|
|
|
4779
4968
|
function orderByEquals(left, right) {
|
|
4780
4969
|
return left.dir === right.dir && left.field.isEqual(right.field);
|
|
4781
4970
|
}
|
|
4782
|
-
|
|
4783
|
-
* Returns true if a document sorts before a bound using the provided sort
|
|
4784
|
-
* order.
|
|
4785
|
-
*/
|
|
4786
|
-
function sortsBeforeDocument(bound, orderBy, doc) {
|
|
4971
|
+
function boundCompareToDocument(bound, orderBy, doc) {
|
|
4787
4972
|
let comparison = 0;
|
|
4788
4973
|
for (let i = 0; i < bound.position.length; i++) {
|
|
4789
4974
|
const orderByComponent = orderBy[i];
|
|
@@ -4802,7 +4987,23 @@ function sortsBeforeDocument(bound, orderBy, doc) {
|
|
|
4802
4987
|
break;
|
|
4803
4988
|
}
|
|
4804
4989
|
}
|
|
4805
|
-
return
|
|
4990
|
+
return comparison;
|
|
4991
|
+
}
|
|
4992
|
+
/**
|
|
4993
|
+
* Returns true if a document sorts after a bound using the provided sort
|
|
4994
|
+
* order.
|
|
4995
|
+
*/
|
|
4996
|
+
function boundSortsAfterDocument(bound, orderBy, doc) {
|
|
4997
|
+
const comparison = boundCompareToDocument(bound, orderBy, doc);
|
|
4998
|
+
return bound.inclusive ? comparison >= 0 : comparison > 0;
|
|
4999
|
+
}
|
|
5000
|
+
/**
|
|
5001
|
+
* Returns true if a document sorts before a bound using the provided sort
|
|
5002
|
+
* order.
|
|
5003
|
+
*/
|
|
5004
|
+
function boundSortsBeforeDocument(bound, orderBy, doc) {
|
|
5005
|
+
const comparison = boundCompareToDocument(bound, orderBy, doc);
|
|
5006
|
+
return bound.inclusive ? comparison <= 0 : comparison < 0;
|
|
4806
5007
|
}
|
|
4807
5008
|
function boundEquals(left, right) {
|
|
4808
5009
|
if (left === null) {
|
|
@@ -4811,7 +5012,7 @@ function boundEquals(left, right) {
|
|
|
4811
5012
|
else if (right === null) {
|
|
4812
5013
|
return false;
|
|
4813
5014
|
}
|
|
4814
|
-
if (left.
|
|
5015
|
+
if (left.inclusive !== right.inclusive ||
|
|
4815
5016
|
left.position.length !== right.position.length) {
|
|
4816
5017
|
return false;
|
|
4817
5018
|
}
|
|
@@ -5015,10 +5216,10 @@ function queryToTarget(query) {
|
|
|
5015
5216
|
}
|
|
5016
5217
|
// We need to swap the cursors to match the now-flipped query ordering.
|
|
5017
5218
|
const startAt = queryImpl.endAt
|
|
5018
|
-
? new Bound(queryImpl.endAt.position, !queryImpl.endAt.
|
|
5219
|
+
? new Bound(queryImpl.endAt.position, !queryImpl.endAt.inclusive)
|
|
5019
5220
|
: null;
|
|
5020
5221
|
const endAt = queryImpl.startAt
|
|
5021
|
-
? new Bound(queryImpl.startAt.position, !queryImpl.startAt.
|
|
5222
|
+
? new Bound(queryImpl.startAt.position, !queryImpl.startAt.inclusive)
|
|
5022
5223
|
: null;
|
|
5023
5224
|
// Now return as a LimitType.First query.
|
|
5024
5225
|
queryImpl.memoizedTarget = newTarget(queryImpl.path, queryImpl.collectionGroup, orderBys, queryImpl.filters, queryImpl.limit, startAt, endAt);
|
|
@@ -5106,11 +5307,11 @@ function queryMatchesFilters(query, doc) {
|
|
|
5106
5307
|
/** Makes sure a document is within the bounds, if provided. */
|
|
5107
5308
|
function queryMatchesBounds(query, doc) {
|
|
5108
5309
|
if (query.startAt &&
|
|
5109
|
-
!
|
|
5310
|
+
!boundSortsBeforeDocument(query.startAt, queryOrderBy(query), doc)) {
|
|
5110
5311
|
return false;
|
|
5111
5312
|
}
|
|
5112
5313
|
if (query.endAt &&
|
|
5113
|
-
|
|
5314
|
+
!boundSortsAfterDocument(query.endAt, queryOrderBy(query), doc)) {
|
|
5114
5315
|
return false;
|
|
5115
5316
|
}
|
|
5116
5317
|
return true;
|
|
@@ -6603,6 +6804,47 @@ class MutationBatchResult {
|
|
|
6603
6804
|
}
|
|
6604
6805
|
}
|
|
6605
6806
|
|
|
6807
|
+
/**
|
|
6808
|
+
* @license
|
|
6809
|
+
* Copyright 2022 Google LLC
|
|
6810
|
+
*
|
|
6811
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6812
|
+
* you may not use this file except in compliance with the License.
|
|
6813
|
+
* You may obtain a copy of the License at
|
|
6814
|
+
*
|
|
6815
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
6816
|
+
*
|
|
6817
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
6818
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
6819
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
6820
|
+
* See the License for the specific language governing permissions and
|
|
6821
|
+
* limitations under the License.
|
|
6822
|
+
*/
|
|
6823
|
+
/**
|
|
6824
|
+
* Representation of an overlay computed by Firestore.
|
|
6825
|
+
*
|
|
6826
|
+
* Holds information about a mutation and the largest batch id in Firestore when
|
|
6827
|
+
* the mutation was created.
|
|
6828
|
+
*/
|
|
6829
|
+
class Overlay {
|
|
6830
|
+
constructor(largestBatchId, mutation) {
|
|
6831
|
+
this.largestBatchId = largestBatchId;
|
|
6832
|
+
this.mutation = mutation;
|
|
6833
|
+
}
|
|
6834
|
+
getKey() {
|
|
6835
|
+
return this.mutation.key;
|
|
6836
|
+
}
|
|
6837
|
+
isEqual(other) {
|
|
6838
|
+
return other !== null && this.mutation === other.mutation;
|
|
6839
|
+
}
|
|
6840
|
+
toString() {
|
|
6841
|
+
return `Overlay{
|
|
6842
|
+
largestBatchId: ${this.largestBatchId},
|
|
6843
|
+
mutation: ${this.mutation.toString()}
|
|
6844
|
+
}`;
|
|
6845
|
+
}
|
|
6846
|
+
}
|
|
6847
|
+
|
|
6606
6848
|
/**
|
|
6607
6849
|
* @license
|
|
6608
6850
|
* Copyright 2017 Google LLC
|
|
@@ -7989,10 +8231,10 @@ function toQueryTarget(serializer, target) {
|
|
|
7989
8231
|
result.structuredQuery.limit = limit;
|
|
7990
8232
|
}
|
|
7991
8233
|
if (target.startAt) {
|
|
7992
|
-
result.structuredQuery.startAt =
|
|
8234
|
+
result.structuredQuery.startAt = toStartAtCursor(target.startAt);
|
|
7993
8235
|
}
|
|
7994
8236
|
if (target.endAt) {
|
|
7995
|
-
result.structuredQuery.endAt =
|
|
8237
|
+
result.structuredQuery.endAt = toEndAtCursor(target.endAt);
|
|
7996
8238
|
}
|
|
7997
8239
|
return result;
|
|
7998
8240
|
}
|
|
@@ -8025,11 +8267,11 @@ function convertQueryTargetToQuery(target) {
|
|
|
8025
8267
|
}
|
|
8026
8268
|
let startAt = null;
|
|
8027
8269
|
if (query.startAt) {
|
|
8028
|
-
startAt =
|
|
8270
|
+
startAt = fromStartAtCursor(query.startAt);
|
|
8029
8271
|
}
|
|
8030
8272
|
let endAt = null;
|
|
8031
8273
|
if (query.endAt) {
|
|
8032
|
-
endAt =
|
|
8274
|
+
endAt = fromEndAtCursor(query.endAt);
|
|
8033
8275
|
}
|
|
8034
8276
|
return newQuery(path, collectionGroup, orderBy, filterBy, limit, "F" /* First */, startAt, endAt);
|
|
8035
8277
|
}
|
|
@@ -8120,16 +8362,27 @@ function toOrder(orderBys) {
|
|
|
8120
8362
|
function fromOrder(orderBys) {
|
|
8121
8363
|
return orderBys.map(order => fromPropertyOrder(order));
|
|
8122
8364
|
}
|
|
8123
|
-
function
|
|
8365
|
+
function toStartAtCursor(cursor) {
|
|
8366
|
+
return {
|
|
8367
|
+
before: cursor.inclusive,
|
|
8368
|
+
values: cursor.position
|
|
8369
|
+
};
|
|
8370
|
+
}
|
|
8371
|
+
function toEndAtCursor(cursor) {
|
|
8124
8372
|
return {
|
|
8125
|
-
before: cursor.
|
|
8373
|
+
before: !cursor.inclusive,
|
|
8126
8374
|
values: cursor.position
|
|
8127
8375
|
};
|
|
8128
8376
|
}
|
|
8129
|
-
function
|
|
8130
|
-
const
|
|
8377
|
+
function fromStartAtCursor(cursor) {
|
|
8378
|
+
const inclusive = !!cursor.before;
|
|
8131
8379
|
const position = cursor.values || [];
|
|
8132
|
-
return new Bound(position,
|
|
8380
|
+
return new Bound(position, inclusive);
|
|
8381
|
+
}
|
|
8382
|
+
function fromEndAtCursor(cursor) {
|
|
8383
|
+
const inclusive = !cursor.before;
|
|
8384
|
+
const position = cursor.values || [];
|
|
8385
|
+
return new Bound(position, inclusive);
|
|
8133
8386
|
}
|
|
8134
8387
|
// visible for testing
|
|
8135
8388
|
function toDirection(dir) {
|
|
@@ -8593,6 +8846,37 @@ function fromBundleMetadata(metadata) {
|
|
|
8593
8846
|
version: metadata.version,
|
|
8594
8847
|
createTime: fromVersion(metadata.createTime)
|
|
8595
8848
|
};
|
|
8849
|
+
}
|
|
8850
|
+
/** Encodes a DbDocumentOverlay object to an Overlay model object. */
|
|
8851
|
+
function fromDbDocumentOverlay(localSerializer, dbDocumentOverlay) {
|
|
8852
|
+
return new Overlay(dbDocumentOverlay.largestBatchId, fromMutation(localSerializer.remoteSerializer, dbDocumentOverlay.overlayMutation));
|
|
8853
|
+
}
|
|
8854
|
+
/** Decodes an Overlay model object into a DbDocumentOverlay object. */
|
|
8855
|
+
function toDbDocumentOverlay(localSerializer, userId, overlay) {
|
|
8856
|
+
const [_, collectionPath, documentId] = toDbDocumentOverlayKey(userId, overlay.mutation.key);
|
|
8857
|
+
return new DbDocumentOverlay(userId, collectionPath, documentId, overlay.mutation.key.getCollectionGroup(), overlay.largestBatchId, toMutation(localSerializer.remoteSerializer, overlay.mutation));
|
|
8858
|
+
}
|
|
8859
|
+
/**
|
|
8860
|
+
* Returns the DbDocumentOverlayKey corresponding to the given user and
|
|
8861
|
+
* document key.
|
|
8862
|
+
*/
|
|
8863
|
+
function toDbDocumentOverlayKey(userId, docKey) {
|
|
8864
|
+
const docId = docKey.path.lastSegment();
|
|
8865
|
+
const collectionPath = encodeResourcePath(docKey.path.popLast());
|
|
8866
|
+
return [userId, collectionPath, docId];
|
|
8867
|
+
}
|
|
8868
|
+
function toDbIndexConfiguration(index) {
|
|
8869
|
+
return new DbIndexConfiguration(index.indexId, index.collectionGroup, index.fields.map(s => [s.fieldPath.canonicalString(), s.kind]));
|
|
8870
|
+
}
|
|
8871
|
+
function fromDbIndexConfiguration(index, state) {
|
|
8872
|
+
const decodedState = state
|
|
8873
|
+
? new IndexState(state.sequenceNumber, new IndexOffset(fromDbTimestamp(state.readTime), new DocumentKey(decodeResourcePath(state.documentKey)), state.largestBatchId))
|
|
8874
|
+
: IndexState.empty();
|
|
8875
|
+
const decodedSegments = index.fields.map(([fieldPath, kind]) => new IndexSegment(FieldPath$1.fromServerFormat(fieldPath), kind));
|
|
8876
|
+
return new FieldIndex(index.indexId, index.collectionGroup, decodedSegments, decodedState);
|
|
8877
|
+
}
|
|
8878
|
+
function toDbIndexState(indexId, user, sequenceNumber, offset) {
|
|
8879
|
+
return new DbIndexState(indexId, user.uid || '', sequenceNumber, toDbTimestamp(offset.readTime), encodeResourcePath(offset.documentKey.path), offset.largestBatchId);
|
|
8596
8880
|
}
|
|
8597
8881
|
|
|
8598
8882
|
/**
|
|
@@ -8652,6 +8936,125 @@ function namedQueriesStore(txn) {
|
|
|
8652
8936
|
return getStore(txn, DbNamedQuery.store);
|
|
8653
8937
|
}
|
|
8654
8938
|
|
|
8939
|
+
/**
|
|
8940
|
+
* @license
|
|
8941
|
+
* Copyright 2022 Google LLC
|
|
8942
|
+
*
|
|
8943
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
8944
|
+
* you may not use this file except in compliance with the License.
|
|
8945
|
+
* You may obtain a copy of the License at
|
|
8946
|
+
*
|
|
8947
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
8948
|
+
*
|
|
8949
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
8950
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
8951
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
8952
|
+
* See the License for the specific language governing permissions and
|
|
8953
|
+
* limitations under the License.
|
|
8954
|
+
*/
|
|
8955
|
+
/**
|
|
8956
|
+
* Implementation of DocumentOverlayCache using IndexedDb.
|
|
8957
|
+
*/
|
|
8958
|
+
class IndexedDbDocumentOverlayCache {
|
|
8959
|
+
/**
|
|
8960
|
+
* @param serializer - The document serializer.
|
|
8961
|
+
* @param userId - The userId for which we are accessing overlays.
|
|
8962
|
+
*/
|
|
8963
|
+
constructor(serializer, userId) {
|
|
8964
|
+
this.serializer = serializer;
|
|
8965
|
+
this.userId = userId;
|
|
8966
|
+
}
|
|
8967
|
+
static forUser(serializer, user) {
|
|
8968
|
+
const userId = user.uid || '';
|
|
8969
|
+
return new IndexedDbDocumentOverlayCache(serializer, userId);
|
|
8970
|
+
}
|
|
8971
|
+
getOverlay(transaction, key) {
|
|
8972
|
+
return documentOverlayStore(transaction)
|
|
8973
|
+
.get(toDbDocumentOverlayKey(this.userId, key))
|
|
8974
|
+
.next(dbOverlay => {
|
|
8975
|
+
if (dbOverlay) {
|
|
8976
|
+
return fromDbDocumentOverlay(this.serializer, dbOverlay);
|
|
8977
|
+
}
|
|
8978
|
+
return null;
|
|
8979
|
+
});
|
|
8980
|
+
}
|
|
8981
|
+
saveOverlays(transaction, largestBatchId, overlays) {
|
|
8982
|
+
const promises = [];
|
|
8983
|
+
overlays.forEach(mutation => {
|
|
8984
|
+
const overlay = new Overlay(largestBatchId, mutation);
|
|
8985
|
+
promises.push(this.saveOverlay(transaction, overlay));
|
|
8986
|
+
});
|
|
8987
|
+
return PersistencePromise.waitFor(promises);
|
|
8988
|
+
}
|
|
8989
|
+
removeOverlaysForBatchId(transaction, documentKeys, batchId) {
|
|
8990
|
+
const collectionPaths = new Set();
|
|
8991
|
+
// Get the set of unique collection paths.
|
|
8992
|
+
documentKeys.forEach(key => collectionPaths.add(encodeResourcePath(key.getCollectionPath())));
|
|
8993
|
+
const promises = [];
|
|
8994
|
+
collectionPaths.forEach(collectionPath => {
|
|
8995
|
+
const range = IDBKeyRange.bound([this.userId, collectionPath, batchId], [this.userId, collectionPath, batchId + 1],
|
|
8996
|
+
/*lowerOpen=*/ false,
|
|
8997
|
+
/*upperOpen=*/ true);
|
|
8998
|
+
promises.push(documentOverlayStore(transaction).deleteAll(DbDocumentOverlay.collectionPathOverlayIndex, range));
|
|
8999
|
+
});
|
|
9000
|
+
return PersistencePromise.waitFor(promises);
|
|
9001
|
+
}
|
|
9002
|
+
getOverlaysForCollection(transaction, collection, sinceBatchId) {
|
|
9003
|
+
const result = new Map();
|
|
9004
|
+
const collectionPath = encodeResourcePath(collection);
|
|
9005
|
+
// We want batch IDs larger than `sinceBatchId`, and so the lower bound
|
|
9006
|
+
// is not inclusive.
|
|
9007
|
+
const range = IDBKeyRange.bound([this.userId, collectionPath, sinceBatchId], [this.userId, collectionPath, Number.POSITIVE_INFINITY],
|
|
9008
|
+
/*lowerOpen=*/ true);
|
|
9009
|
+
return documentOverlayStore(transaction)
|
|
9010
|
+
.loadAll(DbDocumentOverlay.collectionPathOverlayIndex, range)
|
|
9011
|
+
.next(dbOverlays => {
|
|
9012
|
+
for (const dbOverlay of dbOverlays) {
|
|
9013
|
+
const overlay = fromDbDocumentOverlay(this.serializer, dbOverlay);
|
|
9014
|
+
result.set(overlay.getKey(), overlay);
|
|
9015
|
+
}
|
|
9016
|
+
return result;
|
|
9017
|
+
});
|
|
9018
|
+
}
|
|
9019
|
+
getOverlaysForCollectionGroup(transaction, collectionGroup, sinceBatchId, count) {
|
|
9020
|
+
const result = new Map();
|
|
9021
|
+
let currentBatchId = undefined;
|
|
9022
|
+
// We want batch IDs larger than `sinceBatchId`, and so the lower bound
|
|
9023
|
+
// is not inclusive.
|
|
9024
|
+
const range = IDBKeyRange.bound([this.userId, collectionGroup, sinceBatchId], [this.userId, collectionGroup, Number.POSITIVE_INFINITY],
|
|
9025
|
+
/*lowerOpen=*/ true);
|
|
9026
|
+
return documentOverlayStore(transaction)
|
|
9027
|
+
.iterate({
|
|
9028
|
+
index: DbDocumentOverlay.collectionGroupOverlayIndex,
|
|
9029
|
+
range
|
|
9030
|
+
}, (_, dbOverlay, control) => {
|
|
9031
|
+
// We do not want to return partial batch overlays, even if the size
|
|
9032
|
+
// of the result set exceeds the given `count` argument. Therefore, we
|
|
9033
|
+
// continue to aggregate results even after the result size exceeds
|
|
9034
|
+
// `count` if there are more overlays from the `currentBatchId`.
|
|
9035
|
+
const overlay = fromDbDocumentOverlay(this.serializer, dbOverlay);
|
|
9036
|
+
if (result.size < count ||
|
|
9037
|
+
overlay.largestBatchId === currentBatchId) {
|
|
9038
|
+
result.set(overlay.getKey(), overlay);
|
|
9039
|
+
currentBatchId = overlay.largestBatchId;
|
|
9040
|
+
}
|
|
9041
|
+
else {
|
|
9042
|
+
control.done();
|
|
9043
|
+
}
|
|
9044
|
+
})
|
|
9045
|
+
.next(() => result);
|
|
9046
|
+
}
|
|
9047
|
+
saveOverlay(transaction, overlay) {
|
|
9048
|
+
return documentOverlayStore(transaction).put(toDbDocumentOverlay(this.serializer, this.userId, overlay));
|
|
9049
|
+
}
|
|
9050
|
+
}
|
|
9051
|
+
/**
|
|
9052
|
+
* Helper to get a typed SimpleDbStore for the document overlay object store.
|
|
9053
|
+
*/
|
|
9054
|
+
function documentOverlayStore(txn) {
|
|
9055
|
+
return getStore(txn, DbDocumentOverlay.store);
|
|
9056
|
+
}
|
|
9057
|
+
|
|
8655
9058
|
/**
|
|
8656
9059
|
* @license
|
|
8657
9060
|
* Copyright 2019 Google LLC
|
|
@@ -8682,6 +9085,38 @@ class MemoryIndexManager {
|
|
|
8682
9085
|
getCollectionParents(transaction, collectionId) {
|
|
8683
9086
|
return PersistencePromise.resolve(this.collectionParentIndex.getEntries(collectionId));
|
|
8684
9087
|
}
|
|
9088
|
+
addFieldIndex(transaction, index) {
|
|
9089
|
+
// Field indices are not supported with memory persistence.
|
|
9090
|
+
return PersistencePromise.resolve();
|
|
9091
|
+
}
|
|
9092
|
+
deleteFieldIndex(transaction, index) {
|
|
9093
|
+
// Field indices are not supported with memory persistence.
|
|
9094
|
+
return PersistencePromise.resolve();
|
|
9095
|
+
}
|
|
9096
|
+
getDocumentsMatchingTarget(transaction, fieldIndex, target) {
|
|
9097
|
+
// Field indices are not supported with memory persistence.
|
|
9098
|
+
return PersistencePromise.resolve(documentKeySet());
|
|
9099
|
+
}
|
|
9100
|
+
getFieldIndex(transaction, target) {
|
|
9101
|
+
// Field indices are not supported with memory persistence.
|
|
9102
|
+
return PersistencePromise.resolve(null);
|
|
9103
|
+
}
|
|
9104
|
+
getFieldIndexes(transaction, collectionGroup) {
|
|
9105
|
+
// Field indices are not supported with memory persistence.
|
|
9106
|
+
return PersistencePromise.resolve([]);
|
|
9107
|
+
}
|
|
9108
|
+
getNextCollectionGroupToUpdate(transaction) {
|
|
9109
|
+
// Field indices are not supported with memory persistence.
|
|
9110
|
+
return PersistencePromise.resolve(null);
|
|
9111
|
+
}
|
|
9112
|
+
updateCollectionGroup(transaction, collectionGroup, offset) {
|
|
9113
|
+
// Field indices are not supported with memory persistence.
|
|
9114
|
+
return PersistencePromise.resolve();
|
|
9115
|
+
}
|
|
9116
|
+
updateIndexEntries(transaction, documents) {
|
|
9117
|
+
// Field indices are not supported with memory persistence.
|
|
9118
|
+
return PersistencePromise.resolve();
|
|
9119
|
+
}
|
|
8685
9120
|
}
|
|
8686
9121
|
/**
|
|
8687
9122
|
* Internal implementation of the collection-parent index exposed by MemoryIndexManager.
|
|
@@ -8733,17 +9168,22 @@ class MemoryCollectionParentIndex {
|
|
|
8733
9168
|
*/
|
|
8734
9169
|
/**
|
|
8735
9170
|
* A persisted implementation of IndexManager.
|
|
9171
|
+
*
|
|
9172
|
+
* PORTING NOTE: Unlike iOS and Android, the Web SDK does not memoize index
|
|
9173
|
+
* data as it supports multi-tab access.
|
|
8736
9174
|
*/
|
|
8737
9175
|
class IndexedDbIndexManager {
|
|
8738
|
-
constructor() {
|
|
9176
|
+
constructor(user) {
|
|
9177
|
+
this.user = user;
|
|
8739
9178
|
/**
|
|
8740
9179
|
* An in-memory copy of the index entries we've already written since the SDK
|
|
8741
9180
|
* launched. Used to avoid re-writing the same entry repeatedly.
|
|
8742
9181
|
*
|
|
8743
|
-
* This is *NOT* a complete cache of what's in persistence and so can never be
|
|
8744
|
-
* satisfy reads.
|
|
9182
|
+
* This is *NOT* a complete cache of what's in persistence and so can never be
|
|
9183
|
+
* used to satisfy reads.
|
|
8745
9184
|
*/
|
|
8746
9185
|
this.collectionParentsCache = new MemoryCollectionParentIndex();
|
|
9186
|
+
this.uid = user.uid || '';
|
|
8747
9187
|
}
|
|
8748
9188
|
/**
|
|
8749
9189
|
* Adds a new entry to the collection parent index.
|
|
@@ -8790,6 +9230,85 @@ class IndexedDbIndexManager {
|
|
|
8790
9230
|
return parentPaths;
|
|
8791
9231
|
});
|
|
8792
9232
|
}
|
|
9233
|
+
addFieldIndex(transaction, index) {
|
|
9234
|
+
// TODO(indexing): Verify that the auto-incrementing index ID works in
|
|
9235
|
+
// Safari & Firefox.
|
|
9236
|
+
const indexes = indexConfigurationStore(transaction);
|
|
9237
|
+
const dbIndex = toDbIndexConfiguration(index);
|
|
9238
|
+
delete dbIndex.indexId; // `indexId` is auto-populated by IndexedDb
|
|
9239
|
+
return indexes.add(dbIndex).next();
|
|
9240
|
+
}
|
|
9241
|
+
deleteFieldIndex(transaction, index) {
|
|
9242
|
+
const indexes = indexConfigurationStore(transaction);
|
|
9243
|
+
const states = indexStateStore(transaction);
|
|
9244
|
+
const entries = indexEntriesStore(transaction);
|
|
9245
|
+
return indexes
|
|
9246
|
+
.delete(index.indexId)
|
|
9247
|
+
.next(() => states.delete(IDBKeyRange.bound([index.indexId], [index.indexId + 1],
|
|
9248
|
+
/*lowerOpen=*/ false,
|
|
9249
|
+
/*upperOpen=*/ true)))
|
|
9250
|
+
.next(() => entries.delete(IDBKeyRange.bound([index.indexId], [index.indexId + 1],
|
|
9251
|
+
/*lowerOpen=*/ false,
|
|
9252
|
+
/*upperOpen=*/ true)));
|
|
9253
|
+
}
|
|
9254
|
+
getDocumentsMatchingTarget(transaction, fieldIndex, target) {
|
|
9255
|
+
// TODO(indexing): Implement
|
|
9256
|
+
return PersistencePromise.resolve(documentKeySet());
|
|
9257
|
+
}
|
|
9258
|
+
getFieldIndex(transaction, target) {
|
|
9259
|
+
// TODO(indexing): Implement
|
|
9260
|
+
return PersistencePromise.resolve(null);
|
|
9261
|
+
}
|
|
9262
|
+
getFieldIndexes(transaction, collectionGroup) {
|
|
9263
|
+
const indexes = indexConfigurationStore(transaction);
|
|
9264
|
+
const states = indexStateStore(transaction);
|
|
9265
|
+
return (collectionGroup
|
|
9266
|
+
? indexes.loadAll(DbIndexConfiguration.collectionGroupIndex, IDBKeyRange.bound(collectionGroup, collectionGroup))
|
|
9267
|
+
: indexes.loadAll()).next(indexConfigs => {
|
|
9268
|
+
const result = [];
|
|
9269
|
+
return PersistencePromise.forEach(indexConfigs, (indexConfig) => {
|
|
9270
|
+
return states
|
|
9271
|
+
.get([indexConfig.indexId, this.uid])
|
|
9272
|
+
.next(indexState => {
|
|
9273
|
+
result.push(fromDbIndexConfiguration(indexConfig, indexState));
|
|
9274
|
+
});
|
|
9275
|
+
}).next(() => result);
|
|
9276
|
+
});
|
|
9277
|
+
}
|
|
9278
|
+
getNextCollectionGroupToUpdate(transaction) {
|
|
9279
|
+
return this.getFieldIndexes(transaction).next(indexes => {
|
|
9280
|
+
if (indexes.length === 0) {
|
|
9281
|
+
return null;
|
|
9282
|
+
}
|
|
9283
|
+
indexes.sort((l, r) => l.indexState.sequenceNumber - r.indexState.sequenceNumber);
|
|
9284
|
+
return indexes[0].collectionGroup;
|
|
9285
|
+
});
|
|
9286
|
+
}
|
|
9287
|
+
updateCollectionGroup(transaction, collectionGroup, offset) {
|
|
9288
|
+
const indexes = indexConfigurationStore(transaction);
|
|
9289
|
+
const states = indexStateStore(transaction);
|
|
9290
|
+
return this.getNextSequenceNumber(transaction).next(nextSequenceNumber => indexes
|
|
9291
|
+
.loadAll(DbIndexConfiguration.collectionGroupIndex, IDBKeyRange.bound(collectionGroup, collectionGroup))
|
|
9292
|
+
.next(configs => PersistencePromise.forEach(configs, (config) => states.put(toDbIndexState(config.indexId, this.user, nextSequenceNumber, offset)))));
|
|
9293
|
+
}
|
|
9294
|
+
updateIndexEntries(transaction, documents) {
|
|
9295
|
+
// TODO(indexing): Implement
|
|
9296
|
+
return PersistencePromise.resolve();
|
|
9297
|
+
}
|
|
9298
|
+
getNextSequenceNumber(transaction) {
|
|
9299
|
+
let nextSequenceNumber = 1;
|
|
9300
|
+
const states = indexStateStore(transaction);
|
|
9301
|
+
return states
|
|
9302
|
+
.iterate({
|
|
9303
|
+
index: DbIndexState.sequenceNumberIndex,
|
|
9304
|
+
reverse: true,
|
|
9305
|
+
range: IDBKeyRange.upperBound([this.uid, Number.MAX_SAFE_INTEGER])
|
|
9306
|
+
}, (_, state, controller) => {
|
|
9307
|
+
controller.done();
|
|
9308
|
+
nextSequenceNumber = state.sequenceNumber + 1;
|
|
9309
|
+
})
|
|
9310
|
+
.next(() => nextSequenceNumber);
|
|
9311
|
+
}
|
|
8793
9312
|
}
|
|
8794
9313
|
/**
|
|
8795
9314
|
* Helper to get a typed SimpleDbStore for the collectionParents
|
|
@@ -8797,6 +9316,24 @@ class IndexedDbIndexManager {
|
|
|
8797
9316
|
*/
|
|
8798
9317
|
function collectionParentsStore(txn) {
|
|
8799
9318
|
return getStore(txn, DbCollectionParent.store);
|
|
9319
|
+
}
|
|
9320
|
+
/**
|
|
9321
|
+
* Helper to get a typed SimpleDbStore for the index entry object store.
|
|
9322
|
+
*/
|
|
9323
|
+
function indexEntriesStore(txn) {
|
|
9324
|
+
return getStore(txn, DbIndexEntry.store);
|
|
9325
|
+
}
|
|
9326
|
+
/**
|
|
9327
|
+
* Helper to get a typed SimpleDbStore for the index configuration object store.
|
|
9328
|
+
*/
|
|
9329
|
+
function indexConfigurationStore(txn) {
|
|
9330
|
+
return getStore(txn, DbIndexConfiguration.store);
|
|
9331
|
+
}
|
|
9332
|
+
/**
|
|
9333
|
+
* Helper to get a typed SimpleDbStore for the index state object store.
|
|
9334
|
+
*/
|
|
9335
|
+
function indexStateStore(txn) {
|
|
9336
|
+
return getStore(txn, DbIndexState.store);
|
|
8800
9337
|
}
|
|
8801
9338
|
|
|
8802
9339
|
/**
|
|
@@ -10266,12 +10803,10 @@ class RemoteDocumentChangeBuffer {
|
|
|
10266
10803
|
* `newIndexedDbRemoteDocumentCache()`.
|
|
10267
10804
|
*/
|
|
10268
10805
|
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) {
|
|
10806
|
+
constructor(serializer) {
|
|
10274
10807
|
this.serializer = serializer;
|
|
10808
|
+
}
|
|
10809
|
+
setIndexManager(indexManager) {
|
|
10275
10810
|
this.indexManager = indexManager;
|
|
10276
10811
|
}
|
|
10277
10812
|
/**
|
|
@@ -10393,21 +10928,21 @@ class IndexedDbRemoteDocumentCacheImpl {
|
|
|
10393
10928
|
}
|
|
10394
10929
|
});
|
|
10395
10930
|
}
|
|
10396
|
-
|
|
10931
|
+
getAll(transaction, collection, sinceReadTime) {
|
|
10397
10932
|
let results = mutableDocumentMap();
|
|
10398
|
-
const immediateChildrenPathLength =
|
|
10933
|
+
const immediateChildrenPathLength = collection.length + 1;
|
|
10399
10934
|
const iterationOptions = {};
|
|
10400
10935
|
if (sinceReadTime.isEqual(SnapshotVersion.min())) {
|
|
10401
10936
|
// Documents are ordered by key, so we can use a prefix scan to narrow
|
|
10402
10937
|
// down the documents we need to match the query against.
|
|
10403
|
-
const startKey =
|
|
10938
|
+
const startKey = collection.toArray();
|
|
10404
10939
|
iterationOptions.range = IDBKeyRange.lowerBound(startKey);
|
|
10405
10940
|
}
|
|
10406
10941
|
else {
|
|
10407
10942
|
// Execute an index-free query and filter by read time. This is safe
|
|
10408
10943
|
// since all document changes to queries that have a
|
|
10409
10944
|
// lastLimboFreeSnapshotVersion (`sinceReadTime`) have a read time set.
|
|
10410
|
-
const collectionKey =
|
|
10945
|
+
const collectionKey = collection.toArray();
|
|
10411
10946
|
const readTimeKey = toDbTimestampKey(sinceReadTime);
|
|
10412
10947
|
iterationOptions.range = IDBKeyRange.lowerBound([collectionKey, readTimeKey],
|
|
10413
10948
|
/* open= */ true);
|
|
@@ -10424,12 +10959,12 @@ class IndexedDbRemoteDocumentCacheImpl {
|
|
|
10424
10959
|
return;
|
|
10425
10960
|
}
|
|
10426
10961
|
const document = this.maybeDecodeDocument(DocumentKey.fromSegments(key), dbRemoteDoc);
|
|
10427
|
-
if (
|
|
10428
|
-
control.done();
|
|
10429
|
-
}
|
|
10430
|
-
else if (queryMatches(query, document)) {
|
|
10962
|
+
if (collection.isPrefixOf(document.key.path)) {
|
|
10431
10963
|
results = results.insert(document.key, document);
|
|
10432
10964
|
}
|
|
10965
|
+
else {
|
|
10966
|
+
control.done();
|
|
10967
|
+
}
|
|
10433
10968
|
})
|
|
10434
10969
|
.next(() => results);
|
|
10435
10970
|
}
|
|
@@ -10467,14 +11002,9 @@ class IndexedDbRemoteDocumentCacheImpl {
|
|
|
10467
11002
|
return MutableDocument.newInvalidDocument(documentKey);
|
|
10468
11003
|
}
|
|
10469
11004
|
}
|
|
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);
|
|
11005
|
+
/** Creates a new IndexedDbRemoteDocumentCache. */
|
|
11006
|
+
function newIndexedDbRemoteDocumentCache(serializer) {
|
|
11007
|
+
return new IndexedDbRemoteDocumentCacheImpl(serializer);
|
|
10478
11008
|
}
|
|
10479
11009
|
/**
|
|
10480
11010
|
* Returns the set of documents that have changed since the specified read
|
|
@@ -10641,9 +11171,6 @@ class SchemaConverter {
|
|
|
10641
11171
|
* and local feature development.
|
|
10642
11172
|
*/
|
|
10643
11173
|
createOrUpgrade(db, txn, fromVersion, toVersion) {
|
|
10644
|
-
hardAssert(fromVersion < toVersion &&
|
|
10645
|
-
fromVersion >= 0 &&
|
|
10646
|
-
toVersion <= SCHEMA_VERSION);
|
|
10647
11174
|
const simpleDbTransaction = new SimpleDbTransaction('createOrUpgrade', txn);
|
|
10648
11175
|
if (fromVersion < 1 && toVersion >= 1) {
|
|
10649
11176
|
createPrimaryClientStore(db);
|
|
@@ -10710,6 +11237,16 @@ class SchemaConverter {
|
|
|
10710
11237
|
createNamedQueriesStore(db);
|
|
10711
11238
|
});
|
|
10712
11239
|
}
|
|
11240
|
+
if (fromVersion < 12 && toVersion >= 12) {
|
|
11241
|
+
p = p.next(() => {
|
|
11242
|
+
createDocumentOverlayStore(db);
|
|
11243
|
+
});
|
|
11244
|
+
}
|
|
11245
|
+
if (fromVersion < 13 && toVersion >= 13) {
|
|
11246
|
+
p = p.next(() => {
|
|
11247
|
+
createFieldIndex(db);
|
|
11248
|
+
});
|
|
11249
|
+
}
|
|
10713
11250
|
return p;
|
|
10714
11251
|
}
|
|
10715
11252
|
addDocumentGlobal(txn) {
|
|
@@ -10916,6 +11453,27 @@ function createNamedQueriesStore(db) {
|
|
|
10916
11453
|
db.createObjectStore(DbNamedQuery.store, {
|
|
10917
11454
|
keyPath: DbNamedQuery.keyPath
|
|
10918
11455
|
});
|
|
11456
|
+
}
|
|
11457
|
+
function createFieldIndex(db) {
|
|
11458
|
+
const indexConfiguratioStore = db.createObjectStore(DbIndexConfiguration.store, {
|
|
11459
|
+
keyPath: DbIndexConfiguration.keyPath,
|
|
11460
|
+
autoIncrement: true
|
|
11461
|
+
});
|
|
11462
|
+
indexConfiguratioStore.createIndex(DbIndexConfiguration.collectionGroupIndex, DbIndexConfiguration.collectionGroupIndexPath, { unique: false });
|
|
11463
|
+
const indexStateStore = db.createObjectStore(DbIndexState.store, {
|
|
11464
|
+
keyPath: DbIndexState.keyPath
|
|
11465
|
+
});
|
|
11466
|
+
indexStateStore.createIndex(DbIndexState.sequenceNumberIndex, DbIndexState.sequenceNumberIndexPath, { unique: false });
|
|
11467
|
+
db.createObjectStore(DbIndexEntry.store, {
|
|
11468
|
+
keyPath: DbIndexEntry.keyPath
|
|
11469
|
+
});
|
|
11470
|
+
}
|
|
11471
|
+
function createDocumentOverlayStore(db) {
|
|
11472
|
+
const documentOverlayStore = db.createObjectStore(DbDocumentOverlay.store, {
|
|
11473
|
+
keyPath: DbDocumentOverlay.keyPath
|
|
11474
|
+
});
|
|
11475
|
+
documentOverlayStore.createIndex(DbDocumentOverlay.collectionPathOverlayIndex, DbDocumentOverlay.collectionPathOverlayIndexPath, { unique: false });
|
|
11476
|
+
documentOverlayStore.createIndex(DbDocumentOverlay.collectionGroupOverlayIndex, DbDocumentOverlay.collectionGroupOverlayIndexPath, { unique: false });
|
|
10919
11477
|
}
|
|
10920
11478
|
|
|
10921
11479
|
/**
|
|
@@ -11027,7 +11585,7 @@ class IndexedDbPersistence {
|
|
|
11027
11585
|
* If set to true, forcefully obtains database access. Existing tabs will
|
|
11028
11586
|
* no longer be able to access IndexedDB.
|
|
11029
11587
|
*/
|
|
11030
|
-
forceOwningTab) {
|
|
11588
|
+
forceOwningTab, schemaVersion = SCHEMA_VERSION) {
|
|
11031
11589
|
this.allowTabSynchronization = allowTabSynchronization;
|
|
11032
11590
|
this.persistenceKey = persistenceKey;
|
|
11033
11591
|
this.clientId = clientId;
|
|
@@ -11036,6 +11594,7 @@ class IndexedDbPersistence {
|
|
|
11036
11594
|
this.document = document;
|
|
11037
11595
|
this.sequenceNumberSyncer = sequenceNumberSyncer;
|
|
11038
11596
|
this.forceOwningTab = forceOwningTab;
|
|
11597
|
+
this.schemaVersion = schemaVersion;
|
|
11039
11598
|
this.listenSequence = null;
|
|
11040
11599
|
this._started = false;
|
|
11041
11600
|
this.isPrimary = false;
|
|
@@ -11057,10 +11616,9 @@ class IndexedDbPersistence {
|
|
|
11057
11616
|
this.referenceDelegate = new IndexedDbLruDelegateImpl(this, lruParams);
|
|
11058
11617
|
this.dbName = persistenceKey + MAIN_DATABASE;
|
|
11059
11618
|
this.serializer = new LocalSerializer(serializer);
|
|
11060
|
-
this.simpleDb = new SimpleDb(this.dbName,
|
|
11619
|
+
this.simpleDb = new SimpleDb(this.dbName, this.schemaVersion, new SchemaConverter(this.serializer));
|
|
11061
11620
|
this.targetCache = new IndexedDbTargetCache(this.referenceDelegate, this.serializer);
|
|
11062
|
-
this.
|
|
11063
|
-
this.remoteDocumentCache = newIndexedDbRemoteDocumentCache(this.serializer, this.indexManager);
|
|
11621
|
+
this.remoteDocumentCache = newIndexedDbRemoteDocumentCache(this.serializer);
|
|
11064
11622
|
this.bundleCache = new IndexedDbBundleCache();
|
|
11065
11623
|
if (this.window && this.window.localStorage) {
|
|
11066
11624
|
this.webStorage = this.window.localStorage;
|
|
@@ -11396,8 +11954,8 @@ class IndexedDbPersistence {
|
|
|
11396
11954
|
get started() {
|
|
11397
11955
|
return this._started;
|
|
11398
11956
|
}
|
|
11399
|
-
getMutationQueue(user) {
|
|
11400
|
-
return IndexedDbMutationQueue.forUser(user, this.serializer,
|
|
11957
|
+
getMutationQueue(user, indexManager) {
|
|
11958
|
+
return IndexedDbMutationQueue.forUser(user, this.serializer, indexManager, this.referenceDelegate);
|
|
11401
11959
|
}
|
|
11402
11960
|
getTargetCache() {
|
|
11403
11961
|
return this.targetCache;
|
|
@@ -11405,8 +11963,11 @@ class IndexedDbPersistence {
|
|
|
11405
11963
|
getRemoteDocumentCache() {
|
|
11406
11964
|
return this.remoteDocumentCache;
|
|
11407
11965
|
}
|
|
11408
|
-
getIndexManager() {
|
|
11409
|
-
return
|
|
11966
|
+
getIndexManager(user) {
|
|
11967
|
+
return new IndexedDbIndexManager(user);
|
|
11968
|
+
}
|
|
11969
|
+
getDocumentOverlayCache(user) {
|
|
11970
|
+
return IndexedDbDocumentOverlayCache.forUser(this.serializer, user);
|
|
11410
11971
|
}
|
|
11411
11972
|
getBundleCache() {
|
|
11412
11973
|
return this.bundleCache;
|
|
@@ -11414,11 +11975,12 @@ class IndexedDbPersistence {
|
|
|
11414
11975
|
runTransaction(action, mode, transactionOperation) {
|
|
11415
11976
|
logDebug(LOG_TAG$d, 'Starting transaction:', action);
|
|
11416
11977
|
const simpleDbMode = mode === 'readonly' ? 'readonly' : 'readwrite';
|
|
11978
|
+
const objectStores = getObjectStores(this.schemaVersion);
|
|
11417
11979
|
let persistenceTransaction;
|
|
11418
11980
|
// Do all transactions as readwrite against all object stores, since we
|
|
11419
11981
|
// are the only reader/writer.
|
|
11420
11982
|
return this.simpleDb
|
|
11421
|
-
.runTransaction(action, simpleDbMode,
|
|
11983
|
+
.runTransaction(action, simpleDbMode, objectStores, simpleDbTxn => {
|
|
11422
11984
|
persistenceTransaction = new IndexedDbTransaction(simpleDbTxn, this.listenSequence
|
|
11423
11985
|
? this.listenSequence.next()
|
|
11424
11986
|
: ListenSequence.INVALID);
|
|
@@ -11790,39 +12352,28 @@ class LocalDocumentsView {
|
|
|
11790
12352
|
getDocumentsMatchingCollectionQuery(transaction, query, sinceReadTime) {
|
|
11791
12353
|
// Query the remote documents and overlay mutations.
|
|
11792
12354
|
let results;
|
|
11793
|
-
let mutationBatches;
|
|
11794
12355
|
return this.remoteDocumentCache
|
|
11795
|
-
.
|
|
12356
|
+
.getAll(transaction, query.path, sinceReadTime)
|
|
11796
12357
|
.next(queryResults => {
|
|
11797
12358
|
results = queryResults;
|
|
11798
12359
|
return this.mutationQueue.getAllMutationBatchesAffectingQuery(transaction, query);
|
|
11799
12360
|
})
|
|
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
|
-
}
|
|
12361
|
+
.next(mutationBatches => {
|
|
12362
|
+
for (const batch of mutationBatches) {
|
|
12363
|
+
for (const mutation of batch.mutations) {
|
|
12364
|
+
const key = mutation.key;
|
|
12365
|
+
let document = results.get(key);
|
|
12366
|
+
if (document == null) {
|
|
12367
|
+
// Create invalid document to apply mutations on top of
|
|
12368
|
+
document = MutableDocument.newInvalidDocument(key);
|
|
12369
|
+
results = results.insert(key, document);
|
|
12370
|
+
}
|
|
12371
|
+
mutationApplyToLocalView(mutation, document, batch.localWriteTime);
|
|
12372
|
+
if (!document.isFoundDocument()) {
|
|
12373
|
+
results = results.remove(key);
|
|
11823
12374
|
}
|
|
11824
12375
|
}
|
|
11825
|
-
}
|
|
12376
|
+
}
|
|
11826
12377
|
})
|
|
11827
12378
|
.next(() => {
|
|
11828
12379
|
// Finally, filter out any documents that don't actually match
|
|
@@ -11835,29 +12386,6 @@ class LocalDocumentsView {
|
|
|
11835
12386
|
return results;
|
|
11836
12387
|
});
|
|
11837
12388
|
}
|
|
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
12389
|
}
|
|
11862
12390
|
|
|
11863
12391
|
/**
|
|
@@ -11916,11 +12444,18 @@ class LocalStoreImpl {
|
|
|
11916
12444
|
* PORTING NOTE: This is only used for multi-tab synchronization.
|
|
11917
12445
|
*/
|
|
11918
12446
|
this.lastDocumentChangeReadTime = SnapshotVersion.min();
|
|
11919
|
-
this.mutationQueue = persistence.getMutationQueue(initialUser);
|
|
11920
12447
|
this.remoteDocuments = persistence.getRemoteDocumentCache();
|
|
11921
12448
|
this.targetCache = persistence.getTargetCache();
|
|
11922
|
-
this.localDocuments = new LocalDocumentsView(this.remoteDocuments, this.mutationQueue, this.persistence.getIndexManager());
|
|
11923
12449
|
this.bundleCache = persistence.getBundleCache();
|
|
12450
|
+
this.initializeUserComponents(initialUser);
|
|
12451
|
+
}
|
|
12452
|
+
initializeUserComponents(user) {
|
|
12453
|
+
// TODO(indexing): Add spec tests that test these components change after a
|
|
12454
|
+
// user change
|
|
12455
|
+
this.indexManager = this.persistence.getIndexManager(user);
|
|
12456
|
+
this.mutationQueue = this.persistence.getMutationQueue(user, this.indexManager);
|
|
12457
|
+
this.localDocuments = new LocalDocumentsView(this.remoteDocuments, this.mutationQueue, this.indexManager);
|
|
12458
|
+
this.remoteDocuments.setIndexManager(this.indexManager);
|
|
11924
12459
|
this.queryEngine.setLocalDocumentsView(this.localDocuments);
|
|
11925
12460
|
}
|
|
11926
12461
|
collectGarbage(garbageCollector) {
|
|
@@ -11942,8 +12477,6 @@ persistence, queryEngine, initialUser, serializer) {
|
|
|
11942
12477
|
// change.
|
|
11943
12478
|
async function localStoreHandleUserChange(localStore, user) {
|
|
11944
12479
|
const localStoreImpl = debugCast(localStore);
|
|
11945
|
-
let newMutationQueue = localStoreImpl.mutationQueue;
|
|
11946
|
-
let newLocalDocuments = localStoreImpl.localDocuments;
|
|
11947
12480
|
const result = await localStoreImpl.persistence.runTransaction('Handle user change', 'readonly', txn => {
|
|
11948
12481
|
// Swap out the mutation queue, grabbing the pending mutation batches
|
|
11949
12482
|
// before and after.
|
|
@@ -11952,11 +12485,8 @@ async function localStoreHandleUserChange(localStore, user) {
|
|
|
11952
12485
|
.getAllMutationBatches(txn)
|
|
11953
12486
|
.next(promisedOldBatches => {
|
|
11954
12487
|
oldBatches = promisedOldBatches;
|
|
11955
|
-
|
|
11956
|
-
|
|
11957
|
-
// MutationQueue.
|
|
11958
|
-
newLocalDocuments = new LocalDocumentsView(localStoreImpl.remoteDocuments, newMutationQueue, localStoreImpl.persistence.getIndexManager());
|
|
11959
|
-
return newMutationQueue.getAllMutationBatches(txn);
|
|
12488
|
+
localStoreImpl.initializeUserComponents(user);
|
|
12489
|
+
return localStoreImpl.mutationQueue.getAllMutationBatches(txn);
|
|
11960
12490
|
})
|
|
11961
12491
|
.next(newBatches => {
|
|
11962
12492
|
const removedBatchIds = [];
|
|
@@ -11977,7 +12507,7 @@ async function localStoreHandleUserChange(localStore, user) {
|
|
|
11977
12507
|
}
|
|
11978
12508
|
// Return the set of all (potentially) changed documents and the list
|
|
11979
12509
|
// of mutation batch IDs that were affected by change.
|
|
11980
|
-
return
|
|
12510
|
+
return localStoreImpl.localDocuments
|
|
11981
12511
|
.getDocuments(txn, changedKeys)
|
|
11982
12512
|
.next(affectedDocuments => {
|
|
11983
12513
|
return {
|
|
@@ -11988,9 +12518,6 @@ async function localStoreHandleUserChange(localStore, user) {
|
|
|
11988
12518
|
});
|
|
11989
12519
|
});
|
|
11990
12520
|
});
|
|
11991
|
-
localStoreImpl.mutationQueue = newMutationQueue;
|
|
11992
|
-
localStoreImpl.localDocuments = newLocalDocuments;
|
|
11993
|
-
localStoreImpl.queryEngine.setLocalDocumentsView(localStoreImpl.localDocuments);
|
|
11994
12521
|
return result;
|
|
11995
12522
|
}
|
|
11996
12523
|
/* Accepts locally generated Mutations and commit them to storage. */
|
|
@@ -12703,6 +13230,122 @@ class MemoryBundleCache {
|
|
|
12703
13230
|
}
|
|
12704
13231
|
}
|
|
12705
13232
|
|
|
13233
|
+
/**
|
|
13234
|
+
* @license
|
|
13235
|
+
* Copyright 2022 Google LLC
|
|
13236
|
+
*
|
|
13237
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
13238
|
+
* you may not use this file except in compliance with the License.
|
|
13239
|
+
* You may obtain a copy of the License at
|
|
13240
|
+
*
|
|
13241
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
13242
|
+
*
|
|
13243
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13244
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13245
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13246
|
+
* See the License for the specific language governing permissions and
|
|
13247
|
+
* limitations under the License.
|
|
13248
|
+
*/
|
|
13249
|
+
/**
|
|
13250
|
+
* An in-memory implementation of DocumentOverlayCache.
|
|
13251
|
+
*/
|
|
13252
|
+
class MemoryDocumentOverlayCache {
|
|
13253
|
+
constructor() {
|
|
13254
|
+
// A map sorted by DocumentKey, whose value is a pair of the largest batch id
|
|
13255
|
+
// for the overlay and the overlay itself.
|
|
13256
|
+
this.overlays = new SortedMap(DocumentKey.comparator);
|
|
13257
|
+
this.overlayByBatchId = new Map();
|
|
13258
|
+
}
|
|
13259
|
+
getOverlay(transaction, key) {
|
|
13260
|
+
return PersistencePromise.resolve(this.overlays.get(key));
|
|
13261
|
+
}
|
|
13262
|
+
saveOverlays(transaction, largestBatchId, overlays) {
|
|
13263
|
+
overlays.forEach(mutation => {
|
|
13264
|
+
this.saveOverlay(transaction, largestBatchId, mutation);
|
|
13265
|
+
});
|
|
13266
|
+
return PersistencePromise.resolve();
|
|
13267
|
+
}
|
|
13268
|
+
removeOverlaysForBatchId(transaction, documentKeys, batchId) {
|
|
13269
|
+
const keys = this.overlayByBatchId.get(batchId);
|
|
13270
|
+
if (keys !== undefined) {
|
|
13271
|
+
keys.forEach(key => (this.overlays = this.overlays.remove(key)));
|
|
13272
|
+
this.overlayByBatchId.delete(batchId);
|
|
13273
|
+
}
|
|
13274
|
+
return PersistencePromise.resolve();
|
|
13275
|
+
}
|
|
13276
|
+
getOverlaysForCollection(transaction, collection, sinceBatchId) {
|
|
13277
|
+
const result = new Map();
|
|
13278
|
+
const immediateChildrenPathLength = collection.length + 1;
|
|
13279
|
+
const prefix = new DocumentKey(collection.child(''));
|
|
13280
|
+
const iter = this.overlays.getIteratorFrom(prefix);
|
|
13281
|
+
while (iter.hasNext()) {
|
|
13282
|
+
const entry = iter.getNext();
|
|
13283
|
+
const overlay = entry.value;
|
|
13284
|
+
const key = overlay.getKey();
|
|
13285
|
+
if (!collection.isPrefixOf(key.path)) {
|
|
13286
|
+
break;
|
|
13287
|
+
}
|
|
13288
|
+
// Documents from sub-collections
|
|
13289
|
+
if (key.path.length !== immediateChildrenPathLength) {
|
|
13290
|
+
continue;
|
|
13291
|
+
}
|
|
13292
|
+
if (overlay.largestBatchId > sinceBatchId) {
|
|
13293
|
+
result.set(overlay.getKey(), overlay);
|
|
13294
|
+
}
|
|
13295
|
+
}
|
|
13296
|
+
return PersistencePromise.resolve(result);
|
|
13297
|
+
}
|
|
13298
|
+
getOverlaysForCollectionGroup(transaction, collectionGroup, sinceBatchId, count) {
|
|
13299
|
+
let batchIdToOverlays = new SortedMap((key1, key2) => key1 - key2);
|
|
13300
|
+
const iter = this.overlays.getIterator();
|
|
13301
|
+
while (iter.hasNext()) {
|
|
13302
|
+
const entry = iter.getNext();
|
|
13303
|
+
const overlay = entry.value;
|
|
13304
|
+
const key = overlay.getKey();
|
|
13305
|
+
if (key.getCollectionGroup() !== collectionGroup) {
|
|
13306
|
+
continue;
|
|
13307
|
+
}
|
|
13308
|
+
if (overlay.largestBatchId > sinceBatchId) {
|
|
13309
|
+
let overlaysForBatchId = batchIdToOverlays.get(overlay.largestBatchId);
|
|
13310
|
+
if (overlaysForBatchId === null) {
|
|
13311
|
+
overlaysForBatchId = new Map();
|
|
13312
|
+
batchIdToOverlays = batchIdToOverlays.insert(overlay.largestBatchId, overlaysForBatchId);
|
|
13313
|
+
}
|
|
13314
|
+
overlaysForBatchId.set(overlay.getKey(), overlay);
|
|
13315
|
+
}
|
|
13316
|
+
}
|
|
13317
|
+
const result = new Map();
|
|
13318
|
+
const batchIter = batchIdToOverlays.getIterator();
|
|
13319
|
+
while (batchIter.hasNext()) {
|
|
13320
|
+
const entry = batchIter.getNext();
|
|
13321
|
+
const overlays = entry.value;
|
|
13322
|
+
overlays.forEach((overlay, key) => result.set(key, overlay));
|
|
13323
|
+
if (result.size >= count) {
|
|
13324
|
+
break;
|
|
13325
|
+
}
|
|
13326
|
+
}
|
|
13327
|
+
return PersistencePromise.resolve(result);
|
|
13328
|
+
}
|
|
13329
|
+
saveOverlay(transaction, largestBatchId, mutation) {
|
|
13330
|
+
if (mutation === null) {
|
|
13331
|
+
return;
|
|
13332
|
+
}
|
|
13333
|
+
// Remove the association of the overlay to its batch id.
|
|
13334
|
+
const existing = this.overlays.get(mutation.key);
|
|
13335
|
+
if (existing !== null) {
|
|
13336
|
+
this.overlayByBatchId.get(existing.largestBatchId).delete(mutation.key);
|
|
13337
|
+
}
|
|
13338
|
+
this.overlays = this.overlays.insert(mutation.key, new Overlay(largestBatchId, mutation));
|
|
13339
|
+
// Create the association of this overlay to the given largestBatchId.
|
|
13340
|
+
let batch = this.overlayByBatchId.get(largestBatchId);
|
|
13341
|
+
if (batch === undefined) {
|
|
13342
|
+
batch = new Set();
|
|
13343
|
+
this.overlayByBatchId.set(largestBatchId, batch);
|
|
13344
|
+
}
|
|
13345
|
+
batch.add(mutation.key);
|
|
13346
|
+
}
|
|
13347
|
+
}
|
|
13348
|
+
|
|
12706
13349
|
/**
|
|
12707
13350
|
* @license
|
|
12708
13351
|
* Copyright 2017 Google LLC
|
|
@@ -13056,14 +13699,16 @@ class MemoryRemoteDocumentCacheImpl {
|
|
|
13056
13699
|
* expected to just return 0 to avoid unnecessarily doing the work of
|
|
13057
13700
|
* calculating the size.
|
|
13058
13701
|
*/
|
|
13059
|
-
constructor(
|
|
13060
|
-
this.indexManager = indexManager;
|
|
13702
|
+
constructor(sizer) {
|
|
13061
13703
|
this.sizer = sizer;
|
|
13062
13704
|
/** Underlying cache of documents and their read times. */
|
|
13063
13705
|
this.docs = documentEntryMap();
|
|
13064
13706
|
/** Size of all cached documents. */
|
|
13065
13707
|
this.size = 0;
|
|
13066
13708
|
}
|
|
13709
|
+
setIndexManager(indexManager) {
|
|
13710
|
+
this.indexManager = indexManager;
|
|
13711
|
+
}
|
|
13067
13712
|
/**
|
|
13068
13713
|
* Adds the supplied entry to the cache and updates the cache size as appropriate.
|
|
13069
13714
|
*
|
|
@@ -13111,21 +13756,22 @@ class MemoryRemoteDocumentCacheImpl {
|
|
|
13111
13756
|
});
|
|
13112
13757
|
return PersistencePromise.resolve(results);
|
|
13113
13758
|
}
|
|
13114
|
-
|
|
13759
|
+
getAll(transaction, collectionPath, sinceReadTime) {
|
|
13115
13760
|
let results = mutableDocumentMap();
|
|
13116
13761
|
// Documents are ordered by key, so we can use a prefix scan to narrow down
|
|
13117
13762
|
// the documents we need to match the query against.
|
|
13118
|
-
const prefix = new DocumentKey(
|
|
13763
|
+
const prefix = new DocumentKey(collectionPath.child(''));
|
|
13119
13764
|
const iterator = this.docs.getIteratorFrom(prefix);
|
|
13120
13765
|
while (iterator.hasNext()) {
|
|
13121
13766
|
const { key, value: { document } } = iterator.getNext();
|
|
13122
|
-
if (!
|
|
13767
|
+
if (!collectionPath.isPrefixOf(key.path)) {
|
|
13123
13768
|
break;
|
|
13124
13769
|
}
|
|
13125
|
-
if (
|
|
13770
|
+
if (key.path.length > collectionPath.length + 1) {
|
|
13771
|
+
// Exclude entries from subcollections.
|
|
13126
13772
|
continue;
|
|
13127
13773
|
}
|
|
13128
|
-
if (
|
|
13774
|
+
if (document.readTime.compareTo(sinceReadTime) <= 0) {
|
|
13129
13775
|
continue;
|
|
13130
13776
|
}
|
|
13131
13777
|
results = results.insert(document.key, document.mutableCopy());
|
|
@@ -13147,13 +13793,12 @@ class MemoryRemoteDocumentCacheImpl {
|
|
|
13147
13793
|
/**
|
|
13148
13794
|
* Creates a new memory-only RemoteDocumentCache.
|
|
13149
13795
|
*
|
|
13150
|
-
* @param indexManager - A class that manages collection group indices.
|
|
13151
13796
|
* @param sizer - Used to assess the size of a document. For eager GC, this is
|
|
13152
13797
|
* expected to just return 0 to avoid unnecessarily doing the work of
|
|
13153
13798
|
* calculating the size.
|
|
13154
13799
|
*/
|
|
13155
|
-
function newMemoryRemoteDocumentCache(
|
|
13156
|
-
return new MemoryRemoteDocumentCacheImpl(
|
|
13800
|
+
function newMemoryRemoteDocumentCache(sizer) {
|
|
13801
|
+
return new MemoryRemoteDocumentCacheImpl(sizer);
|
|
13157
13802
|
}
|
|
13158
13803
|
/**
|
|
13159
13804
|
* Handles the details of adding and updating documents in the MemoryRemoteDocumentCache.
|
|
@@ -13347,6 +13992,7 @@ class MemoryPersistence {
|
|
|
13347
13992
|
*/
|
|
13348
13993
|
constructor(referenceDelegateFactory, serializer) {
|
|
13349
13994
|
this.mutationQueues = {};
|
|
13995
|
+
this.overlays = {};
|
|
13350
13996
|
this.listenSequence = new ListenSequence(0);
|
|
13351
13997
|
this._started = false;
|
|
13352
13998
|
this._started = true;
|
|
@@ -13354,7 +14000,7 @@ class MemoryPersistence {
|
|
|
13354
14000
|
this.targetCache = new MemoryTargetCache(this);
|
|
13355
14001
|
const sizer = (doc) => this.referenceDelegate.documentSize(doc);
|
|
13356
14002
|
this.indexManager = new MemoryIndexManager();
|
|
13357
|
-
this.remoteDocumentCache = newMemoryRemoteDocumentCache(
|
|
14003
|
+
this.remoteDocumentCache = newMemoryRemoteDocumentCache(sizer);
|
|
13358
14004
|
this.serializer = new LocalSerializer(serializer);
|
|
13359
14005
|
this.bundleCache = new MemoryBundleCache(this.serializer);
|
|
13360
14006
|
}
|
|
@@ -13375,13 +14021,23 @@ class MemoryPersistence {
|
|
|
13375
14021
|
setNetworkEnabled() {
|
|
13376
14022
|
// No op.
|
|
13377
14023
|
}
|
|
13378
|
-
getIndexManager() {
|
|
14024
|
+
getIndexManager(user) {
|
|
14025
|
+
// We do not currently support indices for memory persistence, so we can
|
|
14026
|
+
// return the same shared instance of the memory index manager.
|
|
13379
14027
|
return this.indexManager;
|
|
13380
14028
|
}
|
|
13381
|
-
|
|
14029
|
+
getDocumentOverlayCache(user) {
|
|
14030
|
+
let overlay = this.overlays[user.toKey()];
|
|
14031
|
+
if (!overlay) {
|
|
14032
|
+
overlay = new MemoryDocumentOverlayCache();
|
|
14033
|
+
this.overlays[user.toKey()] = overlay;
|
|
14034
|
+
}
|
|
14035
|
+
return overlay;
|
|
14036
|
+
}
|
|
14037
|
+
getMutationQueue(user, indexManager) {
|
|
13382
14038
|
let queue = this.mutationQueues[user.toKey()];
|
|
13383
14039
|
if (!queue) {
|
|
13384
|
-
queue = new MemoryMutationQueue(
|
|
14040
|
+
queue = new MemoryMutationQueue(indexManager, this.referenceDelegate);
|
|
13385
14041
|
this.mutationQueues[user.toKey()] = queue;
|
|
13386
14042
|
}
|
|
13387
14043
|
return queue;
|
|
@@ -20344,12 +21000,12 @@ async function syncEngineListen(syncEngine, query) {
|
|
|
20344
21000
|
}
|
|
20345
21001
|
else {
|
|
20346
21002
|
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
21003
|
if (syncEngineImpl.isPrimaryClient) {
|
|
20351
21004
|
remoteStoreListen(syncEngineImpl.remoteStore, targetData);
|
|
20352
21005
|
}
|
|
21006
|
+
const status = syncEngineImpl.sharedClientState.addLocalQueryTarget(targetData.targetId);
|
|
21007
|
+
targetId = targetData.targetId;
|
|
21008
|
+
viewSnapshot = await initializeViewAndComputeSnapshot(syncEngineImpl, query, targetId, status === 'current');
|
|
20353
21009
|
}
|
|
20354
21010
|
return viewSnapshot;
|
|
20355
21011
|
}
|
|
@@ -24857,8 +25513,7 @@ class DocumentSnapshot extends DocumentSnapshot$1 {
|
|
|
24857
25513
|
this.metadata = metadata;
|
|
24858
25514
|
}
|
|
24859
25515
|
/**
|
|
24860
|
-
*
|
|
24861
|
-
* exists. True if the document exists.
|
|
25516
|
+
* Returns whether or not the data exists. True if the document exists.
|
|
24862
25517
|
*/
|
|
24863
25518
|
exists() {
|
|
24864
25519
|
return super.exists();
|
|
@@ -25232,51 +25887,53 @@ function limitToLast(limit) {
|
|
|
25232
25887
|
return new QueryLimitConstraint('limitToLast', limit, "L" /* Last */);
|
|
25233
25888
|
}
|
|
25234
25889
|
class QueryStartAtConstraint extends QueryConstraint {
|
|
25235
|
-
constructor(type, _docOrFields,
|
|
25890
|
+
constructor(type, _docOrFields, _inclusive) {
|
|
25236
25891
|
super();
|
|
25237
25892
|
this.type = type;
|
|
25238
25893
|
this._docOrFields = _docOrFields;
|
|
25239
|
-
this.
|
|
25894
|
+
this._inclusive = _inclusive;
|
|
25240
25895
|
}
|
|
25241
25896
|
_apply(query) {
|
|
25242
|
-
const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this.
|
|
25897
|
+
const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this._inclusive);
|
|
25243
25898
|
return new Query(query.firestore, query.converter, queryWithStartAt(query._query, bound));
|
|
25244
25899
|
}
|
|
25245
25900
|
}
|
|
25246
25901
|
function startAt(...docOrFields) {
|
|
25247
|
-
return new QueryStartAtConstraint('startAt', docOrFields,
|
|
25902
|
+
return new QueryStartAtConstraint('startAt', docOrFields,
|
|
25903
|
+
/*inclusive=*/ true);
|
|
25248
25904
|
}
|
|
25249
25905
|
function startAfter(...docOrFields) {
|
|
25250
25906
|
return new QueryStartAtConstraint('startAfter', docOrFields,
|
|
25251
|
-
/*
|
|
25907
|
+
/*inclusive=*/ false);
|
|
25252
25908
|
}
|
|
25253
25909
|
class QueryEndAtConstraint extends QueryConstraint {
|
|
25254
|
-
constructor(type, _docOrFields,
|
|
25910
|
+
constructor(type, _docOrFields, _inclusive) {
|
|
25255
25911
|
super();
|
|
25256
25912
|
this.type = type;
|
|
25257
25913
|
this._docOrFields = _docOrFields;
|
|
25258
|
-
this.
|
|
25914
|
+
this._inclusive = _inclusive;
|
|
25259
25915
|
}
|
|
25260
25916
|
_apply(query) {
|
|
25261
|
-
const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this.
|
|
25917
|
+
const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this._inclusive);
|
|
25262
25918
|
return new Query(query.firestore, query.converter, queryWithEndAt(query._query, bound));
|
|
25263
25919
|
}
|
|
25264
25920
|
}
|
|
25265
25921
|
function endBefore(...docOrFields) {
|
|
25266
|
-
return new QueryEndAtConstraint('endBefore', docOrFields,
|
|
25922
|
+
return new QueryEndAtConstraint('endBefore', docOrFields,
|
|
25923
|
+
/*inclusive=*/ false);
|
|
25267
25924
|
}
|
|
25268
25925
|
function endAt(...docOrFields) {
|
|
25269
|
-
return new QueryEndAtConstraint('endAt', docOrFields, /*
|
|
25926
|
+
return new QueryEndAtConstraint('endAt', docOrFields, /*inclusive=*/ true);
|
|
25270
25927
|
}
|
|
25271
25928
|
/** Helper function to create a bound from a document or fields */
|
|
25272
|
-
function newQueryBoundFromDocOrFields(query, methodName, docOrFields,
|
|
25929
|
+
function newQueryBoundFromDocOrFields(query, methodName, docOrFields, inclusive) {
|
|
25273
25930
|
docOrFields[0] = util$1.getModularInstance(docOrFields[0]);
|
|
25274
25931
|
if (docOrFields[0] instanceof DocumentSnapshot$1) {
|
|
25275
|
-
return newQueryBoundFromDocument(query._query, query.firestore._databaseId, methodName, docOrFields[0]._document,
|
|
25932
|
+
return newQueryBoundFromDocument(query._query, query.firestore._databaseId, methodName, docOrFields[0]._document, inclusive);
|
|
25276
25933
|
}
|
|
25277
25934
|
else {
|
|
25278
25935
|
const reader = newUserDataReader(query.firestore);
|
|
25279
|
-
return newQueryBoundFromFields(query._query, query.firestore._databaseId, reader, methodName, docOrFields,
|
|
25936
|
+
return newQueryBoundFromFields(query._query, query.firestore._databaseId, reader, methodName, docOrFields, inclusive);
|
|
25280
25937
|
}
|
|
25281
25938
|
}
|
|
25282
25939
|
function newQueryFilter(query, methodName, dataReader, databaseId, fieldPath, op, value) {
|
|
@@ -25334,7 +25991,7 @@ function newQueryOrderBy(query, fieldPath, direction) {
|
|
|
25334
25991
|
* of the query or if any of the fields in the order by are an uncommitted
|
|
25335
25992
|
* server timestamp.
|
|
25336
25993
|
*/
|
|
25337
|
-
function newQueryBoundFromDocument(query, databaseId, methodName, doc,
|
|
25994
|
+
function newQueryBoundFromDocument(query, databaseId, methodName, doc, inclusive) {
|
|
25338
25995
|
if (!doc) {
|
|
25339
25996
|
throw new FirestoreError(Code.NOT_FOUND, `Can't use a DocumentSnapshot that doesn't exist for ` +
|
|
25340
25997
|
`${methodName}().`);
|
|
@@ -25371,12 +26028,12 @@ function newQueryBoundFromDocument(query, databaseId, methodName, doc, before) {
|
|
|
25371
26028
|
}
|
|
25372
26029
|
}
|
|
25373
26030
|
}
|
|
25374
|
-
return new Bound(components,
|
|
26031
|
+
return new Bound(components, inclusive);
|
|
25375
26032
|
}
|
|
25376
26033
|
/**
|
|
25377
26034
|
* Converts a list of field values to a `Bound` for the given query.
|
|
25378
26035
|
*/
|
|
25379
|
-
function newQueryBoundFromFields(query, databaseId, dataReader, methodName, values,
|
|
26036
|
+
function newQueryBoundFromFields(query, databaseId, dataReader, methodName, values, inclusive) {
|
|
25380
26037
|
// Use explicit order by's because it has to match the query the user made
|
|
25381
26038
|
const orderBy = query.explicitOrderBy;
|
|
25382
26039
|
if (values.length > orderBy.length) {
|
|
@@ -25413,7 +26070,7 @@ function newQueryBoundFromFields(query, databaseId, dataReader, methodName, valu
|
|
|
25413
26070
|
components.push(wrapped);
|
|
25414
26071
|
}
|
|
25415
26072
|
}
|
|
25416
|
-
return new Bound(components,
|
|
26073
|
+
return new Bound(components, inclusive);
|
|
25417
26074
|
}
|
|
25418
26075
|
/**
|
|
25419
26076
|
* Parses the given `documentIdValue` into a `ReferenceValue`, throwing
|