From 266c7a95004beecc0a88b2822064ce5aee58c571 Mon Sep 17 00:00:00 2001 From: Dinh Le Date: Mon, 3 Aug 2026 09:37:52 +0700 Subject: [PATCH] fix(shared): stop Queue.pull treating undefined as the empty sentinel pull() shifted first and tested the result against undefined, so a legitimately buffered undefined value was consumed, discarded, and the pull parked despite later buffered items. Check items.length before shifting instead, matching push(), which already hands undefined to a waiting resolver. --- packages/shared/src/queue.test.ts | 10 ++++++++++ packages/shared/src/queue.ts | 6 ++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/shared/src/queue.test.ts b/packages/shared/src/queue.test.ts index 05f9b8d..1a5f550 100644 --- a/packages/shared/src/queue.test.ts +++ b/packages/shared/src/queue.test.ts @@ -12,6 +12,16 @@ describe('queue', () => { expect(await queue.pull()).toBe('b') }) + it('returns buffered undefined items in order', async () => { + const queue = new Queue() + + queue.push(undefined) + queue.push('a') + + expect(await queue.pull()).toBeUndefined() + expect(await queue.pull()).toBe('a') + }) + it('resolves a pending pull on push', async () => { const queue = new Queue() diff --git a/packages/shared/src/queue.ts b/packages/shared/src/queue.ts index c152dbf..b4db816 100644 --- a/packages/shared/src/queue.ts +++ b/packages/shared/src/queue.ts @@ -30,10 +30,8 @@ export class Queue { * @throws when the queue is closed or aborted. Note that buffered items can still be pulled after close until the buffer is drained. */ async pull(): Promise { - const item = this.items.shift() - - if (item !== undefined) { - return item + if (this.items.length > 0) { + return this.items.shift() as T } if (this.closed) {