Skip to content

Commit

Permalink
even more iteration protection
Browse files Browse the repository at this point in the history
There's really no way around checking if the iteration index is valid.
This makes me a little bit sad, because testing for index validity is
slow af. But I suppose cache.entries() and friends are not really likely
to be used in performance-critical paths as much as set() and get().

Re: #212
  • Loading branch information
isaacs committed Mar 14, 2022
1 parent 6406220 commit dd5b06a
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 4 deletions.
12 changes: 8 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -244,12 +244,14 @@ class LRUCache {
*indexes ({ allowStale = this.allowStale } = {}) {
if (this.size) {
for (let i = this.tail, j; true; ) {
if (!this.isValidIndex(i)) {
break
}
j = i === this.head
if (allowStale || !this.isStale(i)) {
yield i
}
// either head now, or WAS head and head was deleted
if (i === this.head || j && !this.isValidIndex(i)) {
if (i === this.head) {
break
} else {
i = this.prev[i]
Expand All @@ -261,12 +263,14 @@ class LRUCache {
*rindexes ({ allowStale = this.allowStale } = {}) {
if (this.size) {
for (let i = this.head, j; true; ) {
j = i === this.tail
if (!this.isValidIndex(i)) {
break
}
if (allowStale || !this.isStale(i)) {
yield i
}
// either the tail now, or WAS the tail, and deleted
if (i === this.tail || j && !this.isValidIndex(i)) {
if (i === this.tail) {
break
} else {
i = this.next[i]
Expand Down
32 changes: 32 additions & 0 deletions test/delete-while-iterating.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,35 @@ t.test('rdelete odds', t => {
t.same([...c.keys()], [4, 2, 0])
t.end()
})

t.test('delete two of them', t => {
const c = t.context
t.same([...c.keys()], [4, 3, 2, 1, 0])
for (const k of c.keys()) {
if (k === 3) {
c.delete(3)
c.delete(4)
} else if (k === 1) {
c.delete(1)
c.delete(0)
}
}
t.same([...c.keys()], [2])
t.end()
})

t.test('rdelete two of them', t => {
const c = t.context
t.same([...c.keys()], [4, 3, 2, 1, 0])
for (const k of c.rkeys()) {
if (k === 3) {
c.delete(3)
c.delete(4)
} else if (k === 1) {
c.delete(1)
c.delete(0)
}
}
t.same([...c.keys()], [2])
t.end()
})

0 comments on commit dd5b06a

Please # to comment.