diff --git a/src/queue.js b/src/queue.js index c4ef971..d0f1564 100644 --- a/src/queue.js +++ b/src/queue.js @@ -9,10 +9,10 @@ function Queue(initial = []) { return xs.length - index }, remove: (x) => { - const index = xs.indexOf(x) - return index === -1 + const i = xs.indexOf(x, index) + return i === -1 ? null - : (xs.splice(index, 1), x) + : (xs.splice(i, 1), x) }, push: (x) => (xs.push(x), x), shift: () => { @@ -21,6 +21,9 @@ function Queue(initial = []) { if (index === xs.length) { index = 0 xs = [] + } else if (index > 64 && index * 2 >= xs.length) { + xs = xs.slice(index) + index = 0 } else { xs[index - 1] = undefined } diff --git a/tests/index.js b/tests/index.js index 845c6ce..f7013c4 100644 --- a/tests/index.js +++ b/tests/index.js @@ -6,6 +6,7 @@ import fs from 'fs' import crypto from 'crypto' import postgres from '../src/index.js' +import Queue from '../src/queue.js' const delay = ms => new Promise(r => setTimeout(r, ms)) const rel = x => new URL(x, import.meta.url) @@ -2719,3 +2720,26 @@ t('query during copy error', async() => { await sql`drop table test` ] }) + +t('Queue does not grow when never drained', async() => { + let size = 0 + const q = Queue(new class extends Array { // Queue copies this with .slice(), which keeps the subclass + push(x) { + const length = super.push(x) + size = Math.max(size, length) + return length + } + }()) + + q.push('a') + q.push('b') + q.push('c') + for (let i = 0; i < 10000; i++) + q.push(q.shift()) + + const result = [q.length, q.remove('x'), q.shift(), q.remove('a'), q.length, q.shift(), q.length] + q.push('d') + q.push('e') + result.push(q.remove('d'), q.shift(), size > 0 && size < 1000 || size) + return ['3,,b,a,1,c,0,d,e,true', result.join()] +})