@@ -107,7 +107,7 @@ export class FunctionsService implements _FirebaseService {
107107 messagingProvider : Provider < MessagingInternalComponentName > ,
108108 appCheckProvider : Provider < AppCheckInternalComponentName > ,
109109 regionOrCustomDomain : string = DEFAULT_REGION ,
110- readonly fetchImpl : typeof fetch = fetch ,
110+ readonly fetchImpl : typeof fetch = ( ... args ) => fetch ( ... args ) ,
111111 ) {
112112 this . contextProvider = new ContextProvider (
113113 authProvider ,
@@ -450,6 +450,7 @@ async function streamAtURL(
450450 const reader = response . body ! . getReader ( ) ;
451451 const decoder = new TextDecoder ( ) ;
452452
453+ let pendingLines : string [ ] = [ ] ;
453454 let buffer = '' ;
454455 let resultResolver : ( value : unknown ) => void ;
455456 let resultRejecter : ( reason : any ) => void ;
@@ -470,6 +471,30 @@ async function streamAtURL(
470471
471472 const stream = {
472473 [ Symbol . asyncIterator ] ( ) {
474+
475+ const processLine = ( line : string | undefined ) => {
476+ // ignore all other lines (newline, comments, etc.)
477+ if ( ! line ?. startsWith ( 'data: ' ) ) return null ;
478+
479+ try {
480+ const jsonData = JSON . parse ( line . slice ( 6 ) ) ;
481+ if ( 'result' in jsonData ) {
482+ resultResolver ( decode ( jsonData . result ) ) ;
483+ return { done : true , value : undefined } ;
484+ }
485+ if ( 'message' in jsonData ) {
486+ return { done : false , value : decode ( jsonData . message ) } ;
487+ }
488+ if ( 'error' in jsonData ) {
489+ const error = _errorForResponse ( 0 , jsonData ) ;
490+ resultRejecter ( error ) ;
491+ throw error ;
492+ }
493+ return null ; // Unrecognize keys. Skip this line.
494+ } catch ( error ) {
495+ // Not json. Skip this line.
496+ }
497+ } ;
473498 return {
474499 async next ( ) {
475500 if ( options ?. signal ?. aborted ) {
@@ -481,29 +506,30 @@ async function streamAtURL(
481506 throw error ;
482507 }
483508
509+ while ( pendingLines . length > 0 ) {
510+ const result = processLine ( pendingLines . shift ( ) ) ;
511+ if ( result ) return result ;
512+ }
513+
484514 while ( true ) {
485515 const { value, done } = await reader . read ( ) ;
486- if ( done ) return { done : true , value : undefined } ;
516+
517+ if ( done ) {
518+ if ( buffer . trim ( ) ) {
519+ const result = processLine ( buffer ) ;
520+ if ( result ) return result ;
521+ }
522+ return { done : true , value : undefined } ;
523+ }
487524
488525 buffer += decoder . decode ( value , { stream : true } ) ;
489526 const lines = buffer . split ( '\n' ) ;
490527 buffer = lines . pop ( ) || '' ;
528+ pendingLines . push ( ...lines . filter ( line => line . trim ( ) ) ) ;
491529
492- for ( const line of lines ) {
493- if ( line . startsWith ( 'data: ' ) ) {
494- const jsonData = JSON . parse ( line . slice ( 6 ) ) ;
495- if ( 'result' in jsonData ) {
496- resultResolver ( decode ( jsonData . result ) ) ;
497- return { done : true , value : undefined } ;
498- } else if ( 'message' in jsonData ) {
499- return { done : false , value : decode ( jsonData . message ) } ;
500- } else if ( 'error' in jsonData ) {
501- const error = _errorForResponse ( 0 , jsonData ) ;
502- resultRejecter ( error )
503- throw error ;
504- }
505- }
506- // ignore all other lines (newline, comments, etc.)
530+ if ( pendingLines . length > 0 ) {
531+ const result = processLine ( pendingLines . shift ( ) ) ;
532+ if ( result ) return result ;
507533 }
508534 }
509535 }
0 commit comments