@@ -107,7 +107,7 @@ export class FunctionsService implements _FirebaseService {
107
107
messagingProvider : Provider < MessagingInternalComponentName > ,
108
108
appCheckProvider : Provider < AppCheckInternalComponentName > ,
109
109
regionOrCustomDomain : string = DEFAULT_REGION ,
110
- readonly fetchImpl : typeof fetch = fetch ,
110
+ readonly fetchImpl : typeof fetch = ( ... args ) => fetch ( ... args ) ,
111
111
) {
112
112
this . contextProvider = new ContextProvider (
113
113
authProvider ,
@@ -450,6 +450,7 @@ async function streamAtURL(
450
450
const reader = response . body ! . getReader ( ) ;
451
451
const decoder = new TextDecoder ( ) ;
452
452
453
+ let pendingLines : string [ ] = [ ] ;
453
454
let buffer = '' ;
454
455
let resultResolver : ( value : unknown ) => void ;
455
456
let resultRejecter : ( reason : any ) => void ;
@@ -470,6 +471,30 @@ async function streamAtURL(
470
471
471
472
const stream = {
472
473
[ 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
+ } ;
473
498
return {
474
499
async next ( ) {
475
500
if ( options ?. signal ?. aborted ) {
@@ -481,29 +506,30 @@ async function streamAtURL(
481
506
throw error ;
482
507
}
483
508
509
+ while ( pendingLines . length > 0 ) {
510
+ const result = processLine ( pendingLines . shift ( ) ) ;
511
+ if ( result ) return result ;
512
+ }
513
+
484
514
while ( true ) {
485
515
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
+ }
487
524
488
525
buffer += decoder . decode ( value , { stream : true } ) ;
489
526
const lines = buffer . split ( '\n' ) ;
490
527
buffer = lines . pop ( ) || '' ;
528
+ pendingLines . push ( ...lines . filter ( line => line . trim ( ) ) ) ;
491
529
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 ;
507
533
}
508
534
}
509
535
}
0 commit comments