Svelte → D IR{#each} UnorderedList

{#each}UnorderedList

A Svelte {#each} looks like a loop over markup. In libwasm it is a typed list in the struct graph: UnorderedList!T, which is an HTMLArray!T plus ArrayItemEvents plus assignEventListeners. put appends an item. shrinkTo(0) clears. The item type T is a struct named from the alias (user → something you can still read as the user row). {user} on the item is @prop on that item, not a concatenate on the ul. Index (i) is an int i field on the item — not @prop!"dataset", because dataset is a getter-only DOMStringMap and libwasm will skip the assign. Key (x) is @attr!"data-key".

<ul>{#each} absorbs the wrapper. UnorderedList is already NodeDef!"ul". A printer that emitted an outer ul and an inner ul would nest two lists and would have nowhere honest to hang . {#each} inside a non-ul hangs on that parent as a child. Destructure {#each rows as {name}} and {#each pairs as [x, y]} become item fields. Undeclared lists still demo-seed (one/two) so a Combo file without a string[] still paints.

is @visible!"empty_*" bool list_empty. A host string[] xs; or = [] skips put and inits xs_empty = true (LangCoverage voidsNone). xs = [] in a handler is shrinkTo(0) plus setVisible (G89 Wipe). <ul>{#each} prints ExtrasList — an HTMLArray plus the else @child plus NodeDef!"ul" — so Empty hangs inside the ul (G90). Bare {#each} is UnorderedList plus a sibling else. Those two dests look similar in Svelte and are different graphs; the fixture pair exists so the printer cannot “simplify” them into one.

{#each} plus {#if} on the item

This is the construct that took G94 through G118, and it is the construct an admin list will hit the moment you write {#each users as user}{#if user.ok}. The ul stays. Each li unmounts. {#each}{#if cond}<li> uses sync_items_on. {#each rows as row}{#if row.ok} puts bool ok on the item, seeds the first true, and sync_rows_ok reads it.ok. App ready calls wireEach after render. Wiring before render was G95: construct ran too early, the false item still had no handle, and Flip could not unmount it.

Item-field predicates combine with a host bool. The sync helper is named after the list. Flip of the host bool must not destroy rows that the item field still wants visible. The table is the contract; the paragraphs above it are why the helper names look so specific.

Predicate on the itemSync helperWhat Flip of host on does
row.oksync_rows_okPin fill_rows sets the rest
pick.ok && onsync_picks_onhides picks; ok-rows stay
hold.ok || onsync_holds_onleaves the first hold
!skip.oksync_skips_okfirst seeded-true hidden
!cut.ok && onsync_cuts_onhides cuts
!keep.ok || onsync_keeps_onleaves the !ok keep
drop.ok && !onsync_drops_onhidden at boot; Flip shows first
!both.ok || !onsync_boths_onboot shows !ok; Flip shows both
!nand.ok && !onsync_nands_onhidden at boot; Flip shows !ok
hit.n > 0sync_hits_nint n on the item; seed 1
more.n > 0 && onsync_mores_onhides mores
lot.n > 0 || onsync_lots_onleaves first lot
few.n > 0 && !onsync_fews_onhidden at boot; Flip shows first

ComboIfCmp.svelte walks the next ten comparisons (n > 0, n > 0 || !on, n == 0, n != 0, n < 1, n <= 0, n >= 1, n >= 1 && on, on && n > 0, n > 1) as a table, including unseeded-item and rhs≠0 corners. If you are adding an eleventh mix, add it there, not as a one-off page.

List @connect!("list.items","slot") still takes size_t first. Item parent pointers are @inject!"host" set in the item constructor; compile! does not walk appenders. That is why a click on a row can call back into the page without the item storing a heap pointer you allocated in put.