@firebase/firestore 3.4.4-canary.0482aa5b7 → 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/local/document_overlay_cache.d.ts +72 -0
- package/dist/firestore/src/local/indexeddb_document_overlay_cache.d.ts +45 -0
- package/dist/firestore/src/local/indexeddb_index_manager.d.ts +10 -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 +81 -9
- 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_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/index.esm2017.js +3497 -3134
- package/dist/index.esm2017.js.map +1 -1
- package/dist/index.esm5.js +3448 -3123
- package/dist/index.esm5.js.map +1 -1
- package/dist/index.node.cjs.js +639 -154
- package/dist/index.node.cjs.js.map +1 -1
- package/dist/index.node.mjs +639 -154
- package/dist/index.node.mjs.map +1 -1
- package/dist/index.rn.js +3586 -3227
- package/dist/index.rn.js.map +1 -1
- package/dist/internal.d.ts +83 -12
- package/dist/lite/firestore/src/api/credentials.d.ts +1 -0
- package/dist/lite/firestore/src/local/document_overlay_cache.d.ts +72 -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 +10 -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 +81 -9
- 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_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/index.browser.esm2017.js +1118 -1112
- package/dist/lite/index.browser.esm2017.js.map +1 -1
- package/dist/lite/index.browser.esm5.js +53 -47
- package/dist/lite/index.browser.esm5.js.map +1 -1
- package/dist/lite/index.node.cjs.js +10 -2
- package/dist/lite/index.node.cjs.js.map +1 -1
- package/dist/lite/index.node.mjs +10 -2
- package/dist/lite/index.node.mjs.map +1 -1
- package/dist/lite/index.rn.esm2017.js +1134 -1128
- package/dist/lite/index.rn.esm2017.js.map +1 -1
- package/dist/lite/internal.d.ts +4 -0
- package/dist/lite/packages/firestore/dist/lite/index.browser.esm2017.d.ts +112 -112
- package/dist/lite/packages/firestore/src/api/credentials.d.ts +1 -0
- package/dist/lite/packages/firestore/src/local/document_overlay_cache.d.ts +72 -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 +10 -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 +81 -9
- 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_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/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/local/document_overlay_cache.d.ts +72 -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 +10 -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 +81 -9
- 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_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/private.d.ts +79 -12
- 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 {
|
|
@@ -1214,9 +1221,10 @@ function decodeResourcePath(path) {
|
|
|
1214
1221
|
* an auto-incrementing ID. This is required for Index-Free queries.
|
|
1215
1222
|
* 10. Rewrite the canonical IDs to the explicit Protobuf-based format.
|
|
1216
1223
|
* 11. Add bundles and named_queries for bundle support.
|
|
1217
|
-
* 12. Add
|
|
1224
|
+
* 12. Add document overlays.
|
|
1225
|
+
* 13. Add indexing support.
|
|
1218
1226
|
*/
|
|
1219
|
-
const SCHEMA_VERSION =
|
|
1227
|
+
const SCHEMA_VERSION = 12;
|
|
1220
1228
|
/**
|
|
1221
1229
|
* Wrapper class to store timestamps (seconds and nanos) in IndexedDb objects.
|
|
1222
1230
|
*/
|
|
@@ -1778,7 +1786,10 @@ DbNamedQuery.keyPath = 'name';
|
|
|
1778
1786
|
/** An object representing the global configuration for a field index. */
|
|
1779
1787
|
class DbIndexConfiguration {
|
|
1780
1788
|
constructor(
|
|
1781
|
-
/**
|
|
1789
|
+
/**
|
|
1790
|
+
* The index id for this entry. Undefined for indexes that are not yet
|
|
1791
|
+
* persisted.
|
|
1792
|
+
*/
|
|
1782
1793
|
indexId,
|
|
1783
1794
|
/** The collection group this index belongs to. */
|
|
1784
1795
|
collectionGroup,
|
|
@@ -1792,6 +1803,16 @@ class DbIndexConfiguration {
|
|
|
1792
1803
|
/** Name of the IndexedDb object store. */
|
|
1793
1804
|
DbIndexConfiguration.store = 'indexConfiguration';
|
|
1794
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';
|
|
1795
1816
|
/**
|
|
1796
1817
|
* An object describing how up-to-date the index backfill is for each user and
|
|
1797
1818
|
* index.
|
|
@@ -1833,8 +1854,18 @@ class DbIndexState {
|
|
|
1833
1854
|
/** Name of the IndexedDb object store. */
|
|
1834
1855
|
DbIndexState.store = 'indexState';
|
|
1835
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'];
|
|
1836
1867
|
/** An object that stores the encoded entries for all documents and fields. */
|
|
1837
|
-
class
|
|
1868
|
+
class DbIndexEntry {
|
|
1838
1869
|
constructor(
|
|
1839
1870
|
/** The index id for this entry. */
|
|
1840
1871
|
indexId,
|
|
@@ -1854,14 +1885,54 @@ class DbIndexEntries {
|
|
|
1854
1885
|
}
|
|
1855
1886
|
}
|
|
1856
1887
|
/** Name of the IndexedDb object store. */
|
|
1857
|
-
|
|
1858
|
-
|
|
1888
|
+
DbIndexEntry.store = 'indexEntries';
|
|
1889
|
+
DbIndexEntry.keyPath = [
|
|
1859
1890
|
'indexId',
|
|
1860
1891
|
'uid',
|
|
1861
1892
|
'arrayValue',
|
|
1862
1893
|
'directionalValue',
|
|
1863
1894
|
'documentKey'
|
|
1864
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
|
+
];
|
|
1865
1936
|
// Visible for testing
|
|
1866
1937
|
const V1_STORES = [
|
|
1867
1938
|
DbMutationQueue.store,
|
|
@@ -1885,18 +1956,28 @@ const V8_STORES = [...V6_STORES, DbCollectionParent.store];
|
|
|
1885
1956
|
// V9 does not change the set of stores.
|
|
1886
1957
|
// V10 does not change the set of stores.
|
|
1887
1958
|
const V11_STORES = [...V8_STORES, DbBundle.store, DbNamedQuery.store];
|
|
1888
|
-
[
|
|
1889
|
-
|
|
1959
|
+
const V12_STORES = [...V11_STORES, DbDocumentOverlay.store];
|
|
1960
|
+
const V13_STORES = [
|
|
1961
|
+
...V12_STORES,
|
|
1890
1962
|
DbIndexConfiguration.store,
|
|
1891
1963
|
DbIndexState.store,
|
|
1892
|
-
|
|
1964
|
+
DbIndexEntry.store
|
|
1893
1965
|
];
|
|
1894
|
-
/**
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
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
|
+
}
|
|
1900
1981
|
|
|
1901
1982
|
/**
|
|
1902
1983
|
* @license
|
|
@@ -2193,6 +2274,15 @@ class SimpleDbTransaction {
|
|
|
2193
2274
|
this.transaction.abort();
|
|
2194
2275
|
}
|
|
2195
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
|
+
}
|
|
2196
2286
|
/**
|
|
2197
2287
|
* Returns a SimpleDbStore<KeyType, ValueType> for the specified store. All
|
|
2198
2288
|
* operations performed on the SimpleDbStore happen within the context of this
|
|
@@ -2389,6 +2479,10 @@ class SimpleDb {
|
|
|
2389
2479
|
this.db = await this.ensureDb(action);
|
|
2390
2480
|
const transaction = SimpleDbTransaction.open(this.db, action, readonly ? 'readonly' : 'readwrite', objectStores);
|
|
2391
2481
|
const transactionFnResult = transactionFn(transaction)
|
|
2482
|
+
.next(result => {
|
|
2483
|
+
transaction.maybeCommit();
|
|
2484
|
+
return result;
|
|
2485
|
+
})
|
|
2392
2486
|
.catch(error => {
|
|
2393
2487
|
// Abort the transaction if there was an error.
|
|
2394
2488
|
transaction.abort(error);
|
|
@@ -2561,13 +2655,29 @@ class SimpleDbStore {
|
|
|
2561
2655
|
return wrapRequest(request);
|
|
2562
2656
|
}
|
|
2563
2657
|
loadAll(indexOrRange, range) {
|
|
2564
|
-
const
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
return
|
|
2570
|
-
|
|
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
|
+
}
|
|
2571
2681
|
}
|
|
2572
2682
|
deleteAll(indexOrRange, range) {
|
|
2573
2683
|
logDebug(LOG_TAG$g, 'DELETE ALL', this.store.name);
|
|
@@ -3598,6 +3708,14 @@ class DocumentKey {
|
|
|
3598
3708
|
return (this.path.length >= 2 &&
|
|
3599
3709
|
this.path.get(this.path.length - 2) === collectionId);
|
|
3600
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
|
+
}
|
|
3601
3719
|
isEqual(other) {
|
|
3602
3720
|
return (other !== null && ResourcePath.comparator(this.path, other.path) === 0);
|
|
3603
3721
|
}
|
|
@@ -4421,12 +4539,12 @@ class FieldIndex {
|
|
|
4421
4539
|
/** The collection ID this index applies to. */
|
|
4422
4540
|
collectionGroup,
|
|
4423
4541
|
/** The field segments for this index. */
|
|
4424
|
-
|
|
4542
|
+
fields,
|
|
4425
4543
|
/** Shows how up-to-date the index is for the current user. */
|
|
4426
4544
|
indexState) {
|
|
4427
4545
|
this.indexId = indexId;
|
|
4428
4546
|
this.collectionGroup = collectionGroup;
|
|
4429
|
-
this.
|
|
4547
|
+
this.fields = fields;
|
|
4430
4548
|
this.indexState = indexState;
|
|
4431
4549
|
}
|
|
4432
4550
|
}
|
|
@@ -6686,6 +6804,47 @@ class MutationBatchResult {
|
|
|
6686
6804
|
}
|
|
6687
6805
|
}
|
|
6688
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
|
+
|
|
6689
6848
|
/**
|
|
6690
6849
|
* @license
|
|
6691
6850
|
* Copyright 2017 Google LLC
|
|
@@ -8687,6 +8846,37 @@ function fromBundleMetadata(metadata) {
|
|
|
8687
8846
|
version: metadata.version,
|
|
8688
8847
|
createTime: fromVersion(metadata.createTime)
|
|
8689
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);
|
|
8690
8880
|
}
|
|
8691
8881
|
|
|
8692
8882
|
/**
|
|
@@ -8746,6 +8936,125 @@ function namedQueriesStore(txn) {
|
|
|
8746
8936
|
return getStore(txn, DbNamedQuery.store);
|
|
8747
8937
|
}
|
|
8748
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
|
+
|
|
8749
9058
|
/**
|
|
8750
9059
|
* @license
|
|
8751
9060
|
* Copyright 2019 Google LLC
|
|
@@ -8859,17 +9168,22 @@ class MemoryCollectionParentIndex {
|
|
|
8859
9168
|
*/
|
|
8860
9169
|
/**
|
|
8861
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.
|
|
8862
9174
|
*/
|
|
8863
9175
|
class IndexedDbIndexManager {
|
|
8864
|
-
constructor() {
|
|
9176
|
+
constructor(user) {
|
|
9177
|
+
this.user = user;
|
|
8865
9178
|
/**
|
|
8866
9179
|
* An in-memory copy of the index entries we've already written since the SDK
|
|
8867
9180
|
* launched. Used to avoid re-writing the same entry repeatedly.
|
|
8868
9181
|
*
|
|
8869
|
-
* This is *NOT* a complete cache of what's in persistence and so can never be
|
|
8870
|
-
* satisfy reads.
|
|
9182
|
+
* This is *NOT* a complete cache of what's in persistence and so can never be
|
|
9183
|
+
* used to satisfy reads.
|
|
8871
9184
|
*/
|
|
8872
9185
|
this.collectionParentsCache = new MemoryCollectionParentIndex();
|
|
9186
|
+
this.uid = user.uid || '';
|
|
8873
9187
|
}
|
|
8874
9188
|
/**
|
|
8875
9189
|
* Adds a new entry to the collection parent index.
|
|
@@ -8917,12 +9231,25 @@ class IndexedDbIndexManager {
|
|
|
8917
9231
|
});
|
|
8918
9232
|
}
|
|
8919
9233
|
addFieldIndex(transaction, index) {
|
|
8920
|
-
// TODO(indexing):
|
|
8921
|
-
|
|
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();
|
|
8922
9240
|
}
|
|
8923
9241
|
deleteFieldIndex(transaction, index) {
|
|
8924
|
-
|
|
8925
|
-
|
|
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)));
|
|
8926
9253
|
}
|
|
8927
9254
|
getDocumentsMatchingTarget(transaction, fieldIndex, target) {
|
|
8928
9255
|
// TODO(indexing): Implement
|
|
@@ -8933,21 +9260,55 @@ class IndexedDbIndexManager {
|
|
|
8933
9260
|
return PersistencePromise.resolve(null);
|
|
8934
9261
|
}
|
|
8935
9262
|
getFieldIndexes(transaction, collectionGroup) {
|
|
8936
|
-
|
|
8937
|
-
|
|
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
|
+
});
|
|
8938
9277
|
}
|
|
8939
9278
|
getNextCollectionGroupToUpdate(transaction) {
|
|
8940
|
-
|
|
8941
|
-
|
|
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
|
+
});
|
|
8942
9286
|
}
|
|
8943
9287
|
updateCollectionGroup(transaction, collectionGroup, offset) {
|
|
8944
|
-
|
|
8945
|
-
|
|
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)))));
|
|
8946
9293
|
}
|
|
8947
9294
|
updateIndexEntries(transaction, documents) {
|
|
8948
9295
|
// TODO(indexing): Implement
|
|
8949
9296
|
return PersistencePromise.resolve();
|
|
8950
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
|
+
}
|
|
8951
9312
|
}
|
|
8952
9313
|
/**
|
|
8953
9314
|
* Helper to get a typed SimpleDbStore for the collectionParents
|
|
@@ -8955,6 +9316,24 @@ class IndexedDbIndexManager {
|
|
|
8955
9316
|
*/
|
|
8956
9317
|
function collectionParentsStore(txn) {
|
|
8957
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);
|
|
8958
9337
|
}
|
|
8959
9338
|
|
|
8960
9339
|
/**
|
|
@@ -10424,12 +10803,10 @@ class RemoteDocumentChangeBuffer {
|
|
|
10424
10803
|
* `newIndexedDbRemoteDocumentCache()`.
|
|
10425
10804
|
*/
|
|
10426
10805
|
class IndexedDbRemoteDocumentCacheImpl {
|
|
10427
|
-
|
|
10428
|
-
* @param serializer - The document serializer.
|
|
10429
|
-
* @param indexManager - The query indexes that need to be maintained.
|
|
10430
|
-
*/
|
|
10431
|
-
constructor(serializer, indexManager) {
|
|
10806
|
+
constructor(serializer) {
|
|
10432
10807
|
this.serializer = serializer;
|
|
10808
|
+
}
|
|
10809
|
+
setIndexManager(indexManager) {
|
|
10433
10810
|
this.indexManager = indexManager;
|
|
10434
10811
|
}
|
|
10435
10812
|
/**
|
|
@@ -10551,21 +10928,21 @@ class IndexedDbRemoteDocumentCacheImpl {
|
|
|
10551
10928
|
}
|
|
10552
10929
|
});
|
|
10553
10930
|
}
|
|
10554
|
-
|
|
10931
|
+
getAll(transaction, collection, sinceReadTime) {
|
|
10555
10932
|
let results = mutableDocumentMap();
|
|
10556
|
-
const immediateChildrenPathLength =
|
|
10933
|
+
const immediateChildrenPathLength = collection.length + 1;
|
|
10557
10934
|
const iterationOptions = {};
|
|
10558
10935
|
if (sinceReadTime.isEqual(SnapshotVersion.min())) {
|
|
10559
10936
|
// Documents are ordered by key, so we can use a prefix scan to narrow
|
|
10560
10937
|
// down the documents we need to match the query against.
|
|
10561
|
-
const startKey =
|
|
10938
|
+
const startKey = collection.toArray();
|
|
10562
10939
|
iterationOptions.range = IDBKeyRange.lowerBound(startKey);
|
|
10563
10940
|
}
|
|
10564
10941
|
else {
|
|
10565
10942
|
// Execute an index-free query and filter by read time. This is safe
|
|
10566
10943
|
// since all document changes to queries that have a
|
|
10567
10944
|
// lastLimboFreeSnapshotVersion (`sinceReadTime`) have a read time set.
|
|
10568
|
-
const collectionKey =
|
|
10945
|
+
const collectionKey = collection.toArray();
|
|
10569
10946
|
const readTimeKey = toDbTimestampKey(sinceReadTime);
|
|
10570
10947
|
iterationOptions.range = IDBKeyRange.lowerBound([collectionKey, readTimeKey],
|
|
10571
10948
|
/* open= */ true);
|
|
@@ -10582,12 +10959,12 @@ class IndexedDbRemoteDocumentCacheImpl {
|
|
|
10582
10959
|
return;
|
|
10583
10960
|
}
|
|
10584
10961
|
const document = this.maybeDecodeDocument(DocumentKey.fromSegments(key), dbRemoteDoc);
|
|
10585
|
-
if (
|
|
10586
|
-
control.done();
|
|
10587
|
-
}
|
|
10588
|
-
else if (queryMatches(query, document)) {
|
|
10962
|
+
if (collection.isPrefixOf(document.key.path)) {
|
|
10589
10963
|
results = results.insert(document.key, document);
|
|
10590
10964
|
}
|
|
10965
|
+
else {
|
|
10966
|
+
control.done();
|
|
10967
|
+
}
|
|
10591
10968
|
})
|
|
10592
10969
|
.next(() => results);
|
|
10593
10970
|
}
|
|
@@ -10625,14 +11002,9 @@ class IndexedDbRemoteDocumentCacheImpl {
|
|
|
10625
11002
|
return MutableDocument.newInvalidDocument(documentKey);
|
|
10626
11003
|
}
|
|
10627
11004
|
}
|
|
10628
|
-
/**
|
|
10629
|
-
|
|
10630
|
-
|
|
10631
|
-
* @param serializer - The document serializer.
|
|
10632
|
-
* @param indexManager - The query indexes that need to be maintained.
|
|
10633
|
-
*/
|
|
10634
|
-
function newIndexedDbRemoteDocumentCache(serializer, indexManager) {
|
|
10635
|
-
return new IndexedDbRemoteDocumentCacheImpl(serializer, indexManager);
|
|
11005
|
+
/** Creates a new IndexedDbRemoteDocumentCache. */
|
|
11006
|
+
function newIndexedDbRemoteDocumentCache(serializer) {
|
|
11007
|
+
return new IndexedDbRemoteDocumentCacheImpl(serializer);
|
|
10636
11008
|
}
|
|
10637
11009
|
/**
|
|
10638
11010
|
* Returns the set of documents that have changed since the specified read
|
|
@@ -10866,6 +11238,11 @@ class SchemaConverter {
|
|
|
10866
11238
|
});
|
|
10867
11239
|
}
|
|
10868
11240
|
if (fromVersion < 12 && toVersion >= 12) {
|
|
11241
|
+
p = p.next(() => {
|
|
11242
|
+
createDocumentOverlayStore(db);
|
|
11243
|
+
});
|
|
11244
|
+
}
|
|
11245
|
+
if (fromVersion < 13 && toVersion >= 13) {
|
|
10869
11246
|
p = p.next(() => {
|
|
10870
11247
|
createFieldIndex(db);
|
|
10871
11248
|
});
|
|
@@ -11078,15 +11455,25 @@ function createNamedQueriesStore(db) {
|
|
|
11078
11455
|
});
|
|
11079
11456
|
}
|
|
11080
11457
|
function createFieldIndex(db) {
|
|
11081
|
-
db.createObjectStore(DbIndexConfiguration.store, {
|
|
11082
|
-
keyPath: DbIndexConfiguration.keyPath
|
|
11458
|
+
const indexConfiguratioStore = db.createObjectStore(DbIndexConfiguration.store, {
|
|
11459
|
+
keyPath: DbIndexConfiguration.keyPath,
|
|
11460
|
+
autoIncrement: true
|
|
11083
11461
|
});
|
|
11084
|
-
|
|
11462
|
+
indexConfiguratioStore.createIndex(DbIndexConfiguration.collectionGroupIndex, DbIndexConfiguration.collectionGroupIndexPath, { unique: false });
|
|
11463
|
+
const indexStateStore = db.createObjectStore(DbIndexState.store, {
|
|
11085
11464
|
keyPath: DbIndexState.keyPath
|
|
11086
11465
|
});
|
|
11087
|
-
|
|
11088
|
-
|
|
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
|
|
11089
11474
|
});
|
|
11475
|
+
documentOverlayStore.createIndex(DbDocumentOverlay.collectionPathOverlayIndex, DbDocumentOverlay.collectionPathOverlayIndexPath, { unique: false });
|
|
11476
|
+
documentOverlayStore.createIndex(DbDocumentOverlay.collectionGroupOverlayIndex, DbDocumentOverlay.collectionGroupOverlayIndexPath, { unique: false });
|
|
11090
11477
|
}
|
|
11091
11478
|
|
|
11092
11479
|
/**
|
|
@@ -11198,7 +11585,7 @@ class IndexedDbPersistence {
|
|
|
11198
11585
|
* If set to true, forcefully obtains database access. Existing tabs will
|
|
11199
11586
|
* no longer be able to access IndexedDB.
|
|
11200
11587
|
*/
|
|
11201
|
-
forceOwningTab) {
|
|
11588
|
+
forceOwningTab, schemaVersion = SCHEMA_VERSION) {
|
|
11202
11589
|
this.allowTabSynchronization = allowTabSynchronization;
|
|
11203
11590
|
this.persistenceKey = persistenceKey;
|
|
11204
11591
|
this.clientId = clientId;
|
|
@@ -11207,6 +11594,7 @@ class IndexedDbPersistence {
|
|
|
11207
11594
|
this.document = document;
|
|
11208
11595
|
this.sequenceNumberSyncer = sequenceNumberSyncer;
|
|
11209
11596
|
this.forceOwningTab = forceOwningTab;
|
|
11597
|
+
this.schemaVersion = schemaVersion;
|
|
11210
11598
|
this.listenSequence = null;
|
|
11211
11599
|
this._started = false;
|
|
11212
11600
|
this.isPrimary = false;
|
|
@@ -11228,10 +11616,9 @@ class IndexedDbPersistence {
|
|
|
11228
11616
|
this.referenceDelegate = new IndexedDbLruDelegateImpl(this, lruParams);
|
|
11229
11617
|
this.dbName = persistenceKey + MAIN_DATABASE;
|
|
11230
11618
|
this.serializer = new LocalSerializer(serializer);
|
|
11231
|
-
this.simpleDb = new SimpleDb(this.dbName,
|
|
11619
|
+
this.simpleDb = new SimpleDb(this.dbName, this.schemaVersion, new SchemaConverter(this.serializer));
|
|
11232
11620
|
this.targetCache = new IndexedDbTargetCache(this.referenceDelegate, this.serializer);
|
|
11233
|
-
this.
|
|
11234
|
-
this.remoteDocumentCache = newIndexedDbRemoteDocumentCache(this.serializer, this.indexManager);
|
|
11621
|
+
this.remoteDocumentCache = newIndexedDbRemoteDocumentCache(this.serializer);
|
|
11235
11622
|
this.bundleCache = new IndexedDbBundleCache();
|
|
11236
11623
|
if (this.window && this.window.localStorage) {
|
|
11237
11624
|
this.webStorage = this.window.localStorage;
|
|
@@ -11567,8 +11954,8 @@ class IndexedDbPersistence {
|
|
|
11567
11954
|
get started() {
|
|
11568
11955
|
return this._started;
|
|
11569
11956
|
}
|
|
11570
|
-
getMutationQueue(user) {
|
|
11571
|
-
return IndexedDbMutationQueue.forUser(user, this.serializer,
|
|
11957
|
+
getMutationQueue(user, indexManager) {
|
|
11958
|
+
return IndexedDbMutationQueue.forUser(user, this.serializer, indexManager, this.referenceDelegate);
|
|
11572
11959
|
}
|
|
11573
11960
|
getTargetCache() {
|
|
11574
11961
|
return this.targetCache;
|
|
@@ -11576,8 +11963,11 @@ class IndexedDbPersistence {
|
|
|
11576
11963
|
getRemoteDocumentCache() {
|
|
11577
11964
|
return this.remoteDocumentCache;
|
|
11578
11965
|
}
|
|
11579
|
-
getIndexManager() {
|
|
11580
|
-
return
|
|
11966
|
+
getIndexManager(user) {
|
|
11967
|
+
return new IndexedDbIndexManager(user);
|
|
11968
|
+
}
|
|
11969
|
+
getDocumentOverlayCache(user) {
|
|
11970
|
+
return IndexedDbDocumentOverlayCache.forUser(this.serializer, user);
|
|
11581
11971
|
}
|
|
11582
11972
|
getBundleCache() {
|
|
11583
11973
|
return this.bundleCache;
|
|
@@ -11585,11 +11975,12 @@ class IndexedDbPersistence {
|
|
|
11585
11975
|
runTransaction(action, mode, transactionOperation) {
|
|
11586
11976
|
logDebug(LOG_TAG$d, 'Starting transaction:', action);
|
|
11587
11977
|
const simpleDbMode = mode === 'readonly' ? 'readonly' : 'readwrite';
|
|
11978
|
+
const objectStores = getObjectStores(this.schemaVersion);
|
|
11588
11979
|
let persistenceTransaction;
|
|
11589
11980
|
// Do all transactions as readwrite against all object stores, since we
|
|
11590
11981
|
// are the only reader/writer.
|
|
11591
11982
|
return this.simpleDb
|
|
11592
|
-
.runTransaction(action, simpleDbMode,
|
|
11983
|
+
.runTransaction(action, simpleDbMode, objectStores, simpleDbTxn => {
|
|
11593
11984
|
persistenceTransaction = new IndexedDbTransaction(simpleDbTxn, this.listenSequence
|
|
11594
11985
|
? this.listenSequence.next()
|
|
11595
11986
|
: ListenSequence.INVALID);
|
|
@@ -11961,39 +12352,28 @@ class LocalDocumentsView {
|
|
|
11961
12352
|
getDocumentsMatchingCollectionQuery(transaction, query, sinceReadTime) {
|
|
11962
12353
|
// Query the remote documents and overlay mutations.
|
|
11963
12354
|
let results;
|
|
11964
|
-
let mutationBatches;
|
|
11965
12355
|
return this.remoteDocumentCache
|
|
11966
|
-
.
|
|
12356
|
+
.getAll(transaction, query.path, sinceReadTime)
|
|
11967
12357
|
.next(queryResults => {
|
|
11968
12358
|
results = queryResults;
|
|
11969
12359
|
return this.mutationQueue.getAllMutationBatchesAffectingQuery(transaction, query);
|
|
11970
12360
|
})
|
|
11971
|
-
.next(
|
|
11972
|
-
mutationBatches
|
|
11973
|
-
|
|
11974
|
-
|
|
11975
|
-
|
|
11976
|
-
|
|
11977
|
-
|
|
11978
|
-
|
|
11979
|
-
|
|
11980
|
-
|
|
11981
|
-
|
|
11982
|
-
|
|
11983
|
-
|
|
11984
|
-
let document = results.get(key);
|
|
11985
|
-
if (document == null) {
|
|
11986
|
-
// Create invalid document to apply mutations on top of
|
|
11987
|
-
document = MutableDocument.newInvalidDocument(key);
|
|
11988
|
-
results = results.insert(key, document);
|
|
11989
|
-
}
|
|
11990
|
-
mutationApplyToLocalView(mutation, document, batch.localWriteTime);
|
|
11991
|
-
if (!document.isFoundDocument()) {
|
|
11992
|
-
results = results.remove(key);
|
|
11993
|
-
}
|
|
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);
|
|
11994
12374
|
}
|
|
11995
12375
|
}
|
|
11996
|
-
}
|
|
12376
|
+
}
|
|
11997
12377
|
})
|
|
11998
12378
|
.next(() => {
|
|
11999
12379
|
// Finally, filter out any documents that don't actually match
|
|
@@ -12006,29 +12386,6 @@ class LocalDocumentsView {
|
|
|
12006
12386
|
return results;
|
|
12007
12387
|
});
|
|
12008
12388
|
}
|
|
12009
|
-
addMissingBaseDocuments(transaction, matchingMutationBatches, existingDocuments) {
|
|
12010
|
-
let missingBaseDocEntriesForPatching = documentKeySet();
|
|
12011
|
-
for (const batch of matchingMutationBatches) {
|
|
12012
|
-
for (const mutation of batch.mutations) {
|
|
12013
|
-
if (mutation instanceof PatchMutation &&
|
|
12014
|
-
existingDocuments.get(mutation.key) === null) {
|
|
12015
|
-
missingBaseDocEntriesForPatching =
|
|
12016
|
-
missingBaseDocEntriesForPatching.add(mutation.key);
|
|
12017
|
-
}
|
|
12018
|
-
}
|
|
12019
|
-
}
|
|
12020
|
-
let mergedDocuments = existingDocuments;
|
|
12021
|
-
return this.remoteDocumentCache
|
|
12022
|
-
.getEntries(transaction, missingBaseDocEntriesForPatching)
|
|
12023
|
-
.next(missingBaseDocs => {
|
|
12024
|
-
missingBaseDocs.forEach((key, doc) => {
|
|
12025
|
-
if (doc.isFoundDocument()) {
|
|
12026
|
-
mergedDocuments = mergedDocuments.insert(key, doc);
|
|
12027
|
-
}
|
|
12028
|
-
});
|
|
12029
|
-
return mergedDocuments;
|
|
12030
|
-
});
|
|
12031
|
-
}
|
|
12032
12389
|
}
|
|
12033
12390
|
|
|
12034
12391
|
/**
|
|
@@ -12087,11 +12444,18 @@ class LocalStoreImpl {
|
|
|
12087
12444
|
* PORTING NOTE: This is only used for multi-tab synchronization.
|
|
12088
12445
|
*/
|
|
12089
12446
|
this.lastDocumentChangeReadTime = SnapshotVersion.min();
|
|
12090
|
-
this.mutationQueue = persistence.getMutationQueue(initialUser);
|
|
12091
12447
|
this.remoteDocuments = persistence.getRemoteDocumentCache();
|
|
12092
12448
|
this.targetCache = persistence.getTargetCache();
|
|
12093
|
-
this.localDocuments = new LocalDocumentsView(this.remoteDocuments, this.mutationQueue, this.persistence.getIndexManager());
|
|
12094
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);
|
|
12095
12459
|
this.queryEngine.setLocalDocumentsView(this.localDocuments);
|
|
12096
12460
|
}
|
|
12097
12461
|
collectGarbage(garbageCollector) {
|
|
@@ -12113,8 +12477,6 @@ persistence, queryEngine, initialUser, serializer) {
|
|
|
12113
12477
|
// change.
|
|
12114
12478
|
async function localStoreHandleUserChange(localStore, user) {
|
|
12115
12479
|
const localStoreImpl = debugCast(localStore);
|
|
12116
|
-
let newMutationQueue = localStoreImpl.mutationQueue;
|
|
12117
|
-
let newLocalDocuments = localStoreImpl.localDocuments;
|
|
12118
12480
|
const result = await localStoreImpl.persistence.runTransaction('Handle user change', 'readonly', txn => {
|
|
12119
12481
|
// Swap out the mutation queue, grabbing the pending mutation batches
|
|
12120
12482
|
// before and after.
|
|
@@ -12123,11 +12485,8 @@ async function localStoreHandleUserChange(localStore, user) {
|
|
|
12123
12485
|
.getAllMutationBatches(txn)
|
|
12124
12486
|
.next(promisedOldBatches => {
|
|
12125
12487
|
oldBatches = promisedOldBatches;
|
|
12126
|
-
|
|
12127
|
-
|
|
12128
|
-
// MutationQueue.
|
|
12129
|
-
newLocalDocuments = new LocalDocumentsView(localStoreImpl.remoteDocuments, newMutationQueue, localStoreImpl.persistence.getIndexManager());
|
|
12130
|
-
return newMutationQueue.getAllMutationBatches(txn);
|
|
12488
|
+
localStoreImpl.initializeUserComponents(user);
|
|
12489
|
+
return localStoreImpl.mutationQueue.getAllMutationBatches(txn);
|
|
12131
12490
|
})
|
|
12132
12491
|
.next(newBatches => {
|
|
12133
12492
|
const removedBatchIds = [];
|
|
@@ -12148,7 +12507,7 @@ async function localStoreHandleUserChange(localStore, user) {
|
|
|
12148
12507
|
}
|
|
12149
12508
|
// Return the set of all (potentially) changed documents and the list
|
|
12150
12509
|
// of mutation batch IDs that were affected by change.
|
|
12151
|
-
return
|
|
12510
|
+
return localStoreImpl.localDocuments
|
|
12152
12511
|
.getDocuments(txn, changedKeys)
|
|
12153
12512
|
.next(affectedDocuments => {
|
|
12154
12513
|
return {
|
|
@@ -12159,9 +12518,6 @@ async function localStoreHandleUserChange(localStore, user) {
|
|
|
12159
12518
|
});
|
|
12160
12519
|
});
|
|
12161
12520
|
});
|
|
12162
|
-
localStoreImpl.mutationQueue = newMutationQueue;
|
|
12163
|
-
localStoreImpl.localDocuments = newLocalDocuments;
|
|
12164
|
-
localStoreImpl.queryEngine.setLocalDocumentsView(localStoreImpl.localDocuments);
|
|
12165
12521
|
return result;
|
|
12166
12522
|
}
|
|
12167
12523
|
/* Accepts locally generated Mutations and commit them to storage. */
|
|
@@ -12874,6 +13230,122 @@ class MemoryBundleCache {
|
|
|
12874
13230
|
}
|
|
12875
13231
|
}
|
|
12876
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
|
+
|
|
12877
13349
|
/**
|
|
12878
13350
|
* @license
|
|
12879
13351
|
* Copyright 2017 Google LLC
|
|
@@ -13227,14 +13699,16 @@ class MemoryRemoteDocumentCacheImpl {
|
|
|
13227
13699
|
* expected to just return 0 to avoid unnecessarily doing the work of
|
|
13228
13700
|
* calculating the size.
|
|
13229
13701
|
*/
|
|
13230
|
-
constructor(
|
|
13231
|
-
this.indexManager = indexManager;
|
|
13702
|
+
constructor(sizer) {
|
|
13232
13703
|
this.sizer = sizer;
|
|
13233
13704
|
/** Underlying cache of documents and their read times. */
|
|
13234
13705
|
this.docs = documentEntryMap();
|
|
13235
13706
|
/** Size of all cached documents. */
|
|
13236
13707
|
this.size = 0;
|
|
13237
13708
|
}
|
|
13709
|
+
setIndexManager(indexManager) {
|
|
13710
|
+
this.indexManager = indexManager;
|
|
13711
|
+
}
|
|
13238
13712
|
/**
|
|
13239
13713
|
* Adds the supplied entry to the cache and updates the cache size as appropriate.
|
|
13240
13714
|
*
|
|
@@ -13282,21 +13756,22 @@ class MemoryRemoteDocumentCacheImpl {
|
|
|
13282
13756
|
});
|
|
13283
13757
|
return PersistencePromise.resolve(results);
|
|
13284
13758
|
}
|
|
13285
|
-
|
|
13759
|
+
getAll(transaction, collectionPath, sinceReadTime) {
|
|
13286
13760
|
let results = mutableDocumentMap();
|
|
13287
13761
|
// Documents are ordered by key, so we can use a prefix scan to narrow down
|
|
13288
13762
|
// the documents we need to match the query against.
|
|
13289
|
-
const prefix = new DocumentKey(
|
|
13763
|
+
const prefix = new DocumentKey(collectionPath.child(''));
|
|
13290
13764
|
const iterator = this.docs.getIteratorFrom(prefix);
|
|
13291
13765
|
while (iterator.hasNext()) {
|
|
13292
13766
|
const { key, value: { document } } = iterator.getNext();
|
|
13293
|
-
if (!
|
|
13767
|
+
if (!collectionPath.isPrefixOf(key.path)) {
|
|
13294
13768
|
break;
|
|
13295
13769
|
}
|
|
13296
|
-
if (
|
|
13770
|
+
if (key.path.length > collectionPath.length + 1) {
|
|
13771
|
+
// Exclude entries from subcollections.
|
|
13297
13772
|
continue;
|
|
13298
13773
|
}
|
|
13299
|
-
if (
|
|
13774
|
+
if (document.readTime.compareTo(sinceReadTime) <= 0) {
|
|
13300
13775
|
continue;
|
|
13301
13776
|
}
|
|
13302
13777
|
results = results.insert(document.key, document.mutableCopy());
|
|
@@ -13318,13 +13793,12 @@ class MemoryRemoteDocumentCacheImpl {
|
|
|
13318
13793
|
/**
|
|
13319
13794
|
* Creates a new memory-only RemoteDocumentCache.
|
|
13320
13795
|
*
|
|
13321
|
-
* @param indexManager - A class that manages collection group indices.
|
|
13322
13796
|
* @param sizer - Used to assess the size of a document. For eager GC, this is
|
|
13323
13797
|
* expected to just return 0 to avoid unnecessarily doing the work of
|
|
13324
13798
|
* calculating the size.
|
|
13325
13799
|
*/
|
|
13326
|
-
function newMemoryRemoteDocumentCache(
|
|
13327
|
-
return new MemoryRemoteDocumentCacheImpl(
|
|
13800
|
+
function newMemoryRemoteDocumentCache(sizer) {
|
|
13801
|
+
return new MemoryRemoteDocumentCacheImpl(sizer);
|
|
13328
13802
|
}
|
|
13329
13803
|
/**
|
|
13330
13804
|
* Handles the details of adding and updating documents in the MemoryRemoteDocumentCache.
|
|
@@ -13518,6 +13992,7 @@ class MemoryPersistence {
|
|
|
13518
13992
|
*/
|
|
13519
13993
|
constructor(referenceDelegateFactory, serializer) {
|
|
13520
13994
|
this.mutationQueues = {};
|
|
13995
|
+
this.overlays = {};
|
|
13521
13996
|
this.listenSequence = new ListenSequence(0);
|
|
13522
13997
|
this._started = false;
|
|
13523
13998
|
this._started = true;
|
|
@@ -13525,7 +14000,7 @@ class MemoryPersistence {
|
|
|
13525
14000
|
this.targetCache = new MemoryTargetCache(this);
|
|
13526
14001
|
const sizer = (doc) => this.referenceDelegate.documentSize(doc);
|
|
13527
14002
|
this.indexManager = new MemoryIndexManager();
|
|
13528
|
-
this.remoteDocumentCache = newMemoryRemoteDocumentCache(
|
|
14003
|
+
this.remoteDocumentCache = newMemoryRemoteDocumentCache(sizer);
|
|
13529
14004
|
this.serializer = new LocalSerializer(serializer);
|
|
13530
14005
|
this.bundleCache = new MemoryBundleCache(this.serializer);
|
|
13531
14006
|
}
|
|
@@ -13546,13 +14021,23 @@ class MemoryPersistence {
|
|
|
13546
14021
|
setNetworkEnabled() {
|
|
13547
14022
|
// No op.
|
|
13548
14023
|
}
|
|
13549
|
-
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.
|
|
13550
14027
|
return this.indexManager;
|
|
13551
14028
|
}
|
|
13552
|
-
|
|
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) {
|
|
13553
14038
|
let queue = this.mutationQueues[user.toKey()];
|
|
13554
14039
|
if (!queue) {
|
|
13555
|
-
queue = new MemoryMutationQueue(
|
|
14040
|
+
queue = new MemoryMutationQueue(indexManager, this.referenceDelegate);
|
|
13556
14041
|
this.mutationQueues[user.toKey()] = queue;
|
|
13557
14042
|
}
|
|
13558
14043
|
return queue;
|
|
@@ -20515,12 +21000,12 @@ async function syncEngineListen(syncEngine, query) {
|
|
|
20515
21000
|
}
|
|
20516
21001
|
else {
|
|
20517
21002
|
const targetData = await localStoreAllocateTarget(syncEngineImpl.localStore, queryToTarget(query));
|
|
20518
|
-
const status = syncEngineImpl.sharedClientState.addLocalQueryTarget(targetData.targetId);
|
|
20519
|
-
targetId = targetData.targetId;
|
|
20520
|
-
viewSnapshot = await initializeViewAndComputeSnapshot(syncEngineImpl, query, targetId, status === 'current');
|
|
20521
21003
|
if (syncEngineImpl.isPrimaryClient) {
|
|
20522
21004
|
remoteStoreListen(syncEngineImpl.remoteStore, targetData);
|
|
20523
21005
|
}
|
|
21006
|
+
const status = syncEngineImpl.sharedClientState.addLocalQueryTarget(targetData.targetId);
|
|
21007
|
+
targetId = targetData.targetId;
|
|
21008
|
+
viewSnapshot = await initializeViewAndComputeSnapshot(syncEngineImpl, query, targetId, status === 'current');
|
|
20524
21009
|
}
|
|
20525
21010
|
return viewSnapshot;
|
|
20526
21011
|
}
|