@ -95,14 +95,6 @@ export class Payload {
}
}
/ * *
* @ param { ( value : { head : string , body : string } ) => void } onfulfilled
* /
async then ( onfulfilled ) {
const content = await Payload . # collect _content ( [ this ] , this . type ) ;
return onfulfilled ( content ) ;
}
/ * *
* @ param { string | ( ( ) => Promise < string > ) } content
* /
@ -126,25 +118,11 @@ export class Payload {
compact ( { start , end = this . # out . length , fn } ) {
const child = new Payload ( this . global , this . local , this ) ;
const to _compact = this . # out . splice ( start , end - start , child ) ;
const content = Payload . # collect _content ( to _compact , this . type ) ;
if ( content instanceof Promise ) {
const followup = content
. then ( ( content ) => fn ( content ) )
. then ( ( transformed _content ) =>
Payload . # push _accumulated _content ( child , transformed _content )
) ;
this . promises . followup . push ( followup ) ;
} else {
const transformed _content = fn ( content ) ;
if ( transformed _content instanceof Promise ) {
const followup = transformed _content . then ( ( content ) =>
Payload . # push _accumulated _content ( child , content )
) ;
this . promises . followup . push ( followup ) ;
if ( this . global . mode === 'sync' ) {
Payload . # compact ( fn , child , to _compact , this . type ) ;
} else {
Payload . # push _accumulated _content ( child , transformed _content ) ;
}
this . promises . followup . push ( Payload . # compact _async ( fn , child , to _compact , this . type ) ) ;
}
}
@ -161,16 +139,15 @@ export class Payload {
* @ returns { AccumulatedContent }
* /
collect ( ) {
const content = Payload . # collect _content ( this . # out , this . type ) ;
if ( content instanceof Promise ) {
// TODO improve message
// guess you could also end up here if you called `collect` in an async context but... just don't bro
throw new Error (
'invariant: should never reach this, as child throws when it encounters async work in a synchronous context'
) ;
return Payload . # collect _content ( [ this ] , this . type ) ;
}
return content ;
/ * *
* Collect all of the code from the ` out ` array and return it as a string .
* @ returns { Promise < AccumulatedContent > }
* /
collect _async ( ) {
return Payload . # collect _content _async ( [ this ] , this . type ) ;
}
copy ( ) {
@ -205,63 +182,52 @@ export class Payload {
return this . # out . length ;
}
/ * *
* @ param { ( content : AccumulatedContent ) => AccumulatedContent | Promise < AccumulatedContent > } fn
* @ param { Payload } child
* @ param { PayloadItem [ ] } to _compact
* @ param { PayloadType } type
* /
static # compact ( fn , child , to _compact , type ) {
const content = Payload . # collect _content ( to _compact , type ) ;
const transformed _content = fn ( content ) ;
if ( transformed _content instanceof Promise ) {
throw new Error ( 'invariant: should never reach this' ) ;
} else {
Payload . # push _accumulated _content ( child , transformed _content ) ;
}
}
/ * *
* @ param { ( content : AccumulatedContent ) => AccumulatedContent | Promise < AccumulatedContent > } fn
* @ param { Payload } child
* @ param { PayloadItem [ ] } to _compact
* @ param { PayloadType } type
* /
static async # compact _async ( fn , child , to _compact , type ) {
const content = await Payload . # collect _content _async ( to _compact , type ) ;
const transformed _content = await fn ( content ) ;
Payload . # push _accumulated _content ( child , transformed _content ) ;
}
/ * *
* Collect all of the code from the ` out ` array and return it as a string , or a promise resolving to a string .
* @ param { PayloadItem [ ] } items
* @ param { PayloadType } current _type
* @ param { AccumulatedContent } content
* @ returns { MaybePromise < AccumulatedContent > }
* @ returns { AccumulatedContent}
* /
static # collect _content ( items , current _type , content = { head : '' , body : '' } ) {
/** @type {MaybePromise<AccumulatedContent>[]} */
const segments = [ ] ;
let has _async = false ;
const flush = ( ) => {
if ( content . head || content . body ) {
segments . push ( content ) ;
content = { head : '' , body : '' } ;
}
} ;
for ( const item of items ) {
if ( typeof item === 'string' ) {
content [ current _type ] += item ;
} else if ( item instanceof Payload ) {
Payload . # collect _content ( item . # out , item . type , content ) ;
} else {
flush ( ) ;
if ( item instanceof Promise ) {
has _async = true ;
segments . push (
item . then ( ( resolved ) => {
const content = { head : '' , body : '' } ;
content [ current _type ] = resolved ;
return content ;
} )
) ;
} else if ( item . promises . initial || item . promises . followup . length ) {
has _async = true ;
segments . push ( Payload . # collect _content _async ( [ item ] , current _type ) ) ;
} else {
const sub = Payload . # collect _content ( item . # out , item . type ) ;
if ( sub instanceof Promise ) {
has _async = true ;
throw new Error ( 'invariant: should never reach this' ) ;
}
segments . push ( sub ) ;
}
}
}
flush ( ) ;
if ( has _async ) {
return Promise . all ( segments ) . then ( ( content _array ) =>
Payload . # squash _accumulated _content ( content _array )
) ;
}
// No async segments — combine synchronously
return Payload . # squash _accumulated _content ( /** @type {AccumulatedContent[]} */ ( segments ) ) ;
return content ;
}
/ * *
@ -304,21 +270,6 @@ export class Payload {
tree . # out . push ( child ) ;
}
}
/ * *
* @ param { AccumulatedContent [ ] } content _array
* @ returns { AccumulatedContent }
* /
static # squash _accumulated _content ( content _array ) {
return content _array . reduce (
( acc , content ) => {
acc . head += content . head ;
acc . body += content . body ;
return acc ;
} ,
{ head : '' , body : '' }
) ;
}
}
export class TreeState {