@firebase/firestore 3.4.4-canary.2dd99ae2d → 3.4.4-canary.434d87ee2

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.
Files changed (112) hide show
  1. package/dist/firestore/src/api/snapshot.d.ts +1 -2
  2. package/dist/firestore/src/core/target.d.ts +8 -4
  3. package/dist/firestore/src/lite-api/query.d.ts +2 -2
  4. package/dist/firestore/src/local/index_manager.d.ts +52 -0
  5. package/dist/firestore/src/local/indexeddb_index_manager.d.ts +21 -2
  6. package/dist/firestore/src/local/indexeddb_persistence.d.ts +4 -4
  7. package/dist/firestore/src/local/indexeddb_remote_document_cache.d.ts +2 -8
  8. package/dist/firestore/src/local/indexeddb_schema.d.ts +149 -7
  9. package/dist/firestore/src/local/local_serializer.d.ts +7 -2
  10. package/dist/firestore/src/local/memory_index_manager.d.ts +11 -0
  11. package/dist/firestore/src/local/memory_persistence.d.ts +3 -2
  12. package/dist/firestore/src/local/memory_remote_document_cache.d.ts +1 -3
  13. package/dist/firestore/src/local/persistence.d.ts +2 -2
  14. package/dist/firestore/src/local/remote_document_cache.d.ts +3 -0
  15. package/dist/firestore/src/local/simple_db.d.ts +1 -0
  16. package/dist/firestore/src/model/field_index.d.ts +2 -2
  17. package/dist/firestore/test/unit/local/persistence_test_helpers.d.ts +1 -0
  18. package/dist/firestore/test/unit/local/test_index_manager.d.ts +11 -0
  19. package/dist/firestore/test/unit/local/test_remote_document_cache.d.ts +2 -0
  20. package/dist/firestore/test/unit/local/test_remote_document_change_buffer.d.ts +1 -1
  21. package/dist/firestore/test/util/helpers.d.ts +1 -1
  22. package/dist/index.d.ts +1 -2
  23. package/dist/index.esm2017.js +3329 -3095
  24. package/dist/index.esm2017.js.map +1 -1
  25. package/dist/index.esm5.js +3590 -3370
  26. package/dist/index.esm5.js.map +1 -1
  27. package/dist/index.node.cjs.js +446 -150
  28. package/dist/index.node.cjs.js.map +1 -1
  29. package/dist/index.node.mjs +446 -150
  30. package/dist/index.node.mjs.map +1 -1
  31. package/dist/index.rn.js +3536 -3302
  32. package/dist/index.rn.js.map +1 -1
  33. package/dist/internal.d.ts +175 -6
  34. package/dist/lite/firestore/src/api/snapshot.d.ts +1 -2
  35. package/dist/lite/firestore/src/core/target.d.ts +8 -4
  36. package/dist/lite/firestore/src/lite-api/query.d.ts +2 -2
  37. package/dist/lite/firestore/src/local/index_manager.d.ts +52 -0
  38. package/dist/lite/firestore/src/local/indexeddb_index_manager.d.ts +21 -2
  39. package/dist/lite/firestore/src/local/indexeddb_persistence.d.ts +4 -4
  40. package/dist/lite/firestore/src/local/indexeddb_remote_document_cache.d.ts +2 -8
  41. package/dist/lite/firestore/src/local/indexeddb_schema.d.ts +149 -7
  42. package/dist/lite/firestore/src/local/local_serializer.d.ts +7 -2
  43. package/dist/lite/firestore/src/local/memory_index_manager.d.ts +11 -0
  44. package/dist/lite/firestore/src/local/memory_persistence.d.ts +3 -2
  45. package/dist/lite/firestore/src/local/memory_remote_document_cache.d.ts +1 -3
  46. package/dist/lite/firestore/src/local/persistence.d.ts +2 -2
  47. package/dist/lite/firestore/src/local/remote_document_cache.d.ts +3 -0
  48. package/dist/lite/firestore/src/local/simple_db.d.ts +1 -0
  49. package/dist/lite/firestore/src/model/field_index.d.ts +2 -2
  50. package/dist/lite/firestore/test/unit/local/persistence_test_helpers.d.ts +1 -0
  51. package/dist/lite/firestore/test/unit/local/test_index_manager.d.ts +11 -0
  52. package/dist/lite/firestore/test/unit/local/test_remote_document_cache.d.ts +2 -0
  53. package/dist/lite/firestore/test/unit/local/test_remote_document_change_buffer.d.ts +1 -1
  54. package/dist/lite/firestore/test/util/helpers.d.ts +1 -1
  55. package/dist/lite/index.browser.esm2017.js +1146 -1143
  56. package/dist/lite/index.browser.esm2017.js.map +1 -1
  57. package/dist/lite/index.browser.esm5.js +332 -331
  58. package/dist/lite/index.browser.esm5.js.map +1 -1
  59. package/dist/lite/index.node.cjs.js +36 -29
  60. package/dist/lite/index.node.cjs.js.map +1 -1
  61. package/dist/lite/index.node.mjs +36 -29
  62. package/dist/lite/index.node.mjs.map +1 -1
  63. package/dist/lite/index.rn.esm2017.js +301 -298
  64. package/dist/lite/index.rn.esm2017.js.map +1 -1
  65. package/dist/lite/internal.d.ts +2 -2
  66. package/dist/lite/packages/firestore/dist/lite/index.browser.esm2017.d.ts +121 -121
  67. package/dist/lite/packages/firestore/src/api/snapshot.d.ts +1 -2
  68. package/dist/lite/packages/firestore/src/core/target.d.ts +8 -4
  69. package/dist/lite/packages/firestore/src/lite-api/query.d.ts +2 -2
  70. package/dist/lite/packages/firestore/src/local/index_manager.d.ts +52 -0
  71. package/dist/lite/packages/firestore/src/local/indexeddb_index_manager.d.ts +21 -2
  72. package/dist/lite/packages/firestore/src/local/indexeddb_persistence.d.ts +4 -4
  73. package/dist/lite/packages/firestore/src/local/indexeddb_remote_document_cache.d.ts +2 -8
  74. package/dist/lite/packages/firestore/src/local/indexeddb_schema.d.ts +149 -7
  75. package/dist/lite/packages/firestore/src/local/local_serializer.d.ts +7 -2
  76. package/dist/lite/packages/firestore/src/local/memory_index_manager.d.ts +11 -0
  77. package/dist/lite/packages/firestore/src/local/memory_persistence.d.ts +3 -2
  78. package/dist/lite/packages/firestore/src/local/memory_remote_document_cache.d.ts +1 -3
  79. package/dist/lite/packages/firestore/src/local/persistence.d.ts +2 -2
  80. package/dist/lite/packages/firestore/src/local/remote_document_cache.d.ts +3 -0
  81. package/dist/lite/packages/firestore/src/local/simple_db.d.ts +1 -0
  82. package/dist/lite/packages/firestore/src/model/field_index.d.ts +2 -2
  83. package/dist/lite/packages/firestore/test/unit/local/persistence_test_helpers.d.ts +1 -0
  84. package/dist/lite/packages/firestore/test/unit/local/test_index_manager.d.ts +11 -0
  85. package/dist/lite/packages/firestore/test/unit/local/test_remote_document_cache.d.ts +2 -0
  86. package/dist/lite/packages/firestore/test/unit/local/test_remote_document_change_buffer.d.ts +1 -1
  87. package/dist/lite/packages/firestore/test/util/helpers.d.ts +1 -1
  88. package/dist/lite/private.d.ts +2 -2
  89. package/dist/packages/firestore/dist/index.esm2017.d.ts +176 -176
  90. package/dist/packages/firestore/src/api/snapshot.d.ts +1 -2
  91. package/dist/packages/firestore/src/core/target.d.ts +8 -4
  92. package/dist/packages/firestore/src/lite-api/query.d.ts +2 -2
  93. package/dist/packages/firestore/src/local/index_manager.d.ts +52 -0
  94. package/dist/packages/firestore/src/local/indexeddb_index_manager.d.ts +21 -2
  95. package/dist/packages/firestore/src/local/indexeddb_persistence.d.ts +4 -4
  96. package/dist/packages/firestore/src/local/indexeddb_remote_document_cache.d.ts +2 -8
  97. package/dist/packages/firestore/src/local/indexeddb_schema.d.ts +149 -7
  98. package/dist/packages/firestore/src/local/local_serializer.d.ts +7 -2
  99. package/dist/packages/firestore/src/local/memory_index_manager.d.ts +11 -0
  100. package/dist/packages/firestore/src/local/memory_persistence.d.ts +3 -2
  101. package/dist/packages/firestore/src/local/memory_remote_document_cache.d.ts +1 -3
  102. package/dist/packages/firestore/src/local/persistence.d.ts +2 -2
  103. package/dist/packages/firestore/src/local/remote_document_cache.d.ts +3 -0
  104. package/dist/packages/firestore/src/local/simple_db.d.ts +1 -0
  105. package/dist/packages/firestore/src/model/field_index.d.ts +2 -2
  106. package/dist/packages/firestore/test/unit/local/persistence_test_helpers.d.ts +1 -0
  107. package/dist/packages/firestore/test/unit/local/test_index_manager.d.ts +11 -0
  108. package/dist/packages/firestore/test/unit/local/test_remote_document_cache.d.ts +2 -0
  109. package/dist/packages/firestore/test/unit/local/test_remote_document_change_buffer.d.ts +1 -1
  110. package/dist/packages/firestore/test/util/helpers.d.ts +1 -1
  111. package/dist/private.d.ts +175 -6
  112. package/package.json +9 -9
@@ -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.2dd99ae2d";
11
+ const version$1 = "3.4.4-canary.434d87ee2";
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.5-canary.2dd99ae2d";
64
+ const version = "9.6.6-canary.434d87ee2";
65
65
 
66
66
  /**
67
67
  * @license
@@ -1192,23 +1192,6 @@ function decodeResourcePath(path) {
1192
1192
  }
1193
1193
  return new ResourcePath(segments);
1194
1194
  }
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
1195
  /**
1213
1196
  * Schema Version for the Web client:
1214
1197
  * 1. Initial version including Mutation Queue, Query Cache, and Remote
@@ -1227,6 +1210,7 @@ function decodeResourcePath(path) {
1227
1210
  * an auto-incrementing ID. This is required for Index-Free queries.
1228
1211
  * 10. Rewrite the canonical IDs to the explicit Protobuf-based format.
1229
1212
  * 11. Add bundles and named_queries for bundle support.
1213
+ * 12. Add indexing support.
1230
1214
  */
1231
1215
  const SCHEMA_VERSION = 11;
1232
1216
  /**
@@ -1753,9 +1737,7 @@ class DbClientMetadata {
1753
1737
  DbClientMetadata.store = 'clientMetadata';
1754
1738
  /** Keys are automatically assigned via the clientId properties. */
1755
1739
  DbClientMetadata.keyPath = 'clientId';
1756
- /**
1757
- * A object representing a bundle loaded by the SDK.
1758
- */
1740
+ /** An object representing a bundle loaded by the SDK. */
1759
1741
  class DbBundle {
1760
1742
  constructor(
1761
1743
  /** The ID of the loaded bundle. */
@@ -1772,9 +1754,7 @@ class DbBundle {
1772
1754
  /** Name of the IndexedDb object store. */
1773
1755
  DbBundle.store = 'bundles';
1774
1756
  DbBundle.keyPath = 'bundleId';
1775
- /**
1776
- * A object representing a named query loaded by the SDK via a bundle.
1777
- */
1757
+ /** An object representing a named query loaded by the SDK via a bundle. */
1778
1758
  class DbNamedQuery {
1779
1759
  constructor(
1780
1760
  /** The name of the query. */
@@ -1791,6 +1771,116 @@ class DbNamedQuery {
1791
1771
  /** Name of the IndexedDb object store. */
1792
1772
  DbNamedQuery.store = 'namedQueries';
1793
1773
  DbNamedQuery.keyPath = 'name';
1774
+ /** An object representing the global configuration for a field index. */
1775
+ class DbIndexConfiguration {
1776
+ constructor(
1777
+ /**
1778
+ * The index id for this entry. Undefined for indexes that are not yet
1779
+ * persisted.
1780
+ */
1781
+ indexId,
1782
+ /** The collection group this index belongs to. */
1783
+ collectionGroup,
1784
+ /** The fields to index for this index. */
1785
+ fields) {
1786
+ this.indexId = indexId;
1787
+ this.collectionGroup = collectionGroup;
1788
+ this.fields = fields;
1789
+ }
1790
+ }
1791
+ /** Name of the IndexedDb object store. */
1792
+ DbIndexConfiguration.store = 'indexConfiguration';
1793
+ DbIndexConfiguration.keyPath = 'indexId';
1794
+ /**
1795
+ * An index that provides access to the index configurations by collection
1796
+ * group.
1797
+ *
1798
+ * PORTING NOTE: iOS and Android maintain this index in-memory, but this is
1799
+ * not possible here as the Web client supports concurrent access to
1800
+ * persistence via multi-tab.
1801
+ */
1802
+ DbIndexConfiguration.collectionGroupIndex = 'collectionGroupIndex';
1803
+ DbIndexConfiguration.collectionGroupIndexPath = 'collectionGroup';
1804
+ /**
1805
+ * An object describing how up-to-date the index backfill is for each user and
1806
+ * index.
1807
+ */
1808
+ class DbIndexState {
1809
+ constructor(
1810
+ /** The index id for this entry. */
1811
+ indexId,
1812
+ /** The user id for this entry. */
1813
+ uid,
1814
+ /**
1815
+ * A number that indicates when the index was last updated (relative to
1816
+ * other indexes).
1817
+ */
1818
+ sequenceNumber,
1819
+ /**
1820
+ * The latest read time that has been indexed by Firestore for this field
1821
+ * index. Set to `{seconds: 0, nanos: 0}` if no documents have been indexed.
1822
+ */
1823
+ readTime,
1824
+ /**
1825
+ * The last document that has been indexed for this field index. Empty if
1826
+ * no documents have been indexed.
1827
+ */
1828
+ documentKey,
1829
+ /**
1830
+ * The largest mutation batch id that has been processed for this index. -1
1831
+ * if no mutations have been indexed.
1832
+ */
1833
+ largestBatchId) {
1834
+ this.indexId = indexId;
1835
+ this.uid = uid;
1836
+ this.sequenceNumber = sequenceNumber;
1837
+ this.readTime = readTime;
1838
+ this.documentKey = documentKey;
1839
+ this.largestBatchId = largestBatchId;
1840
+ }
1841
+ }
1842
+ /** Name of the IndexedDb object store. */
1843
+ DbIndexState.store = 'indexState';
1844
+ DbIndexState.keyPath = ['indexId', 'uid'];
1845
+ /**
1846
+ * An index that provides access to documents in a collection sorted by last
1847
+ * update time. Used by the backfiller.
1848
+ *
1849
+ * PORTING NOTE: iOS and Android maintain this index in-memory, but this is
1850
+ * not possible here as the Web client supports concurrent access to
1851
+ * persistence via multi-tab.
1852
+ */
1853
+ DbIndexState.sequenceNumberIndex = 'sequenceNumberIndex';
1854
+ DbIndexState.sequenceNumberIndexPath = ['uid', 'sequenceNumber'];
1855
+ /** An object that stores the encoded entries for all documents and fields. */
1856
+ class DbIndexEntry {
1857
+ constructor(
1858
+ /** The index id for this entry. */
1859
+ indexId,
1860
+ /** The user id for this entry. */
1861
+ uid,
1862
+ /** The encoded array index value for this entry. */
1863
+ arrayValue,
1864
+ /** The encoded directional value for equality and inequality filters. */
1865
+ directionalValue,
1866
+ /** The document key this entry points to. */
1867
+ documentKey) {
1868
+ this.indexId = indexId;
1869
+ this.uid = uid;
1870
+ this.arrayValue = arrayValue;
1871
+ this.directionalValue = directionalValue;
1872
+ this.documentKey = documentKey;
1873
+ }
1874
+ }
1875
+ /** Name of the IndexedDb object store. */
1876
+ DbIndexEntry.store = 'indexEntries';
1877
+ DbIndexEntry.keyPath = [
1878
+ 'indexId',
1879
+ 'uid',
1880
+ 'arrayValue',
1881
+ 'directionalValue',
1882
+ 'documentKey'
1883
+ ];
1794
1884
  // Visible for testing
1795
1885
  const V1_STORES = [
1796
1886
  DbMutationQueue.store,
@@ -1805,7 +1895,6 @@ const V1_STORES = [
1805
1895
  // V2 is no longer usable (see comment at top of file)
1806
1896
  // Visible for testing
1807
1897
  const V3_STORES = V1_STORES;
1808
- // Visible for testing
1809
1898
  // Note: DbRemoteDocumentChanges is no longer used and dropped with v9.
1810
1899
  const V4_STORES = [...V3_STORES, DbClientMetadata.store];
1811
1900
  // V5 does not change the set of stores.
@@ -1815,12 +1904,24 @@ const V8_STORES = [...V6_STORES, DbCollectionParent.store];
1815
1904
  // V9 does not change the set of stores.
1816
1905
  // V10 does not change the set of stores.
1817
1906
  const V11_STORES = [...V8_STORES, DbBundle.store, DbNamedQuery.store];
1818
- /**
1819
- * The list of all default IndexedDB stores used throughout the SDK. This is
1820
- * used when creating transactions so that access across all stores is done
1821
- * atomically.
1822
- */
1823
- const ALL_STORES = V11_STORES;
1907
+ const V12_STORES = [
1908
+ ...V11_STORES,
1909
+ DbIndexConfiguration.store,
1910
+ DbIndexState.store,
1911
+ DbIndexEntry.store
1912
+ ];
1913
+ /** Returns the object stores for the provided schema. */
1914
+ function getObjectStores(schemaVersion) {
1915
+ if (schemaVersion === 12) {
1916
+ return V12_STORES;
1917
+ }
1918
+ else if (schemaVersion === 11) {
1919
+ return V11_STORES;
1920
+ }
1921
+ else {
1922
+ fail();
1923
+ }
1924
+ }
1824
1925
 
1825
1926
  /**
1826
1927
  * @license
@@ -2117,6 +2218,15 @@ class SimpleDbTransaction {
2117
2218
  this.transaction.abort();
2118
2219
  }
2119
2220
  }
2221
+ maybeCommit() {
2222
+ // If the browser supports V3 IndexedDB, we invoke commit() explicitly to
2223
+ // speed up index DB processing if the event loop remains blocks.
2224
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2225
+ const maybeV3IndexedDb = this.transaction;
2226
+ if (!this.aborted && typeof maybeV3IndexedDb.commit === 'function') {
2227
+ maybeV3IndexedDb.commit();
2228
+ }
2229
+ }
2120
2230
  /**
2121
2231
  * Returns a SimpleDbStore<KeyType, ValueType> for the specified store. All
2122
2232
  * operations performed on the SimpleDbStore happen within the context of this
@@ -2313,6 +2423,10 @@ class SimpleDb {
2313
2423
  this.db = await this.ensureDb(action);
2314
2424
  const transaction = SimpleDbTransaction.open(this.db, action, readonly ? 'readonly' : 'readwrite', objectStores);
2315
2425
  const transactionFnResult = transactionFn(transaction)
2426
+ .next(result => {
2427
+ transaction.maybeCommit();
2428
+ return result;
2429
+ })
2316
2430
  .catch(error => {
2317
2431
  // Abort the transaction if there was an error.
2318
2432
  transaction.abort(error);
@@ -4345,12 +4459,12 @@ class FieldIndex {
4345
4459
  /** The collection ID this index applies to. */
4346
4460
  collectionGroup,
4347
4461
  /** The field segments for this index. */
4348
- segments,
4462
+ fields,
4349
4463
  /** Shows how up-to-date the index is for the current user. */
4350
4464
  indexState) {
4351
4465
  this.indexId = indexId;
4352
4466
  this.collectionGroup = collectionGroup;
4353
- this.segments = segments;
4467
+ this.fields = fields;
4354
4468
  this.indexState = indexState;
4355
4469
  }
4356
4470
  }
@@ -4460,27 +4574,29 @@ function newTarget(path, collectionGroup = null, orderBy = [], filters = [], lim
4460
4574
  function canonifyTarget(target) {
4461
4575
  const targetImpl = debugCast(target);
4462
4576
  if (targetImpl.memoizedCanonicalId === null) {
4463
- let canonicalId = targetImpl.path.canonicalString();
4577
+ let str = targetImpl.path.canonicalString();
4464
4578
  if (targetImpl.collectionGroup !== null) {
4465
- canonicalId += '|cg:' + targetImpl.collectionGroup;
4579
+ str += '|cg:' + targetImpl.collectionGroup;
4466
4580
  }
4467
- canonicalId += '|f:';
4468
- canonicalId += targetImpl.filters.map(f => canonifyFilter(f)).join(',');
4469
- canonicalId += '|ob:';
4470
- canonicalId += targetImpl.orderBy.map(o => canonifyOrderBy(o)).join(',');
4581
+ str += '|f:';
4582
+ str += targetImpl.filters.map(f => canonifyFilter(f)).join(',');
4583
+ str += '|ob:';
4584
+ str += targetImpl.orderBy.map(o => canonifyOrderBy(o)).join(',');
4471
4585
  if (!isNullOrUndefined(targetImpl.limit)) {
4472
- canonicalId += '|l:';
4473
- canonicalId += targetImpl.limit;
4586
+ str += '|l:';
4587
+ str += targetImpl.limit;
4474
4588
  }
4475
4589
  if (targetImpl.startAt) {
4476
- canonicalId += '|lb:';
4477
- canonicalId += canonifyBound(targetImpl.startAt);
4590
+ str += '|lb:';
4591
+ str += targetImpl.startAt.inclusive ? 'b:' : 'a:';
4592
+ str += targetImpl.startAt.position.map(p => canonicalId(p)).join(',');
4478
4593
  }
4479
4594
  if (targetImpl.endAt) {
4480
- canonicalId += '|ub:';
4481
- canonicalId += canonifyBound(targetImpl.endAt);
4595
+ str += '|ub:';
4596
+ str += targetImpl.endAt.inclusive ? 'a:' : 'b:';
4597
+ str += targetImpl.endAt.position.map(p => canonicalId(p)).join(',');
4482
4598
  }
4483
- targetImpl.memoizedCanonicalId = canonicalId;
4599
+ targetImpl.memoizedCanonicalId = str;
4484
4600
  }
4485
4601
  return targetImpl.memoizedCanonicalId;
4486
4602
  }
@@ -4503,10 +4619,14 @@ function stringifyTarget(target) {
4503
4619
  .join(', ')}]`;
4504
4620
  }
4505
4621
  if (target.startAt) {
4506
- str += ', startAt: ' + canonifyBound(target.startAt);
4622
+ str += ', startAt: ';
4623
+ str += target.startAt.inclusive ? 'b:' : 'a:';
4624
+ str += target.startAt.position.map(p => canonicalId(p)).join(',');
4507
4625
  }
4508
4626
  if (target.endAt) {
4509
- str += ', endAt: ' + canonifyBound(target.endAt);
4627
+ str += ', endAt: ';
4628
+ str += target.endAt.inclusive ? 'a:' : 'b:';
4629
+ str += target.endAt.position.map(p => canonicalId(p)).join(',');
4510
4630
  }
4511
4631
  return `Target(${str})`;
4512
4632
  }
@@ -4729,7 +4849,6 @@ class ArrayContainsAnyFilter extends FieldFilter {
4729
4849
  return other.arrayValue.values.some(val => arrayValueContains(this.value.arrayValue, val));
4730
4850
  }
4731
4851
  }
4732
- // TODO(indexing): Change Bound.before to "inclusive"
4733
4852
  /**
4734
4853
  * Represents a bound of a query.
4735
4854
  *
@@ -4745,17 +4864,11 @@ class ArrayContainsAnyFilter extends FieldFilter {
4745
4864
  * just after the provided values.
4746
4865
  */
4747
4866
  class Bound {
4748
- constructor(position, before) {
4867
+ constructor(position, inclusive) {
4749
4868
  this.position = position;
4750
- this.before = before;
4869
+ this.inclusive = inclusive;
4751
4870
  }
4752
4871
  }
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
4872
  /**
4760
4873
  * An ordering on a field, in some Direction. Direction defaults to ASCENDING.
4761
4874
  */
@@ -4775,11 +4888,7 @@ function stringifyOrderBy(orderBy) {
4775
4888
  function orderByEquals(left, right) {
4776
4889
  return left.dir === right.dir && left.field.isEqual(right.field);
4777
4890
  }
4778
- /**
4779
- * Returns true if a document sorts before a bound using the provided sort
4780
- * order.
4781
- */
4782
- function sortsBeforeDocument(bound, orderBy, doc) {
4891
+ function boundCompareToDocument(bound, orderBy, doc) {
4783
4892
  let comparison = 0;
4784
4893
  for (let i = 0; i < bound.position.length; i++) {
4785
4894
  const orderByComponent = orderBy[i];
@@ -4798,7 +4907,23 @@ function sortsBeforeDocument(bound, orderBy, doc) {
4798
4907
  break;
4799
4908
  }
4800
4909
  }
4801
- return bound.before ? comparison <= 0 : comparison < 0;
4910
+ return comparison;
4911
+ }
4912
+ /**
4913
+ * Returns true if a document sorts after a bound using the provided sort
4914
+ * order.
4915
+ */
4916
+ function boundSortsAfterDocument(bound, orderBy, doc) {
4917
+ const comparison = boundCompareToDocument(bound, orderBy, doc);
4918
+ return bound.inclusive ? comparison >= 0 : comparison > 0;
4919
+ }
4920
+ /**
4921
+ * Returns true if a document sorts before a bound using the provided sort
4922
+ * order.
4923
+ */
4924
+ function boundSortsBeforeDocument(bound, orderBy, doc) {
4925
+ const comparison = boundCompareToDocument(bound, orderBy, doc);
4926
+ return bound.inclusive ? comparison <= 0 : comparison < 0;
4802
4927
  }
4803
4928
  function boundEquals(left, right) {
4804
4929
  if (left === null) {
@@ -4807,7 +4932,7 @@ function boundEquals(left, right) {
4807
4932
  else if (right === null) {
4808
4933
  return false;
4809
4934
  }
4810
- if (left.before !== right.before ||
4935
+ if (left.inclusive !== right.inclusive ||
4811
4936
  left.position.length !== right.position.length) {
4812
4937
  return false;
4813
4938
  }
@@ -5011,10 +5136,10 @@ function queryToTarget(query) {
5011
5136
  }
5012
5137
  // We need to swap the cursors to match the now-flipped query ordering.
5013
5138
  const startAt = queryImpl.endAt
5014
- ? new Bound(queryImpl.endAt.position, !queryImpl.endAt.before)
5139
+ ? new Bound(queryImpl.endAt.position, !queryImpl.endAt.inclusive)
5015
5140
  : null;
5016
5141
  const endAt = queryImpl.startAt
5017
- ? new Bound(queryImpl.startAt.position, !queryImpl.startAt.before)
5142
+ ? new Bound(queryImpl.startAt.position, !queryImpl.startAt.inclusive)
5018
5143
  : null;
5019
5144
  // Now return as a LimitType.First query.
5020
5145
  queryImpl.memoizedTarget = newTarget(queryImpl.path, queryImpl.collectionGroup, orderBys, queryImpl.filters, queryImpl.limit, startAt, endAt);
@@ -5102,11 +5227,11 @@ function queryMatchesFilters(query, doc) {
5102
5227
  /** Makes sure a document is within the bounds, if provided. */
5103
5228
  function queryMatchesBounds(query, doc) {
5104
5229
  if (query.startAt &&
5105
- !sortsBeforeDocument(query.startAt, queryOrderBy(query), doc)) {
5230
+ !boundSortsBeforeDocument(query.startAt, queryOrderBy(query), doc)) {
5106
5231
  return false;
5107
5232
  }
5108
5233
  if (query.endAt &&
5109
- sortsBeforeDocument(query.endAt, queryOrderBy(query), doc)) {
5234
+ !boundSortsAfterDocument(query.endAt, queryOrderBy(query), doc)) {
5110
5235
  return false;
5111
5236
  }
5112
5237
  return true;
@@ -7985,10 +8110,10 @@ function toQueryTarget(serializer, target) {
7985
8110
  result.structuredQuery.limit = limit;
7986
8111
  }
7987
8112
  if (target.startAt) {
7988
- result.structuredQuery.startAt = toCursor(target.startAt);
8113
+ result.structuredQuery.startAt = toStartAtCursor(target.startAt);
7989
8114
  }
7990
8115
  if (target.endAt) {
7991
- result.structuredQuery.endAt = toCursor(target.endAt);
8116
+ result.structuredQuery.endAt = toEndAtCursor(target.endAt);
7992
8117
  }
7993
8118
  return result;
7994
8119
  }
@@ -8021,11 +8146,11 @@ function convertQueryTargetToQuery(target) {
8021
8146
  }
8022
8147
  let startAt = null;
8023
8148
  if (query.startAt) {
8024
- startAt = fromCursor(query.startAt);
8149
+ startAt = fromStartAtCursor(query.startAt);
8025
8150
  }
8026
8151
  let endAt = null;
8027
8152
  if (query.endAt) {
8028
- endAt = fromCursor(query.endAt);
8153
+ endAt = fromEndAtCursor(query.endAt);
8029
8154
  }
8030
8155
  return newQuery(path, collectionGroup, orderBy, filterBy, limit, "F" /* First */, startAt, endAt);
8031
8156
  }
@@ -8116,16 +8241,27 @@ function toOrder(orderBys) {
8116
8241
  function fromOrder(orderBys) {
8117
8242
  return orderBys.map(order => fromPropertyOrder(order));
8118
8243
  }
8119
- function toCursor(cursor) {
8244
+ function toStartAtCursor(cursor) {
8120
8245
  return {
8121
- before: cursor.before,
8246
+ before: cursor.inclusive,
8122
8247
  values: cursor.position
8123
8248
  };
8124
8249
  }
8125
- function fromCursor(cursor) {
8126
- const before = !!cursor.before;
8250
+ function toEndAtCursor(cursor) {
8251
+ return {
8252
+ before: !cursor.inclusive,
8253
+ values: cursor.position
8254
+ };
8255
+ }
8256
+ function fromStartAtCursor(cursor) {
8257
+ const inclusive = !!cursor.before;
8127
8258
  const position = cursor.values || [];
8128
- return new Bound(position, before);
8259
+ return new Bound(position, inclusive);
8260
+ }
8261
+ function fromEndAtCursor(cursor) {
8262
+ const inclusive = !cursor.before;
8263
+ const position = cursor.values || [];
8264
+ return new Bound(position, inclusive);
8129
8265
  }
8130
8266
  // visible for testing
8131
8267
  function toDirection(dir) {
@@ -8589,6 +8725,19 @@ function fromBundleMetadata(metadata) {
8589
8725
  version: metadata.version,
8590
8726
  createTime: fromVersion(metadata.createTime)
8591
8727
  };
8728
+ }
8729
+ function toDbIndexConfiguration(index) {
8730
+ return new DbIndexConfiguration(index.indexId, index.collectionGroup, index.fields.map(s => [s.fieldPath.canonicalString(), s.kind]));
8731
+ }
8732
+ function fromDbIndexConfiguration(index, state) {
8733
+ const decodedState = state
8734
+ ? new IndexState(state.sequenceNumber, new IndexOffset(fromDbTimestamp(state.readTime), new DocumentKey(decodeResourcePath(state.documentKey)), state.largestBatchId))
8735
+ : IndexState.empty();
8736
+ const decodedSegments = index.fields.map(([fieldPath, kind]) => new IndexSegment(FieldPath$1.fromServerFormat(fieldPath), kind));
8737
+ return new FieldIndex(index.indexId, index.collectionGroup, decodedSegments, decodedState);
8738
+ }
8739
+ function toDbIndexState(indexId, user, sequenceNumber, offset) {
8740
+ return new DbIndexState(indexId, user.uid || '', sequenceNumber, toDbTimestamp(offset.readTime), encodeResourcePath(offset.documentKey.path), offset.largestBatchId);
8592
8741
  }
8593
8742
 
8594
8743
  /**
@@ -8678,6 +8827,38 @@ class MemoryIndexManager {
8678
8827
  getCollectionParents(transaction, collectionId) {
8679
8828
  return PersistencePromise.resolve(this.collectionParentIndex.getEntries(collectionId));
8680
8829
  }
8830
+ addFieldIndex(transaction, index) {
8831
+ // Field indices are not supported with memory persistence.
8832
+ return PersistencePromise.resolve();
8833
+ }
8834
+ deleteFieldIndex(transaction, index) {
8835
+ // Field indices are not supported with memory persistence.
8836
+ return PersistencePromise.resolve();
8837
+ }
8838
+ getDocumentsMatchingTarget(transaction, fieldIndex, target) {
8839
+ // Field indices are not supported with memory persistence.
8840
+ return PersistencePromise.resolve(documentKeySet());
8841
+ }
8842
+ getFieldIndex(transaction, target) {
8843
+ // Field indices are not supported with memory persistence.
8844
+ return PersistencePromise.resolve(null);
8845
+ }
8846
+ getFieldIndexes(transaction, collectionGroup) {
8847
+ // Field indices are not supported with memory persistence.
8848
+ return PersistencePromise.resolve([]);
8849
+ }
8850
+ getNextCollectionGroupToUpdate(transaction) {
8851
+ // Field indices are not supported with memory persistence.
8852
+ return PersistencePromise.resolve(null);
8853
+ }
8854
+ updateCollectionGroup(transaction, collectionGroup, offset) {
8855
+ // Field indices are not supported with memory persistence.
8856
+ return PersistencePromise.resolve();
8857
+ }
8858
+ updateIndexEntries(transaction, documents) {
8859
+ // Field indices are not supported with memory persistence.
8860
+ return PersistencePromise.resolve();
8861
+ }
8681
8862
  }
8682
8863
  /**
8683
8864
  * Internal implementation of the collection-parent index exposed by MemoryIndexManager.
@@ -8729,17 +8910,22 @@ class MemoryCollectionParentIndex {
8729
8910
  */
8730
8911
  /**
8731
8912
  * A persisted implementation of IndexManager.
8913
+ *
8914
+ * PORTING NOTE: Unlike iOS and Android, the Web SDK does not memoize index
8915
+ * data as it supports multi-tab access.
8732
8916
  */
8733
8917
  class IndexedDbIndexManager {
8734
- constructor() {
8918
+ constructor(user) {
8919
+ this.user = user;
8735
8920
  /**
8736
8921
  * An in-memory copy of the index entries we've already written since the SDK
8737
8922
  * launched. Used to avoid re-writing the same entry repeatedly.
8738
8923
  *
8739
- * This is *NOT* a complete cache of what's in persistence and so can never be used to
8740
- * satisfy reads.
8924
+ * This is *NOT* a complete cache of what's in persistence and so can never be
8925
+ * used to satisfy reads.
8741
8926
  */
8742
8927
  this.collectionParentsCache = new MemoryCollectionParentIndex();
8928
+ this.uid = user.uid || '';
8743
8929
  }
8744
8930
  /**
8745
8931
  * Adds a new entry to the collection parent index.
@@ -8786,6 +8972,85 @@ class IndexedDbIndexManager {
8786
8972
  return parentPaths;
8787
8973
  });
8788
8974
  }
8975
+ addFieldIndex(transaction, index) {
8976
+ // TODO(indexing): Verify that the auto-incrementing index ID works in
8977
+ // Safari & Firefox.
8978
+ const indexes = indexConfigurationStore(transaction);
8979
+ const dbIndex = toDbIndexConfiguration(index);
8980
+ delete dbIndex.indexId; // `indexId` is auto-populated by IndexedDb
8981
+ return indexes.add(dbIndex).next();
8982
+ }
8983
+ deleteFieldIndex(transaction, index) {
8984
+ const indexes = indexConfigurationStore(transaction);
8985
+ const states = indexStateStore(transaction);
8986
+ const entries = indexEntriesStore(transaction);
8987
+ return indexes
8988
+ .delete(index.indexId)
8989
+ .next(() => states.delete(IDBKeyRange.bound([index.indexId], [index.indexId + 1],
8990
+ /*lowerOpen=*/ false,
8991
+ /*upperOpen=*/ true)))
8992
+ .next(() => entries.delete(IDBKeyRange.bound([index.indexId], [index.indexId + 1],
8993
+ /*lowerOpen=*/ false,
8994
+ /*upperOpen=*/ true)));
8995
+ }
8996
+ getDocumentsMatchingTarget(transaction, fieldIndex, target) {
8997
+ // TODO(indexing): Implement
8998
+ return PersistencePromise.resolve(documentKeySet());
8999
+ }
9000
+ getFieldIndex(transaction, target) {
9001
+ // TODO(indexing): Implement
9002
+ return PersistencePromise.resolve(null);
9003
+ }
9004
+ getFieldIndexes(transaction, collectionGroup) {
9005
+ const indexes = indexConfigurationStore(transaction);
9006
+ const states = indexStateStore(transaction);
9007
+ return (collectionGroup
9008
+ ? indexes.loadAll(DbIndexConfiguration.collectionGroupIndex, IDBKeyRange.bound(collectionGroup, collectionGroup))
9009
+ : indexes.loadAll()).next(indexConfigs => {
9010
+ const result = [];
9011
+ return PersistencePromise.forEach(indexConfigs, (indexConfig) => {
9012
+ return states
9013
+ .get([indexConfig.indexId, this.uid])
9014
+ .next(indexState => {
9015
+ result.push(fromDbIndexConfiguration(indexConfig, indexState));
9016
+ });
9017
+ }).next(() => result);
9018
+ });
9019
+ }
9020
+ getNextCollectionGroupToUpdate(transaction) {
9021
+ return this.getFieldIndexes(transaction).next(indexes => {
9022
+ if (indexes.length === 0) {
9023
+ return null;
9024
+ }
9025
+ indexes.sort((l, r) => l.indexState.sequenceNumber - r.indexState.sequenceNumber);
9026
+ return indexes[0].collectionGroup;
9027
+ });
9028
+ }
9029
+ updateCollectionGroup(transaction, collectionGroup, offset) {
9030
+ const indexes = indexConfigurationStore(transaction);
9031
+ const states = indexStateStore(transaction);
9032
+ return this.getNextSequenceNumber(transaction).next(nextSequenceNumber => indexes
9033
+ .loadAll(DbIndexConfiguration.collectionGroupIndex, IDBKeyRange.bound(collectionGroup, collectionGroup))
9034
+ .next(configs => PersistencePromise.forEach(configs, (config) => states.put(toDbIndexState(config.indexId, this.user, nextSequenceNumber, offset)))));
9035
+ }
9036
+ updateIndexEntries(transaction, documents) {
9037
+ // TODO(indexing): Implement
9038
+ return PersistencePromise.resolve();
9039
+ }
9040
+ getNextSequenceNumber(transaction) {
9041
+ let nextSequenceNumber = 1;
9042
+ const states = indexStateStore(transaction);
9043
+ return states
9044
+ .iterate({
9045
+ index: DbIndexState.sequenceNumberIndex,
9046
+ reverse: true,
9047
+ range: IDBKeyRange.upperBound([this.uid, Number.MAX_SAFE_INTEGER])
9048
+ }, (_, state, controller) => {
9049
+ controller.done();
9050
+ nextSequenceNumber = state.sequenceNumber + 1;
9051
+ })
9052
+ .next(() => nextSequenceNumber);
9053
+ }
8789
9054
  }
8790
9055
  /**
8791
9056
  * Helper to get a typed SimpleDbStore for the collectionParents
@@ -8793,6 +9058,24 @@ class IndexedDbIndexManager {
8793
9058
  */
8794
9059
  function collectionParentsStore(txn) {
8795
9060
  return getStore(txn, DbCollectionParent.store);
9061
+ }
9062
+ /**
9063
+ * Helper to get a typed SimpleDbStore for the index entry object store.
9064
+ */
9065
+ function indexEntriesStore(txn) {
9066
+ return getStore(txn, DbIndexEntry.store);
9067
+ }
9068
+ /**
9069
+ * Helper to get a typed SimpleDbStore for the index configuration object store.
9070
+ */
9071
+ function indexConfigurationStore(txn) {
9072
+ return getStore(txn, DbIndexConfiguration.store);
9073
+ }
9074
+ /**
9075
+ * Helper to get a typed SimpleDbStore for the index state object store.
9076
+ */
9077
+ function indexStateStore(txn) {
9078
+ return getStore(txn, DbIndexState.store);
8796
9079
  }
8797
9080
 
8798
9081
  /**
@@ -10262,12 +10545,10 @@ class RemoteDocumentChangeBuffer {
10262
10545
  * `newIndexedDbRemoteDocumentCache()`.
10263
10546
  */
10264
10547
  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) {
10548
+ constructor(serializer) {
10270
10549
  this.serializer = serializer;
10550
+ }
10551
+ setIndexManager(indexManager) {
10271
10552
  this.indexManager = indexManager;
10272
10553
  }
10273
10554
  /**
@@ -10463,14 +10744,9 @@ class IndexedDbRemoteDocumentCacheImpl {
10463
10744
  return MutableDocument.newInvalidDocument(documentKey);
10464
10745
  }
10465
10746
  }
10466
- /**
10467
- * Creates a new IndexedDbRemoteDocumentCache.
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);
10747
+ /** Creates a new IndexedDbRemoteDocumentCache. */
10748
+ function newIndexedDbRemoteDocumentCache(serializer) {
10749
+ return new IndexedDbRemoteDocumentCacheImpl(serializer);
10474
10750
  }
10475
10751
  /**
10476
10752
  * Returns the set of documents that have changed since the specified read
@@ -10637,9 +10913,6 @@ class SchemaConverter {
10637
10913
  * and local feature development.
10638
10914
  */
10639
10915
  createOrUpgrade(db, txn, fromVersion, toVersion) {
10640
- hardAssert(fromVersion < toVersion &&
10641
- fromVersion >= 0 &&
10642
- toVersion <= SCHEMA_VERSION);
10643
10916
  const simpleDbTransaction = new SimpleDbTransaction('createOrUpgrade', txn);
10644
10917
  if (fromVersion < 1 && toVersion >= 1) {
10645
10918
  createPrimaryClientStore(db);
@@ -10706,6 +10979,11 @@ class SchemaConverter {
10706
10979
  createNamedQueriesStore(db);
10707
10980
  });
10708
10981
  }
10982
+ if (fromVersion < 12 && toVersion >= 12) {
10983
+ p = p.next(() => {
10984
+ createFieldIndex(db);
10985
+ });
10986
+ }
10709
10987
  return p;
10710
10988
  }
10711
10989
  addDocumentGlobal(txn) {
@@ -10912,6 +11190,20 @@ function createNamedQueriesStore(db) {
10912
11190
  db.createObjectStore(DbNamedQuery.store, {
10913
11191
  keyPath: DbNamedQuery.keyPath
10914
11192
  });
11193
+ }
11194
+ function createFieldIndex(db) {
11195
+ const indexConfiguratioStore = db.createObjectStore(DbIndexConfiguration.store, {
11196
+ keyPath: DbIndexConfiguration.keyPath,
11197
+ autoIncrement: true
11198
+ });
11199
+ indexConfiguratioStore.createIndex(DbIndexConfiguration.collectionGroupIndex, DbIndexConfiguration.collectionGroupIndexPath, { unique: false });
11200
+ const indexStateStore = db.createObjectStore(DbIndexState.store, {
11201
+ keyPath: DbIndexState.keyPath
11202
+ });
11203
+ indexStateStore.createIndex(DbIndexState.sequenceNumberIndex, DbIndexState.sequenceNumberIndexPath, { unique: false });
11204
+ db.createObjectStore(DbIndexEntry.store, {
11205
+ keyPath: DbIndexEntry.keyPath
11206
+ });
10915
11207
  }
10916
11208
 
10917
11209
  /**
@@ -11023,7 +11315,7 @@ class IndexedDbPersistence {
11023
11315
  * If set to true, forcefully obtains database access. Existing tabs will
11024
11316
  * no longer be able to access IndexedDB.
11025
11317
  */
11026
- forceOwningTab) {
11318
+ forceOwningTab, schemaVersion = SCHEMA_VERSION) {
11027
11319
  this.allowTabSynchronization = allowTabSynchronization;
11028
11320
  this.persistenceKey = persistenceKey;
11029
11321
  this.clientId = clientId;
@@ -11032,6 +11324,7 @@ class IndexedDbPersistence {
11032
11324
  this.document = document;
11033
11325
  this.sequenceNumberSyncer = sequenceNumberSyncer;
11034
11326
  this.forceOwningTab = forceOwningTab;
11327
+ this.schemaVersion = schemaVersion;
11035
11328
  this.listenSequence = null;
11036
11329
  this._started = false;
11037
11330
  this.isPrimary = false;
@@ -11053,10 +11346,9 @@ class IndexedDbPersistence {
11053
11346
  this.referenceDelegate = new IndexedDbLruDelegateImpl(this, lruParams);
11054
11347
  this.dbName = persistenceKey + MAIN_DATABASE;
11055
11348
  this.serializer = new LocalSerializer(serializer);
11056
- this.simpleDb = new SimpleDb(this.dbName, SCHEMA_VERSION, new SchemaConverter(this.serializer));
11349
+ this.simpleDb = new SimpleDb(this.dbName, this.schemaVersion, new SchemaConverter(this.serializer));
11057
11350
  this.targetCache = new IndexedDbTargetCache(this.referenceDelegate, this.serializer);
11058
- this.indexManager = new IndexedDbIndexManager();
11059
- this.remoteDocumentCache = newIndexedDbRemoteDocumentCache(this.serializer, this.indexManager);
11351
+ this.remoteDocumentCache = newIndexedDbRemoteDocumentCache(this.serializer);
11060
11352
  this.bundleCache = new IndexedDbBundleCache();
11061
11353
  if (this.window && this.window.localStorage) {
11062
11354
  this.webStorage = this.window.localStorage;
@@ -11392,8 +11684,8 @@ class IndexedDbPersistence {
11392
11684
  get started() {
11393
11685
  return this._started;
11394
11686
  }
11395
- getMutationQueue(user) {
11396
- return IndexedDbMutationQueue.forUser(user, this.serializer, this.indexManager, this.referenceDelegate);
11687
+ getMutationQueue(user, indexManager) {
11688
+ return IndexedDbMutationQueue.forUser(user, this.serializer, indexManager, this.referenceDelegate);
11397
11689
  }
11398
11690
  getTargetCache() {
11399
11691
  return this.targetCache;
@@ -11401,8 +11693,8 @@ class IndexedDbPersistence {
11401
11693
  getRemoteDocumentCache() {
11402
11694
  return this.remoteDocumentCache;
11403
11695
  }
11404
- getIndexManager() {
11405
- return this.indexManager;
11696
+ getIndexManager(user) {
11697
+ return new IndexedDbIndexManager(user);
11406
11698
  }
11407
11699
  getBundleCache() {
11408
11700
  return this.bundleCache;
@@ -11410,11 +11702,12 @@ class IndexedDbPersistence {
11410
11702
  runTransaction(action, mode, transactionOperation) {
11411
11703
  logDebug(LOG_TAG$d, 'Starting transaction:', action);
11412
11704
  const simpleDbMode = mode === 'readonly' ? 'readonly' : 'readwrite';
11705
+ const objectStores = getObjectStores(this.schemaVersion);
11413
11706
  let persistenceTransaction;
11414
11707
  // Do all transactions as readwrite against all object stores, since we
11415
11708
  // are the only reader/writer.
11416
11709
  return this.simpleDb
11417
- .runTransaction(action, simpleDbMode, ALL_STORES, simpleDbTxn => {
11710
+ .runTransaction(action, simpleDbMode, objectStores, simpleDbTxn => {
11418
11711
  persistenceTransaction = new IndexedDbTransaction(simpleDbTxn, this.listenSequence
11419
11712
  ? this.listenSequence.next()
11420
11713
  : ListenSequence.INVALID);
@@ -11912,11 +12205,18 @@ class LocalStoreImpl {
11912
12205
  * PORTING NOTE: This is only used for multi-tab synchronization.
11913
12206
  */
11914
12207
  this.lastDocumentChangeReadTime = SnapshotVersion.min();
11915
- this.mutationQueue = persistence.getMutationQueue(initialUser);
11916
12208
  this.remoteDocuments = persistence.getRemoteDocumentCache();
11917
12209
  this.targetCache = persistence.getTargetCache();
11918
- this.localDocuments = new LocalDocumentsView(this.remoteDocuments, this.mutationQueue, this.persistence.getIndexManager());
11919
12210
  this.bundleCache = persistence.getBundleCache();
12211
+ this.initializeUserComponents(initialUser);
12212
+ }
12213
+ initializeUserComponents(user) {
12214
+ // TODO(indexing): Add spec tests that test these components change after a
12215
+ // user change
12216
+ this.indexManager = this.persistence.getIndexManager(user);
12217
+ this.mutationQueue = this.persistence.getMutationQueue(user, this.indexManager);
12218
+ this.localDocuments = new LocalDocumentsView(this.remoteDocuments, this.mutationQueue, this.indexManager);
12219
+ this.remoteDocuments.setIndexManager(this.indexManager);
11920
12220
  this.queryEngine.setLocalDocumentsView(this.localDocuments);
11921
12221
  }
11922
12222
  collectGarbage(garbageCollector) {
@@ -11938,8 +12238,6 @@ persistence, queryEngine, initialUser, serializer) {
11938
12238
  // change.
11939
12239
  async function localStoreHandleUserChange(localStore, user) {
11940
12240
  const localStoreImpl = debugCast(localStore);
11941
- let newMutationQueue = localStoreImpl.mutationQueue;
11942
- let newLocalDocuments = localStoreImpl.localDocuments;
11943
12241
  const result = await localStoreImpl.persistence.runTransaction('Handle user change', 'readonly', txn => {
11944
12242
  // Swap out the mutation queue, grabbing the pending mutation batches
11945
12243
  // before and after.
@@ -11948,11 +12246,8 @@ async function localStoreHandleUserChange(localStore, user) {
11948
12246
  .getAllMutationBatches(txn)
11949
12247
  .next(promisedOldBatches => {
11950
12248
  oldBatches = promisedOldBatches;
11951
- newMutationQueue = localStoreImpl.persistence.getMutationQueue(user);
11952
- // Recreate our LocalDocumentsView using the new
11953
- // MutationQueue.
11954
- newLocalDocuments = new LocalDocumentsView(localStoreImpl.remoteDocuments, newMutationQueue, localStoreImpl.persistence.getIndexManager());
11955
- return newMutationQueue.getAllMutationBatches(txn);
12249
+ localStoreImpl.initializeUserComponents(user);
12250
+ return localStoreImpl.mutationQueue.getAllMutationBatches(txn);
11956
12251
  })
11957
12252
  .next(newBatches => {
11958
12253
  const removedBatchIds = [];
@@ -11973,7 +12268,7 @@ async function localStoreHandleUserChange(localStore, user) {
11973
12268
  }
11974
12269
  // Return the set of all (potentially) changed documents and the list
11975
12270
  // of mutation batch IDs that were affected by change.
11976
- return newLocalDocuments
12271
+ return localStoreImpl.localDocuments
11977
12272
  .getDocuments(txn, changedKeys)
11978
12273
  .next(affectedDocuments => {
11979
12274
  return {
@@ -11984,9 +12279,6 @@ async function localStoreHandleUserChange(localStore, user) {
11984
12279
  });
11985
12280
  });
11986
12281
  });
11987
- localStoreImpl.mutationQueue = newMutationQueue;
11988
- localStoreImpl.localDocuments = newLocalDocuments;
11989
- localStoreImpl.queryEngine.setLocalDocumentsView(localStoreImpl.localDocuments);
11990
12282
  return result;
11991
12283
  }
11992
12284
  /* Accepts locally generated Mutations and commit them to storage. */
@@ -13052,14 +13344,16 @@ class MemoryRemoteDocumentCacheImpl {
13052
13344
  * expected to just return 0 to avoid unnecessarily doing the work of
13053
13345
  * calculating the size.
13054
13346
  */
13055
- constructor(indexManager, sizer) {
13056
- this.indexManager = indexManager;
13347
+ constructor(sizer) {
13057
13348
  this.sizer = sizer;
13058
13349
  /** Underlying cache of documents and their read times. */
13059
13350
  this.docs = documentEntryMap();
13060
13351
  /** Size of all cached documents. */
13061
13352
  this.size = 0;
13062
13353
  }
13354
+ setIndexManager(indexManager) {
13355
+ this.indexManager = indexManager;
13356
+ }
13063
13357
  /**
13064
13358
  * Adds the supplied entry to the cache and updates the cache size as appropriate.
13065
13359
  *
@@ -13143,13 +13437,12 @@ class MemoryRemoteDocumentCacheImpl {
13143
13437
  /**
13144
13438
  * Creates a new memory-only RemoteDocumentCache.
13145
13439
  *
13146
- * @param indexManager - A class that manages collection group indices.
13147
13440
  * @param sizer - Used to assess the size of a document. For eager GC, this is
13148
13441
  * expected to just return 0 to avoid unnecessarily doing the work of
13149
13442
  * calculating the size.
13150
13443
  */
13151
- function newMemoryRemoteDocumentCache(indexManager, sizer) {
13152
- return new MemoryRemoteDocumentCacheImpl(indexManager, sizer);
13444
+ function newMemoryRemoteDocumentCache(sizer) {
13445
+ return new MemoryRemoteDocumentCacheImpl(sizer);
13153
13446
  }
13154
13447
  /**
13155
13448
  * Handles the details of adding and updating documents in the MemoryRemoteDocumentCache.
@@ -13350,7 +13643,7 @@ class MemoryPersistence {
13350
13643
  this.targetCache = new MemoryTargetCache(this);
13351
13644
  const sizer = (doc) => this.referenceDelegate.documentSize(doc);
13352
13645
  this.indexManager = new MemoryIndexManager();
13353
- this.remoteDocumentCache = newMemoryRemoteDocumentCache(this.indexManager, sizer);
13646
+ this.remoteDocumentCache = newMemoryRemoteDocumentCache(sizer);
13354
13647
  this.serializer = new LocalSerializer(serializer);
13355
13648
  this.bundleCache = new MemoryBundleCache(this.serializer);
13356
13649
  }
@@ -13371,13 +13664,15 @@ class MemoryPersistence {
13371
13664
  setNetworkEnabled() {
13372
13665
  // No op.
13373
13666
  }
13374
- getIndexManager() {
13667
+ getIndexManager(user) {
13668
+ // We do not currently support indices for memory persistence, so we can
13669
+ // return the same shared instance of the memory index manager.
13375
13670
  return this.indexManager;
13376
13671
  }
13377
- getMutationQueue(user) {
13672
+ getMutationQueue(user, indexManager) {
13378
13673
  let queue = this.mutationQueues[user.toKey()];
13379
13674
  if (!queue) {
13380
- queue = new MemoryMutationQueue(this.indexManager, this.referenceDelegate);
13675
+ queue = new MemoryMutationQueue(indexManager, this.referenceDelegate);
13381
13676
  this.mutationQueues[user.toKey()] = queue;
13382
13677
  }
13383
13678
  return queue;
@@ -20340,12 +20635,12 @@ async function syncEngineListen(syncEngine, query) {
20340
20635
  }
20341
20636
  else {
20342
20637
  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
20638
  if (syncEngineImpl.isPrimaryClient) {
20347
20639
  remoteStoreListen(syncEngineImpl.remoteStore, targetData);
20348
20640
  }
20641
+ const status = syncEngineImpl.sharedClientState.addLocalQueryTarget(targetData.targetId);
20642
+ targetId = targetData.targetId;
20643
+ viewSnapshot = await initializeViewAndComputeSnapshot(syncEngineImpl, query, targetId, status === 'current');
20349
20644
  }
20350
20645
  return viewSnapshot;
20351
20646
  }
@@ -24853,8 +25148,7 @@ class DocumentSnapshot extends DocumentSnapshot$1 {
24853
25148
  this.metadata = metadata;
24854
25149
  }
24855
25150
  /**
24856
- * Property of the `DocumentSnapshot` that signals whether or not the data
24857
- * exists. True if the document exists.
25151
+ * Returns whether or not the data exists. True if the document exists.
24858
25152
  */
24859
25153
  exists() {
24860
25154
  return super.exists();
@@ -25228,51 +25522,53 @@ function limitToLast(limit) {
25228
25522
  return new QueryLimitConstraint('limitToLast', limit, "L" /* Last */);
25229
25523
  }
25230
25524
  class QueryStartAtConstraint extends QueryConstraint {
25231
- constructor(type, _docOrFields, _before) {
25525
+ constructor(type, _docOrFields, _inclusive) {
25232
25526
  super();
25233
25527
  this.type = type;
25234
25528
  this._docOrFields = _docOrFields;
25235
- this._before = _before;
25529
+ this._inclusive = _inclusive;
25236
25530
  }
25237
25531
  _apply(query) {
25238
- const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this._before);
25532
+ const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this._inclusive);
25239
25533
  return new Query(query.firestore, query.converter, queryWithStartAt(query._query, bound));
25240
25534
  }
25241
25535
  }
25242
25536
  function startAt(...docOrFields) {
25243
- return new QueryStartAtConstraint('startAt', docOrFields, /*before=*/ true);
25537
+ return new QueryStartAtConstraint('startAt', docOrFields,
25538
+ /*inclusive=*/ true);
25244
25539
  }
25245
25540
  function startAfter(...docOrFields) {
25246
25541
  return new QueryStartAtConstraint('startAfter', docOrFields,
25247
- /*before=*/ false);
25542
+ /*inclusive=*/ false);
25248
25543
  }
25249
25544
  class QueryEndAtConstraint extends QueryConstraint {
25250
- constructor(type, _docOrFields, _before) {
25545
+ constructor(type, _docOrFields, _inclusive) {
25251
25546
  super();
25252
25547
  this.type = type;
25253
25548
  this._docOrFields = _docOrFields;
25254
- this._before = _before;
25549
+ this._inclusive = _inclusive;
25255
25550
  }
25256
25551
  _apply(query) {
25257
- const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this._before);
25552
+ const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this._inclusive);
25258
25553
  return new Query(query.firestore, query.converter, queryWithEndAt(query._query, bound));
25259
25554
  }
25260
25555
  }
25261
25556
  function endBefore(...docOrFields) {
25262
- return new QueryEndAtConstraint('endBefore', docOrFields, /*before=*/ true);
25557
+ return new QueryEndAtConstraint('endBefore', docOrFields,
25558
+ /*inclusive=*/ false);
25263
25559
  }
25264
25560
  function endAt(...docOrFields) {
25265
- return new QueryEndAtConstraint('endAt', docOrFields, /*before=*/ false);
25561
+ return new QueryEndAtConstraint('endAt', docOrFields, /*inclusive=*/ true);
25266
25562
  }
25267
25563
  /** Helper function to create a bound from a document or fields */
25268
- function newQueryBoundFromDocOrFields(query, methodName, docOrFields, before) {
25564
+ function newQueryBoundFromDocOrFields(query, methodName, docOrFields, inclusive) {
25269
25565
  docOrFields[0] = getModularInstance(docOrFields[0]);
25270
25566
  if (docOrFields[0] instanceof DocumentSnapshot$1) {
25271
- return newQueryBoundFromDocument(query._query, query.firestore._databaseId, methodName, docOrFields[0]._document, before);
25567
+ return newQueryBoundFromDocument(query._query, query.firestore._databaseId, methodName, docOrFields[0]._document, inclusive);
25272
25568
  }
25273
25569
  else {
25274
25570
  const reader = newUserDataReader(query.firestore);
25275
- return newQueryBoundFromFields(query._query, query.firestore._databaseId, reader, methodName, docOrFields, before);
25571
+ return newQueryBoundFromFields(query._query, query.firestore._databaseId, reader, methodName, docOrFields, inclusive);
25276
25572
  }
25277
25573
  }
25278
25574
  function newQueryFilter(query, methodName, dataReader, databaseId, fieldPath, op, value) {
@@ -25330,7 +25626,7 @@ function newQueryOrderBy(query, fieldPath, direction) {
25330
25626
  * of the query or if any of the fields in the order by are an uncommitted
25331
25627
  * server timestamp.
25332
25628
  */
25333
- function newQueryBoundFromDocument(query, databaseId, methodName, doc, before) {
25629
+ function newQueryBoundFromDocument(query, databaseId, methodName, doc, inclusive) {
25334
25630
  if (!doc) {
25335
25631
  throw new FirestoreError(Code.NOT_FOUND, `Can't use a DocumentSnapshot that doesn't exist for ` +
25336
25632
  `${methodName}().`);
@@ -25367,12 +25663,12 @@ function newQueryBoundFromDocument(query, databaseId, methodName, doc, before) {
25367
25663
  }
25368
25664
  }
25369
25665
  }
25370
- return new Bound(components, before);
25666
+ return new Bound(components, inclusive);
25371
25667
  }
25372
25668
  /**
25373
25669
  * Converts a list of field values to a `Bound` for the given query.
25374
25670
  */
25375
- function newQueryBoundFromFields(query, databaseId, dataReader, methodName, values, before) {
25671
+ function newQueryBoundFromFields(query, databaseId, dataReader, methodName, values, inclusive) {
25376
25672
  // Use explicit order by's because it has to match the query the user made
25377
25673
  const orderBy = query.explicitOrderBy;
25378
25674
  if (values.length > orderBy.length) {
@@ -25409,7 +25705,7 @@ function newQueryBoundFromFields(query, databaseId, dataReader, methodName, valu
25409
25705
  components.push(wrapped);
25410
25706
  }
25411
25707
  }
25412
- return new Bound(components, before);
25708
+ return new Bound(components, inclusive);
25413
25709
  }
25414
25710
  /**
25415
25711
  * Parses the given `documentIdValue` into a `ReferenceValue`, throwing