@tldraw/store 4.3.0-canary.bf87ebaf143a → 4.3.0-canary.c08047039e53

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.
@@ -174,20 +174,10 @@ function SetRef(ref?: Ref): void {
174
174
  }
175
175
  }
176
176
 
177
- // http://jsperf.com/copy-array-inline
178
- function arrCopy<I>(arr: Array<I>, offset?: number): Array<I> {
179
- offset = offset || 0
180
- const len = Math.max(0, arr.length - offset)
181
- const newArr: Array<I> = new Array(len)
182
- for (let ii = 0; ii < len; ii++) {
183
- // We may want to guard for undefined values with `if (arr[ii + offset] !== undefined`, but ths should not happen by design
184
- newArr[ii] = arr[ii + offset]
185
- }
186
- return newArr
177
+ function arrCopy<I>(arr: Array<I>, offset = 0): Array<I> {
178
+ return arr.slice(offset)
187
179
  }
188
180
 
189
- const is = Object.is
190
-
191
181
  class OwnerID {}
192
182
 
193
183
  /**
@@ -481,7 +471,7 @@ class ArrayMapNode<K, V> {
481
471
  get(_shift: unknown, _keyHash: unknown, key: K, notSetValue?: V) {
482
472
  const entries = this.entries
483
473
  for (let ii = 0, len = entries.length; ii < len; ii++) {
484
- if (is(key, entries[ii][0])) {
474
+ if (Object.is(key, entries[ii][0])) {
485
475
  return entries[ii][1]
486
476
  }
487
477
  }
@@ -503,7 +493,7 @@ class ArrayMapNode<K, V> {
503
493
  let idx = 0
504
494
  const len = entries.length
505
495
  for (; idx < len; idx++) {
506
- if (is(key, entries[idx][0])) {
496
+ if (Object.is(key, entries[idx][0])) {
507
497
  break
508
498
  }
509
499
  }
@@ -514,8 +504,7 @@ class ArrayMapNode<K, V> {
514
504
  }
515
505
 
516
506
  SetRef(didAlter)
517
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
518
- ;(removed || !exists) && SetRef(didChangeSize)
507
+ if (removed || !exists) SetRef(didChangeSize)
519
508
 
520
509
  if (removed && entries.length === 1) {
521
510
  return // undefined
@@ -530,8 +519,11 @@ class ArrayMapNode<K, V> {
530
519
 
531
520
  if (exists) {
532
521
  if (removed) {
533
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
534
- idx === len - 1 ? newEntries.pop() : (newEntries[idx] = newEntries.pop()!)
522
+ if (idx === len - 1) {
523
+ newEntries.pop()
524
+ } else {
525
+ newEntries[idx] = newEntries.pop()!
526
+ }
535
527
  } else {
536
528
  newEntries[idx] = [key, value]
537
529
  }
@@ -719,7 +711,7 @@ class HashCollisionNode<K, V> {
719
711
  get(shift: number, keyHash: number, key: K, notSetValue?: V) {
720
712
  const entries = this.entries
721
713
  for (let ii = 0, len = entries.length; ii < len; ii++) {
722
- if (is(key, entries[ii][0])) {
714
+ if (Object.is(key, entries[ii][0])) {
723
715
  return entries[ii][1]
724
716
  }
725
717
  }
@@ -754,7 +746,7 @@ class HashCollisionNode<K, V> {
754
746
  let idx = 0
755
747
  const len = entries.length
756
748
  for (; idx < len; idx++) {
757
- if (is(key, entries[idx][0])) {
749
+ if (Object.is(key, entries[idx][0])) {
758
750
  break
759
751
  }
760
752
  }
@@ -765,8 +757,7 @@ class HashCollisionNode<K, V> {
765
757
  }
766
758
 
767
759
  SetRef(didAlter)
768
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
769
- ;(removed || !exists) && SetRef(didChangeSize)
760
+ if (removed || !exists) SetRef(didChangeSize)
770
761
 
771
762
  if (removed && len === 2) {
772
763
  return new ValueNode(ownerID, this.keyHash, entries[idx ^ 1])
@@ -777,8 +768,11 @@ class HashCollisionNode<K, V> {
777
768
 
778
769
  if (exists) {
779
770
  if (removed) {
780
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
781
- idx === len - 1 ? newEntries.pop() : (newEntries[idx] = newEntries.pop()!)
771
+ if (idx === len - 1) {
772
+ newEntries.pop()
773
+ } else {
774
+ newEntries[idx] = newEntries.pop()!
775
+ }
782
776
  } else {
783
777
  newEntries[idx] = [key, value]
784
778
  }
@@ -803,7 +797,7 @@ class ValueNode<K, V> {
803
797
  ) {}
804
798
 
805
799
  get(shift: number, keyHash: number, key: K, notSetValue?: V) {
806
- return is(key, this.entry[0]) ? this.entry[1] : notSetValue
800
+ return Object.is(key, this.entry[0]) ? this.entry[1] : notSetValue
807
801
  }
808
802
 
809
803
  update(
@@ -816,7 +810,7 @@ class ValueNode<K, V> {
816
810
  didAlter?: Ref
817
811
  ) {
818
812
  const removed = value === NOT_SET
819
- const keyMatch = is(key, this.entry[0])
813
+ const keyMatch = Object.is(key, this.entry[0])
820
814
  if (keyMatch ? value === this.entry[1] : removed) {
821
815
  return this
822
816
  }
@@ -927,13 +921,11 @@ function iteratorValue<K, V>(
927
921
  iteratorResult?: IteratorResult<any>
928
922
  ) {
929
923
  const value = type === ITERATE_KEYS ? k : type === ITERATE_VALUES ? v : [k, v]
930
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
931
- iteratorResult
932
- ? (iteratorResult.value = value)
933
- : (iteratorResult = {
934
- value: value,
935
- done: false,
936
- })
924
+ if (iteratorResult) {
925
+ iteratorResult.value = value
926
+ } else {
927
+ iteratorResult = { value, done: false }
928
+ }
937
929
  return iteratorResult
938
930
  }
939
931
 
@@ -592,15 +592,22 @@ export class StoreSchema<R extends UnknownRecord, P = unknown> {
592
592
 
593
593
  for (const migration of migrationsToApply) {
594
594
  if (migration.scope === 'record') {
595
+ // Collect updates during iteration, then apply them after.
596
+ // This avoids issues with live iterators (e.g., SQLite) where updating
597
+ // records during iteration can cause them to be visited multiple times.
598
+ const updates: [string, R][] = []
595
599
  for (const [id, state] of storage.entries()) {
596
600
  const shouldApply = migration.filter ? migration.filter(state) : true
597
601
  if (!shouldApply) continue
598
602
  const record = structuredClone(state)
599
603
  const result = migration.up!(record as any) ?? record
600
604
  if (!isEqual(result, state)) {
601
- storage.set(id, result as R)
605
+ updates.push([id, result as R])
602
606
  }
603
607
  }
608
+ for (const [id, record] of updates) {
609
+ storage.set(id, record)
610
+ }
604
611
  } else if (migration.scope === 'store') {
605
612
  // legacy
606
613
  const prevStore = Object.fromEntries(storage.entries())