@firebase/firestore 3.4.4-canary.b20cf306a → 3.4.4-canary.bb8f37c3e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/firestore/src/api/credentials.d.ts +1 -0
- package/dist/firestore/src/api/snapshot.d.ts +1 -2
- package/dist/firestore/src/core/target.d.ts +8 -4
- package/dist/firestore/src/lite-api/query.d.ts +2 -2
- package/dist/firestore/src/local/index_manager.d.ts +52 -0
- package/dist/firestore/src/local/indexeddb_index_manager.d.ts +21 -2
- package/dist/firestore/src/local/indexeddb_persistence.d.ts +4 -4
- package/dist/firestore/src/local/indexeddb_remote_document_cache.d.ts +2 -8
- package/dist/firestore/src/local/indexeddb_schema.d.ts +149 -7
- package/dist/firestore/src/local/local_documents_view.d.ts +0 -1
- package/dist/firestore/src/local/local_serializer.d.ts +7 -2
- package/dist/firestore/src/local/memory_index_manager.d.ts +11 -0
- package/dist/firestore/src/local/memory_persistence.d.ts +3 -2
- package/dist/firestore/src/local/memory_remote_document_cache.d.ts +1 -3
- package/dist/firestore/src/local/persistence.d.ts +2 -2
- package/dist/firestore/src/local/remote_document_cache.d.ts +7 -9
- package/dist/firestore/src/local/simple_db.d.ts +1 -0
- package/dist/firestore/src/model/field_index.d.ts +2 -2
- package/dist/firestore/src/model/target_index_matcher.d.ts +70 -0
- package/dist/firestore/test/unit/local/counting_query_engine.d.ts +3 -3
- package/dist/firestore/test/unit/local/persistence_test_helpers.d.ts +1 -0
- package/dist/firestore/test/unit/local/test_index_manager.d.ts +11 -0
- package/dist/firestore/test/unit/local/test_remote_document_cache.d.ts +4 -2
- package/dist/firestore/test/unit/local/test_remote_document_change_buffer.d.ts +1 -1
- package/dist/firestore/test/unit/model/target_index_matcher.test.d.ts +17 -0
- package/dist/firestore/test/util/helpers.d.ts +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.esm2017.js +3373 -3129
- package/dist/index.esm2017.js.map +1 -1
- package/dist/index.esm5.js +3823 -3602
- package/dist/index.esm5.js.map +1 -1
- package/dist/index.node.cjs.js +506 -220
- package/dist/index.node.cjs.js.map +1 -1
- package/dist/index.node.mjs +506 -220
- package/dist/index.node.mjs.map +1 -1
- package/dist/index.rn.js +3623 -3379
- package/dist/index.rn.js.map +1 -1
- package/dist/internal.d.ts +178 -14
- package/dist/lite/firestore/src/api/credentials.d.ts +1 -0
- package/dist/lite/firestore/src/api/snapshot.d.ts +1 -2
- package/dist/lite/firestore/src/core/target.d.ts +8 -4
- package/dist/lite/firestore/src/lite-api/query.d.ts +2 -2
- package/dist/lite/firestore/src/local/index_manager.d.ts +52 -0
- package/dist/lite/firestore/src/local/indexeddb_index_manager.d.ts +21 -2
- package/dist/lite/firestore/src/local/indexeddb_persistence.d.ts +4 -4
- package/dist/lite/firestore/src/local/indexeddb_remote_document_cache.d.ts +2 -8
- package/dist/lite/firestore/src/local/indexeddb_schema.d.ts +149 -7
- package/dist/lite/firestore/src/local/local_documents_view.d.ts +0 -1
- package/dist/lite/firestore/src/local/local_serializer.d.ts +7 -2
- package/dist/lite/firestore/src/local/memory_index_manager.d.ts +11 -0
- package/dist/lite/firestore/src/local/memory_persistence.d.ts +3 -2
- package/dist/lite/firestore/src/local/memory_remote_document_cache.d.ts +1 -3
- package/dist/lite/firestore/src/local/persistence.d.ts +2 -2
- package/dist/lite/firestore/src/local/remote_document_cache.d.ts +7 -9
- package/dist/lite/firestore/src/local/simple_db.d.ts +1 -0
- package/dist/lite/firestore/src/model/field_index.d.ts +2 -2
- package/dist/lite/firestore/src/model/target_index_matcher.d.ts +70 -0
- package/dist/lite/firestore/test/unit/local/counting_query_engine.d.ts +3 -3
- package/dist/lite/firestore/test/unit/local/persistence_test_helpers.d.ts +1 -0
- package/dist/lite/firestore/test/unit/local/test_index_manager.d.ts +11 -0
- package/dist/lite/firestore/test/unit/local/test_remote_document_cache.d.ts +4 -2
- package/dist/lite/firestore/test/unit/local/test_remote_document_change_buffer.d.ts +1 -1
- package/dist/lite/firestore/test/unit/model/target_index_matcher.test.d.ts +17 -0
- package/dist/lite/firestore/test/util/helpers.d.ts +1 -1
- package/dist/lite/index.browser.esm2017.js +1146 -1143
- package/dist/lite/index.browser.esm2017.js.map +1 -1
- package/dist/lite/index.browser.esm5.js +332 -331
- package/dist/lite/index.browser.esm5.js.map +1 -1
- package/dist/lite/index.node.cjs.js +36 -29
- package/dist/lite/index.node.cjs.js.map +1 -1
- package/dist/lite/index.node.mjs +36 -29
- package/dist/lite/index.node.mjs.map +1 -1
- package/dist/lite/index.rn.esm2017.js +301 -298
- package/dist/lite/index.rn.esm2017.js.map +1 -1
- package/dist/lite/internal.d.ts +2 -2
- package/dist/lite/packages/firestore/dist/lite/index.browser.esm2017.d.ts +121 -121
- package/dist/lite/packages/firestore/src/api/credentials.d.ts +1 -0
- package/dist/lite/packages/firestore/src/api/snapshot.d.ts +1 -2
- package/dist/lite/packages/firestore/src/core/target.d.ts +8 -4
- package/dist/lite/packages/firestore/src/lite-api/query.d.ts +2 -2
- package/dist/lite/packages/firestore/src/local/index_manager.d.ts +52 -0
- package/dist/lite/packages/firestore/src/local/indexeddb_index_manager.d.ts +21 -2
- package/dist/lite/packages/firestore/src/local/indexeddb_persistence.d.ts +4 -4
- package/dist/lite/packages/firestore/src/local/indexeddb_remote_document_cache.d.ts +2 -8
- package/dist/lite/packages/firestore/src/local/indexeddb_schema.d.ts +149 -7
- package/dist/lite/packages/firestore/src/local/local_documents_view.d.ts +0 -1
- package/dist/lite/packages/firestore/src/local/local_serializer.d.ts +7 -2
- package/dist/lite/packages/firestore/src/local/memory_index_manager.d.ts +11 -0
- package/dist/lite/packages/firestore/src/local/memory_persistence.d.ts +3 -2
- package/dist/lite/packages/firestore/src/local/memory_remote_document_cache.d.ts +1 -3
- package/dist/lite/packages/firestore/src/local/persistence.d.ts +2 -2
- package/dist/lite/packages/firestore/src/local/remote_document_cache.d.ts +7 -9
- package/dist/lite/packages/firestore/src/local/simple_db.d.ts +1 -0
- package/dist/lite/packages/firestore/src/model/field_index.d.ts +2 -2
- package/dist/lite/packages/firestore/src/model/target_index_matcher.d.ts +70 -0
- package/dist/lite/packages/firestore/test/unit/local/counting_query_engine.d.ts +3 -3
- package/dist/lite/packages/firestore/test/unit/local/persistence_test_helpers.d.ts +1 -0
- package/dist/lite/packages/firestore/test/unit/local/test_index_manager.d.ts +11 -0
- package/dist/lite/packages/firestore/test/unit/local/test_remote_document_cache.d.ts +4 -2
- package/dist/lite/packages/firestore/test/unit/local/test_remote_document_change_buffer.d.ts +1 -1
- package/dist/lite/packages/firestore/test/unit/model/target_index_matcher.test.d.ts +17 -0
- package/dist/lite/packages/firestore/test/util/helpers.d.ts +1 -1
- package/dist/lite/private.d.ts +2 -2
- package/dist/packages/firestore/dist/index.esm2017.d.ts +170 -170
- package/dist/packages/firestore/src/api/credentials.d.ts +1 -0
- package/dist/packages/firestore/src/api/snapshot.d.ts +1 -2
- package/dist/packages/firestore/src/core/target.d.ts +8 -4
- package/dist/packages/firestore/src/lite-api/query.d.ts +2 -2
- package/dist/packages/firestore/src/local/index_manager.d.ts +52 -0
- package/dist/packages/firestore/src/local/indexeddb_index_manager.d.ts +21 -2
- package/dist/packages/firestore/src/local/indexeddb_persistence.d.ts +4 -4
- package/dist/packages/firestore/src/local/indexeddb_remote_document_cache.d.ts +2 -8
- package/dist/packages/firestore/src/local/indexeddb_schema.d.ts +149 -7
- package/dist/packages/firestore/src/local/local_documents_view.d.ts +0 -1
- package/dist/packages/firestore/src/local/local_serializer.d.ts +7 -2
- package/dist/packages/firestore/src/local/memory_index_manager.d.ts +11 -0
- package/dist/packages/firestore/src/local/memory_persistence.d.ts +3 -2
- package/dist/packages/firestore/src/local/memory_remote_document_cache.d.ts +1 -3
- package/dist/packages/firestore/src/local/persistence.d.ts +2 -2
- package/dist/packages/firestore/src/local/remote_document_cache.d.ts +7 -9
- package/dist/packages/firestore/src/local/simple_db.d.ts +1 -0
- package/dist/packages/firestore/src/model/field_index.d.ts +2 -2
- package/dist/packages/firestore/src/model/target_index_matcher.d.ts +70 -0
- package/dist/packages/firestore/test/unit/local/counting_query_engine.d.ts +3 -3
- package/dist/packages/firestore/test/unit/local/persistence_test_helpers.d.ts +1 -0
- package/dist/packages/firestore/test/unit/local/test_index_manager.d.ts +11 -0
- package/dist/packages/firestore/test/unit/local/test_remote_document_cache.d.ts +4 -2
- package/dist/packages/firestore/test/unit/local/test_remote_document_change_buffer.d.ts +1 -1
- package/dist/packages/firestore/test/unit/model/target_index_matcher.test.d.ts +17 -0
- package/dist/packages/firestore/test/util/helpers.d.ts +1 -1
- package/dist/private.d.ts +178 -14
- package/package.json +9 -9
package/dist/index.node.mjs
CHANGED
|
@@ -8,7 +8,7 @@ import { credentials, loadPackageDefinition, Metadata } from '@grpc/grpc-js';
|
|
|
8
8
|
import { fromJSON } from '@grpc/proto-loader';
|
|
9
9
|
|
|
10
10
|
const name = "@firebase/firestore";
|
|
11
|
-
const version$1 = "3.4.4-canary.
|
|
11
|
+
const version$1 = "3.4.4-canary.bb8f37c3e";
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* @license
|
|
@@ -61,7 +61,7 @@ User.GOOGLE_CREDENTIALS = new User('google-credentials-uid');
|
|
|
61
61
|
User.FIRST_PARTY = new User('first-party-uid');
|
|
62
62
|
User.MOCK_USER = new User('mock-user');
|
|
63
63
|
|
|
64
|
-
const version = "9.6.
|
|
64
|
+
const version = "9.6.6-canary.bb8f37c3e";
|
|
65
65
|
|
|
66
66
|
/**
|
|
67
67
|
* @license
|
|
@@ -666,13 +666,19 @@ class FirebaseAppCheckTokenProvider {
|
|
|
666
666
|
this.appCheckProvider = appCheckProvider;
|
|
667
667
|
this.forceRefresh = false;
|
|
668
668
|
this.appCheck = null;
|
|
669
|
+
this.latestAppCheckToken = null;
|
|
669
670
|
}
|
|
670
671
|
start(asyncQueue, changeListener) {
|
|
671
672
|
const onTokenChanged = tokenResult => {
|
|
672
673
|
if (tokenResult.error != null) {
|
|
673
674
|
logDebug('FirebaseAppCheckTokenProvider', `Error getting App Check token; using placeholder token instead. Error: ${tokenResult.error.message}`);
|
|
674
675
|
}
|
|
675
|
-
|
|
676
|
+
const tokenUpdated = tokenResult.token !== this.latestAppCheckToken;
|
|
677
|
+
this.latestAppCheckToken = tokenResult.token;
|
|
678
|
+
logDebug('FirebaseAppCheckTokenProvider', `Received ${tokenUpdated ? 'new' : 'existing'} token.`);
|
|
679
|
+
return tokenUpdated
|
|
680
|
+
? changeListener(tokenResult.token)
|
|
681
|
+
: Promise.resolve();
|
|
676
682
|
};
|
|
677
683
|
this.tokenListener = (tokenResult) => {
|
|
678
684
|
asyncQueue.enqueueRetryable(() => onTokenChanged(tokenResult));
|
|
@@ -707,6 +713,7 @@ class FirebaseAppCheckTokenProvider {
|
|
|
707
713
|
return this.appCheck.getToken(forceRefresh).then(tokenResult => {
|
|
708
714
|
if (tokenResult) {
|
|
709
715
|
hardAssert(typeof tokenResult.token === 'string');
|
|
716
|
+
this.latestAppCheckToken = tokenResult.token;
|
|
710
717
|
return new AppCheckToken(tokenResult.token);
|
|
711
718
|
}
|
|
712
719
|
else {
|
|
@@ -1192,23 +1199,6 @@ function decodeResourcePath(path) {
|
|
|
1192
1199
|
}
|
|
1193
1200
|
return new ResourcePath(segments);
|
|
1194
1201
|
}
|
|
1195
|
-
|
|
1196
|
-
/**
|
|
1197
|
-
* @license
|
|
1198
|
-
* Copyright 2017 Google LLC
|
|
1199
|
-
*
|
|
1200
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
1201
|
-
* you may not use this file except in compliance with the License.
|
|
1202
|
-
* You may obtain a copy of the License at
|
|
1203
|
-
*
|
|
1204
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
1205
|
-
*
|
|
1206
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
1207
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
1208
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
1209
|
-
* See the License for the specific language governing permissions and
|
|
1210
|
-
* limitations under the License.
|
|
1211
|
-
*/
|
|
1212
1202
|
/**
|
|
1213
1203
|
* Schema Version for the Web client:
|
|
1214
1204
|
* 1. Initial version including Mutation Queue, Query Cache, and Remote
|
|
@@ -1227,6 +1217,7 @@ function decodeResourcePath(path) {
|
|
|
1227
1217
|
* an auto-incrementing ID. This is required for Index-Free queries.
|
|
1228
1218
|
* 10. Rewrite the canonical IDs to the explicit Protobuf-based format.
|
|
1229
1219
|
* 11. Add bundles and named_queries for bundle support.
|
|
1220
|
+
* 12. Add indexing support.
|
|
1230
1221
|
*/
|
|
1231
1222
|
const SCHEMA_VERSION = 11;
|
|
1232
1223
|
/**
|
|
@@ -1753,9 +1744,7 @@ class DbClientMetadata {
|
|
|
1753
1744
|
DbClientMetadata.store = 'clientMetadata';
|
|
1754
1745
|
/** Keys are automatically assigned via the clientId properties. */
|
|
1755
1746
|
DbClientMetadata.keyPath = 'clientId';
|
|
1756
|
-
/**
|
|
1757
|
-
* A object representing a bundle loaded by the SDK.
|
|
1758
|
-
*/
|
|
1747
|
+
/** An object representing a bundle loaded by the SDK. */
|
|
1759
1748
|
class DbBundle {
|
|
1760
1749
|
constructor(
|
|
1761
1750
|
/** The ID of the loaded bundle. */
|
|
@@ -1772,9 +1761,7 @@ class DbBundle {
|
|
|
1772
1761
|
/** Name of the IndexedDb object store. */
|
|
1773
1762
|
DbBundle.store = 'bundles';
|
|
1774
1763
|
DbBundle.keyPath = 'bundleId';
|
|
1775
|
-
/**
|
|
1776
|
-
* A object representing a named query loaded by the SDK via a bundle.
|
|
1777
|
-
*/
|
|
1764
|
+
/** An object representing a named query loaded by the SDK via a bundle. */
|
|
1778
1765
|
class DbNamedQuery {
|
|
1779
1766
|
constructor(
|
|
1780
1767
|
/** The name of the query. */
|
|
@@ -1791,6 +1778,116 @@ class DbNamedQuery {
|
|
|
1791
1778
|
/** Name of the IndexedDb object store. */
|
|
1792
1779
|
DbNamedQuery.store = 'namedQueries';
|
|
1793
1780
|
DbNamedQuery.keyPath = 'name';
|
|
1781
|
+
/** An object representing the global configuration for a field index. */
|
|
1782
|
+
class DbIndexConfiguration {
|
|
1783
|
+
constructor(
|
|
1784
|
+
/**
|
|
1785
|
+
* The index id for this entry. Undefined for indexes that are not yet
|
|
1786
|
+
* persisted.
|
|
1787
|
+
*/
|
|
1788
|
+
indexId,
|
|
1789
|
+
/** The collection group this index belongs to. */
|
|
1790
|
+
collectionGroup,
|
|
1791
|
+
/** The fields to index for this index. */
|
|
1792
|
+
fields) {
|
|
1793
|
+
this.indexId = indexId;
|
|
1794
|
+
this.collectionGroup = collectionGroup;
|
|
1795
|
+
this.fields = fields;
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
/** Name of the IndexedDb object store. */
|
|
1799
|
+
DbIndexConfiguration.store = 'indexConfiguration';
|
|
1800
|
+
DbIndexConfiguration.keyPath = 'indexId';
|
|
1801
|
+
/**
|
|
1802
|
+
* An index that provides access to the index configurations by collection
|
|
1803
|
+
* group.
|
|
1804
|
+
*
|
|
1805
|
+
* PORTING NOTE: iOS and Android maintain this index in-memory, but this is
|
|
1806
|
+
* not possible here as the Web client supports concurrent access to
|
|
1807
|
+
* persistence via multi-tab.
|
|
1808
|
+
*/
|
|
1809
|
+
DbIndexConfiguration.collectionGroupIndex = 'collectionGroupIndex';
|
|
1810
|
+
DbIndexConfiguration.collectionGroupIndexPath = 'collectionGroup';
|
|
1811
|
+
/**
|
|
1812
|
+
* An object describing how up-to-date the index backfill is for each user and
|
|
1813
|
+
* index.
|
|
1814
|
+
*/
|
|
1815
|
+
class DbIndexState {
|
|
1816
|
+
constructor(
|
|
1817
|
+
/** The index id for this entry. */
|
|
1818
|
+
indexId,
|
|
1819
|
+
/** The user id for this entry. */
|
|
1820
|
+
uid,
|
|
1821
|
+
/**
|
|
1822
|
+
* A number that indicates when the index was last updated (relative to
|
|
1823
|
+
* other indexes).
|
|
1824
|
+
*/
|
|
1825
|
+
sequenceNumber,
|
|
1826
|
+
/**
|
|
1827
|
+
* The latest read time that has been indexed by Firestore for this field
|
|
1828
|
+
* index. Set to `{seconds: 0, nanos: 0}` if no documents have been indexed.
|
|
1829
|
+
*/
|
|
1830
|
+
readTime,
|
|
1831
|
+
/**
|
|
1832
|
+
* The last document that has been indexed for this field index. Empty if
|
|
1833
|
+
* no documents have been indexed.
|
|
1834
|
+
*/
|
|
1835
|
+
documentKey,
|
|
1836
|
+
/**
|
|
1837
|
+
* The largest mutation batch id that has been processed for this index. -1
|
|
1838
|
+
* if no mutations have been indexed.
|
|
1839
|
+
*/
|
|
1840
|
+
largestBatchId) {
|
|
1841
|
+
this.indexId = indexId;
|
|
1842
|
+
this.uid = uid;
|
|
1843
|
+
this.sequenceNumber = sequenceNumber;
|
|
1844
|
+
this.readTime = readTime;
|
|
1845
|
+
this.documentKey = documentKey;
|
|
1846
|
+
this.largestBatchId = largestBatchId;
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
/** Name of the IndexedDb object store. */
|
|
1850
|
+
DbIndexState.store = 'indexState';
|
|
1851
|
+
DbIndexState.keyPath = ['indexId', 'uid'];
|
|
1852
|
+
/**
|
|
1853
|
+
* An index that provides access to documents in a collection sorted by last
|
|
1854
|
+
* update time. Used by the backfiller.
|
|
1855
|
+
*
|
|
1856
|
+
* PORTING NOTE: iOS and Android maintain this index in-memory, but this is
|
|
1857
|
+
* not possible here as the Web client supports concurrent access to
|
|
1858
|
+
* persistence via multi-tab.
|
|
1859
|
+
*/
|
|
1860
|
+
DbIndexState.sequenceNumberIndex = 'sequenceNumberIndex';
|
|
1861
|
+
DbIndexState.sequenceNumberIndexPath = ['uid', 'sequenceNumber'];
|
|
1862
|
+
/** An object that stores the encoded entries for all documents and fields. */
|
|
1863
|
+
class DbIndexEntry {
|
|
1864
|
+
constructor(
|
|
1865
|
+
/** The index id for this entry. */
|
|
1866
|
+
indexId,
|
|
1867
|
+
/** The user id for this entry. */
|
|
1868
|
+
uid,
|
|
1869
|
+
/** The encoded array index value for this entry. */
|
|
1870
|
+
arrayValue,
|
|
1871
|
+
/** The encoded directional value for equality and inequality filters. */
|
|
1872
|
+
directionalValue,
|
|
1873
|
+
/** The document key this entry points to. */
|
|
1874
|
+
documentKey) {
|
|
1875
|
+
this.indexId = indexId;
|
|
1876
|
+
this.uid = uid;
|
|
1877
|
+
this.arrayValue = arrayValue;
|
|
1878
|
+
this.directionalValue = directionalValue;
|
|
1879
|
+
this.documentKey = documentKey;
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1882
|
+
/** Name of the IndexedDb object store. */
|
|
1883
|
+
DbIndexEntry.store = 'indexEntries';
|
|
1884
|
+
DbIndexEntry.keyPath = [
|
|
1885
|
+
'indexId',
|
|
1886
|
+
'uid',
|
|
1887
|
+
'arrayValue',
|
|
1888
|
+
'directionalValue',
|
|
1889
|
+
'documentKey'
|
|
1890
|
+
];
|
|
1794
1891
|
// Visible for testing
|
|
1795
1892
|
const V1_STORES = [
|
|
1796
1893
|
DbMutationQueue.store,
|
|
@@ -1805,7 +1902,6 @@ const V1_STORES = [
|
|
|
1805
1902
|
// V2 is no longer usable (see comment at top of file)
|
|
1806
1903
|
// Visible for testing
|
|
1807
1904
|
const V3_STORES = V1_STORES;
|
|
1808
|
-
// Visible for testing
|
|
1809
1905
|
// Note: DbRemoteDocumentChanges is no longer used and dropped with v9.
|
|
1810
1906
|
const V4_STORES = [...V3_STORES, DbClientMetadata.store];
|
|
1811
1907
|
// V5 does not change the set of stores.
|
|
@@ -1815,12 +1911,24 @@ const V8_STORES = [...V6_STORES, DbCollectionParent.store];
|
|
|
1815
1911
|
// V9 does not change the set of stores.
|
|
1816
1912
|
// V10 does not change the set of stores.
|
|
1817
1913
|
const V11_STORES = [...V8_STORES, DbBundle.store, DbNamedQuery.store];
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1914
|
+
const V12_STORES = [
|
|
1915
|
+
...V11_STORES,
|
|
1916
|
+
DbIndexConfiguration.store,
|
|
1917
|
+
DbIndexState.store,
|
|
1918
|
+
DbIndexEntry.store
|
|
1919
|
+
];
|
|
1920
|
+
/** Returns the object stores for the provided schema. */
|
|
1921
|
+
function getObjectStores(schemaVersion) {
|
|
1922
|
+
if (schemaVersion === 12) {
|
|
1923
|
+
return V12_STORES;
|
|
1924
|
+
}
|
|
1925
|
+
else if (schemaVersion === 11) {
|
|
1926
|
+
return V11_STORES;
|
|
1927
|
+
}
|
|
1928
|
+
else {
|
|
1929
|
+
fail();
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1824
1932
|
|
|
1825
1933
|
/**
|
|
1826
1934
|
* @license
|
|
@@ -2117,6 +2225,15 @@ class SimpleDbTransaction {
|
|
|
2117
2225
|
this.transaction.abort();
|
|
2118
2226
|
}
|
|
2119
2227
|
}
|
|
2228
|
+
maybeCommit() {
|
|
2229
|
+
// If the browser supports V3 IndexedDB, we invoke commit() explicitly to
|
|
2230
|
+
// speed up index DB processing if the event loop remains blocks.
|
|
2231
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2232
|
+
const maybeV3IndexedDb = this.transaction;
|
|
2233
|
+
if (!this.aborted && typeof maybeV3IndexedDb.commit === 'function') {
|
|
2234
|
+
maybeV3IndexedDb.commit();
|
|
2235
|
+
}
|
|
2236
|
+
}
|
|
2120
2237
|
/**
|
|
2121
2238
|
* Returns a SimpleDbStore<KeyType, ValueType> for the specified store. All
|
|
2122
2239
|
* operations performed on the SimpleDbStore happen within the context of this
|
|
@@ -2313,6 +2430,10 @@ class SimpleDb {
|
|
|
2313
2430
|
this.db = await this.ensureDb(action);
|
|
2314
2431
|
const transaction = SimpleDbTransaction.open(this.db, action, readonly ? 'readonly' : 'readwrite', objectStores);
|
|
2315
2432
|
const transactionFnResult = transactionFn(transaction)
|
|
2433
|
+
.next(result => {
|
|
2434
|
+
transaction.maybeCommit();
|
|
2435
|
+
return result;
|
|
2436
|
+
})
|
|
2316
2437
|
.catch(error => {
|
|
2317
2438
|
// Abort the transaction if there was an error.
|
|
2318
2439
|
transaction.abort(error);
|
|
@@ -2485,13 +2606,29 @@ class SimpleDbStore {
|
|
|
2485
2606
|
return wrapRequest(request);
|
|
2486
2607
|
}
|
|
2487
2608
|
loadAll(indexOrRange, range) {
|
|
2488
|
-
const
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
return
|
|
2494
|
-
|
|
2609
|
+
const iterateOptions = this.options(indexOrRange, range);
|
|
2610
|
+
// Use `getAll()` if the browser supports IndexedDB v3, as it is roughly
|
|
2611
|
+
// 20% faster. Unfortunately, getAll() does not support custom indices.
|
|
2612
|
+
if (!iterateOptions.index && typeof this.store.getAll === 'function') {
|
|
2613
|
+
const request = this.store.getAll(iterateOptions.range);
|
|
2614
|
+
return new PersistencePromise((resolve, reject) => {
|
|
2615
|
+
request.onerror = (event) => {
|
|
2616
|
+
reject(event.target.error);
|
|
2617
|
+
};
|
|
2618
|
+
request.onsuccess = (event) => {
|
|
2619
|
+
resolve(event.target.result);
|
|
2620
|
+
};
|
|
2621
|
+
});
|
|
2622
|
+
}
|
|
2623
|
+
else {
|
|
2624
|
+
const cursor = this.cursor(iterateOptions);
|
|
2625
|
+
const results = [];
|
|
2626
|
+
return this.iterateCursor(cursor, (key, value) => {
|
|
2627
|
+
results.push(value);
|
|
2628
|
+
}).next(() => {
|
|
2629
|
+
return results;
|
|
2630
|
+
});
|
|
2631
|
+
}
|
|
2495
2632
|
}
|
|
2496
2633
|
deleteAll(indexOrRange, range) {
|
|
2497
2634
|
logDebug(LOG_TAG$g, 'DELETE ALL', this.store.name);
|
|
@@ -4345,12 +4482,12 @@ class FieldIndex {
|
|
|
4345
4482
|
/** The collection ID this index applies to. */
|
|
4346
4483
|
collectionGroup,
|
|
4347
4484
|
/** The field segments for this index. */
|
|
4348
|
-
|
|
4485
|
+
fields,
|
|
4349
4486
|
/** Shows how up-to-date the index is for the current user. */
|
|
4350
4487
|
indexState) {
|
|
4351
4488
|
this.indexId = indexId;
|
|
4352
4489
|
this.collectionGroup = collectionGroup;
|
|
4353
|
-
this.
|
|
4490
|
+
this.fields = fields;
|
|
4354
4491
|
this.indexState = indexState;
|
|
4355
4492
|
}
|
|
4356
4493
|
}
|
|
@@ -4460,27 +4597,29 @@ function newTarget(path, collectionGroup = null, orderBy = [], filters = [], lim
|
|
|
4460
4597
|
function canonifyTarget(target) {
|
|
4461
4598
|
const targetImpl = debugCast(target);
|
|
4462
4599
|
if (targetImpl.memoizedCanonicalId === null) {
|
|
4463
|
-
let
|
|
4600
|
+
let str = targetImpl.path.canonicalString();
|
|
4464
4601
|
if (targetImpl.collectionGroup !== null) {
|
|
4465
|
-
|
|
4602
|
+
str += '|cg:' + targetImpl.collectionGroup;
|
|
4466
4603
|
}
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4604
|
+
str += '|f:';
|
|
4605
|
+
str += targetImpl.filters.map(f => canonifyFilter(f)).join(',');
|
|
4606
|
+
str += '|ob:';
|
|
4607
|
+
str += targetImpl.orderBy.map(o => canonifyOrderBy(o)).join(',');
|
|
4471
4608
|
if (!isNullOrUndefined(targetImpl.limit)) {
|
|
4472
|
-
|
|
4473
|
-
|
|
4609
|
+
str += '|l:';
|
|
4610
|
+
str += targetImpl.limit;
|
|
4474
4611
|
}
|
|
4475
4612
|
if (targetImpl.startAt) {
|
|
4476
|
-
|
|
4477
|
-
|
|
4613
|
+
str += '|lb:';
|
|
4614
|
+
str += targetImpl.startAt.inclusive ? 'b:' : 'a:';
|
|
4615
|
+
str += targetImpl.startAt.position.map(p => canonicalId(p)).join(',');
|
|
4478
4616
|
}
|
|
4479
4617
|
if (targetImpl.endAt) {
|
|
4480
|
-
|
|
4481
|
-
|
|
4618
|
+
str += '|ub:';
|
|
4619
|
+
str += targetImpl.endAt.inclusive ? 'a:' : 'b:';
|
|
4620
|
+
str += targetImpl.endAt.position.map(p => canonicalId(p)).join(',');
|
|
4482
4621
|
}
|
|
4483
|
-
targetImpl.memoizedCanonicalId =
|
|
4622
|
+
targetImpl.memoizedCanonicalId = str;
|
|
4484
4623
|
}
|
|
4485
4624
|
return targetImpl.memoizedCanonicalId;
|
|
4486
4625
|
}
|
|
@@ -4503,10 +4642,14 @@ function stringifyTarget(target) {
|
|
|
4503
4642
|
.join(', ')}]`;
|
|
4504
4643
|
}
|
|
4505
4644
|
if (target.startAt) {
|
|
4506
|
-
str += ', startAt: '
|
|
4645
|
+
str += ', startAt: ';
|
|
4646
|
+
str += target.startAt.inclusive ? 'b:' : 'a:';
|
|
4647
|
+
str += target.startAt.position.map(p => canonicalId(p)).join(',');
|
|
4507
4648
|
}
|
|
4508
4649
|
if (target.endAt) {
|
|
4509
|
-
str += ', endAt: '
|
|
4650
|
+
str += ', endAt: ';
|
|
4651
|
+
str += target.endAt.inclusive ? 'a:' : 'b:';
|
|
4652
|
+
str += target.endAt.position.map(p => canonicalId(p)).join(',');
|
|
4510
4653
|
}
|
|
4511
4654
|
return `Target(${str})`;
|
|
4512
4655
|
}
|
|
@@ -4729,7 +4872,6 @@ class ArrayContainsAnyFilter extends FieldFilter {
|
|
|
4729
4872
|
return other.arrayValue.values.some(val => arrayValueContains(this.value.arrayValue, val));
|
|
4730
4873
|
}
|
|
4731
4874
|
}
|
|
4732
|
-
// TODO(indexing): Change Bound.before to "inclusive"
|
|
4733
4875
|
/**
|
|
4734
4876
|
* Represents a bound of a query.
|
|
4735
4877
|
*
|
|
@@ -4745,17 +4887,11 @@ class ArrayContainsAnyFilter extends FieldFilter {
|
|
|
4745
4887
|
* just after the provided values.
|
|
4746
4888
|
*/
|
|
4747
4889
|
class Bound {
|
|
4748
|
-
constructor(position,
|
|
4890
|
+
constructor(position, inclusive) {
|
|
4749
4891
|
this.position = position;
|
|
4750
|
-
this.
|
|
4892
|
+
this.inclusive = inclusive;
|
|
4751
4893
|
}
|
|
4752
4894
|
}
|
|
4753
|
-
function canonifyBound(bound) {
|
|
4754
|
-
// TODO(b/29183165): Make this collision robust.
|
|
4755
|
-
return `${bound.before ? 'b' : 'a'}:${bound.position
|
|
4756
|
-
.map(p => canonicalId(p))
|
|
4757
|
-
.join(',')}`;
|
|
4758
|
-
}
|
|
4759
4895
|
/**
|
|
4760
4896
|
* An ordering on a field, in some Direction. Direction defaults to ASCENDING.
|
|
4761
4897
|
*/
|
|
@@ -4775,11 +4911,7 @@ function stringifyOrderBy(orderBy) {
|
|
|
4775
4911
|
function orderByEquals(left, right) {
|
|
4776
4912
|
return left.dir === right.dir && left.field.isEqual(right.field);
|
|
4777
4913
|
}
|
|
4778
|
-
|
|
4779
|
-
* Returns true if a document sorts before a bound using the provided sort
|
|
4780
|
-
* order.
|
|
4781
|
-
*/
|
|
4782
|
-
function sortsBeforeDocument(bound, orderBy, doc) {
|
|
4914
|
+
function boundCompareToDocument(bound, orderBy, doc) {
|
|
4783
4915
|
let comparison = 0;
|
|
4784
4916
|
for (let i = 0; i < bound.position.length; i++) {
|
|
4785
4917
|
const orderByComponent = orderBy[i];
|
|
@@ -4798,7 +4930,23 @@ function sortsBeforeDocument(bound, orderBy, doc) {
|
|
|
4798
4930
|
break;
|
|
4799
4931
|
}
|
|
4800
4932
|
}
|
|
4801
|
-
return
|
|
4933
|
+
return comparison;
|
|
4934
|
+
}
|
|
4935
|
+
/**
|
|
4936
|
+
* Returns true if a document sorts after a bound using the provided sort
|
|
4937
|
+
* order.
|
|
4938
|
+
*/
|
|
4939
|
+
function boundSortsAfterDocument(bound, orderBy, doc) {
|
|
4940
|
+
const comparison = boundCompareToDocument(bound, orderBy, doc);
|
|
4941
|
+
return bound.inclusive ? comparison >= 0 : comparison > 0;
|
|
4942
|
+
}
|
|
4943
|
+
/**
|
|
4944
|
+
* Returns true if a document sorts before a bound using the provided sort
|
|
4945
|
+
* order.
|
|
4946
|
+
*/
|
|
4947
|
+
function boundSortsBeforeDocument(bound, orderBy, doc) {
|
|
4948
|
+
const comparison = boundCompareToDocument(bound, orderBy, doc);
|
|
4949
|
+
return bound.inclusive ? comparison <= 0 : comparison < 0;
|
|
4802
4950
|
}
|
|
4803
4951
|
function boundEquals(left, right) {
|
|
4804
4952
|
if (left === null) {
|
|
@@ -4807,7 +4955,7 @@ function boundEquals(left, right) {
|
|
|
4807
4955
|
else if (right === null) {
|
|
4808
4956
|
return false;
|
|
4809
4957
|
}
|
|
4810
|
-
if (left.
|
|
4958
|
+
if (left.inclusive !== right.inclusive ||
|
|
4811
4959
|
left.position.length !== right.position.length) {
|
|
4812
4960
|
return false;
|
|
4813
4961
|
}
|
|
@@ -5011,10 +5159,10 @@ function queryToTarget(query) {
|
|
|
5011
5159
|
}
|
|
5012
5160
|
// We need to swap the cursors to match the now-flipped query ordering.
|
|
5013
5161
|
const startAt = queryImpl.endAt
|
|
5014
|
-
? new Bound(queryImpl.endAt.position, !queryImpl.endAt.
|
|
5162
|
+
? new Bound(queryImpl.endAt.position, !queryImpl.endAt.inclusive)
|
|
5015
5163
|
: null;
|
|
5016
5164
|
const endAt = queryImpl.startAt
|
|
5017
|
-
? new Bound(queryImpl.startAt.position, !queryImpl.startAt.
|
|
5165
|
+
? new Bound(queryImpl.startAt.position, !queryImpl.startAt.inclusive)
|
|
5018
5166
|
: null;
|
|
5019
5167
|
// Now return as a LimitType.First query.
|
|
5020
5168
|
queryImpl.memoizedTarget = newTarget(queryImpl.path, queryImpl.collectionGroup, orderBys, queryImpl.filters, queryImpl.limit, startAt, endAt);
|
|
@@ -5102,11 +5250,11 @@ function queryMatchesFilters(query, doc) {
|
|
|
5102
5250
|
/** Makes sure a document is within the bounds, if provided. */
|
|
5103
5251
|
function queryMatchesBounds(query, doc) {
|
|
5104
5252
|
if (query.startAt &&
|
|
5105
|
-
!
|
|
5253
|
+
!boundSortsBeforeDocument(query.startAt, queryOrderBy(query), doc)) {
|
|
5106
5254
|
return false;
|
|
5107
5255
|
}
|
|
5108
5256
|
if (query.endAt &&
|
|
5109
|
-
|
|
5257
|
+
!boundSortsAfterDocument(query.endAt, queryOrderBy(query), doc)) {
|
|
5110
5258
|
return false;
|
|
5111
5259
|
}
|
|
5112
5260
|
return true;
|
|
@@ -7985,10 +8133,10 @@ function toQueryTarget(serializer, target) {
|
|
|
7985
8133
|
result.structuredQuery.limit = limit;
|
|
7986
8134
|
}
|
|
7987
8135
|
if (target.startAt) {
|
|
7988
|
-
result.structuredQuery.startAt =
|
|
8136
|
+
result.structuredQuery.startAt = toStartAtCursor(target.startAt);
|
|
7989
8137
|
}
|
|
7990
8138
|
if (target.endAt) {
|
|
7991
|
-
result.structuredQuery.endAt =
|
|
8139
|
+
result.structuredQuery.endAt = toEndAtCursor(target.endAt);
|
|
7992
8140
|
}
|
|
7993
8141
|
return result;
|
|
7994
8142
|
}
|
|
@@ -8021,11 +8169,11 @@ function convertQueryTargetToQuery(target) {
|
|
|
8021
8169
|
}
|
|
8022
8170
|
let startAt = null;
|
|
8023
8171
|
if (query.startAt) {
|
|
8024
|
-
startAt =
|
|
8172
|
+
startAt = fromStartAtCursor(query.startAt);
|
|
8025
8173
|
}
|
|
8026
8174
|
let endAt = null;
|
|
8027
8175
|
if (query.endAt) {
|
|
8028
|
-
endAt =
|
|
8176
|
+
endAt = fromEndAtCursor(query.endAt);
|
|
8029
8177
|
}
|
|
8030
8178
|
return newQuery(path, collectionGroup, orderBy, filterBy, limit, "F" /* First */, startAt, endAt);
|
|
8031
8179
|
}
|
|
@@ -8116,16 +8264,27 @@ function toOrder(orderBys) {
|
|
|
8116
8264
|
function fromOrder(orderBys) {
|
|
8117
8265
|
return orderBys.map(order => fromPropertyOrder(order));
|
|
8118
8266
|
}
|
|
8119
|
-
function
|
|
8267
|
+
function toStartAtCursor(cursor) {
|
|
8120
8268
|
return {
|
|
8121
|
-
before: cursor.
|
|
8269
|
+
before: cursor.inclusive,
|
|
8122
8270
|
values: cursor.position
|
|
8123
8271
|
};
|
|
8124
8272
|
}
|
|
8125
|
-
function
|
|
8126
|
-
|
|
8273
|
+
function toEndAtCursor(cursor) {
|
|
8274
|
+
return {
|
|
8275
|
+
before: !cursor.inclusive,
|
|
8276
|
+
values: cursor.position
|
|
8277
|
+
};
|
|
8278
|
+
}
|
|
8279
|
+
function fromStartAtCursor(cursor) {
|
|
8280
|
+
const inclusive = !!cursor.before;
|
|
8281
|
+
const position = cursor.values || [];
|
|
8282
|
+
return new Bound(position, inclusive);
|
|
8283
|
+
}
|
|
8284
|
+
function fromEndAtCursor(cursor) {
|
|
8285
|
+
const inclusive = !cursor.before;
|
|
8127
8286
|
const position = cursor.values || [];
|
|
8128
|
-
return new Bound(position,
|
|
8287
|
+
return new Bound(position, inclusive);
|
|
8129
8288
|
}
|
|
8130
8289
|
// visible for testing
|
|
8131
8290
|
function toDirection(dir) {
|
|
@@ -8589,6 +8748,19 @@ function fromBundleMetadata(metadata) {
|
|
|
8589
8748
|
version: metadata.version,
|
|
8590
8749
|
createTime: fromVersion(metadata.createTime)
|
|
8591
8750
|
};
|
|
8751
|
+
}
|
|
8752
|
+
function toDbIndexConfiguration(index) {
|
|
8753
|
+
return new DbIndexConfiguration(index.indexId, index.collectionGroup, index.fields.map(s => [s.fieldPath.canonicalString(), s.kind]));
|
|
8754
|
+
}
|
|
8755
|
+
function fromDbIndexConfiguration(index, state) {
|
|
8756
|
+
const decodedState = state
|
|
8757
|
+
? new IndexState(state.sequenceNumber, new IndexOffset(fromDbTimestamp(state.readTime), new DocumentKey(decodeResourcePath(state.documentKey)), state.largestBatchId))
|
|
8758
|
+
: IndexState.empty();
|
|
8759
|
+
const decodedSegments = index.fields.map(([fieldPath, kind]) => new IndexSegment(FieldPath$1.fromServerFormat(fieldPath), kind));
|
|
8760
|
+
return new FieldIndex(index.indexId, index.collectionGroup, decodedSegments, decodedState);
|
|
8761
|
+
}
|
|
8762
|
+
function toDbIndexState(indexId, user, sequenceNumber, offset) {
|
|
8763
|
+
return new DbIndexState(indexId, user.uid || '', sequenceNumber, toDbTimestamp(offset.readTime), encodeResourcePath(offset.documentKey.path), offset.largestBatchId);
|
|
8592
8764
|
}
|
|
8593
8765
|
|
|
8594
8766
|
/**
|
|
@@ -8678,6 +8850,38 @@ class MemoryIndexManager {
|
|
|
8678
8850
|
getCollectionParents(transaction, collectionId) {
|
|
8679
8851
|
return PersistencePromise.resolve(this.collectionParentIndex.getEntries(collectionId));
|
|
8680
8852
|
}
|
|
8853
|
+
addFieldIndex(transaction, index) {
|
|
8854
|
+
// Field indices are not supported with memory persistence.
|
|
8855
|
+
return PersistencePromise.resolve();
|
|
8856
|
+
}
|
|
8857
|
+
deleteFieldIndex(transaction, index) {
|
|
8858
|
+
// Field indices are not supported with memory persistence.
|
|
8859
|
+
return PersistencePromise.resolve();
|
|
8860
|
+
}
|
|
8861
|
+
getDocumentsMatchingTarget(transaction, fieldIndex, target) {
|
|
8862
|
+
// Field indices are not supported with memory persistence.
|
|
8863
|
+
return PersistencePromise.resolve(documentKeySet());
|
|
8864
|
+
}
|
|
8865
|
+
getFieldIndex(transaction, target) {
|
|
8866
|
+
// Field indices are not supported with memory persistence.
|
|
8867
|
+
return PersistencePromise.resolve(null);
|
|
8868
|
+
}
|
|
8869
|
+
getFieldIndexes(transaction, collectionGroup) {
|
|
8870
|
+
// Field indices are not supported with memory persistence.
|
|
8871
|
+
return PersistencePromise.resolve([]);
|
|
8872
|
+
}
|
|
8873
|
+
getNextCollectionGroupToUpdate(transaction) {
|
|
8874
|
+
// Field indices are not supported with memory persistence.
|
|
8875
|
+
return PersistencePromise.resolve(null);
|
|
8876
|
+
}
|
|
8877
|
+
updateCollectionGroup(transaction, collectionGroup, offset) {
|
|
8878
|
+
// Field indices are not supported with memory persistence.
|
|
8879
|
+
return PersistencePromise.resolve();
|
|
8880
|
+
}
|
|
8881
|
+
updateIndexEntries(transaction, documents) {
|
|
8882
|
+
// Field indices are not supported with memory persistence.
|
|
8883
|
+
return PersistencePromise.resolve();
|
|
8884
|
+
}
|
|
8681
8885
|
}
|
|
8682
8886
|
/**
|
|
8683
8887
|
* Internal implementation of the collection-parent index exposed by MemoryIndexManager.
|
|
@@ -8729,17 +8933,22 @@ class MemoryCollectionParentIndex {
|
|
|
8729
8933
|
*/
|
|
8730
8934
|
/**
|
|
8731
8935
|
* A persisted implementation of IndexManager.
|
|
8936
|
+
*
|
|
8937
|
+
* PORTING NOTE: Unlike iOS and Android, the Web SDK does not memoize index
|
|
8938
|
+
* data as it supports multi-tab access.
|
|
8732
8939
|
*/
|
|
8733
8940
|
class IndexedDbIndexManager {
|
|
8734
|
-
constructor() {
|
|
8941
|
+
constructor(user) {
|
|
8942
|
+
this.user = user;
|
|
8735
8943
|
/**
|
|
8736
8944
|
* An in-memory copy of the index entries we've already written since the SDK
|
|
8737
8945
|
* launched. Used to avoid re-writing the same entry repeatedly.
|
|
8738
8946
|
*
|
|
8739
|
-
* This is *NOT* a complete cache of what's in persistence and so can never be
|
|
8740
|
-
* satisfy reads.
|
|
8947
|
+
* This is *NOT* a complete cache of what's in persistence and so can never be
|
|
8948
|
+
* used to satisfy reads.
|
|
8741
8949
|
*/
|
|
8742
8950
|
this.collectionParentsCache = new MemoryCollectionParentIndex();
|
|
8951
|
+
this.uid = user.uid || '';
|
|
8743
8952
|
}
|
|
8744
8953
|
/**
|
|
8745
8954
|
* Adds a new entry to the collection parent index.
|
|
@@ -8786,6 +8995,85 @@ class IndexedDbIndexManager {
|
|
|
8786
8995
|
return parentPaths;
|
|
8787
8996
|
});
|
|
8788
8997
|
}
|
|
8998
|
+
addFieldIndex(transaction, index) {
|
|
8999
|
+
// TODO(indexing): Verify that the auto-incrementing index ID works in
|
|
9000
|
+
// Safari & Firefox.
|
|
9001
|
+
const indexes = indexConfigurationStore(transaction);
|
|
9002
|
+
const dbIndex = toDbIndexConfiguration(index);
|
|
9003
|
+
delete dbIndex.indexId; // `indexId` is auto-populated by IndexedDb
|
|
9004
|
+
return indexes.add(dbIndex).next();
|
|
9005
|
+
}
|
|
9006
|
+
deleteFieldIndex(transaction, index) {
|
|
9007
|
+
const indexes = indexConfigurationStore(transaction);
|
|
9008
|
+
const states = indexStateStore(transaction);
|
|
9009
|
+
const entries = indexEntriesStore(transaction);
|
|
9010
|
+
return indexes
|
|
9011
|
+
.delete(index.indexId)
|
|
9012
|
+
.next(() => states.delete(IDBKeyRange.bound([index.indexId], [index.indexId + 1],
|
|
9013
|
+
/*lowerOpen=*/ false,
|
|
9014
|
+
/*upperOpen=*/ true)))
|
|
9015
|
+
.next(() => entries.delete(IDBKeyRange.bound([index.indexId], [index.indexId + 1],
|
|
9016
|
+
/*lowerOpen=*/ false,
|
|
9017
|
+
/*upperOpen=*/ true)));
|
|
9018
|
+
}
|
|
9019
|
+
getDocumentsMatchingTarget(transaction, fieldIndex, target) {
|
|
9020
|
+
// TODO(indexing): Implement
|
|
9021
|
+
return PersistencePromise.resolve(documentKeySet());
|
|
9022
|
+
}
|
|
9023
|
+
getFieldIndex(transaction, target) {
|
|
9024
|
+
// TODO(indexing): Implement
|
|
9025
|
+
return PersistencePromise.resolve(null);
|
|
9026
|
+
}
|
|
9027
|
+
getFieldIndexes(transaction, collectionGroup) {
|
|
9028
|
+
const indexes = indexConfigurationStore(transaction);
|
|
9029
|
+
const states = indexStateStore(transaction);
|
|
9030
|
+
return (collectionGroup
|
|
9031
|
+
? indexes.loadAll(DbIndexConfiguration.collectionGroupIndex, IDBKeyRange.bound(collectionGroup, collectionGroup))
|
|
9032
|
+
: indexes.loadAll()).next(indexConfigs => {
|
|
9033
|
+
const result = [];
|
|
9034
|
+
return PersistencePromise.forEach(indexConfigs, (indexConfig) => {
|
|
9035
|
+
return states
|
|
9036
|
+
.get([indexConfig.indexId, this.uid])
|
|
9037
|
+
.next(indexState => {
|
|
9038
|
+
result.push(fromDbIndexConfiguration(indexConfig, indexState));
|
|
9039
|
+
});
|
|
9040
|
+
}).next(() => result);
|
|
9041
|
+
});
|
|
9042
|
+
}
|
|
9043
|
+
getNextCollectionGroupToUpdate(transaction) {
|
|
9044
|
+
return this.getFieldIndexes(transaction).next(indexes => {
|
|
9045
|
+
if (indexes.length === 0) {
|
|
9046
|
+
return null;
|
|
9047
|
+
}
|
|
9048
|
+
indexes.sort((l, r) => l.indexState.sequenceNumber - r.indexState.sequenceNumber);
|
|
9049
|
+
return indexes[0].collectionGroup;
|
|
9050
|
+
});
|
|
9051
|
+
}
|
|
9052
|
+
updateCollectionGroup(transaction, collectionGroup, offset) {
|
|
9053
|
+
const indexes = indexConfigurationStore(transaction);
|
|
9054
|
+
const states = indexStateStore(transaction);
|
|
9055
|
+
return this.getNextSequenceNumber(transaction).next(nextSequenceNumber => indexes
|
|
9056
|
+
.loadAll(DbIndexConfiguration.collectionGroupIndex, IDBKeyRange.bound(collectionGroup, collectionGroup))
|
|
9057
|
+
.next(configs => PersistencePromise.forEach(configs, (config) => states.put(toDbIndexState(config.indexId, this.user, nextSequenceNumber, offset)))));
|
|
9058
|
+
}
|
|
9059
|
+
updateIndexEntries(transaction, documents) {
|
|
9060
|
+
// TODO(indexing): Implement
|
|
9061
|
+
return PersistencePromise.resolve();
|
|
9062
|
+
}
|
|
9063
|
+
getNextSequenceNumber(transaction) {
|
|
9064
|
+
let nextSequenceNumber = 1;
|
|
9065
|
+
const states = indexStateStore(transaction);
|
|
9066
|
+
return states
|
|
9067
|
+
.iterate({
|
|
9068
|
+
index: DbIndexState.sequenceNumberIndex,
|
|
9069
|
+
reverse: true,
|
|
9070
|
+
range: IDBKeyRange.upperBound([this.uid, Number.MAX_SAFE_INTEGER])
|
|
9071
|
+
}, (_, state, controller) => {
|
|
9072
|
+
controller.done();
|
|
9073
|
+
nextSequenceNumber = state.sequenceNumber + 1;
|
|
9074
|
+
})
|
|
9075
|
+
.next(() => nextSequenceNumber);
|
|
9076
|
+
}
|
|
8789
9077
|
}
|
|
8790
9078
|
/**
|
|
8791
9079
|
* Helper to get a typed SimpleDbStore for the collectionParents
|
|
@@ -8793,6 +9081,24 @@ class IndexedDbIndexManager {
|
|
|
8793
9081
|
*/
|
|
8794
9082
|
function collectionParentsStore(txn) {
|
|
8795
9083
|
return getStore(txn, DbCollectionParent.store);
|
|
9084
|
+
}
|
|
9085
|
+
/**
|
|
9086
|
+
* Helper to get a typed SimpleDbStore for the index entry object store.
|
|
9087
|
+
*/
|
|
9088
|
+
function indexEntriesStore(txn) {
|
|
9089
|
+
return getStore(txn, DbIndexEntry.store);
|
|
9090
|
+
}
|
|
9091
|
+
/**
|
|
9092
|
+
* Helper to get a typed SimpleDbStore for the index configuration object store.
|
|
9093
|
+
*/
|
|
9094
|
+
function indexConfigurationStore(txn) {
|
|
9095
|
+
return getStore(txn, DbIndexConfiguration.store);
|
|
9096
|
+
}
|
|
9097
|
+
/**
|
|
9098
|
+
* Helper to get a typed SimpleDbStore for the index state object store.
|
|
9099
|
+
*/
|
|
9100
|
+
function indexStateStore(txn) {
|
|
9101
|
+
return getStore(txn, DbIndexState.store);
|
|
8796
9102
|
}
|
|
8797
9103
|
|
|
8798
9104
|
/**
|
|
@@ -10262,12 +10568,10 @@ class RemoteDocumentChangeBuffer {
|
|
|
10262
10568
|
* `newIndexedDbRemoteDocumentCache()`.
|
|
10263
10569
|
*/
|
|
10264
10570
|
class IndexedDbRemoteDocumentCacheImpl {
|
|
10265
|
-
|
|
10266
|
-
* @param serializer - The document serializer.
|
|
10267
|
-
* @param indexManager - The query indexes that need to be maintained.
|
|
10268
|
-
*/
|
|
10269
|
-
constructor(serializer, indexManager) {
|
|
10571
|
+
constructor(serializer) {
|
|
10270
10572
|
this.serializer = serializer;
|
|
10573
|
+
}
|
|
10574
|
+
setIndexManager(indexManager) {
|
|
10271
10575
|
this.indexManager = indexManager;
|
|
10272
10576
|
}
|
|
10273
10577
|
/**
|
|
@@ -10389,21 +10693,21 @@ class IndexedDbRemoteDocumentCacheImpl {
|
|
|
10389
10693
|
}
|
|
10390
10694
|
});
|
|
10391
10695
|
}
|
|
10392
|
-
|
|
10696
|
+
getAll(transaction, collection, sinceReadTime) {
|
|
10393
10697
|
let results = mutableDocumentMap();
|
|
10394
|
-
const immediateChildrenPathLength =
|
|
10698
|
+
const immediateChildrenPathLength = collection.length + 1;
|
|
10395
10699
|
const iterationOptions = {};
|
|
10396
10700
|
if (sinceReadTime.isEqual(SnapshotVersion.min())) {
|
|
10397
10701
|
// Documents are ordered by key, so we can use a prefix scan to narrow
|
|
10398
10702
|
// down the documents we need to match the query against.
|
|
10399
|
-
const startKey =
|
|
10703
|
+
const startKey = collection.toArray();
|
|
10400
10704
|
iterationOptions.range = IDBKeyRange.lowerBound(startKey);
|
|
10401
10705
|
}
|
|
10402
10706
|
else {
|
|
10403
10707
|
// Execute an index-free query and filter by read time. This is safe
|
|
10404
10708
|
// since all document changes to queries that have a
|
|
10405
10709
|
// lastLimboFreeSnapshotVersion (`sinceReadTime`) have a read time set.
|
|
10406
|
-
const collectionKey =
|
|
10710
|
+
const collectionKey = collection.toArray();
|
|
10407
10711
|
const readTimeKey = toDbTimestampKey(sinceReadTime);
|
|
10408
10712
|
iterationOptions.range = IDBKeyRange.lowerBound([collectionKey, readTimeKey],
|
|
10409
10713
|
/* open= */ true);
|
|
@@ -10420,12 +10724,12 @@ class IndexedDbRemoteDocumentCacheImpl {
|
|
|
10420
10724
|
return;
|
|
10421
10725
|
}
|
|
10422
10726
|
const document = this.maybeDecodeDocument(DocumentKey.fromSegments(key), dbRemoteDoc);
|
|
10423
|
-
if (
|
|
10424
|
-
control.done();
|
|
10425
|
-
}
|
|
10426
|
-
else if (queryMatches(query, document)) {
|
|
10727
|
+
if (collection.isPrefixOf(document.key.path)) {
|
|
10427
10728
|
results = results.insert(document.key, document);
|
|
10428
10729
|
}
|
|
10730
|
+
else {
|
|
10731
|
+
control.done();
|
|
10732
|
+
}
|
|
10429
10733
|
})
|
|
10430
10734
|
.next(() => results);
|
|
10431
10735
|
}
|
|
@@ -10463,14 +10767,9 @@ class IndexedDbRemoteDocumentCacheImpl {
|
|
|
10463
10767
|
return MutableDocument.newInvalidDocument(documentKey);
|
|
10464
10768
|
}
|
|
10465
10769
|
}
|
|
10466
|
-
/**
|
|
10467
|
-
|
|
10468
|
-
|
|
10469
|
-
* @param serializer - The document serializer.
|
|
10470
|
-
* @param indexManager - The query indexes that need to be maintained.
|
|
10471
|
-
*/
|
|
10472
|
-
function newIndexedDbRemoteDocumentCache(serializer, indexManager) {
|
|
10473
|
-
return new IndexedDbRemoteDocumentCacheImpl(serializer, indexManager);
|
|
10770
|
+
/** Creates a new IndexedDbRemoteDocumentCache. */
|
|
10771
|
+
function newIndexedDbRemoteDocumentCache(serializer) {
|
|
10772
|
+
return new IndexedDbRemoteDocumentCacheImpl(serializer);
|
|
10474
10773
|
}
|
|
10475
10774
|
/**
|
|
10476
10775
|
* Returns the set of documents that have changed since the specified read
|
|
@@ -10637,9 +10936,6 @@ class SchemaConverter {
|
|
|
10637
10936
|
* and local feature development.
|
|
10638
10937
|
*/
|
|
10639
10938
|
createOrUpgrade(db, txn, fromVersion, toVersion) {
|
|
10640
|
-
hardAssert(fromVersion < toVersion &&
|
|
10641
|
-
fromVersion >= 0 &&
|
|
10642
|
-
toVersion <= SCHEMA_VERSION);
|
|
10643
10939
|
const simpleDbTransaction = new SimpleDbTransaction('createOrUpgrade', txn);
|
|
10644
10940
|
if (fromVersion < 1 && toVersion >= 1) {
|
|
10645
10941
|
createPrimaryClientStore(db);
|
|
@@ -10706,6 +11002,11 @@ class SchemaConverter {
|
|
|
10706
11002
|
createNamedQueriesStore(db);
|
|
10707
11003
|
});
|
|
10708
11004
|
}
|
|
11005
|
+
if (fromVersion < 12 && toVersion >= 12) {
|
|
11006
|
+
p = p.next(() => {
|
|
11007
|
+
createFieldIndex(db);
|
|
11008
|
+
});
|
|
11009
|
+
}
|
|
10709
11010
|
return p;
|
|
10710
11011
|
}
|
|
10711
11012
|
addDocumentGlobal(txn) {
|
|
@@ -10912,6 +11213,20 @@ function createNamedQueriesStore(db) {
|
|
|
10912
11213
|
db.createObjectStore(DbNamedQuery.store, {
|
|
10913
11214
|
keyPath: DbNamedQuery.keyPath
|
|
10914
11215
|
});
|
|
11216
|
+
}
|
|
11217
|
+
function createFieldIndex(db) {
|
|
11218
|
+
const indexConfiguratioStore = db.createObjectStore(DbIndexConfiguration.store, {
|
|
11219
|
+
keyPath: DbIndexConfiguration.keyPath,
|
|
11220
|
+
autoIncrement: true
|
|
11221
|
+
});
|
|
11222
|
+
indexConfiguratioStore.createIndex(DbIndexConfiguration.collectionGroupIndex, DbIndexConfiguration.collectionGroupIndexPath, { unique: false });
|
|
11223
|
+
const indexStateStore = db.createObjectStore(DbIndexState.store, {
|
|
11224
|
+
keyPath: DbIndexState.keyPath
|
|
11225
|
+
});
|
|
11226
|
+
indexStateStore.createIndex(DbIndexState.sequenceNumberIndex, DbIndexState.sequenceNumberIndexPath, { unique: false });
|
|
11227
|
+
db.createObjectStore(DbIndexEntry.store, {
|
|
11228
|
+
keyPath: DbIndexEntry.keyPath
|
|
11229
|
+
});
|
|
10915
11230
|
}
|
|
10916
11231
|
|
|
10917
11232
|
/**
|
|
@@ -11023,7 +11338,7 @@ class IndexedDbPersistence {
|
|
|
11023
11338
|
* If set to true, forcefully obtains database access. Existing tabs will
|
|
11024
11339
|
* no longer be able to access IndexedDB.
|
|
11025
11340
|
*/
|
|
11026
|
-
forceOwningTab) {
|
|
11341
|
+
forceOwningTab, schemaVersion = SCHEMA_VERSION) {
|
|
11027
11342
|
this.allowTabSynchronization = allowTabSynchronization;
|
|
11028
11343
|
this.persistenceKey = persistenceKey;
|
|
11029
11344
|
this.clientId = clientId;
|
|
@@ -11032,6 +11347,7 @@ class IndexedDbPersistence {
|
|
|
11032
11347
|
this.document = document;
|
|
11033
11348
|
this.sequenceNumberSyncer = sequenceNumberSyncer;
|
|
11034
11349
|
this.forceOwningTab = forceOwningTab;
|
|
11350
|
+
this.schemaVersion = schemaVersion;
|
|
11035
11351
|
this.listenSequence = null;
|
|
11036
11352
|
this._started = false;
|
|
11037
11353
|
this.isPrimary = false;
|
|
@@ -11053,10 +11369,9 @@ class IndexedDbPersistence {
|
|
|
11053
11369
|
this.referenceDelegate = new IndexedDbLruDelegateImpl(this, lruParams);
|
|
11054
11370
|
this.dbName = persistenceKey + MAIN_DATABASE;
|
|
11055
11371
|
this.serializer = new LocalSerializer(serializer);
|
|
11056
|
-
this.simpleDb = new SimpleDb(this.dbName,
|
|
11372
|
+
this.simpleDb = new SimpleDb(this.dbName, this.schemaVersion, new SchemaConverter(this.serializer));
|
|
11057
11373
|
this.targetCache = new IndexedDbTargetCache(this.referenceDelegate, this.serializer);
|
|
11058
|
-
this.
|
|
11059
|
-
this.remoteDocumentCache = newIndexedDbRemoteDocumentCache(this.serializer, this.indexManager);
|
|
11374
|
+
this.remoteDocumentCache = newIndexedDbRemoteDocumentCache(this.serializer);
|
|
11060
11375
|
this.bundleCache = new IndexedDbBundleCache();
|
|
11061
11376
|
if (this.window && this.window.localStorage) {
|
|
11062
11377
|
this.webStorage = this.window.localStorage;
|
|
@@ -11392,8 +11707,8 @@ class IndexedDbPersistence {
|
|
|
11392
11707
|
get started() {
|
|
11393
11708
|
return this._started;
|
|
11394
11709
|
}
|
|
11395
|
-
getMutationQueue(user) {
|
|
11396
|
-
return IndexedDbMutationQueue.forUser(user, this.serializer,
|
|
11710
|
+
getMutationQueue(user, indexManager) {
|
|
11711
|
+
return IndexedDbMutationQueue.forUser(user, this.serializer, indexManager, this.referenceDelegate);
|
|
11397
11712
|
}
|
|
11398
11713
|
getTargetCache() {
|
|
11399
11714
|
return this.targetCache;
|
|
@@ -11401,8 +11716,8 @@ class IndexedDbPersistence {
|
|
|
11401
11716
|
getRemoteDocumentCache() {
|
|
11402
11717
|
return this.remoteDocumentCache;
|
|
11403
11718
|
}
|
|
11404
|
-
getIndexManager() {
|
|
11405
|
-
return
|
|
11719
|
+
getIndexManager(user) {
|
|
11720
|
+
return new IndexedDbIndexManager(user);
|
|
11406
11721
|
}
|
|
11407
11722
|
getBundleCache() {
|
|
11408
11723
|
return this.bundleCache;
|
|
@@ -11410,11 +11725,12 @@ class IndexedDbPersistence {
|
|
|
11410
11725
|
runTransaction(action, mode, transactionOperation) {
|
|
11411
11726
|
logDebug(LOG_TAG$d, 'Starting transaction:', action);
|
|
11412
11727
|
const simpleDbMode = mode === 'readonly' ? 'readonly' : 'readwrite';
|
|
11728
|
+
const objectStores = getObjectStores(this.schemaVersion);
|
|
11413
11729
|
let persistenceTransaction;
|
|
11414
11730
|
// Do all transactions as readwrite against all object stores, since we
|
|
11415
11731
|
// are the only reader/writer.
|
|
11416
11732
|
return this.simpleDb
|
|
11417
|
-
.runTransaction(action, simpleDbMode,
|
|
11733
|
+
.runTransaction(action, simpleDbMode, objectStores, simpleDbTxn => {
|
|
11418
11734
|
persistenceTransaction = new IndexedDbTransaction(simpleDbTxn, this.listenSequence
|
|
11419
11735
|
? this.listenSequence.next()
|
|
11420
11736
|
: ListenSequence.INVALID);
|
|
@@ -11786,39 +12102,28 @@ class LocalDocumentsView {
|
|
|
11786
12102
|
getDocumentsMatchingCollectionQuery(transaction, query, sinceReadTime) {
|
|
11787
12103
|
// Query the remote documents and overlay mutations.
|
|
11788
12104
|
let results;
|
|
11789
|
-
let mutationBatches;
|
|
11790
12105
|
return this.remoteDocumentCache
|
|
11791
|
-
.
|
|
12106
|
+
.getAll(transaction, query.path, sinceReadTime)
|
|
11792
12107
|
.next(queryResults => {
|
|
11793
12108
|
results = queryResults;
|
|
11794
12109
|
return this.mutationQueue.getAllMutationBatchesAffectingQuery(transaction, query);
|
|
11795
12110
|
})
|
|
11796
|
-
.next(
|
|
11797
|
-
mutationBatches
|
|
11798
|
-
|
|
11799
|
-
|
|
11800
|
-
|
|
11801
|
-
|
|
11802
|
-
|
|
11803
|
-
|
|
11804
|
-
|
|
11805
|
-
|
|
11806
|
-
|
|
11807
|
-
|
|
11808
|
-
|
|
11809
|
-
let document = results.get(key);
|
|
11810
|
-
if (document == null) {
|
|
11811
|
-
// Create invalid document to apply mutations on top of
|
|
11812
|
-
document = MutableDocument.newInvalidDocument(key);
|
|
11813
|
-
results = results.insert(key, document);
|
|
11814
|
-
}
|
|
11815
|
-
mutationApplyToLocalView(mutation, document, batch.localWriteTime);
|
|
11816
|
-
if (!document.isFoundDocument()) {
|
|
11817
|
-
results = results.remove(key);
|
|
11818
|
-
}
|
|
12111
|
+
.next(mutationBatches => {
|
|
12112
|
+
for (const batch of mutationBatches) {
|
|
12113
|
+
for (const mutation of batch.mutations) {
|
|
12114
|
+
const key = mutation.key;
|
|
12115
|
+
let document = results.get(key);
|
|
12116
|
+
if (document == null) {
|
|
12117
|
+
// Create invalid document to apply mutations on top of
|
|
12118
|
+
document = MutableDocument.newInvalidDocument(key);
|
|
12119
|
+
results = results.insert(key, document);
|
|
12120
|
+
}
|
|
12121
|
+
mutationApplyToLocalView(mutation, document, batch.localWriteTime);
|
|
12122
|
+
if (!document.isFoundDocument()) {
|
|
12123
|
+
results = results.remove(key);
|
|
11819
12124
|
}
|
|
11820
12125
|
}
|
|
11821
|
-
}
|
|
12126
|
+
}
|
|
11822
12127
|
})
|
|
11823
12128
|
.next(() => {
|
|
11824
12129
|
// Finally, filter out any documents that don't actually match
|
|
@@ -11831,29 +12136,6 @@ class LocalDocumentsView {
|
|
|
11831
12136
|
return results;
|
|
11832
12137
|
});
|
|
11833
12138
|
}
|
|
11834
|
-
addMissingBaseDocuments(transaction, matchingMutationBatches, existingDocuments) {
|
|
11835
|
-
let missingBaseDocEntriesForPatching = documentKeySet();
|
|
11836
|
-
for (const batch of matchingMutationBatches) {
|
|
11837
|
-
for (const mutation of batch.mutations) {
|
|
11838
|
-
if (mutation instanceof PatchMutation &&
|
|
11839
|
-
existingDocuments.get(mutation.key) === null) {
|
|
11840
|
-
missingBaseDocEntriesForPatching =
|
|
11841
|
-
missingBaseDocEntriesForPatching.add(mutation.key);
|
|
11842
|
-
}
|
|
11843
|
-
}
|
|
11844
|
-
}
|
|
11845
|
-
let mergedDocuments = existingDocuments;
|
|
11846
|
-
return this.remoteDocumentCache
|
|
11847
|
-
.getEntries(transaction, missingBaseDocEntriesForPatching)
|
|
11848
|
-
.next(missingBaseDocs => {
|
|
11849
|
-
missingBaseDocs.forEach((key, doc) => {
|
|
11850
|
-
if (doc.isFoundDocument()) {
|
|
11851
|
-
mergedDocuments = mergedDocuments.insert(key, doc);
|
|
11852
|
-
}
|
|
11853
|
-
});
|
|
11854
|
-
return mergedDocuments;
|
|
11855
|
-
});
|
|
11856
|
-
}
|
|
11857
12139
|
}
|
|
11858
12140
|
|
|
11859
12141
|
/**
|
|
@@ -11912,11 +12194,18 @@ class LocalStoreImpl {
|
|
|
11912
12194
|
* PORTING NOTE: This is only used for multi-tab synchronization.
|
|
11913
12195
|
*/
|
|
11914
12196
|
this.lastDocumentChangeReadTime = SnapshotVersion.min();
|
|
11915
|
-
this.mutationQueue = persistence.getMutationQueue(initialUser);
|
|
11916
12197
|
this.remoteDocuments = persistence.getRemoteDocumentCache();
|
|
11917
12198
|
this.targetCache = persistence.getTargetCache();
|
|
11918
|
-
this.localDocuments = new LocalDocumentsView(this.remoteDocuments, this.mutationQueue, this.persistence.getIndexManager());
|
|
11919
12199
|
this.bundleCache = persistence.getBundleCache();
|
|
12200
|
+
this.initializeUserComponents(initialUser);
|
|
12201
|
+
}
|
|
12202
|
+
initializeUserComponents(user) {
|
|
12203
|
+
// TODO(indexing): Add spec tests that test these components change after a
|
|
12204
|
+
// user change
|
|
12205
|
+
this.indexManager = this.persistence.getIndexManager(user);
|
|
12206
|
+
this.mutationQueue = this.persistence.getMutationQueue(user, this.indexManager);
|
|
12207
|
+
this.localDocuments = new LocalDocumentsView(this.remoteDocuments, this.mutationQueue, this.indexManager);
|
|
12208
|
+
this.remoteDocuments.setIndexManager(this.indexManager);
|
|
11920
12209
|
this.queryEngine.setLocalDocumentsView(this.localDocuments);
|
|
11921
12210
|
}
|
|
11922
12211
|
collectGarbage(garbageCollector) {
|
|
@@ -11938,8 +12227,6 @@ persistence, queryEngine, initialUser, serializer) {
|
|
|
11938
12227
|
// change.
|
|
11939
12228
|
async function localStoreHandleUserChange(localStore, user) {
|
|
11940
12229
|
const localStoreImpl = debugCast(localStore);
|
|
11941
|
-
let newMutationQueue = localStoreImpl.mutationQueue;
|
|
11942
|
-
let newLocalDocuments = localStoreImpl.localDocuments;
|
|
11943
12230
|
const result = await localStoreImpl.persistence.runTransaction('Handle user change', 'readonly', txn => {
|
|
11944
12231
|
// Swap out the mutation queue, grabbing the pending mutation batches
|
|
11945
12232
|
// before and after.
|
|
@@ -11948,11 +12235,8 @@ async function localStoreHandleUserChange(localStore, user) {
|
|
|
11948
12235
|
.getAllMutationBatches(txn)
|
|
11949
12236
|
.next(promisedOldBatches => {
|
|
11950
12237
|
oldBatches = promisedOldBatches;
|
|
11951
|
-
|
|
11952
|
-
|
|
11953
|
-
// MutationQueue.
|
|
11954
|
-
newLocalDocuments = new LocalDocumentsView(localStoreImpl.remoteDocuments, newMutationQueue, localStoreImpl.persistence.getIndexManager());
|
|
11955
|
-
return newMutationQueue.getAllMutationBatches(txn);
|
|
12238
|
+
localStoreImpl.initializeUserComponents(user);
|
|
12239
|
+
return localStoreImpl.mutationQueue.getAllMutationBatches(txn);
|
|
11956
12240
|
})
|
|
11957
12241
|
.next(newBatches => {
|
|
11958
12242
|
const removedBatchIds = [];
|
|
@@ -11973,7 +12257,7 @@ async function localStoreHandleUserChange(localStore, user) {
|
|
|
11973
12257
|
}
|
|
11974
12258
|
// Return the set of all (potentially) changed documents and the list
|
|
11975
12259
|
// of mutation batch IDs that were affected by change.
|
|
11976
|
-
return
|
|
12260
|
+
return localStoreImpl.localDocuments
|
|
11977
12261
|
.getDocuments(txn, changedKeys)
|
|
11978
12262
|
.next(affectedDocuments => {
|
|
11979
12263
|
return {
|
|
@@ -11984,9 +12268,6 @@ async function localStoreHandleUserChange(localStore, user) {
|
|
|
11984
12268
|
});
|
|
11985
12269
|
});
|
|
11986
12270
|
});
|
|
11987
|
-
localStoreImpl.mutationQueue = newMutationQueue;
|
|
11988
|
-
localStoreImpl.localDocuments = newLocalDocuments;
|
|
11989
|
-
localStoreImpl.queryEngine.setLocalDocumentsView(localStoreImpl.localDocuments);
|
|
11990
12271
|
return result;
|
|
11991
12272
|
}
|
|
11992
12273
|
/* Accepts locally generated Mutations and commit them to storage. */
|
|
@@ -13052,14 +13333,16 @@ class MemoryRemoteDocumentCacheImpl {
|
|
|
13052
13333
|
* expected to just return 0 to avoid unnecessarily doing the work of
|
|
13053
13334
|
* calculating the size.
|
|
13054
13335
|
*/
|
|
13055
|
-
constructor(
|
|
13056
|
-
this.indexManager = indexManager;
|
|
13336
|
+
constructor(sizer) {
|
|
13057
13337
|
this.sizer = sizer;
|
|
13058
13338
|
/** Underlying cache of documents and their read times. */
|
|
13059
13339
|
this.docs = documentEntryMap();
|
|
13060
13340
|
/** Size of all cached documents. */
|
|
13061
13341
|
this.size = 0;
|
|
13062
13342
|
}
|
|
13343
|
+
setIndexManager(indexManager) {
|
|
13344
|
+
this.indexManager = indexManager;
|
|
13345
|
+
}
|
|
13063
13346
|
/**
|
|
13064
13347
|
* Adds the supplied entry to the cache and updates the cache size as appropriate.
|
|
13065
13348
|
*
|
|
@@ -13107,21 +13390,22 @@ class MemoryRemoteDocumentCacheImpl {
|
|
|
13107
13390
|
});
|
|
13108
13391
|
return PersistencePromise.resolve(results);
|
|
13109
13392
|
}
|
|
13110
|
-
|
|
13393
|
+
getAll(transaction, collectionPath, sinceReadTime) {
|
|
13111
13394
|
let results = mutableDocumentMap();
|
|
13112
13395
|
// Documents are ordered by key, so we can use a prefix scan to narrow down
|
|
13113
13396
|
// the documents we need to match the query against.
|
|
13114
|
-
const prefix = new DocumentKey(
|
|
13397
|
+
const prefix = new DocumentKey(collectionPath.child(''));
|
|
13115
13398
|
const iterator = this.docs.getIteratorFrom(prefix);
|
|
13116
13399
|
while (iterator.hasNext()) {
|
|
13117
13400
|
const { key, value: { document } } = iterator.getNext();
|
|
13118
|
-
if (!
|
|
13401
|
+
if (!collectionPath.isPrefixOf(key.path)) {
|
|
13119
13402
|
break;
|
|
13120
13403
|
}
|
|
13121
|
-
if (
|
|
13404
|
+
if (key.path.length > collectionPath.length + 1) {
|
|
13405
|
+
// Exclude entries from subcollections.
|
|
13122
13406
|
continue;
|
|
13123
13407
|
}
|
|
13124
|
-
if (
|
|
13408
|
+
if (document.readTime.compareTo(sinceReadTime) <= 0) {
|
|
13125
13409
|
continue;
|
|
13126
13410
|
}
|
|
13127
13411
|
results = results.insert(document.key, document.mutableCopy());
|
|
@@ -13143,13 +13427,12 @@ class MemoryRemoteDocumentCacheImpl {
|
|
|
13143
13427
|
/**
|
|
13144
13428
|
* Creates a new memory-only RemoteDocumentCache.
|
|
13145
13429
|
*
|
|
13146
|
-
* @param indexManager - A class that manages collection group indices.
|
|
13147
13430
|
* @param sizer - Used to assess the size of a document. For eager GC, this is
|
|
13148
13431
|
* expected to just return 0 to avoid unnecessarily doing the work of
|
|
13149
13432
|
* calculating the size.
|
|
13150
13433
|
*/
|
|
13151
|
-
function newMemoryRemoteDocumentCache(
|
|
13152
|
-
return new MemoryRemoteDocumentCacheImpl(
|
|
13434
|
+
function newMemoryRemoteDocumentCache(sizer) {
|
|
13435
|
+
return new MemoryRemoteDocumentCacheImpl(sizer);
|
|
13153
13436
|
}
|
|
13154
13437
|
/**
|
|
13155
13438
|
* Handles the details of adding and updating documents in the MemoryRemoteDocumentCache.
|
|
@@ -13350,7 +13633,7 @@ class MemoryPersistence {
|
|
|
13350
13633
|
this.targetCache = new MemoryTargetCache(this);
|
|
13351
13634
|
const sizer = (doc) => this.referenceDelegate.documentSize(doc);
|
|
13352
13635
|
this.indexManager = new MemoryIndexManager();
|
|
13353
|
-
this.remoteDocumentCache = newMemoryRemoteDocumentCache(
|
|
13636
|
+
this.remoteDocumentCache = newMemoryRemoteDocumentCache(sizer);
|
|
13354
13637
|
this.serializer = new LocalSerializer(serializer);
|
|
13355
13638
|
this.bundleCache = new MemoryBundleCache(this.serializer);
|
|
13356
13639
|
}
|
|
@@ -13371,13 +13654,15 @@ class MemoryPersistence {
|
|
|
13371
13654
|
setNetworkEnabled() {
|
|
13372
13655
|
// No op.
|
|
13373
13656
|
}
|
|
13374
|
-
getIndexManager() {
|
|
13657
|
+
getIndexManager(user) {
|
|
13658
|
+
// We do not currently support indices for memory persistence, so we can
|
|
13659
|
+
// return the same shared instance of the memory index manager.
|
|
13375
13660
|
return this.indexManager;
|
|
13376
13661
|
}
|
|
13377
|
-
getMutationQueue(user) {
|
|
13662
|
+
getMutationQueue(user, indexManager) {
|
|
13378
13663
|
let queue = this.mutationQueues[user.toKey()];
|
|
13379
13664
|
if (!queue) {
|
|
13380
|
-
queue = new MemoryMutationQueue(
|
|
13665
|
+
queue = new MemoryMutationQueue(indexManager, this.referenceDelegate);
|
|
13381
13666
|
this.mutationQueues[user.toKey()] = queue;
|
|
13382
13667
|
}
|
|
13383
13668
|
return queue;
|
|
@@ -20340,12 +20625,12 @@ async function syncEngineListen(syncEngine, query) {
|
|
|
20340
20625
|
}
|
|
20341
20626
|
else {
|
|
20342
20627
|
const targetData = await localStoreAllocateTarget(syncEngineImpl.localStore, queryToTarget(query));
|
|
20343
|
-
const status = syncEngineImpl.sharedClientState.addLocalQueryTarget(targetData.targetId);
|
|
20344
|
-
targetId = targetData.targetId;
|
|
20345
|
-
viewSnapshot = await initializeViewAndComputeSnapshot(syncEngineImpl, query, targetId, status === 'current');
|
|
20346
20628
|
if (syncEngineImpl.isPrimaryClient) {
|
|
20347
20629
|
remoteStoreListen(syncEngineImpl.remoteStore, targetData);
|
|
20348
20630
|
}
|
|
20631
|
+
const status = syncEngineImpl.sharedClientState.addLocalQueryTarget(targetData.targetId);
|
|
20632
|
+
targetId = targetData.targetId;
|
|
20633
|
+
viewSnapshot = await initializeViewAndComputeSnapshot(syncEngineImpl, query, targetId, status === 'current');
|
|
20349
20634
|
}
|
|
20350
20635
|
return viewSnapshot;
|
|
20351
20636
|
}
|
|
@@ -24853,8 +25138,7 @@ class DocumentSnapshot extends DocumentSnapshot$1 {
|
|
|
24853
25138
|
this.metadata = metadata;
|
|
24854
25139
|
}
|
|
24855
25140
|
/**
|
|
24856
|
-
*
|
|
24857
|
-
* exists. True if the document exists.
|
|
25141
|
+
* Returns whether or not the data exists. True if the document exists.
|
|
24858
25142
|
*/
|
|
24859
25143
|
exists() {
|
|
24860
25144
|
return super.exists();
|
|
@@ -25228,51 +25512,53 @@ function limitToLast(limit) {
|
|
|
25228
25512
|
return new QueryLimitConstraint('limitToLast', limit, "L" /* Last */);
|
|
25229
25513
|
}
|
|
25230
25514
|
class QueryStartAtConstraint extends QueryConstraint {
|
|
25231
|
-
constructor(type, _docOrFields,
|
|
25515
|
+
constructor(type, _docOrFields, _inclusive) {
|
|
25232
25516
|
super();
|
|
25233
25517
|
this.type = type;
|
|
25234
25518
|
this._docOrFields = _docOrFields;
|
|
25235
|
-
this.
|
|
25519
|
+
this._inclusive = _inclusive;
|
|
25236
25520
|
}
|
|
25237
25521
|
_apply(query) {
|
|
25238
|
-
const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this.
|
|
25522
|
+
const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this._inclusive);
|
|
25239
25523
|
return new Query(query.firestore, query.converter, queryWithStartAt(query._query, bound));
|
|
25240
25524
|
}
|
|
25241
25525
|
}
|
|
25242
25526
|
function startAt(...docOrFields) {
|
|
25243
|
-
return new QueryStartAtConstraint('startAt', docOrFields,
|
|
25527
|
+
return new QueryStartAtConstraint('startAt', docOrFields,
|
|
25528
|
+
/*inclusive=*/ true);
|
|
25244
25529
|
}
|
|
25245
25530
|
function startAfter(...docOrFields) {
|
|
25246
25531
|
return new QueryStartAtConstraint('startAfter', docOrFields,
|
|
25247
|
-
/*
|
|
25532
|
+
/*inclusive=*/ false);
|
|
25248
25533
|
}
|
|
25249
25534
|
class QueryEndAtConstraint extends QueryConstraint {
|
|
25250
|
-
constructor(type, _docOrFields,
|
|
25535
|
+
constructor(type, _docOrFields, _inclusive) {
|
|
25251
25536
|
super();
|
|
25252
25537
|
this.type = type;
|
|
25253
25538
|
this._docOrFields = _docOrFields;
|
|
25254
|
-
this.
|
|
25539
|
+
this._inclusive = _inclusive;
|
|
25255
25540
|
}
|
|
25256
25541
|
_apply(query) {
|
|
25257
|
-
const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this.
|
|
25542
|
+
const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this._inclusive);
|
|
25258
25543
|
return new Query(query.firestore, query.converter, queryWithEndAt(query._query, bound));
|
|
25259
25544
|
}
|
|
25260
25545
|
}
|
|
25261
25546
|
function endBefore(...docOrFields) {
|
|
25262
|
-
return new QueryEndAtConstraint('endBefore', docOrFields,
|
|
25547
|
+
return new QueryEndAtConstraint('endBefore', docOrFields,
|
|
25548
|
+
/*inclusive=*/ false);
|
|
25263
25549
|
}
|
|
25264
25550
|
function endAt(...docOrFields) {
|
|
25265
|
-
return new QueryEndAtConstraint('endAt', docOrFields, /*
|
|
25551
|
+
return new QueryEndAtConstraint('endAt', docOrFields, /*inclusive=*/ true);
|
|
25266
25552
|
}
|
|
25267
25553
|
/** Helper function to create a bound from a document or fields */
|
|
25268
|
-
function newQueryBoundFromDocOrFields(query, methodName, docOrFields,
|
|
25554
|
+
function newQueryBoundFromDocOrFields(query, methodName, docOrFields, inclusive) {
|
|
25269
25555
|
docOrFields[0] = getModularInstance(docOrFields[0]);
|
|
25270
25556
|
if (docOrFields[0] instanceof DocumentSnapshot$1) {
|
|
25271
|
-
return newQueryBoundFromDocument(query._query, query.firestore._databaseId, methodName, docOrFields[0]._document,
|
|
25557
|
+
return newQueryBoundFromDocument(query._query, query.firestore._databaseId, methodName, docOrFields[0]._document, inclusive);
|
|
25272
25558
|
}
|
|
25273
25559
|
else {
|
|
25274
25560
|
const reader = newUserDataReader(query.firestore);
|
|
25275
|
-
return newQueryBoundFromFields(query._query, query.firestore._databaseId, reader, methodName, docOrFields,
|
|
25561
|
+
return newQueryBoundFromFields(query._query, query.firestore._databaseId, reader, methodName, docOrFields, inclusive);
|
|
25276
25562
|
}
|
|
25277
25563
|
}
|
|
25278
25564
|
function newQueryFilter(query, methodName, dataReader, databaseId, fieldPath, op, value) {
|
|
@@ -25330,7 +25616,7 @@ function newQueryOrderBy(query, fieldPath, direction) {
|
|
|
25330
25616
|
* of the query or if any of the fields in the order by are an uncommitted
|
|
25331
25617
|
* server timestamp.
|
|
25332
25618
|
*/
|
|
25333
|
-
function newQueryBoundFromDocument(query, databaseId, methodName, doc,
|
|
25619
|
+
function newQueryBoundFromDocument(query, databaseId, methodName, doc, inclusive) {
|
|
25334
25620
|
if (!doc) {
|
|
25335
25621
|
throw new FirestoreError(Code.NOT_FOUND, `Can't use a DocumentSnapshot that doesn't exist for ` +
|
|
25336
25622
|
`${methodName}().`);
|
|
@@ -25367,12 +25653,12 @@ function newQueryBoundFromDocument(query, databaseId, methodName, doc, before) {
|
|
|
25367
25653
|
}
|
|
25368
25654
|
}
|
|
25369
25655
|
}
|
|
25370
|
-
return new Bound(components,
|
|
25656
|
+
return new Bound(components, inclusive);
|
|
25371
25657
|
}
|
|
25372
25658
|
/**
|
|
25373
25659
|
* Converts a list of field values to a `Bound` for the given query.
|
|
25374
25660
|
*/
|
|
25375
|
-
function newQueryBoundFromFields(query, databaseId, dataReader, methodName, values,
|
|
25661
|
+
function newQueryBoundFromFields(query, databaseId, dataReader, methodName, values, inclusive) {
|
|
25376
25662
|
// Use explicit order by's because it has to match the query the user made
|
|
25377
25663
|
const orderBy = query.explicitOrderBy;
|
|
25378
25664
|
if (values.length > orderBy.length) {
|
|
@@ -25409,7 +25695,7 @@ function newQueryBoundFromFields(query, databaseId, dataReader, methodName, valu
|
|
|
25409
25695
|
components.push(wrapped);
|
|
25410
25696
|
}
|
|
25411
25697
|
}
|
|
25412
|
-
return new Bound(components,
|
|
25698
|
+
return new Bound(components, inclusive);
|
|
25413
25699
|
}
|
|
25414
25700
|
/**
|
|
25415
25701
|
* Parses the given `documentIdValue` into a `ReferenceValue`, throwing
|