Scripts, style, runes
A .svelte file is allowed to carry more than markup, and each extra block has a cell. Mixing those cells up — putting vibe.0 in the instance script, putting D in context="module", treating $effect as a reactive runtime — is how a file that “looks like Svelte” fails in ways the official language server cannot explain. The official language server is not running this compile.
<script lang="d">
This is the component. The body is libdparse-checked and printed onto the struct that owns the markup. The printed module is nothrow: @safe:. Author import std.algorithm (and the rest of spa-phobos) is lifted above nothrow, to module scope. It is not left inside the struct, where it would be a nested import in a nothrow context. std.file, std.stdio, and std.socket are not on this cell.
--foptimize-nothrow is the LDC 1.43 default on wasm, and it deletes landing pads inside nothrow functions. The engine therefore passes --foptimize-nothrow=false. Even then, keep throwing APIs such as std.conv.to inside try/catch. The struct remains nothrow; an uncaught throw is an abort, not a boundary.
See script lang=“d” for the author-facing contract, libwasm for the runtime that contract names, and lifetime for construct / onMount / ready.
<script lang="ts"> and context="module"
These are spliced into src-ts/modules/generated/ and folded into libwasm.init. Exported functions are also registered on window.__svelteD.ts[<module>] so lang=d can call them by the simple name. See cross-calling and lang=ts splice. Other lang values are ignored.
<style>
The CSS block is stripped from the D. It is not ignored. Classes become addCss plus @style!".box" on the matching NodeDef. :global(.wide) still yields .wide — the :global wrapper is an official-compiler concern this printer does not reimplement, but the class name must survive or DaisyUI / Tailwind utilities in the engine would vanish. Static class="a b" on an element is tokenized @style on that element’s NodeDef, not on the first @child. Getting that wrong was G88: a button’s classes landed on a span.
<svelte:options>
Printed as a comment on the host: // svelte:options name=value. There is no second compile!. Options that would change the official compiler’s output (immutable, accessors, custom elements as a runtime) are not a second IR. Fixture: ComboRest.svelte.
Runes
Svelte 5 runes are recognized so a file that uses them does not die at scan. They are not a reactive runtime. $state(x) and $derived(expr) peel to the inner expression; the field is a normal D field. $effect(() => { … }) becomes an onMount body. $props() is stripped; the parent assigns @child fields in construct. There is no $effect graph, no fine-grained invalidation, and no signal. If you need updates, you write this.update. Treating runes as if the official runtime were present is how a page “works in VS Code” and does nothing in wasm.