docs / Language
Statement Mode
Markup and control flow directly as statements: bare JSX, if/for/while/switch/try, guard-clause returns, and for-key/index clauses.
Statement mode is a first-class component body style: markup and control flow appear directly as statements, no `return` wrapper required. Every feature that works in expression mode also works in statement mode, and vice versa.
app/components/List.vsk
component List(props: { items: string[] }) {
let &[filter] = track("");
if (filter !== "") {
<p>Filtered by: {filter}</p>
}
for (const item of props.items; key item) {
<div>{item}</div>
} empty {
<p>No items.</p>
}
}
Statements the compiler understands
| Statement | IR handling |
|---|---|
| Bare JSX element / fragment | rendered, tracked |
| {expr} expression container | rendered; .map() calls become a MapRegion |
| if / else | conditional region |
| for...of, for...in, classic for | loop region |
| while / do...while | loop region |
| switch | switch region |
| try / catch | try region (fallback content on error) |
| return <jsx> | guard-clause early return — renders and stops |
| {#server} / {#client} blocks | client-boundary regions |
| let &[x] = track(0) | TrackDecl |
| Anything else | preserved verbatim as a runtime statement |
`class Foo {}` inside a component body raises a compiler error — components are markup/state units, not class containers.
for key / index clauses
app/components/Table.vsk
component Table(props: { rows: Row[] }) {
for (const row of props.rows; key row.id; index i) {
<Row data={row} index={i} />
} empty {
<p>No rows.</p>
}
}
- `; key <expr>` sets the reconciliation key expression.
- `; index <ident>` binds the loop index to an identifier.
- Clauses are optional and combinable; only for...of/for...in headers may carry them (classic `for` keeps its normal semicolons).
- The compiler blanks the clause text before parsing and recovers it from annotations, preserving source offsets.
Guard-clause early returns
app/components/List.vsk
component List(props: { items: string[] }) {
let &[filter] = track("");
if (filter !== "") {
<p>Filtered by: {filter}</p>
}
for (const item of props.items; key item) {
<div>{item}</div>
} empty {
<p>No items.</p>
}
}