@@ -240,6 +240,7 @@ export class UrbitSSEClient {
240240 const decoder = new TextDecoder ( ) ;
241241 let buffer = "" ;
242242 let bufferBytes = 0 ;
243+ let pendingDelimiterNewline = false ;
243244
244245 const appendPending = ( text : string ) => {
245246 const previousCodeUnit = buffer . charCodeAt ( buffer . length - 1 ) ;
@@ -261,19 +262,25 @@ export class UrbitSSEClient {
261262 } ;
262263 const consumeText = ( text : string ) => {
263264 let offset = 0 ;
264- while ( offset < text . length ) {
265- // The blank-line delimiter can straddle chunks. Drain it before
266- // counting later events against the retained pending-event budget.
267- if ( buffer . endsWith ( "\n" ) && text [ offset ] === "\n" ) {
268- this . processEvent ( buffer . slice ( 0 , - 1 ) ) ;
265+ if ( pendingDelimiterNewline && text . length > 0 ) {
266+ pendingDelimiterNewline = false ;
267+ if ( text . startsWith ( "\n" ) ) {
268+ this . processEvent ( buffer ) ;
269269 buffer = "" ;
270270 bufferBytes = 0 ;
271- offset += 1 ;
272- continue ;
271+ offset = 1 ;
272+ } else {
273+ // A trailing newline stays outside the budget until the next byte
274+ // distinguishes an event delimiter from retained event data.
275+ appendPending ( "\n" ) ;
273276 }
277+ }
278+ while ( offset < text . length ) {
274279 const eventEnd = text . indexOf ( "\n\n" , offset ) ;
275280 if ( eventEnd === - 1 ) {
276- appendPending ( text . slice ( offset ) ) ;
281+ const endsWithNewline = text . endsWith ( "\n" ) ;
282+ appendPending ( text . slice ( offset , endsWithNewline ? - 1 : undefined ) ) ;
283+ pendingDelimiterNewline = endsWithNewline ;
277284 return ;
278285 }
279286 appendPending ( text . slice ( offset , eventEnd ) ) ;
0 commit comments