@ -81,7 +81,19 @@ export function process_children(nodes, { visit, state }) {
flush ( ) ;
const expression = /** @type {Expression} */ ( visit ( node . expression ) ) ;
state . template . push ( create _push ( b . call ( '$.escape' , expression ) , node . metadata . expression ) ) ;
let call = b . call (
'$$renderer.push' ,
b . thunk ( b . call ( '$.escape' , expression ) , node . metadata . expression . has _await )
) ;
const blockers = node . metadata . expression . blockers ( ) ;
if ( blockers . elements . length > 0 ) {
call = b . call ( '$$renderer.async' , blockers , b . arrow ( [ b . id ( '$$renderer' ) ] , call ) ) ;
}
state . template . push ( b . stmt ( call ) ) ;
} else if ( node . type === 'Text' || node . type === 'Comment' || node . type === 'ExpressionTag' ) {
sequence . push ( node ) ;
} else {
@ -262,72 +274,20 @@ export function build_getter(node, state) {
}
/ * *
* Creates a ` $ $ renderer.child(...) ` expression statement
* @ param { BlockStatement | Expression } body
* @ returns { Statement }
* /
export function create _child _block ( body ) {
return b . stmt ( b . call ( '$$renderer.child' , b . arrow ( [ b . id ( '$$renderer' ) ] , body , true ) ) ) ;
}
/ * *
* Creates a ` $ $ renderer.async(...) ` expression statement
* @ param { BlockStatement | Expression } body
* @ param { Statement [ ] } statements
* @ param { ArrayExpression } blockers
* @ param { boolean } has _await
* @ param { boolean } needs _hydration _markers
* /
export function create _async _block (
body ,
blockers = b . array ( [ ] ) ,
has _await = true ,
needs _hydration _markers = true
) {
return b . stmt (
b . call (
needs _hydration _markers ? '$$renderer.async_block' : '$$renderer.async' ,
blockers ,
b . arrow ( [ b . id ( '$$renderer' ) ] , body , has _await )
)
) ;
}
/ * *
* @ param { Expression } expression
* @ param { ExpressionMetadata } metadata
* @ param { boolean } needs _hydration _markers
* @ returns { Expression | Statement }
* /
export function create _push ( expression , metadata , needs _hydration _markers = false ) {
if ( metadata . is _async ( ) ) {
let statement = b . stmt ( b . call ( '$$renderer.push' , b . thunk ( expression , metadata . has _await ) ) ) ;
const blockers = metadata . blockers ( ) ;
if ( blockers . elements . length > 0 ) {
statement = create _async _block (
b . block ( [ statement ] ) ,
blockers ,
false ,
needs _hydration _markers
) ;
}
return statement ;
export function create _child _block ( statements , blockers , has _await ) {
if ( blockers . elements . length === 0 && ! has _await ) {
return statements ;
}
return expression ;
}
const fn = b . arrow ( [ b . id ( '$$renderer' ) ] , b . block ( statements ) , has _await ) ;
/ * *
* @ param { BlockStatement | Expression } body
* @ param { Identifier | false } component _fn _id
* @ returns { Statement }
* /
export function call _component _renderer ( body , component _fn _id ) {
return b . stmt (
b . call ( '$$renderer.component' , b . arrow ( [ b . id ( '$$renderer' ) ] , body , false ) , component _fn _id )
) ;
return blockers . elements . length > 0
? [ b . stmt ( b . call ( '$$renderer.async_block' , blockers , fn ) ) ]
: [ b . stmt ( b . call ( '$$renderer.child_block' , fn ) ) ] ;
}
/ * *
@ -373,7 +333,7 @@ export class PromiseOptimiser {
}
}
apply ( ) {
# apply ( ) {
if ( this . expressions . length === 0 ) {
return b . empty ;
}
@ -403,4 +363,38 @@ export class PromiseOptimiser {
is _async ( ) {
return this . expressions . length > 0 || this . # blockers . size > 0 ;
}
/ * *
* @ param { Statement [ ] } statements
* @ returns { Statement [ ] }
* /
render ( statements ) {
if ( ! this . is _async ( ) ) {
return statements ;
}
const fn = b . arrow (
[ b . id ( '$$renderer' ) ] ,
b . block ( [ this . # apply ( ) , ... statements ] ) ,
this . has _await
) ;
const blockers = this . blockers ( ) ;
return blockers . elements . length > 0
? [ b . stmt ( b . call ( '$$renderer.async' , blockers , fn ) ) ]
: [ b . stmt ( b . call ( '$$renderer.child' , fn ) ) ] ;
}
/ * *
* @ param { Statement [ ] } statements
* @ returns { Statement [ ] }
* /
render _block ( statements ) {
if ( ! this . is _async ( ) ) {
return statements ;
}
return create _child _block ( [ this . # apply ( ) , ... statements ] , this . blockers ( ) , this . has _await ) ;
}
}