@@ -13,6 +13,7 @@ import {
1313} from '../../../dist/runtime/server/render/util.js' ;
1414import {
1515 createComponent ,
16+ Fragment ,
1617 render as renderTemplate ,
1718 renderComponent ,
1819 renderSlot ,
@@ -320,6 +321,59 @@ describe('Allows using the Fragment element', async () => {
320321 const $ = cheerio . load ( await response . text ( ) ) ;
321322 assert . equal ( $ ( '#one' ) . length , 1 ) ;
322323 } ) ;
324+
325+ it ( 'streams sync siblings before async children resolve (issue #13283)' , async ( ) => {
326+ // A deferred promise simulates a slow async child inside the Fragment.
327+ let resolveAsync ;
328+ const asyncChild = new Promise ( ( resolve ) => {
329+ resolveAsync = resolve ;
330+ } ) ;
331+
332+ const DEFAULT_RESULT = { clientDirectives : new Map ( ) } ;
333+
334+ // Build a Fragment whose default slot contains a sync <p> followed by an async <p>.
335+ const renderInstance = renderComponent (
336+ DEFAULT_RESULT ,
337+ 'Fragment' ,
338+ Fragment ,
339+ { } ,
340+ {
341+ default : ( _result ) =>
342+ renderTemplate `<p id="sync">sync</p>${ asyncChild . then (
343+ ( ) => renderTemplate `<p id="async">async</p>` ,
344+ ) } `,
345+ } ,
346+ ) ;
347+
348+ // Collect chunks as they are written so we can inspect ordering.
349+ const chunks = [ ] ;
350+ const destination = {
351+ write ( chunk ) {
352+ chunks . push ( String ( chunk ) ) ;
353+ } ,
354+ } ;
355+
356+ // Start rendering — do NOT await yet so we can inspect mid-flight state.
357+ const instance = await Promise . resolve ( renderInstance ) ;
358+ const renderPromise = instance . render ( destination ) ;
359+
360+ // Yield to the microtask queue so the sync portion can flush.
361+ await Promise . resolve ( ) ;
362+
363+ // The sync <p> must have been written before the async promise resolved.
364+ const syncFlushed = chunks . join ( '' ) . includes ( 'sync' ) ;
365+ assert . ok ( syncFlushed , 'sync sibling should stream before async child resolves' ) ;
366+
367+ // Now resolve the async child and finish rendering.
368+ resolveAsync ( ) ;
369+ await renderPromise ;
370+
371+ const html = chunks . join ( '' ) ;
372+ assert . ok ( html . includes ( 'sync' ) , 'sync content present in final output' ) ;
373+ assert . ok ( html . includes ( 'async' ) , 'async content present in final output' ) ;
374+ // Sync must appear before async in the output.
375+ assert . ok ( html . indexOf ( 'sync' ) < html . indexOf ( 'async' ) , 'sync appears before async in output' ) ;
376+ } ) ;
323377} ) ;
324378
325379describe ( 'renders the components top-down' , async ( ) => {
0 commit comments