@@ -149,7 +149,7 @@ function testShareSyncRejectsUnbounded() {
149149function testShareSyncDropNewest ( ) {
150150 let pulls = 0 ;
151151 function * source ( ) {
152- for ( let i = 0 ; i < 3 ; i ++ ) {
152+ for ( let i = 0 ; i < 4 ; i ++ ) {
153153 pulls ++ ;
154154 const chunk = new Uint8Array ( 16384 ) ;
155155 chunk [ 0 ] = i ;
@@ -165,11 +165,50 @@ function testShareSyncDropNewest() {
165165 const slow = shared . pull ( ) [ Symbol . iterator ] ( ) ;
166166
167167 assert . strictEqual ( fast . next ( ) . value [ 0 ] [ 0 ] , 0 ) ;
168+
169+ // The budget is exhausted and the slow consumer cannot advance while this
170+ // call is running, so exactly one entry is dropped and no value is
171+ // available. The consumer is not detached.
168172 assert . strictEqual ( fast . next ( ) . done , true ) ;
169- assert . strictEqual ( pulls , 3 ) ;
173+ assert . strictEqual ( pulls , 2 ) ;
170174
175+ // The slow consumer still sees the buffered entry, which releases budget.
171176 assert . strictEqual ( slow . next ( ) . value [ 0 ] [ 0 ] , 0 ) ;
172- assert . strictEqual ( slow . next ( ) . done , true ) ;
177+
178+ // Entry 1 was dropped for every consumer, so both resume at entry 2.
179+ assert . strictEqual ( slow . next ( ) . value [ 0 ] [ 0 ] , 2 ) ;
180+ assert . strictEqual ( pulls , 3 ) ;
181+ assert . strictEqual ( fast . next ( ) . value [ 0 ] [ 0 ] , 2 ) ;
182+ }
183+
184+ // Regression test: a full buffer must not spin pulling-and-discarding from an
185+ // unbounded source, since discarding never reclaims budget.
186+ function testShareSyncDropNewestUnboundedSource ( ) {
187+ let pulls = 0 ;
188+ function * source ( ) {
189+ for ( ; ; ) {
190+ pulls ++ ;
191+ yield [ new Uint8Array ( 16384 ) ] ;
192+ }
193+ }
194+
195+ const shared = shareSync ( source ( ) , {
196+ budget : 16384 ,
197+ backpressure : 'drop-newest' ,
198+ } ) ;
199+ const fast = shared . pull ( ) [ Symbol . iterator ] ( ) ;
200+ shared . pull ( ) ;
201+
202+ assert . strictEqual ( fast . next ( ) . done , false ) ;
203+ assert . strictEqual ( pulls , 1 ) ;
204+
205+ // Each blocked call drops at most one entry and returns without a value.
206+ for ( let i = 0 ; i < 3 ; i ++ ) {
207+ assert . strictEqual ( fast . next ( ) . done , true ) ;
208+ assert . strictEqual ( pulls , 2 + i ) ;
209+ }
210+
211+ shared . cancel ( ) ;
173212}
174213
175214// shareSync() accepts string source directly (normalized via fromSync())
@@ -189,5 +228,6 @@ Promise.all([
189228 testShareSyncSourceError ( ) ,
190229 testShareSyncRejectsUnbounded ( ) ,
191230 testShareSyncDropNewest ( ) ,
231+ testShareSyncDropNewestUnboundedSource ( ) ,
192232 testShareSyncStringSource ( ) ,
193233] ) . then ( common . mustCall ( ) ) ;
0 commit comments