@firebase/firestore 3.4.7 → 3.4.8-2022312211851

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 (65) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/firestore/src/local/index_manager.d.ts +3 -2
  3. package/dist/firestore/src/local/indexeddb_index_manager.d.ts +11 -3
  4. package/dist/firestore/src/local/indexeddb_remote_document_cache.d.ts +9 -0
  5. package/dist/firestore/src/local/indexeddb_schema.d.ts +7 -2
  6. package/dist/firestore/src/local/indexeddb_sentinels.d.ts +9 -2
  7. package/dist/firestore/src/local/memory_index_manager.d.ts +3 -2
  8. package/dist/firestore/src/local/simple_db.d.ts +2 -0
  9. package/dist/firestore/src/model/field_index.d.ts +6 -0
  10. package/dist/firestore/test/unit/local/test_index_manager.d.ts +3 -2
  11. package/dist/firestore/test/unit/local/test_remote_document_cache.d.ts +0 -4
  12. package/dist/index.esm2017.js +3268 -3209
  13. package/dist/index.esm2017.js.map +1 -1
  14. package/dist/index.esm5.js +3571 -3518
  15. package/dist/index.esm5.js.map +1 -1
  16. package/dist/index.node.cjs.js +192 -124
  17. package/dist/index.node.cjs.js.map +1 -1
  18. package/dist/index.node.mjs +192 -124
  19. package/dist/index.node.mjs.map +1 -1
  20. package/dist/index.rn.js +3089 -3030
  21. package/dist/index.rn.js.map +1 -1
  22. package/dist/internal.d.ts +1 -1
  23. package/dist/lite/firestore/src/local/index_manager.d.ts +3 -2
  24. package/dist/lite/firestore/src/local/indexeddb_index_manager.d.ts +11 -3
  25. package/dist/lite/firestore/src/local/indexeddb_remote_document_cache.d.ts +9 -0
  26. package/dist/lite/firestore/src/local/indexeddb_schema.d.ts +7 -2
  27. package/dist/lite/firestore/src/local/indexeddb_sentinels.d.ts +9 -2
  28. package/dist/lite/firestore/src/local/memory_index_manager.d.ts +3 -2
  29. package/dist/lite/firestore/src/local/simple_db.d.ts +2 -0
  30. package/dist/lite/firestore/src/model/field_index.d.ts +6 -0
  31. package/dist/lite/firestore/test/unit/local/test_index_manager.d.ts +3 -2
  32. package/dist/lite/firestore/test/unit/local/test_remote_document_cache.d.ts +0 -4
  33. package/dist/lite/index.browser.esm2017.js +2 -2
  34. package/dist/lite/index.browser.esm2017.js.map +1 -1
  35. package/dist/lite/index.browser.esm5.js +2 -2
  36. package/dist/lite/index.browser.esm5.js.map +1 -1
  37. package/dist/lite/index.node.cjs.js +2 -2
  38. package/dist/lite/index.node.cjs.js.map +1 -1
  39. package/dist/lite/index.node.mjs +2 -2
  40. package/dist/lite/index.node.mjs.map +1 -1
  41. package/dist/lite/index.rn.esm2017.js +2 -2
  42. package/dist/lite/index.rn.esm2017.js.map +1 -1
  43. package/dist/lite/packages/firestore/src/local/index_manager.d.ts +3 -2
  44. package/dist/lite/packages/firestore/src/local/indexeddb_index_manager.d.ts +11 -3
  45. package/dist/lite/packages/firestore/src/local/indexeddb_remote_document_cache.d.ts +9 -0
  46. package/dist/lite/packages/firestore/src/local/indexeddb_schema.d.ts +7 -2
  47. package/dist/lite/packages/firestore/src/local/indexeddb_sentinels.d.ts +9 -2
  48. package/dist/lite/packages/firestore/src/local/memory_index_manager.d.ts +3 -2
  49. package/dist/lite/packages/firestore/src/local/simple_db.d.ts +2 -0
  50. package/dist/lite/packages/firestore/src/model/field_index.d.ts +6 -0
  51. package/dist/lite/packages/firestore/test/unit/local/test_index_manager.d.ts +3 -2
  52. package/dist/lite/packages/firestore/test/unit/local/test_remote_document_cache.d.ts +0 -4
  53. package/dist/packages/firestore/dist/index.esm2017.d.ts +163 -163
  54. package/dist/packages/firestore/src/local/index_manager.d.ts +3 -2
  55. package/dist/packages/firestore/src/local/indexeddb_index_manager.d.ts +11 -3
  56. package/dist/packages/firestore/src/local/indexeddb_remote_document_cache.d.ts +9 -0
  57. package/dist/packages/firestore/src/local/indexeddb_schema.d.ts +7 -2
  58. package/dist/packages/firestore/src/local/indexeddb_sentinels.d.ts +9 -2
  59. package/dist/packages/firestore/src/local/memory_index_manager.d.ts +3 -2
  60. package/dist/packages/firestore/src/local/simple_db.d.ts +2 -0
  61. package/dist/packages/firestore/src/model/field_index.d.ts +6 -0
  62. package/dist/packages/firestore/test/unit/local/test_index_manager.d.ts +3 -2
  63. package/dist/packages/firestore/test/unit/local/test_remote_document_cache.d.ts +0 -4
  64. package/dist/private.d.ts +1 -1
  65. package/package.json +7 -7
@@ -8,7 +8,7 @@ import * as grpc from '@grpc/grpc-js';
8
8
  import * as protoLoader from '@grpc/proto-loader';
9
9
 
10
10
  const name = "@firebase/firestore";
11
- const version$1 = "3.4.7";
11
+ const version$1 = "3.4.8-2022312211851";
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.10";
64
+ const version = "9.6.11-2022312211851";
65
65
 
66
66
  /**
67
67
  * @license
@@ -1393,13 +1393,14 @@ const DbIndexEntryKeyPath = [
1393
1393
  'uid',
1394
1394
  'arrayValue',
1395
1395
  'directionalValue',
1396
+ 'orderedDocumentKey',
1396
1397
  'documentKey'
1397
1398
  ];
1398
1399
  const DbIndexEntryDocumentKeyIndex = 'documentKeyIndex';
1399
1400
  const DbIndexEntryDocumentKeyIndexPath = [
1400
1401
  'indexId',
1401
1402
  'uid',
1402
- 'documentKey'
1403
+ 'orderedDocumentKey'
1403
1404
  ];
1404
1405
  /** Name of the IndexedDb object store. */
1405
1406
  const DbDocumentOverlayStore = 'documentOverlays';
@@ -2285,9 +2286,7 @@ class SimpleDbStore {
2285
2286
  cursor.continue(controller.skipToKey);
2286
2287
  }
2287
2288
  };
2288
- }).next(() => {
2289
- return PersistencePromise.waitFor(results);
2290
- });
2289
+ }).next(() => PersistencePromise.waitFor(results));
2291
2290
  }
2292
2291
  options(indexOrRange, range) {
2293
2292
  let indexName = undefined;
@@ -4196,6 +4195,17 @@ function fieldIndexGetArraySegment(fieldIndex) {
4196
4195
  function fieldIndexGetDirectionalSegments(fieldIndex) {
4197
4196
  return fieldIndex.fields.filter(s => s.kind !== 2 /* CONTAINS */);
4198
4197
  }
4198
+ /**
4199
+ * Returns the order of the document key component for the given index.
4200
+ *
4201
+ * PORTING NOTE: This is only used in the Web IndexedDb implementation.
4202
+ */
4203
+ function fieldIndexGetKeyOrder(fieldIndex) {
4204
+ const directionalSegments = fieldIndexGetDirectionalSegments(fieldIndex);
4205
+ return directionalSegments.length === 0
4206
+ ? 0 /* ASCENDING */
4207
+ : directionalSegments[directionalSegments.length - 1].kind;
4208
+ }
4199
4209
  /** Returns a debug representation of the field index */
4200
4210
  function fieldIndexToString(fieldIndex) {
4201
4211
  return `id=${fieldIndex.indexId}|cg=${fieldIndex.collectionGroup}|f=${fieldIndex.fields.map(f => `${f.fieldPath}:${f.kind}`).join(',')}`;
@@ -4496,58 +4506,15 @@ function targetGetLowerBound(target, fieldIndex) {
4496
4506
  // For each segment, retrieve a lower bound if there is a suitable filter or
4497
4507
  // startAt.
4498
4508
  for (const segment of fieldIndexGetDirectionalSegments(fieldIndex)) {
4499
- let segmentValue = undefined;
4500
- let segmentInclusive = true;
4501
- // Process all filters to find a value for the current field segment
4502
- for (const fieldFilter of targetGetFieldFiltersForPath(target, segment.fieldPath)) {
4503
- let filterValue = undefined;
4504
- let filterInclusive = true;
4505
- switch (fieldFilter.op) {
4506
- case "<" /* LESS_THAN */:
4507
- case "<=" /* LESS_THAN_OR_EQUAL */:
4508
- filterValue = valuesGetLowerBound(fieldFilter.value);
4509
- break;
4510
- case "==" /* EQUAL */:
4511
- case "in" /* IN */:
4512
- case ">=" /* GREATER_THAN_OR_EQUAL */:
4513
- filterValue = fieldFilter.value;
4514
- break;
4515
- case ">" /* GREATER_THAN */:
4516
- filterValue = fieldFilter.value;
4517
- filterInclusive = false;
4518
- break;
4519
- case "!=" /* NOT_EQUAL */:
4520
- case "not-in" /* NOT_IN */:
4521
- filterValue = MIN_VALUE;
4522
- break;
4523
- // Remaining filters cannot be used as lower bounds.
4524
- }
4525
- if (valuesMax(segmentValue, filterValue) === filterValue) {
4526
- segmentValue = filterValue;
4527
- segmentInclusive = filterInclusive;
4528
- }
4529
- }
4530
- // If there is a startAt bound, compare the values against the existing
4531
- // boundary to see if we can narrow the scope.
4532
- if (target.startAt !== null) {
4533
- for (let i = 0; i < target.orderBy.length; ++i) {
4534
- const orderBy = target.orderBy[i];
4535
- if (orderBy.field.isEqual(segment.fieldPath)) {
4536
- const cursorValue = target.startAt.position[i];
4537
- if (valuesMax(segmentValue, cursorValue) === cursorValue) {
4538
- segmentValue = cursorValue;
4539
- segmentInclusive = target.startAt.inclusive;
4540
- }
4541
- break;
4542
- }
4543
- }
4544
- }
4545
- if (segmentValue === undefined) {
4509
+ const segmentBound = segment.kind === 0 /* ASCENDING */
4510
+ ? targetGetLowerBoundForField(target, segment.fieldPath, target.startAt)
4511
+ : targetGetUpperBoundForField(target, segment.fieldPath, target.startAt);
4512
+ if (!segmentBound.value) {
4546
4513
  // No lower bound exists
4547
4514
  return null;
4548
4515
  }
4549
- values.push(segmentValue);
4550
- inclusive && (inclusive = segmentInclusive);
4516
+ values.push(segmentBound.value);
4517
+ inclusive && (inclusive = segmentBound.inclusive);
4551
4518
  }
4552
4519
  return new Bound(values, inclusive);
4553
4520
  }
@@ -4562,62 +4529,125 @@ function targetGetUpperBound(target, fieldIndex) {
4562
4529
  // For each segment, retrieve an upper bound if there is a suitable filter or
4563
4530
  // endAt.
4564
4531
  for (const segment of fieldIndexGetDirectionalSegments(fieldIndex)) {
4565
- let segmentValue = undefined;
4566
- let segmentInclusive = true;
4567
- // Process all filters to find a value for the current field segment
4568
- for (const fieldFilter of targetGetFieldFiltersForPath(target, segment.fieldPath)) {
4569
- let filterValue = undefined;
4570
- let filterInclusive = true;
4571
- switch (fieldFilter.op) {
4572
- case ">=" /* GREATER_THAN_OR_EQUAL */:
4573
- case ">" /* GREATER_THAN */:
4574
- filterValue = valuesGetUpperBound(fieldFilter.value);
4575
- filterInclusive = false;
4576
- break;
4577
- case "==" /* EQUAL */:
4578
- case "in" /* IN */:
4579
- case "<=" /* LESS_THAN_OR_EQUAL */:
4580
- filterValue = fieldFilter.value;
4581
- break;
4582
- case "<" /* LESS_THAN */:
4583
- filterValue = fieldFilter.value;
4584
- filterInclusive = false;
4585
- break;
4586
- case "!=" /* NOT_EQUAL */:
4587
- case "not-in" /* NOT_IN */:
4588
- filterValue = MAX_VALUE;
4589
- break;
4590
- // Remaining filters cannot be used as upper bounds.
4591
- }
4592
- if (valuesMin(segmentValue, filterValue) === filterValue) {
4593
- segmentValue = filterValue;
4594
- segmentInclusive = filterInclusive;
4595
- }
4596
- }
4597
- // If there is a endAt bound, compare the values against the existing
4598
- // boundary to see if we can narrow the scope.
4599
- if (target.endAt !== null) {
4600
- for (let i = 0; i < target.orderBy.length; ++i) {
4601
- const orderBy = target.orderBy[i];
4602
- if (orderBy.field.isEqual(segment.fieldPath)) {
4603
- const cursorValue = target.endAt.position[i];
4604
- if (valuesMin(segmentValue, cursorValue) === cursorValue) {
4605
- segmentValue = cursorValue;
4606
- segmentInclusive = target.endAt.inclusive;
4607
- }
4608
- break;
4609
- }
4610
- }
4611
- }
4612
- if (segmentValue === undefined) {
4532
+ const segmentBound = segment.kind === 0 /* ASCENDING */
4533
+ ? targetGetUpperBoundForField(target, segment.fieldPath, target.endAt)
4534
+ : targetGetLowerBoundForField(target, segment.fieldPath, target.endAt);
4535
+ if (!segmentBound.value) {
4613
4536
  // No upper bound exists
4614
4537
  return null;
4615
4538
  }
4616
- values.push(segmentValue);
4617
- inclusive && (inclusive = segmentInclusive);
4539
+ values.push(segmentBound.value);
4540
+ inclusive && (inclusive = segmentBound.inclusive);
4618
4541
  }
4619
4542
  return new Bound(values, inclusive);
4620
4543
  }
4544
+ /**
4545
+ * Returns the value to use as the lower bound for ascending index segment at
4546
+ * the provided `fieldPath` (or the upper bound for an descending segment).
4547
+ */
4548
+ function targetGetLowerBoundForField(target, fieldPath, bound) {
4549
+ let value = undefined;
4550
+ let inclusive = true;
4551
+ // Process all filters to find a value for the current field segment
4552
+ for (const fieldFilter of targetGetFieldFiltersForPath(target, fieldPath)) {
4553
+ let filterValue = undefined;
4554
+ let filterInclusive = true;
4555
+ switch (fieldFilter.op) {
4556
+ case "<" /* LESS_THAN */:
4557
+ case "<=" /* LESS_THAN_OR_EQUAL */:
4558
+ filterValue = valuesGetLowerBound(fieldFilter.value);
4559
+ break;
4560
+ case "==" /* EQUAL */:
4561
+ case "in" /* IN */:
4562
+ case ">=" /* GREATER_THAN_OR_EQUAL */:
4563
+ filterValue = fieldFilter.value;
4564
+ break;
4565
+ case ">" /* GREATER_THAN */:
4566
+ filterValue = fieldFilter.value;
4567
+ filterInclusive = false;
4568
+ break;
4569
+ case "!=" /* NOT_EQUAL */:
4570
+ case "not-in" /* NOT_IN */:
4571
+ filterValue = MIN_VALUE;
4572
+ break;
4573
+ // Remaining filters cannot be used as lower bounds.
4574
+ }
4575
+ if (valuesMax(value, filterValue) === filterValue) {
4576
+ value = filterValue;
4577
+ inclusive = filterInclusive;
4578
+ }
4579
+ }
4580
+ // If there is an additional bound, compare the values against the existing
4581
+ // range to see if we can narrow the scope.
4582
+ if (bound !== null) {
4583
+ for (let i = 0; i < target.orderBy.length; ++i) {
4584
+ const orderBy = target.orderBy[i];
4585
+ if (orderBy.field.isEqual(fieldPath)) {
4586
+ const cursorValue = bound.position[i];
4587
+ if (valuesMax(value, cursorValue) === cursorValue) {
4588
+ value = cursorValue;
4589
+ inclusive = bound.inclusive;
4590
+ }
4591
+ break;
4592
+ }
4593
+ }
4594
+ }
4595
+ return { value, inclusive };
4596
+ }
4597
+ /**
4598
+ * Returns the value to use as the upper bound for ascending index segment at
4599
+ * the provided `fieldPath` (or the lower bound for an descending segment).
4600
+ */
4601
+ function targetGetUpperBoundForField(target, fieldPath, bound) {
4602
+ let value = undefined;
4603
+ let inclusive = true;
4604
+ // Process all filters to find a value for the current field segment
4605
+ for (const fieldFilter of targetGetFieldFiltersForPath(target, fieldPath)) {
4606
+ let filterValue = undefined;
4607
+ let filterInclusive = true;
4608
+ switch (fieldFilter.op) {
4609
+ case ">=" /* GREATER_THAN_OR_EQUAL */:
4610
+ case ">" /* GREATER_THAN */:
4611
+ filterValue = valuesGetUpperBound(fieldFilter.value);
4612
+ filterInclusive = false;
4613
+ break;
4614
+ case "==" /* EQUAL */:
4615
+ case "in" /* IN */:
4616
+ case "<=" /* LESS_THAN_OR_EQUAL */:
4617
+ filterValue = fieldFilter.value;
4618
+ break;
4619
+ case "<" /* LESS_THAN */:
4620
+ filterValue = fieldFilter.value;
4621
+ filterInclusive = false;
4622
+ break;
4623
+ case "!=" /* NOT_EQUAL */:
4624
+ case "not-in" /* NOT_IN */:
4625
+ filterValue = MAX_VALUE;
4626
+ break;
4627
+ // Remaining filters cannot be used as upper bounds.
4628
+ }
4629
+ if (valuesMin(value, filterValue) === filterValue) {
4630
+ value = filterValue;
4631
+ inclusive = filterInclusive;
4632
+ }
4633
+ }
4634
+ // If there is an additional bound, compare the values against the existing
4635
+ // range to see if we can narrow the scope.
4636
+ if (bound !== null) {
4637
+ for (let i = 0; i < target.orderBy.length; ++i) {
4638
+ const orderBy = target.orderBy[i];
4639
+ if (orderBy.field.isEqual(fieldPath)) {
4640
+ const cursorValue = bound.position[i];
4641
+ if (valuesMin(value, cursorValue) === cursorValue) {
4642
+ value = cursorValue;
4643
+ inclusive = bound.inclusive;
4644
+ }
4645
+ break;
4646
+ }
4647
+ }
4648
+ }
4649
+ return { value, inclusive };
4650
+ }
4621
4651
  class Filter {
4622
4652
  }
4623
4653
  class FieldFilter extends Filter {
@@ -10021,8 +10051,9 @@ const EMPTY_VALUE = new Uint8Array(0);
10021
10051
  * data as it supports multi-tab access.
10022
10052
  */
10023
10053
  class IndexedDbIndexManager {
10024
- constructor(user) {
10054
+ constructor(user, databaseId) {
10025
10055
  this.user = user;
10056
+ this.databaseId = databaseId;
10026
10057
  /**
10027
10058
  * An in-memory copy of the index entries we've already written since the SDK
10028
10059
  * launched. Used to avoid re-writing the same entry repeatedly.
@@ -10118,7 +10149,8 @@ class IndexedDbIndexManager {
10118
10149
  return PersistencePromise.resolve(null);
10119
10150
  }
10120
10151
  else {
10121
- let result = documentKeySet();
10152
+ let existingKeys = documentKeySet();
10153
+ const result = [];
10122
10154
  return PersistencePromise.forEach(indexes, (index, subTarget) => {
10123
10155
  logDebug(LOG_TAG$f, `Using index ${fieldIndexToString(index)} to execute ${canonifyTarget(target)}`);
10124
10156
  const arrayValues = targetGetArrayValues(subTarget, index);
@@ -10134,7 +10166,11 @@ class IndexedDbIndexManager {
10134
10166
  .loadFirst(indexRange, target.limit)
10135
10167
  .next(entries => {
10136
10168
  entries.forEach(entry => {
10137
- result = result.add(new DocumentKey(decodeResourcePath(entry.documentKey)));
10169
+ const documentKey = DocumentKey.fromSegments(entry.documentKey);
10170
+ if (!existingKeys.has(documentKey)) {
10171
+ existingKeys = existingKeys.add(documentKey);
10172
+ result.push(documentKey);
10173
+ }
10138
10174
  });
10139
10175
  });
10140
10176
  });
@@ -10233,6 +10269,15 @@ class IndexedDbIndexManager {
10233
10269
  FirestoreIndexValueWriter.INSTANCE.writeIndexValue(value, encoder.forKind(0 /* ASCENDING */));
10234
10270
  return encoder.encodedBytes();
10235
10271
  }
10272
+ /**
10273
+ * Returns an encoded form of the document key that sorts based on the key
10274
+ * ordering of the field index.
10275
+ */
10276
+ encodeDirectionalKey(fieldIndex, documentKey) {
10277
+ const encoder = new IndexByteEncoder();
10278
+ FirestoreIndexValueWriter.INSTANCE.writeIndexValue(refValue(this.databaseId, documentKey), encoder.forKind(fieldIndexGetKeyOrder(fieldIndex)));
10279
+ return encoder.encodedBytes();
10280
+ }
10236
10281
  /**
10237
10282
  * Encodes the given field values according to the specification in `target`.
10238
10283
  * For IN queries, a list of possible values is returned.
@@ -10356,7 +10401,7 @@ class IndexedDbIndexManager {
10356
10401
  return this.getExistingIndexEntries(transaction, key, fieldIndex).next(existingEntries => {
10357
10402
  const newEntries = this.computeIndexEntries(doc, fieldIndex);
10358
10403
  if (!existingEntries.isEqual(newEntries)) {
10359
- return this.updateEntries(transaction, doc, existingEntries, newEntries);
10404
+ return this.updateEntries(transaction, doc, fieldIndex, existingEntries, newEntries);
10360
10405
  }
10361
10406
  return PersistencePromise.resolve();
10362
10407
  });
@@ -10364,24 +10409,26 @@ class IndexedDbIndexManager {
10364
10409
  });
10365
10410
  });
10366
10411
  }
10367
- addIndexEntry(transaction, document, indexEntry) {
10412
+ addIndexEntry(transaction, document, fieldIndex, indexEntry) {
10368
10413
  const indexEntries = indexEntriesStore(transaction);
10369
10414
  return indexEntries.put({
10370
10415
  indexId: indexEntry.indexId,
10371
10416
  uid: this.uid,
10372
10417
  arrayValue: indexEntry.arrayValue,
10373
10418
  directionalValue: indexEntry.directionalValue,
10374
- documentKey: encodeResourcePath(document.key.path)
10419
+ orderedDocumentKey: this.encodeDirectionalKey(fieldIndex, document.key),
10420
+ documentKey: document.key.path.toArray()
10375
10421
  });
10376
10422
  }
10377
- deleteIndexEntry(transaction, document, indexEntry) {
10423
+ deleteIndexEntry(transaction, document, fieldIndex, indexEntry) {
10378
10424
  const indexEntries = indexEntriesStore(transaction);
10379
10425
  return indexEntries.delete([
10380
10426
  indexEntry.indexId,
10381
10427
  this.uid,
10382
10428
  indexEntry.arrayValue,
10383
10429
  indexEntry.directionalValue,
10384
- encodeResourcePath(document.key.path)
10430
+ this.encodeDirectionalKey(fieldIndex, document.key),
10431
+ document.key.path.toArray()
10385
10432
  ]);
10386
10433
  }
10387
10434
  getExistingIndexEntries(transaction, documentKey, fieldIndex) {
@@ -10393,7 +10440,7 @@ class IndexedDbIndexManager {
10393
10440
  range: IDBKeyRange.only([
10394
10441
  fieldIndex.indexId,
10395
10442
  this.uid,
10396
- encodeResourcePath(documentKey.path)
10443
+ this.encodeDirectionalKey(fieldIndex, documentKey)
10397
10444
  ])
10398
10445
  }, (_, entry) => {
10399
10446
  results = results.add(new IndexEntry(fieldIndex.indexId, documentKey, entry.arrayValue, entry.directionalValue));
@@ -10426,15 +10473,15 @@ class IndexedDbIndexManager {
10426
10473
  * that are no longer referenced in `newEntries` and adding all newly added
10427
10474
  * entries.
10428
10475
  */
10429
- updateEntries(transaction, document, existingEntries, newEntries) {
10476
+ updateEntries(transaction, document, fieldIndex, existingEntries, newEntries) {
10430
10477
  logDebug(LOG_TAG$f, "Updating index entries for document '%s'", document.key);
10431
10478
  const promises = [];
10432
10479
  diffSortedSets(existingEntries, newEntries, indexEntryComparator,
10433
10480
  /* onAdd= */ entry => {
10434
- promises.push(this.addIndexEntry(transaction, document, entry));
10481
+ promises.push(this.addIndexEntry(transaction, document, fieldIndex, entry));
10435
10482
  },
10436
10483
  /* onRemove= */ entry => {
10437
- promises.push(this.deleteIndexEntry(transaction, document, entry));
10484
+ promises.push(this.deleteIndexEntry(transaction, document, fieldIndex, entry));
10438
10485
  });
10439
10486
  return PersistencePromise.waitFor(promises);
10440
10487
  }
@@ -10491,13 +10538,15 @@ class IndexedDbIndexManager {
10491
10538
  this.uid,
10492
10539
  bounds[i].arrayValue,
10493
10540
  bounds[i].directionalValue,
10494
- ''
10541
+ EMPTY_VALUE,
10542
+ []
10495
10543
  ], [
10496
10544
  bounds[i + 1].indexId,
10497
10545
  this.uid,
10498
10546
  bounds[i + 1].arrayValue,
10499
10547
  bounds[i + 1].directionalValue,
10500
- ''
10548
+ EMPTY_VALUE,
10549
+ []
10501
10550
  ]));
10502
10551
  }
10503
10552
  return ranges;
@@ -12251,12 +12300,31 @@ function dbCollectionGroupKey(collectionGroup, offset) {
12251
12300
  }
12252
12301
  /**
12253
12302
  * Comparator that compares document keys according to the primary key sorting
12254
- * used by the `DbRemoteDocumentDocument` store (by collection path and then
12255
- * document ID).
12303
+ * used by the `DbRemoteDocumentDocument` store (by prefix path, collection id
12304
+ * and then document ID).
12305
+ *
12306
+ * Visible for testing.
12256
12307
  */
12257
12308
  function dbKeyComparator(l, r) {
12258
- const cmp = l.path.length - r.path.length;
12259
- return cmp !== 0 ? cmp : DocumentKey.comparator(l, r);
12309
+ const left = l.path.toArray();
12310
+ const right = r.path.toArray();
12311
+ // The ordering is based on https://chromium.googlesource.com/chromium/blink/+/fe5c21fef94dae71c1c3344775b8d8a7f7e6d9ec/Source/modules/indexeddb/IDBKey.cpp#74
12312
+ let cmp = 0;
12313
+ for (let i = 0; i < left.length - 2 && i < right.length - 2; ++i) {
12314
+ cmp = primitiveComparator(left[i], right[i]);
12315
+ if (cmp) {
12316
+ return cmp;
12317
+ }
12318
+ }
12319
+ cmp = primitiveComparator(left.length, right.length);
12320
+ if (cmp) {
12321
+ return cmp;
12322
+ }
12323
+ cmp = primitiveComparator(left[left.length - 2], right[right.length - 2]);
12324
+ if (cmp) {
12325
+ return cmp;
12326
+ }
12327
+ return primitiveComparator(left[left.length - 1], right[right.length - 1]);
12260
12328
  }
12261
12329
  /**
12262
12330
  * Schema Version for the Web client:
@@ -13157,7 +13225,7 @@ class IndexedDbPersistence {
13157
13225
  return this.remoteDocumentCache;
13158
13226
  }
13159
13227
  getIndexManager(user) {
13160
- return new IndexedDbIndexManager(user);
13228
+ return new IndexedDbIndexManager(user, this.serializer.remoteSerializer.databaseId);
13161
13229
  }
13162
13230
  getDocumentOverlayCache(user) {
13163
13231
  return IndexedDbDocumentOverlayCache.forUser(this.serializer, user);