@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
@@ -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.2dd99ae2d";
15
+ const version$1 = "3.4.4-canary.434d87ee2";
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.5-canary.2dd99ae2d";
68
+ const version = "9.6.6-canary.434d87ee2";
69
69
 
70
70
  /**
71
71
  * @license
@@ -1196,23 +1196,6 @@ function decodeResourcePath(path) {
1196
1196
  }
1197
1197
  return new ResourcePath(segments);
1198
1198
  }
1199
-
1200
- /**
1201
- * @license
1202
- * Copyright 2017 Google LLC
1203
- *
1204
- * Licensed under the Apache License, Version 2.0 (the "License");
1205
- * you may not use this file except in compliance with the License.
1206
- * You may obtain a copy of the License at
1207
- *
1208
- * http://www.apache.org/licenses/LICENSE-2.0
1209
- *
1210
- * Unless required by applicable law or agreed to in writing, software
1211
- * distributed under the License is distributed on an "AS IS" BASIS,
1212
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1213
- * See the License for the specific language governing permissions and
1214
- * limitations under the License.
1215
- */
1216
1199
  /**
1217
1200
  * Schema Version for the Web client:
1218
1201
  * 1. Initial version including Mutation Queue, Query Cache, and Remote
@@ -1231,6 +1214,7 @@ function decodeResourcePath(path) {
1231
1214
  * an auto-incrementing ID. This is required for Index-Free queries.
1232
1215
  * 10. Rewrite the canonical IDs to the explicit Protobuf-based format.
1233
1216
  * 11. Add bundles and named_queries for bundle support.
1217
+ * 12. Add indexing support.
1234
1218
  */
1235
1219
  const SCHEMA_VERSION = 11;
1236
1220
  /**
@@ -1757,9 +1741,7 @@ class DbClientMetadata {
1757
1741
  DbClientMetadata.store = 'clientMetadata';
1758
1742
  /** Keys are automatically assigned via the clientId properties. */
1759
1743
  DbClientMetadata.keyPath = 'clientId';
1760
- /**
1761
- * A object representing a bundle loaded by the SDK.
1762
- */
1744
+ /** An object representing a bundle loaded by the SDK. */
1763
1745
  class DbBundle {
1764
1746
  constructor(
1765
1747
  /** The ID of the loaded bundle. */
@@ -1776,9 +1758,7 @@ class DbBundle {
1776
1758
  /** Name of the IndexedDb object store. */
1777
1759
  DbBundle.store = 'bundles';
1778
1760
  DbBundle.keyPath = 'bundleId';
1779
- /**
1780
- * A object representing a named query loaded by the SDK via a bundle.
1781
- */
1761
+ /** An object representing a named query loaded by the SDK via a bundle. */
1782
1762
  class DbNamedQuery {
1783
1763
  constructor(
1784
1764
  /** The name of the query. */
@@ -1795,6 +1775,116 @@ class DbNamedQuery {
1795
1775
  /** Name of the IndexedDb object store. */
1796
1776
  DbNamedQuery.store = 'namedQueries';
1797
1777
  DbNamedQuery.keyPath = 'name';
1778
+ /** An object representing the global configuration for a field index. */
1779
+ class DbIndexConfiguration {
1780
+ constructor(
1781
+ /**
1782
+ * The index id for this entry. Undefined for indexes that are not yet
1783
+ * persisted.
1784
+ */
1785
+ indexId,
1786
+ /** The collection group this index belongs to. */
1787
+ collectionGroup,
1788
+ /** The fields to index for this index. */
1789
+ fields) {
1790
+ this.indexId = indexId;
1791
+ this.collectionGroup = collectionGroup;
1792
+ this.fields = fields;
1793
+ }
1794
+ }
1795
+ /** Name of the IndexedDb object store. */
1796
+ DbIndexConfiguration.store = 'indexConfiguration';
1797
+ DbIndexConfiguration.keyPath = 'indexId';
1798
+ /**
1799
+ * An index that provides access to the index configurations by collection
1800
+ * group.
1801
+ *
1802
+ * PORTING NOTE: iOS and Android maintain this index in-memory, but this is
1803
+ * not possible here as the Web client supports concurrent access to
1804
+ * persistence via multi-tab.
1805
+ */
1806
+ DbIndexConfiguration.collectionGroupIndex = 'collectionGroupIndex';
1807
+ DbIndexConfiguration.collectionGroupIndexPath = 'collectionGroup';
1808
+ /**
1809
+ * An object describing how up-to-date the index backfill is for each user and
1810
+ * index.
1811
+ */
1812
+ class DbIndexState {
1813
+ constructor(
1814
+ /** The index id for this entry. */
1815
+ indexId,
1816
+ /** The user id for this entry. */
1817
+ uid,
1818
+ /**
1819
+ * A number that indicates when the index was last updated (relative to
1820
+ * other indexes).
1821
+ */
1822
+ sequenceNumber,
1823
+ /**
1824
+ * The latest read time that has been indexed by Firestore for this field
1825
+ * index. Set to `{seconds: 0, nanos: 0}` if no documents have been indexed.
1826
+ */
1827
+ readTime,
1828
+ /**
1829
+ * The last document that has been indexed for this field index. Empty if
1830
+ * no documents have been indexed.
1831
+ */
1832
+ documentKey,
1833
+ /**
1834
+ * The largest mutation batch id that has been processed for this index. -1
1835
+ * if no mutations have been indexed.
1836
+ */
1837
+ largestBatchId) {
1838
+ this.indexId = indexId;
1839
+ this.uid = uid;
1840
+ this.sequenceNumber = sequenceNumber;
1841
+ this.readTime = readTime;
1842
+ this.documentKey = documentKey;
1843
+ this.largestBatchId = largestBatchId;
1844
+ }
1845
+ }
1846
+ /** Name of the IndexedDb object store. */
1847
+ DbIndexState.store = 'indexState';
1848
+ DbIndexState.keyPath = ['indexId', 'uid'];
1849
+ /**
1850
+ * An index that provides access to documents in a collection sorted by last
1851
+ * update time. Used by the backfiller.
1852
+ *
1853
+ * PORTING NOTE: iOS and Android maintain this index in-memory, but this is
1854
+ * not possible here as the Web client supports concurrent access to
1855
+ * persistence via multi-tab.
1856
+ */
1857
+ DbIndexState.sequenceNumberIndex = 'sequenceNumberIndex';
1858
+ DbIndexState.sequenceNumberIndexPath = ['uid', 'sequenceNumber'];
1859
+ /** An object that stores the encoded entries for all documents and fields. */
1860
+ class DbIndexEntry {
1861
+ constructor(
1862
+ /** The index id for this entry. */
1863
+ indexId,
1864
+ /** The user id for this entry. */
1865
+ uid,
1866
+ /** The encoded array index value for this entry. */
1867
+ arrayValue,
1868
+ /** The encoded directional value for equality and inequality filters. */
1869
+ directionalValue,
1870
+ /** The document key this entry points to. */
1871
+ documentKey) {
1872
+ this.indexId = indexId;
1873
+ this.uid = uid;
1874
+ this.arrayValue = arrayValue;
1875
+ this.directionalValue = directionalValue;
1876
+ this.documentKey = documentKey;
1877
+ }
1878
+ }
1879
+ /** Name of the IndexedDb object store. */
1880
+ DbIndexEntry.store = 'indexEntries';
1881
+ DbIndexEntry.keyPath = [
1882
+ 'indexId',
1883
+ 'uid',
1884
+ 'arrayValue',
1885
+ 'directionalValue',
1886
+ 'documentKey'
1887
+ ];
1798
1888
  // Visible for testing
1799
1889
  const V1_STORES = [
1800
1890
  DbMutationQueue.store,
@@ -1809,7 +1899,6 @@ const V1_STORES = [
1809
1899
  // V2 is no longer usable (see comment at top of file)
1810
1900
  // Visible for testing
1811
1901
  const V3_STORES = V1_STORES;
1812
- // Visible for testing
1813
1902
  // Note: DbRemoteDocumentChanges is no longer used and dropped with v9.
1814
1903
  const V4_STORES = [...V3_STORES, DbClientMetadata.store];
1815
1904
  // V5 does not change the set of stores.
@@ -1819,12 +1908,24 @@ const V8_STORES = [...V6_STORES, DbCollectionParent.store];
1819
1908
  // V9 does not change the set of stores.
1820
1909
  // V10 does not change the set of stores.
1821
1910
  const V11_STORES = [...V8_STORES, DbBundle.store, DbNamedQuery.store];
1822
- /**
1823
- * The list of all default IndexedDB stores used throughout the SDK. This is
1824
- * used when creating transactions so that access across all stores is done
1825
- * atomically.
1826
- */
1827
- const ALL_STORES = V11_STORES;
1911
+ const V12_STORES = [
1912
+ ...V11_STORES,
1913
+ DbIndexConfiguration.store,
1914
+ DbIndexState.store,
1915
+ DbIndexEntry.store
1916
+ ];
1917
+ /** Returns the object stores for the provided schema. */
1918
+ function getObjectStores(schemaVersion) {
1919
+ if (schemaVersion === 12) {
1920
+ return V12_STORES;
1921
+ }
1922
+ else if (schemaVersion === 11) {
1923
+ return V11_STORES;
1924
+ }
1925
+ else {
1926
+ fail();
1927
+ }
1928
+ }
1828
1929
 
1829
1930
  /**
1830
1931
  * @license
@@ -2121,6 +2222,15 @@ class SimpleDbTransaction {
2121
2222
  this.transaction.abort();
2122
2223
  }
2123
2224
  }
2225
+ maybeCommit() {
2226
+ // If the browser supports V3 IndexedDB, we invoke commit() explicitly to
2227
+ // speed up index DB processing if the event loop remains blocks.
2228
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2229
+ const maybeV3IndexedDb = this.transaction;
2230
+ if (!this.aborted && typeof maybeV3IndexedDb.commit === 'function') {
2231
+ maybeV3IndexedDb.commit();
2232
+ }
2233
+ }
2124
2234
  /**
2125
2235
  * Returns a SimpleDbStore<KeyType, ValueType> for the specified store. All
2126
2236
  * operations performed on the SimpleDbStore happen within the context of this
@@ -2317,6 +2427,10 @@ class SimpleDb {
2317
2427
  this.db = await this.ensureDb(action);
2318
2428
  const transaction = SimpleDbTransaction.open(this.db, action, readonly ? 'readonly' : 'readwrite', objectStores);
2319
2429
  const transactionFnResult = transactionFn(transaction)
2430
+ .next(result => {
2431
+ transaction.maybeCommit();
2432
+ return result;
2433
+ })
2320
2434
  .catch(error => {
2321
2435
  // Abort the transaction if there was an error.
2322
2436
  transaction.abort(error);
@@ -4349,12 +4463,12 @@ class FieldIndex {
4349
4463
  /** The collection ID this index applies to. */
4350
4464
  collectionGroup,
4351
4465
  /** The field segments for this index. */
4352
- segments,
4466
+ fields,
4353
4467
  /** Shows how up-to-date the index is for the current user. */
4354
4468
  indexState) {
4355
4469
  this.indexId = indexId;
4356
4470
  this.collectionGroup = collectionGroup;
4357
- this.segments = segments;
4471
+ this.fields = fields;
4358
4472
  this.indexState = indexState;
4359
4473
  }
4360
4474
  }
@@ -4464,27 +4578,29 @@ function newTarget(path, collectionGroup = null, orderBy = [], filters = [], lim
4464
4578
  function canonifyTarget(target) {
4465
4579
  const targetImpl = debugCast(target);
4466
4580
  if (targetImpl.memoizedCanonicalId === null) {
4467
- let canonicalId = targetImpl.path.canonicalString();
4581
+ let str = targetImpl.path.canonicalString();
4468
4582
  if (targetImpl.collectionGroup !== null) {
4469
- canonicalId += '|cg:' + targetImpl.collectionGroup;
4583
+ str += '|cg:' + targetImpl.collectionGroup;
4470
4584
  }
4471
- canonicalId += '|f:';
4472
- canonicalId += targetImpl.filters.map(f => canonifyFilter(f)).join(',');
4473
- canonicalId += '|ob:';
4474
- canonicalId += targetImpl.orderBy.map(o => canonifyOrderBy(o)).join(',');
4585
+ str += '|f:';
4586
+ str += targetImpl.filters.map(f => canonifyFilter(f)).join(',');
4587
+ str += '|ob:';
4588
+ str += targetImpl.orderBy.map(o => canonifyOrderBy(o)).join(',');
4475
4589
  if (!isNullOrUndefined(targetImpl.limit)) {
4476
- canonicalId += '|l:';
4477
- canonicalId += targetImpl.limit;
4590
+ str += '|l:';
4591
+ str += targetImpl.limit;
4478
4592
  }
4479
4593
  if (targetImpl.startAt) {
4480
- canonicalId += '|lb:';
4481
- canonicalId += canonifyBound(targetImpl.startAt);
4594
+ str += '|lb:';
4595
+ str += targetImpl.startAt.inclusive ? 'b:' : 'a:';
4596
+ str += targetImpl.startAt.position.map(p => canonicalId(p)).join(',');
4482
4597
  }
4483
4598
  if (targetImpl.endAt) {
4484
- canonicalId += '|ub:';
4485
- canonicalId += canonifyBound(targetImpl.endAt);
4599
+ str += '|ub:';
4600
+ str += targetImpl.endAt.inclusive ? 'a:' : 'b:';
4601
+ str += targetImpl.endAt.position.map(p => canonicalId(p)).join(',');
4486
4602
  }
4487
- targetImpl.memoizedCanonicalId = canonicalId;
4603
+ targetImpl.memoizedCanonicalId = str;
4488
4604
  }
4489
4605
  return targetImpl.memoizedCanonicalId;
4490
4606
  }
@@ -4507,10 +4623,14 @@ function stringifyTarget(target) {
4507
4623
  .join(', ')}]`;
4508
4624
  }
4509
4625
  if (target.startAt) {
4510
- str += ', startAt: ' + canonifyBound(target.startAt);
4626
+ str += ', startAt: ';
4627
+ str += target.startAt.inclusive ? 'b:' : 'a:';
4628
+ str += target.startAt.position.map(p => canonicalId(p)).join(',');
4511
4629
  }
4512
4630
  if (target.endAt) {
4513
- str += ', endAt: ' + canonifyBound(target.endAt);
4631
+ str += ', endAt: ';
4632
+ str += target.endAt.inclusive ? 'a:' : 'b:';
4633
+ str += target.endAt.position.map(p => canonicalId(p)).join(',');
4514
4634
  }
4515
4635
  return `Target(${str})`;
4516
4636
  }
@@ -4733,7 +4853,6 @@ class ArrayContainsAnyFilter extends FieldFilter {
4733
4853
  return other.arrayValue.values.some(val => arrayValueContains(this.value.arrayValue, val));
4734
4854
  }
4735
4855
  }
4736
- // TODO(indexing): Change Bound.before to "inclusive"
4737
4856
  /**
4738
4857
  * Represents a bound of a query.
4739
4858
  *
@@ -4749,17 +4868,11 @@ class ArrayContainsAnyFilter extends FieldFilter {
4749
4868
  * just after the provided values.
4750
4869
  */
4751
4870
  class Bound {
4752
- constructor(position, before) {
4871
+ constructor(position, inclusive) {
4753
4872
  this.position = position;
4754
- this.before = before;
4873
+ this.inclusive = inclusive;
4755
4874
  }
4756
4875
  }
4757
- function canonifyBound(bound) {
4758
- // TODO(b/29183165): Make this collision robust.
4759
- return `${bound.before ? 'b' : 'a'}:${bound.position
4760
- .map(p => canonicalId(p))
4761
- .join(',')}`;
4762
- }
4763
4876
  /**
4764
4877
  * An ordering on a field, in some Direction. Direction defaults to ASCENDING.
4765
4878
  */
@@ -4779,11 +4892,7 @@ function stringifyOrderBy(orderBy) {
4779
4892
  function orderByEquals(left, right) {
4780
4893
  return left.dir === right.dir && left.field.isEqual(right.field);
4781
4894
  }
4782
- /**
4783
- * Returns true if a document sorts before a bound using the provided sort
4784
- * order.
4785
- */
4786
- function sortsBeforeDocument(bound, orderBy, doc) {
4895
+ function boundCompareToDocument(bound, orderBy, doc) {
4787
4896
  let comparison = 0;
4788
4897
  for (let i = 0; i < bound.position.length; i++) {
4789
4898
  const orderByComponent = orderBy[i];
@@ -4802,7 +4911,23 @@ function sortsBeforeDocument(bound, orderBy, doc) {
4802
4911
  break;
4803
4912
  }
4804
4913
  }
4805
- return bound.before ? comparison <= 0 : comparison < 0;
4914
+ return comparison;
4915
+ }
4916
+ /**
4917
+ * Returns true if a document sorts after a bound using the provided sort
4918
+ * order.
4919
+ */
4920
+ function boundSortsAfterDocument(bound, orderBy, doc) {
4921
+ const comparison = boundCompareToDocument(bound, orderBy, doc);
4922
+ return bound.inclusive ? comparison >= 0 : comparison > 0;
4923
+ }
4924
+ /**
4925
+ * Returns true if a document sorts before a bound using the provided sort
4926
+ * order.
4927
+ */
4928
+ function boundSortsBeforeDocument(bound, orderBy, doc) {
4929
+ const comparison = boundCompareToDocument(bound, orderBy, doc);
4930
+ return bound.inclusive ? comparison <= 0 : comparison < 0;
4806
4931
  }
4807
4932
  function boundEquals(left, right) {
4808
4933
  if (left === null) {
@@ -4811,7 +4936,7 @@ function boundEquals(left, right) {
4811
4936
  else if (right === null) {
4812
4937
  return false;
4813
4938
  }
4814
- if (left.before !== right.before ||
4939
+ if (left.inclusive !== right.inclusive ||
4815
4940
  left.position.length !== right.position.length) {
4816
4941
  return false;
4817
4942
  }
@@ -5015,10 +5140,10 @@ function queryToTarget(query) {
5015
5140
  }
5016
5141
  // We need to swap the cursors to match the now-flipped query ordering.
5017
5142
  const startAt = queryImpl.endAt
5018
- ? new Bound(queryImpl.endAt.position, !queryImpl.endAt.before)
5143
+ ? new Bound(queryImpl.endAt.position, !queryImpl.endAt.inclusive)
5019
5144
  : null;
5020
5145
  const endAt = queryImpl.startAt
5021
- ? new Bound(queryImpl.startAt.position, !queryImpl.startAt.before)
5146
+ ? new Bound(queryImpl.startAt.position, !queryImpl.startAt.inclusive)
5022
5147
  : null;
5023
5148
  // Now return as a LimitType.First query.
5024
5149
  queryImpl.memoizedTarget = newTarget(queryImpl.path, queryImpl.collectionGroup, orderBys, queryImpl.filters, queryImpl.limit, startAt, endAt);
@@ -5106,11 +5231,11 @@ function queryMatchesFilters(query, doc) {
5106
5231
  /** Makes sure a document is within the bounds, if provided. */
5107
5232
  function queryMatchesBounds(query, doc) {
5108
5233
  if (query.startAt &&
5109
- !sortsBeforeDocument(query.startAt, queryOrderBy(query), doc)) {
5234
+ !boundSortsBeforeDocument(query.startAt, queryOrderBy(query), doc)) {
5110
5235
  return false;
5111
5236
  }
5112
5237
  if (query.endAt &&
5113
- sortsBeforeDocument(query.endAt, queryOrderBy(query), doc)) {
5238
+ !boundSortsAfterDocument(query.endAt, queryOrderBy(query), doc)) {
5114
5239
  return false;
5115
5240
  }
5116
5241
  return true;
@@ -7989,10 +8114,10 @@ function toQueryTarget(serializer, target) {
7989
8114
  result.structuredQuery.limit = limit;
7990
8115
  }
7991
8116
  if (target.startAt) {
7992
- result.structuredQuery.startAt = toCursor(target.startAt);
8117
+ result.structuredQuery.startAt = toStartAtCursor(target.startAt);
7993
8118
  }
7994
8119
  if (target.endAt) {
7995
- result.structuredQuery.endAt = toCursor(target.endAt);
8120
+ result.structuredQuery.endAt = toEndAtCursor(target.endAt);
7996
8121
  }
7997
8122
  return result;
7998
8123
  }
@@ -8025,11 +8150,11 @@ function convertQueryTargetToQuery(target) {
8025
8150
  }
8026
8151
  let startAt = null;
8027
8152
  if (query.startAt) {
8028
- startAt = fromCursor(query.startAt);
8153
+ startAt = fromStartAtCursor(query.startAt);
8029
8154
  }
8030
8155
  let endAt = null;
8031
8156
  if (query.endAt) {
8032
- endAt = fromCursor(query.endAt);
8157
+ endAt = fromEndAtCursor(query.endAt);
8033
8158
  }
8034
8159
  return newQuery(path, collectionGroup, orderBy, filterBy, limit, "F" /* First */, startAt, endAt);
8035
8160
  }
@@ -8120,16 +8245,27 @@ function toOrder(orderBys) {
8120
8245
  function fromOrder(orderBys) {
8121
8246
  return orderBys.map(order => fromPropertyOrder(order));
8122
8247
  }
8123
- function toCursor(cursor) {
8248
+ function toStartAtCursor(cursor) {
8124
8249
  return {
8125
- before: cursor.before,
8250
+ before: cursor.inclusive,
8126
8251
  values: cursor.position
8127
8252
  };
8128
8253
  }
8129
- function fromCursor(cursor) {
8130
- const before = !!cursor.before;
8254
+ function toEndAtCursor(cursor) {
8255
+ return {
8256
+ before: !cursor.inclusive,
8257
+ values: cursor.position
8258
+ };
8259
+ }
8260
+ function fromStartAtCursor(cursor) {
8261
+ const inclusive = !!cursor.before;
8131
8262
  const position = cursor.values || [];
8132
- return new Bound(position, before);
8263
+ return new Bound(position, inclusive);
8264
+ }
8265
+ function fromEndAtCursor(cursor) {
8266
+ const inclusive = !cursor.before;
8267
+ const position = cursor.values || [];
8268
+ return new Bound(position, inclusive);
8133
8269
  }
8134
8270
  // visible for testing
8135
8271
  function toDirection(dir) {
@@ -8593,6 +8729,19 @@ function fromBundleMetadata(metadata) {
8593
8729
  version: metadata.version,
8594
8730
  createTime: fromVersion(metadata.createTime)
8595
8731
  };
8732
+ }
8733
+ function toDbIndexConfiguration(index) {
8734
+ return new DbIndexConfiguration(index.indexId, index.collectionGroup, index.fields.map(s => [s.fieldPath.canonicalString(), s.kind]));
8735
+ }
8736
+ function fromDbIndexConfiguration(index, state) {
8737
+ const decodedState = state
8738
+ ? new IndexState(state.sequenceNumber, new IndexOffset(fromDbTimestamp(state.readTime), new DocumentKey(decodeResourcePath(state.documentKey)), state.largestBatchId))
8739
+ : IndexState.empty();
8740
+ const decodedSegments = index.fields.map(([fieldPath, kind]) => new IndexSegment(FieldPath$1.fromServerFormat(fieldPath), kind));
8741
+ return new FieldIndex(index.indexId, index.collectionGroup, decodedSegments, decodedState);
8742
+ }
8743
+ function toDbIndexState(indexId, user, sequenceNumber, offset) {
8744
+ return new DbIndexState(indexId, user.uid || '', sequenceNumber, toDbTimestamp(offset.readTime), encodeResourcePath(offset.documentKey.path), offset.largestBatchId);
8596
8745
  }
8597
8746
 
8598
8747
  /**
@@ -8682,6 +8831,38 @@ class MemoryIndexManager {
8682
8831
  getCollectionParents(transaction, collectionId) {
8683
8832
  return PersistencePromise.resolve(this.collectionParentIndex.getEntries(collectionId));
8684
8833
  }
8834
+ addFieldIndex(transaction, index) {
8835
+ // Field indices are not supported with memory persistence.
8836
+ return PersistencePromise.resolve();
8837
+ }
8838
+ deleteFieldIndex(transaction, index) {
8839
+ // Field indices are not supported with memory persistence.
8840
+ return PersistencePromise.resolve();
8841
+ }
8842
+ getDocumentsMatchingTarget(transaction, fieldIndex, target) {
8843
+ // Field indices are not supported with memory persistence.
8844
+ return PersistencePromise.resolve(documentKeySet());
8845
+ }
8846
+ getFieldIndex(transaction, target) {
8847
+ // Field indices are not supported with memory persistence.
8848
+ return PersistencePromise.resolve(null);
8849
+ }
8850
+ getFieldIndexes(transaction, collectionGroup) {
8851
+ // Field indices are not supported with memory persistence.
8852
+ return PersistencePromise.resolve([]);
8853
+ }
8854
+ getNextCollectionGroupToUpdate(transaction) {
8855
+ // Field indices are not supported with memory persistence.
8856
+ return PersistencePromise.resolve(null);
8857
+ }
8858
+ updateCollectionGroup(transaction, collectionGroup, offset) {
8859
+ // Field indices are not supported with memory persistence.
8860
+ return PersistencePromise.resolve();
8861
+ }
8862
+ updateIndexEntries(transaction, documents) {
8863
+ // Field indices are not supported with memory persistence.
8864
+ return PersistencePromise.resolve();
8865
+ }
8685
8866
  }
8686
8867
  /**
8687
8868
  * Internal implementation of the collection-parent index exposed by MemoryIndexManager.
@@ -8733,17 +8914,22 @@ class MemoryCollectionParentIndex {
8733
8914
  */
8734
8915
  /**
8735
8916
  * A persisted implementation of IndexManager.
8917
+ *
8918
+ * PORTING NOTE: Unlike iOS and Android, the Web SDK does not memoize index
8919
+ * data as it supports multi-tab access.
8736
8920
  */
8737
8921
  class IndexedDbIndexManager {
8738
- constructor() {
8922
+ constructor(user) {
8923
+ this.user = user;
8739
8924
  /**
8740
8925
  * An in-memory copy of the index entries we've already written since the SDK
8741
8926
  * launched. Used to avoid re-writing the same entry repeatedly.
8742
8927
  *
8743
- * This is *NOT* a complete cache of what's in persistence and so can never be used to
8744
- * satisfy reads.
8928
+ * This is *NOT* a complete cache of what's in persistence and so can never be
8929
+ * used to satisfy reads.
8745
8930
  */
8746
8931
  this.collectionParentsCache = new MemoryCollectionParentIndex();
8932
+ this.uid = user.uid || '';
8747
8933
  }
8748
8934
  /**
8749
8935
  * Adds a new entry to the collection parent index.
@@ -8790,6 +8976,85 @@ class IndexedDbIndexManager {
8790
8976
  return parentPaths;
8791
8977
  });
8792
8978
  }
8979
+ addFieldIndex(transaction, index) {
8980
+ // TODO(indexing): Verify that the auto-incrementing index ID works in
8981
+ // Safari & Firefox.
8982
+ const indexes = indexConfigurationStore(transaction);
8983
+ const dbIndex = toDbIndexConfiguration(index);
8984
+ delete dbIndex.indexId; // `indexId` is auto-populated by IndexedDb
8985
+ return indexes.add(dbIndex).next();
8986
+ }
8987
+ deleteFieldIndex(transaction, index) {
8988
+ const indexes = indexConfigurationStore(transaction);
8989
+ const states = indexStateStore(transaction);
8990
+ const entries = indexEntriesStore(transaction);
8991
+ return indexes
8992
+ .delete(index.indexId)
8993
+ .next(() => states.delete(IDBKeyRange.bound([index.indexId], [index.indexId + 1],
8994
+ /*lowerOpen=*/ false,
8995
+ /*upperOpen=*/ true)))
8996
+ .next(() => entries.delete(IDBKeyRange.bound([index.indexId], [index.indexId + 1],
8997
+ /*lowerOpen=*/ false,
8998
+ /*upperOpen=*/ true)));
8999
+ }
9000
+ getDocumentsMatchingTarget(transaction, fieldIndex, target) {
9001
+ // TODO(indexing): Implement
9002
+ return PersistencePromise.resolve(documentKeySet());
9003
+ }
9004
+ getFieldIndex(transaction, target) {
9005
+ // TODO(indexing): Implement
9006
+ return PersistencePromise.resolve(null);
9007
+ }
9008
+ getFieldIndexes(transaction, collectionGroup) {
9009
+ const indexes = indexConfigurationStore(transaction);
9010
+ const states = indexStateStore(transaction);
9011
+ return (collectionGroup
9012
+ ? indexes.loadAll(DbIndexConfiguration.collectionGroupIndex, IDBKeyRange.bound(collectionGroup, collectionGroup))
9013
+ : indexes.loadAll()).next(indexConfigs => {
9014
+ const result = [];
9015
+ return PersistencePromise.forEach(indexConfigs, (indexConfig) => {
9016
+ return states
9017
+ .get([indexConfig.indexId, this.uid])
9018
+ .next(indexState => {
9019
+ result.push(fromDbIndexConfiguration(indexConfig, indexState));
9020
+ });
9021
+ }).next(() => result);
9022
+ });
9023
+ }
9024
+ getNextCollectionGroupToUpdate(transaction) {
9025
+ return this.getFieldIndexes(transaction).next(indexes => {
9026
+ if (indexes.length === 0) {
9027
+ return null;
9028
+ }
9029
+ indexes.sort((l, r) => l.indexState.sequenceNumber - r.indexState.sequenceNumber);
9030
+ return indexes[0].collectionGroup;
9031
+ });
9032
+ }
9033
+ updateCollectionGroup(transaction, collectionGroup, offset) {
9034
+ const indexes = indexConfigurationStore(transaction);
9035
+ const states = indexStateStore(transaction);
9036
+ return this.getNextSequenceNumber(transaction).next(nextSequenceNumber => indexes
9037
+ .loadAll(DbIndexConfiguration.collectionGroupIndex, IDBKeyRange.bound(collectionGroup, collectionGroup))
9038
+ .next(configs => PersistencePromise.forEach(configs, (config) => states.put(toDbIndexState(config.indexId, this.user, nextSequenceNumber, offset)))));
9039
+ }
9040
+ updateIndexEntries(transaction, documents) {
9041
+ // TODO(indexing): Implement
9042
+ return PersistencePromise.resolve();
9043
+ }
9044
+ getNextSequenceNumber(transaction) {
9045
+ let nextSequenceNumber = 1;
9046
+ const states = indexStateStore(transaction);
9047
+ return states
9048
+ .iterate({
9049
+ index: DbIndexState.sequenceNumberIndex,
9050
+ reverse: true,
9051
+ range: IDBKeyRange.upperBound([this.uid, Number.MAX_SAFE_INTEGER])
9052
+ }, (_, state, controller) => {
9053
+ controller.done();
9054
+ nextSequenceNumber = state.sequenceNumber + 1;
9055
+ })
9056
+ .next(() => nextSequenceNumber);
9057
+ }
8793
9058
  }
8794
9059
  /**
8795
9060
  * Helper to get a typed SimpleDbStore for the collectionParents
@@ -8797,6 +9062,24 @@ class IndexedDbIndexManager {
8797
9062
  */
8798
9063
  function collectionParentsStore(txn) {
8799
9064
  return getStore(txn, DbCollectionParent.store);
9065
+ }
9066
+ /**
9067
+ * Helper to get a typed SimpleDbStore for the index entry object store.
9068
+ */
9069
+ function indexEntriesStore(txn) {
9070
+ return getStore(txn, DbIndexEntry.store);
9071
+ }
9072
+ /**
9073
+ * Helper to get a typed SimpleDbStore for the index configuration object store.
9074
+ */
9075
+ function indexConfigurationStore(txn) {
9076
+ return getStore(txn, DbIndexConfiguration.store);
9077
+ }
9078
+ /**
9079
+ * Helper to get a typed SimpleDbStore for the index state object store.
9080
+ */
9081
+ function indexStateStore(txn) {
9082
+ return getStore(txn, DbIndexState.store);
8800
9083
  }
8801
9084
 
8802
9085
  /**
@@ -10266,12 +10549,10 @@ class RemoteDocumentChangeBuffer {
10266
10549
  * `newIndexedDbRemoteDocumentCache()`.
10267
10550
  */
10268
10551
  class IndexedDbRemoteDocumentCacheImpl {
10269
- /**
10270
- * @param serializer - The document serializer.
10271
- * @param indexManager - The query indexes that need to be maintained.
10272
- */
10273
- constructor(serializer, indexManager) {
10552
+ constructor(serializer) {
10274
10553
  this.serializer = serializer;
10554
+ }
10555
+ setIndexManager(indexManager) {
10275
10556
  this.indexManager = indexManager;
10276
10557
  }
10277
10558
  /**
@@ -10467,14 +10748,9 @@ class IndexedDbRemoteDocumentCacheImpl {
10467
10748
  return MutableDocument.newInvalidDocument(documentKey);
10468
10749
  }
10469
10750
  }
10470
- /**
10471
- * Creates a new IndexedDbRemoteDocumentCache.
10472
- *
10473
- * @param serializer - The document serializer.
10474
- * @param indexManager - The query indexes that need to be maintained.
10475
- */
10476
- function newIndexedDbRemoteDocumentCache(serializer, indexManager) {
10477
- return new IndexedDbRemoteDocumentCacheImpl(serializer, indexManager);
10751
+ /** Creates a new IndexedDbRemoteDocumentCache. */
10752
+ function newIndexedDbRemoteDocumentCache(serializer) {
10753
+ return new IndexedDbRemoteDocumentCacheImpl(serializer);
10478
10754
  }
10479
10755
  /**
10480
10756
  * Returns the set of documents that have changed since the specified read
@@ -10641,9 +10917,6 @@ class SchemaConverter {
10641
10917
  * and local feature development.
10642
10918
  */
10643
10919
  createOrUpgrade(db, txn, fromVersion, toVersion) {
10644
- hardAssert(fromVersion < toVersion &&
10645
- fromVersion >= 0 &&
10646
- toVersion <= SCHEMA_VERSION);
10647
10920
  const simpleDbTransaction = new SimpleDbTransaction('createOrUpgrade', txn);
10648
10921
  if (fromVersion < 1 && toVersion >= 1) {
10649
10922
  createPrimaryClientStore(db);
@@ -10710,6 +10983,11 @@ class SchemaConverter {
10710
10983
  createNamedQueriesStore(db);
10711
10984
  });
10712
10985
  }
10986
+ if (fromVersion < 12 && toVersion >= 12) {
10987
+ p = p.next(() => {
10988
+ createFieldIndex(db);
10989
+ });
10990
+ }
10713
10991
  return p;
10714
10992
  }
10715
10993
  addDocumentGlobal(txn) {
@@ -10916,6 +11194,20 @@ function createNamedQueriesStore(db) {
10916
11194
  db.createObjectStore(DbNamedQuery.store, {
10917
11195
  keyPath: DbNamedQuery.keyPath
10918
11196
  });
11197
+ }
11198
+ function createFieldIndex(db) {
11199
+ const indexConfiguratioStore = db.createObjectStore(DbIndexConfiguration.store, {
11200
+ keyPath: DbIndexConfiguration.keyPath,
11201
+ autoIncrement: true
11202
+ });
11203
+ indexConfiguratioStore.createIndex(DbIndexConfiguration.collectionGroupIndex, DbIndexConfiguration.collectionGroupIndexPath, { unique: false });
11204
+ const indexStateStore = db.createObjectStore(DbIndexState.store, {
11205
+ keyPath: DbIndexState.keyPath
11206
+ });
11207
+ indexStateStore.createIndex(DbIndexState.sequenceNumberIndex, DbIndexState.sequenceNumberIndexPath, { unique: false });
11208
+ db.createObjectStore(DbIndexEntry.store, {
11209
+ keyPath: DbIndexEntry.keyPath
11210
+ });
10919
11211
  }
10920
11212
 
10921
11213
  /**
@@ -11027,7 +11319,7 @@ class IndexedDbPersistence {
11027
11319
  * If set to true, forcefully obtains database access. Existing tabs will
11028
11320
  * no longer be able to access IndexedDB.
11029
11321
  */
11030
- forceOwningTab) {
11322
+ forceOwningTab, schemaVersion = SCHEMA_VERSION) {
11031
11323
  this.allowTabSynchronization = allowTabSynchronization;
11032
11324
  this.persistenceKey = persistenceKey;
11033
11325
  this.clientId = clientId;
@@ -11036,6 +11328,7 @@ class IndexedDbPersistence {
11036
11328
  this.document = document;
11037
11329
  this.sequenceNumberSyncer = sequenceNumberSyncer;
11038
11330
  this.forceOwningTab = forceOwningTab;
11331
+ this.schemaVersion = schemaVersion;
11039
11332
  this.listenSequence = null;
11040
11333
  this._started = false;
11041
11334
  this.isPrimary = false;
@@ -11057,10 +11350,9 @@ class IndexedDbPersistence {
11057
11350
  this.referenceDelegate = new IndexedDbLruDelegateImpl(this, lruParams);
11058
11351
  this.dbName = persistenceKey + MAIN_DATABASE;
11059
11352
  this.serializer = new LocalSerializer(serializer);
11060
- this.simpleDb = new SimpleDb(this.dbName, SCHEMA_VERSION, new SchemaConverter(this.serializer));
11353
+ this.simpleDb = new SimpleDb(this.dbName, this.schemaVersion, new SchemaConverter(this.serializer));
11061
11354
  this.targetCache = new IndexedDbTargetCache(this.referenceDelegate, this.serializer);
11062
- this.indexManager = new IndexedDbIndexManager();
11063
- this.remoteDocumentCache = newIndexedDbRemoteDocumentCache(this.serializer, this.indexManager);
11355
+ this.remoteDocumentCache = newIndexedDbRemoteDocumentCache(this.serializer);
11064
11356
  this.bundleCache = new IndexedDbBundleCache();
11065
11357
  if (this.window && this.window.localStorage) {
11066
11358
  this.webStorage = this.window.localStorage;
@@ -11396,8 +11688,8 @@ class IndexedDbPersistence {
11396
11688
  get started() {
11397
11689
  return this._started;
11398
11690
  }
11399
- getMutationQueue(user) {
11400
- return IndexedDbMutationQueue.forUser(user, this.serializer, this.indexManager, this.referenceDelegate);
11691
+ getMutationQueue(user, indexManager) {
11692
+ return IndexedDbMutationQueue.forUser(user, this.serializer, indexManager, this.referenceDelegate);
11401
11693
  }
11402
11694
  getTargetCache() {
11403
11695
  return this.targetCache;
@@ -11405,8 +11697,8 @@ class IndexedDbPersistence {
11405
11697
  getRemoteDocumentCache() {
11406
11698
  return this.remoteDocumentCache;
11407
11699
  }
11408
- getIndexManager() {
11409
- return this.indexManager;
11700
+ getIndexManager(user) {
11701
+ return new IndexedDbIndexManager(user);
11410
11702
  }
11411
11703
  getBundleCache() {
11412
11704
  return this.bundleCache;
@@ -11414,11 +11706,12 @@ class IndexedDbPersistence {
11414
11706
  runTransaction(action, mode, transactionOperation) {
11415
11707
  logDebug(LOG_TAG$d, 'Starting transaction:', action);
11416
11708
  const simpleDbMode = mode === 'readonly' ? 'readonly' : 'readwrite';
11709
+ const objectStores = getObjectStores(this.schemaVersion);
11417
11710
  let persistenceTransaction;
11418
11711
  // Do all transactions as readwrite against all object stores, since we
11419
11712
  // are the only reader/writer.
11420
11713
  return this.simpleDb
11421
- .runTransaction(action, simpleDbMode, ALL_STORES, simpleDbTxn => {
11714
+ .runTransaction(action, simpleDbMode, objectStores, simpleDbTxn => {
11422
11715
  persistenceTransaction = new IndexedDbTransaction(simpleDbTxn, this.listenSequence
11423
11716
  ? this.listenSequence.next()
11424
11717
  : ListenSequence.INVALID);
@@ -11916,11 +12209,18 @@ class LocalStoreImpl {
11916
12209
  * PORTING NOTE: This is only used for multi-tab synchronization.
11917
12210
  */
11918
12211
  this.lastDocumentChangeReadTime = SnapshotVersion.min();
11919
- this.mutationQueue = persistence.getMutationQueue(initialUser);
11920
12212
  this.remoteDocuments = persistence.getRemoteDocumentCache();
11921
12213
  this.targetCache = persistence.getTargetCache();
11922
- this.localDocuments = new LocalDocumentsView(this.remoteDocuments, this.mutationQueue, this.persistence.getIndexManager());
11923
12214
  this.bundleCache = persistence.getBundleCache();
12215
+ this.initializeUserComponents(initialUser);
12216
+ }
12217
+ initializeUserComponents(user) {
12218
+ // TODO(indexing): Add spec tests that test these components change after a
12219
+ // user change
12220
+ this.indexManager = this.persistence.getIndexManager(user);
12221
+ this.mutationQueue = this.persistence.getMutationQueue(user, this.indexManager);
12222
+ this.localDocuments = new LocalDocumentsView(this.remoteDocuments, this.mutationQueue, this.indexManager);
12223
+ this.remoteDocuments.setIndexManager(this.indexManager);
11924
12224
  this.queryEngine.setLocalDocumentsView(this.localDocuments);
11925
12225
  }
11926
12226
  collectGarbage(garbageCollector) {
@@ -11942,8 +12242,6 @@ persistence, queryEngine, initialUser, serializer) {
11942
12242
  // change.
11943
12243
  async function localStoreHandleUserChange(localStore, user) {
11944
12244
  const localStoreImpl = debugCast(localStore);
11945
- let newMutationQueue = localStoreImpl.mutationQueue;
11946
- let newLocalDocuments = localStoreImpl.localDocuments;
11947
12245
  const result = await localStoreImpl.persistence.runTransaction('Handle user change', 'readonly', txn => {
11948
12246
  // Swap out the mutation queue, grabbing the pending mutation batches
11949
12247
  // before and after.
@@ -11952,11 +12250,8 @@ async function localStoreHandleUserChange(localStore, user) {
11952
12250
  .getAllMutationBatches(txn)
11953
12251
  .next(promisedOldBatches => {
11954
12252
  oldBatches = promisedOldBatches;
11955
- newMutationQueue = localStoreImpl.persistence.getMutationQueue(user);
11956
- // Recreate our LocalDocumentsView using the new
11957
- // MutationQueue.
11958
- newLocalDocuments = new LocalDocumentsView(localStoreImpl.remoteDocuments, newMutationQueue, localStoreImpl.persistence.getIndexManager());
11959
- return newMutationQueue.getAllMutationBatches(txn);
12253
+ localStoreImpl.initializeUserComponents(user);
12254
+ return localStoreImpl.mutationQueue.getAllMutationBatches(txn);
11960
12255
  })
11961
12256
  .next(newBatches => {
11962
12257
  const removedBatchIds = [];
@@ -11977,7 +12272,7 @@ async function localStoreHandleUserChange(localStore, user) {
11977
12272
  }
11978
12273
  // Return the set of all (potentially) changed documents and the list
11979
12274
  // of mutation batch IDs that were affected by change.
11980
- return newLocalDocuments
12275
+ return localStoreImpl.localDocuments
11981
12276
  .getDocuments(txn, changedKeys)
11982
12277
  .next(affectedDocuments => {
11983
12278
  return {
@@ -11988,9 +12283,6 @@ async function localStoreHandleUserChange(localStore, user) {
11988
12283
  });
11989
12284
  });
11990
12285
  });
11991
- localStoreImpl.mutationQueue = newMutationQueue;
11992
- localStoreImpl.localDocuments = newLocalDocuments;
11993
- localStoreImpl.queryEngine.setLocalDocumentsView(localStoreImpl.localDocuments);
11994
12286
  return result;
11995
12287
  }
11996
12288
  /* Accepts locally generated Mutations and commit them to storage. */
@@ -13056,14 +13348,16 @@ class MemoryRemoteDocumentCacheImpl {
13056
13348
  * expected to just return 0 to avoid unnecessarily doing the work of
13057
13349
  * calculating the size.
13058
13350
  */
13059
- constructor(indexManager, sizer) {
13060
- this.indexManager = indexManager;
13351
+ constructor(sizer) {
13061
13352
  this.sizer = sizer;
13062
13353
  /** Underlying cache of documents and their read times. */
13063
13354
  this.docs = documentEntryMap();
13064
13355
  /** Size of all cached documents. */
13065
13356
  this.size = 0;
13066
13357
  }
13358
+ setIndexManager(indexManager) {
13359
+ this.indexManager = indexManager;
13360
+ }
13067
13361
  /**
13068
13362
  * Adds the supplied entry to the cache and updates the cache size as appropriate.
13069
13363
  *
@@ -13147,13 +13441,12 @@ class MemoryRemoteDocumentCacheImpl {
13147
13441
  /**
13148
13442
  * Creates a new memory-only RemoteDocumentCache.
13149
13443
  *
13150
- * @param indexManager - A class that manages collection group indices.
13151
13444
  * @param sizer - Used to assess the size of a document. For eager GC, this is
13152
13445
  * expected to just return 0 to avoid unnecessarily doing the work of
13153
13446
  * calculating the size.
13154
13447
  */
13155
- function newMemoryRemoteDocumentCache(indexManager, sizer) {
13156
- return new MemoryRemoteDocumentCacheImpl(indexManager, sizer);
13448
+ function newMemoryRemoteDocumentCache(sizer) {
13449
+ return new MemoryRemoteDocumentCacheImpl(sizer);
13157
13450
  }
13158
13451
  /**
13159
13452
  * Handles the details of adding and updating documents in the MemoryRemoteDocumentCache.
@@ -13354,7 +13647,7 @@ class MemoryPersistence {
13354
13647
  this.targetCache = new MemoryTargetCache(this);
13355
13648
  const sizer = (doc) => this.referenceDelegate.documentSize(doc);
13356
13649
  this.indexManager = new MemoryIndexManager();
13357
- this.remoteDocumentCache = newMemoryRemoteDocumentCache(this.indexManager, sizer);
13650
+ this.remoteDocumentCache = newMemoryRemoteDocumentCache(sizer);
13358
13651
  this.serializer = new LocalSerializer(serializer);
13359
13652
  this.bundleCache = new MemoryBundleCache(this.serializer);
13360
13653
  }
@@ -13375,13 +13668,15 @@ class MemoryPersistence {
13375
13668
  setNetworkEnabled() {
13376
13669
  // No op.
13377
13670
  }
13378
- getIndexManager() {
13671
+ getIndexManager(user) {
13672
+ // We do not currently support indices for memory persistence, so we can
13673
+ // return the same shared instance of the memory index manager.
13379
13674
  return this.indexManager;
13380
13675
  }
13381
- getMutationQueue(user) {
13676
+ getMutationQueue(user, indexManager) {
13382
13677
  let queue = this.mutationQueues[user.toKey()];
13383
13678
  if (!queue) {
13384
- queue = new MemoryMutationQueue(this.indexManager, this.referenceDelegate);
13679
+ queue = new MemoryMutationQueue(indexManager, this.referenceDelegate);
13385
13680
  this.mutationQueues[user.toKey()] = queue;
13386
13681
  }
13387
13682
  return queue;
@@ -20344,12 +20639,12 @@ async function syncEngineListen(syncEngine, query) {
20344
20639
  }
20345
20640
  else {
20346
20641
  const targetData = await localStoreAllocateTarget(syncEngineImpl.localStore, queryToTarget(query));
20347
- const status = syncEngineImpl.sharedClientState.addLocalQueryTarget(targetData.targetId);
20348
- targetId = targetData.targetId;
20349
- viewSnapshot = await initializeViewAndComputeSnapshot(syncEngineImpl, query, targetId, status === 'current');
20350
20642
  if (syncEngineImpl.isPrimaryClient) {
20351
20643
  remoteStoreListen(syncEngineImpl.remoteStore, targetData);
20352
20644
  }
20645
+ const status = syncEngineImpl.sharedClientState.addLocalQueryTarget(targetData.targetId);
20646
+ targetId = targetData.targetId;
20647
+ viewSnapshot = await initializeViewAndComputeSnapshot(syncEngineImpl, query, targetId, status === 'current');
20353
20648
  }
20354
20649
  return viewSnapshot;
20355
20650
  }
@@ -24857,8 +25152,7 @@ class DocumentSnapshot extends DocumentSnapshot$1 {
24857
25152
  this.metadata = metadata;
24858
25153
  }
24859
25154
  /**
24860
- * Property of the `DocumentSnapshot` that signals whether or not the data
24861
- * exists. True if the document exists.
25155
+ * Returns whether or not the data exists. True if the document exists.
24862
25156
  */
24863
25157
  exists() {
24864
25158
  return super.exists();
@@ -25232,51 +25526,53 @@ function limitToLast(limit) {
25232
25526
  return new QueryLimitConstraint('limitToLast', limit, "L" /* Last */);
25233
25527
  }
25234
25528
  class QueryStartAtConstraint extends QueryConstraint {
25235
- constructor(type, _docOrFields, _before) {
25529
+ constructor(type, _docOrFields, _inclusive) {
25236
25530
  super();
25237
25531
  this.type = type;
25238
25532
  this._docOrFields = _docOrFields;
25239
- this._before = _before;
25533
+ this._inclusive = _inclusive;
25240
25534
  }
25241
25535
  _apply(query) {
25242
- const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this._before);
25536
+ const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this._inclusive);
25243
25537
  return new Query(query.firestore, query.converter, queryWithStartAt(query._query, bound));
25244
25538
  }
25245
25539
  }
25246
25540
  function startAt(...docOrFields) {
25247
- return new QueryStartAtConstraint('startAt', docOrFields, /*before=*/ true);
25541
+ return new QueryStartAtConstraint('startAt', docOrFields,
25542
+ /*inclusive=*/ true);
25248
25543
  }
25249
25544
  function startAfter(...docOrFields) {
25250
25545
  return new QueryStartAtConstraint('startAfter', docOrFields,
25251
- /*before=*/ false);
25546
+ /*inclusive=*/ false);
25252
25547
  }
25253
25548
  class QueryEndAtConstraint extends QueryConstraint {
25254
- constructor(type, _docOrFields, _before) {
25549
+ constructor(type, _docOrFields, _inclusive) {
25255
25550
  super();
25256
25551
  this.type = type;
25257
25552
  this._docOrFields = _docOrFields;
25258
- this._before = _before;
25553
+ this._inclusive = _inclusive;
25259
25554
  }
25260
25555
  _apply(query) {
25261
- const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this._before);
25556
+ const bound = newQueryBoundFromDocOrFields(query, this.type, this._docOrFields, this._inclusive);
25262
25557
  return new Query(query.firestore, query.converter, queryWithEndAt(query._query, bound));
25263
25558
  }
25264
25559
  }
25265
25560
  function endBefore(...docOrFields) {
25266
- return new QueryEndAtConstraint('endBefore', docOrFields, /*before=*/ true);
25561
+ return new QueryEndAtConstraint('endBefore', docOrFields,
25562
+ /*inclusive=*/ false);
25267
25563
  }
25268
25564
  function endAt(...docOrFields) {
25269
- return new QueryEndAtConstraint('endAt', docOrFields, /*before=*/ false);
25565
+ return new QueryEndAtConstraint('endAt', docOrFields, /*inclusive=*/ true);
25270
25566
  }
25271
25567
  /** Helper function to create a bound from a document or fields */
25272
- function newQueryBoundFromDocOrFields(query, methodName, docOrFields, before) {
25568
+ function newQueryBoundFromDocOrFields(query, methodName, docOrFields, inclusive) {
25273
25569
  docOrFields[0] = util$1.getModularInstance(docOrFields[0]);
25274
25570
  if (docOrFields[0] instanceof DocumentSnapshot$1) {
25275
- return newQueryBoundFromDocument(query._query, query.firestore._databaseId, methodName, docOrFields[0]._document, before);
25571
+ return newQueryBoundFromDocument(query._query, query.firestore._databaseId, methodName, docOrFields[0]._document, inclusive);
25276
25572
  }
25277
25573
  else {
25278
25574
  const reader = newUserDataReader(query.firestore);
25279
- return newQueryBoundFromFields(query._query, query.firestore._databaseId, reader, methodName, docOrFields, before);
25575
+ return newQueryBoundFromFields(query._query, query.firestore._databaseId, reader, methodName, docOrFields, inclusive);
25280
25576
  }
25281
25577
  }
25282
25578
  function newQueryFilter(query, methodName, dataReader, databaseId, fieldPath, op, value) {
@@ -25334,7 +25630,7 @@ function newQueryOrderBy(query, fieldPath, direction) {
25334
25630
  * of the query or if any of the fields in the order by are an uncommitted
25335
25631
  * server timestamp.
25336
25632
  */
25337
- function newQueryBoundFromDocument(query, databaseId, methodName, doc, before) {
25633
+ function newQueryBoundFromDocument(query, databaseId, methodName, doc, inclusive) {
25338
25634
  if (!doc) {
25339
25635
  throw new FirestoreError(Code.NOT_FOUND, `Can't use a DocumentSnapshot that doesn't exist for ` +
25340
25636
  `${methodName}().`);
@@ -25371,12 +25667,12 @@ function newQueryBoundFromDocument(query, databaseId, methodName, doc, before) {
25371
25667
  }
25372
25668
  }
25373
25669
  }
25374
- return new Bound(components, before);
25670
+ return new Bound(components, inclusive);
25375
25671
  }
25376
25672
  /**
25377
25673
  * Converts a list of field values to a `Bound` for the given query.
25378
25674
  */
25379
- function newQueryBoundFromFields(query, databaseId, dataReader, methodName, values, before) {
25675
+ function newQueryBoundFromFields(query, databaseId, dataReader, methodName, values, inclusive) {
25380
25676
  // Use explicit order by's because it has to match the query the user made
25381
25677
  const orderBy = query.explicitOrderBy;
25382
25678
  if (values.length > orderBy.length) {
@@ -25413,7 +25709,7 @@ function newQueryBoundFromFields(query, databaseId, dataReader, methodName, valu
25413
25709
  components.push(wrapped);
25414
25710
  }
25415
25711
  }
25416
- return new Bound(components, before);
25712
+ return new Bound(components, inclusive);
25417
25713
  }
25418
25714
  /**
25419
25715
  * Parses the given `documentIdValue` into a `ReferenceValue`, throwing