Skip to content

Commit af166ff

Browse files
committed
feat(wasi): land #485 filesystem, #487 sockio, #486 wrap-default, #56-A
Preview1 lowerings for wasi:filesystem (file_open/read/fd_write/close) and sock_recv/send/accept; componentize.sh defaults to --command without flipping the compiler's preview1 emit; stdlib Dom/Console + Pixi gap-fill. Refs #485 #486 #487 #56
1 parent c38d311 commit af166ff

39 files changed

Lines changed: 1487 additions & 59 deletions

‎affinescript-dom/src/dom.affine‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,45 @@ pub fn text(content: String) -> VNode = VText(content);
6060
pub fn h(tag: String, attrs: [(String, String)], children: [VNode]) -> VNode =
6161
VElem(tag, attrs, children);
6262

63+
/// Convenience constructors (#56-A). Thin wrappers over `h` so idaptik's
64+
/// pilot `Dom.div` / `Dom.h1` / `Dom.p` surface compiles without going
65+
/// through the low-level tag string.
66+
pub fn div(attrs: [(String, String)], children: [VNode]) -> VNode =
67+
h("div", attrs, children);
68+
69+
pub fn h1(attrs: [(String, String)], content: String) -> VNode =
70+
h("h1", attrs, [text(content)]);
71+
72+
pub fn h2(attrs: [(String, String)], content: String) -> VNode =
73+
h("h2", attrs, [text(content)]);
74+
75+
pub fn h3(attrs: [(String, String)], content: String) -> VNode =
76+
h("h3", attrs, [text(content)]);
77+
78+
pub fn p(attrs: [(String, String)], content: String) -> VNode =
79+
h("p", attrs, [text(content)]);
80+
81+
pub fn span(attrs: [(String, String)], content: String) -> VNode =
82+
h("span", attrs, [text(content)]);
83+
84+
pub fn button(attrs: [(String, String)], content: String) -> VNode =
85+
h("button", attrs, [text(content)]);
86+
87+
pub fn input(attrs: [(String, String)]) -> VNode =
88+
h("input", attrs, []);
89+
90+
pub fn a(attrs: [(String, String)], content: String) -> VNode =
91+
h("a", attrs, [text(content)]);
92+
93+
pub fn img(attrs: [(String, String)]) -> VNode =
94+
h("img", attrs, []);
95+
96+
pub fn ul(attrs: [(String, String)], children: [VNode]) -> VNode =
97+
h("ul", attrs, children);
98+
99+
pub fn li(attrs: [(String, String)], children: [VNode]) -> VNode =
100+
h("li", attrs, children);
101+
63102
// `len` is not available in the standalone wasm-AOT subset; a `for`-count
64103
// helper is (proven: tests/codegen/test_for_loop). Monomorphic, not
65104
// generic, since wasm codegen generic support is not relied on here.
@@ -103,6 +142,12 @@ pub fn mount(selector: String, vnode: VNode) -> Bool {
103142
}
104143
}
105144

145+
/// Replace `document.body` contents with `vnode` (#56-A). Equivalent
146+
/// to `mount("body", vnode)`. Declared below `mount` because codegen
147+
/// is single-pass in source order.
148+
pub fn replaceBody(vnode: VNode) -> Bool =
149+
mount("body", vnode);
150+
106151
// ── Reconciler: minimal mutation between two VNode trees ─────────────────────
107152

108153
fn attr_has(attrs: [(String, String)], key: String) -> Bool {

‎docs/CAPABILITY-MATRIX.adoc‎

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,11 @@ The compiler emits to many targets. *Maturity is not uniform; do not claim
176176
|Target |Status |Notes
177177

178178
|WASM (core) |works |Cross-module imports + `extern fn` → WASM import
179-
emission. The reference target.
179+
emission. The reference target. WASI preview1 on-demand imports cover
180+
clock/env/args/sockets/filesystem (`file_open`/`file_read`/
181+
`file_fd_write`/`file_close`, `net_recv`/`net_send`/`net_accept`);
182+
`tools/componentize.sh` defaults to the command adapter (#486). Native
183+
preview2 import lowering is still the one-way door.
180184

181185
|WASM-GC |partial |Variant-with-args + same-arity `PatCon` destructuring;
182186
silent-bad-codegen fallbacks eliminated. Mixed-arity matches need uniform
@@ -288,8 +292,11 @@ their own ledger (link:SOUNDNESS.adoc[SOUNDNESS.adoc]), gated by
288292
* The satellite ecosystem is mixed maturity — see the satellite registry
289293
in `ECOSYSTEM.adoc`. `affinescript-tea` (INT-07/#182) and
290294
`affinescript-dom` (INT-08/#183) shipped runtimes; `affinescript-cadre`
291-
(INT-09) closed 2026-07-25. `affinescript-pixijs` remains a scaffold
292-
(#56). The `-dom-loader` satellite was folded into `affine-js` (#489).
295+
(INT-09) closed 2026-07-25. `affinescript-pixijs` in-tree bindings
296+
(`stdlib/Pixi.affine` + UI/Sound) plus 56-A `stdlib/Dom.affine` /
297+
`stdlib/Console.affine` landed 2026-09-21; full idaptik surface is
298+
still open (#56). The `-dom-loader` satellite was folded into
299+
`affine-js` (#489).
293300

294301
== Change control
295302

‎docs/ECOSYSTEM.adoc‎

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,11 @@ Phase-3 (#177); the INT-01..12 integration roadmap; the satellite registry
7777
made real; #228/ADR-014 module-qualified paths (estate port unblocker). |
7878
*CLOSED 2026-07-25* |Substrate (INT-01..04 + CORE-01) closed 2026-05-31;
7979
remaining original #175 children INT-07 (#182) and INT-08 (#183) closed
80-
2026-07-25. Residual WASI slices live as independent follow-ups (#485 S5
81-
filesystem, #486 S6c default-flip, #487 sockets); satellite remainder is
82-
#56. Stage E is now the frontier.
80+
2026-07-25. Residual WASI follow-ups #485 (S5 filesystem) and #487
81+
(socket recv/send/accept) have preview1 lowerings + gated smokes in
82+
tree; #486 flipped the wrap default to `--command` without the one-way
83+
compiler re-target. Satellite remainder is #56 (56-A Dom/Console + Pixi
84+
gap-fill landed). Stage E is now the frontier.
8385

8486
|*E* |typed-wasm convergence hardening (the transition runway): the
8587
AffineScript↔typed-wasm contract widened from L7+L10 toward full
@@ -158,7 +160,10 @@ runtime is *VERIFIED end-to-end* (2026-07-07): `affinescript-dom/e2e/run.sh`
158160
drives mount + in-place attr patch + text update + surplus-child removal
159161
against a real Int-handle host DOM, mutation log asserted.
160162

161-
|`affinescript-pixijs` |skeleton |Migration-prerequisite scaffold (#56).
163+
|`affinescript-pixijs` |in-tree bindings |#56 partial: `stdlib/Pixi.affine`
164+
(+ UI/Sound) is the operational binding; 56-A also landed
165+
`stdlib/Dom.affine` + `stdlib/Console.affine`. Remaining: full idaptik
166+
surface.
162167

163168
|`affinescript-vite` |scaffold |Build-tool integration shell.
164169

@@ -192,10 +197,10 @@ object, `typedwasm.ownership` accessor.
192197
== Integration roadmap — INT-01..12
193198

194199
Critical path: *INT-01..INT-04 are substrate and block most satellites.*
195-
GitHub index #175 is closed (8/8 original sub-issues complete, owner close
196-
2026-09-21); severity/blocked-by also in
197-
link:TECH-DEBT.adoc[TECH-DEBT.adoc]. Residual WASI work is #485/#486/#487;
198-
satellite remainder is #56.
200+
GitHub index #175: 8/8 original sub-issues complete; severity/blocked-by
201+
also in link:TECH-DEBT.adoc[TECH-DEBT.adoc]. Residual WASI work is
202+
#485/#486/#487 (preview1 FS + sockio + wrap-default in tree; native
203+
preview2 re-target still the one-way door); satellite remainder is #56.
199204

200205
[cols="1,3,1,2"]
201206
|===
@@ -245,16 +250,15 @@ dropped; 81d9fc7). Test gates:
245250
`tests/componentize/{smoke,command_smoke,sockets_smoke}.sh` cover
246251
the contract end-to-end; ownership section byte-survives every
247252
wrap; combo-import canonical-order regression. Residual (filed
248-
2026-05-31): #485 — S5 native `wasi:filesystem`
249-
(open/read/write/close), unblocks INT-06 (server-side runtime
250-
profile); #486 — S6c flip default wasm target preview1 →
251-
component, bundled with native-preview2 cleanup replacing the
252-
on-demand preview1 shims emitted by S4a/S4b/S6b with direct
253-
`wasi:clocks` / `wasi:cli` / `wasi:sockets` calls (only pays off
254-
once preview2 is the default — the one-way door that ends
255-
reversibility); #487 — socket recv/send/accept primitives
256-
(byte-level buffer / network-address marshalling, helper mirrors
257-
`gen_str_at_via_get`). WIT world of record: `wit/affinescript.wit`
253+
2026-05-31, status 2026-09-21): #485 — S5 native `wasi:filesystem`
254+
preview1 lowering LANDED (`file_open`/`file_read`/`file_fd_write`/
255+
`file_close`, Effect `File`, gated
256+
`tests/componentize/filesystem_smoke.sh`); #486 — S6c wrap default
257+
flipped to `--command` (S3 reactor smoke now passes `--reactor`);
258+
compiler still emits preview1 core; native-preview2 cleanup remains
259+
the one-way door; #487 — `net_recv`/`net_send`/`net_accept` preview1
260+
lowering LANDED (gated `tests/componentize/sockio_smoke.sh`). WIT
261+
world of record: `wit/affinescript.wit`
258262
|INT-04 |Publish compiler + runtime to JSR (then npm) |#181 |runtime
259263
packaging READY (affine-js + affinescript-tea JSR dry-run green;
260264
manual-only `publish-jsr.yml`; docs/PACKAGING.adoc). INT-01 dep
@@ -264,7 +268,7 @@ auth). Compiler-binary distribution = design fork #260
264268
(INT-02 dep cleared 2026-05-31 via #179; no other blockers — next-up
265269
candidate for an issue-spinout)
266270
|INT-06 |Server-side runtime profile (on INT-03 WASI p2) |ledger-only
267-
|planned (blocked by #485)
271+
|planned (#485 FS slice unblocked 2026-09-21)
268272
|INT-07 |`affinescript-tea` runtime satellite |#182 **CLOSED 2026-07-25** |runtime + run loop
269273
shipped (`TeaApp`/`parseTeaLayout`, Linear-msg enforced); INT-01 dep
270274
cleared (#253). Router/nav = separate INT-09

‎docs/TECH-DEBT.adoc‎

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,14 @@ link:CAPABILITY-MATRIX.adoc[CAPABILITY-MATRIX.adoc].
2020
2121
GitHub index #175: **8/8 original sub-issues CLOSED** as of 2026-07-25
2222
(#176 DOC, #177 CORE-01, #178 INT-01, #179 INT-02, #180 INT-03,
23-
#181 INT-04-JSR, #182 INT-07, #183 INT-08). The GitHub ticket itself is a
24-
closed index (owner close 2026-09-21); this ledger remains the durable
25-
index. Residual WASI work lives as independent follow-ups (#485 S5
26-
filesystem, #486 S6c default-flip, #487 socket recv/send/accept);
27-
satellite remainder is #56.
23+
#181 INT-04-JSR, #182 INT-07, #183 INT-08). The GitHub ticket is a pure
24+
index whose children are complete; this ledger remains the durable
25+
index. Residual WASI follow-ups #485 (S5 filesystem) and #487
26+
(socket recv/send/accept) have preview1 lowerings + gated smokes in
27+
tree; #486 flipped the *wrap* default to `--command` without the
28+
one-way compiler re-target (native-preview2 cleanup still open).
29+
Satellite remainder is #56 (56-A Dom/Console + Pixi gap-fill landed;
30+
full idaptik surface still open).
2831
====
2932

3033
toc::[]
@@ -409,11 +412,21 @@ export lifting via `_start : () -> ()` shim around parameter-less
409412
`wasi_snapshot_preview1.sock_shutdown` (command adapter bridges to
410413
`wasi:sockets/tcp`; 81d9fc7). Gates:
411414
`tests/componentize/{smoke,command_smoke,sockets_smoke}.sh`.
412-
Residual (filed 2026-05-31): #485 S5 native `wasi:filesystem`
413-
(open/read/write/close — unblocks INT-06), #486 S6c flip default
414-
wasm target preview1 → component + native-preview2 cleanup (one-way
415-
door), #487 socket recv/send/accept primitives (byte-level buffer
416-
/ network-address marshalling)
415+
Residual (filed 2026-05-31, status 2026-09-21):
416+
#485 S5 native `wasi:filesystem` — *preview1 lowering LANDED*
417+
(`file_open`/`file_read`/`file_fd_write`/`file_close` →
418+
`path_open`/`fd_read`/`fd_write`/`fd_close`, Effect `File`,
419+
dirfd 3, combo canonical-order lock + gated
420+
`tests/componentize/filesystem_smoke.sh` hermetic `--dir`
421+
round-trip). Unblocks INT-06's FS slice.
422+
#486 S6c — *wrap default LANDED* (`tools/componentize.sh` now
423+
defaults to `--command`; S3 reactor smoke requests `--reactor`
424+
explicitly). Compiler still emits preview1 core wasm;
425+
native-preview2 import cleanup remains the one-way door.
426+
#487 socket recv/send/accept — *preview1 lowering LANDED*
427+
(`net_recv`/`net_send`/`net_accept` → `sock_recv`/`sock_send`/
428+
`sock_accept`, Effect `Net`, gated
429+
`tests/componentize/sockio_smoke.sh`)
417430
|INT-04 |Publish to JSR/npm |S2 |#181 packaging READY (dry-run green,
418431
manual workflow); compiler-binary distribution decided = **ADR-019**
419432
(#260, Releases + thin Deno/JSR shim, staged S1..S4; per-file record
@@ -448,7 +461,8 @@ end-to-end now (was code-correct but inert before today's publish).
448461
|INT-05 |Loader-driven multi-module app bundling |S2 |planned (INT-02 dep
449462
cleared 2026-05-31 via #179; candidate for an issue-spinout)
450463
|INT-06 |Server-side runtime profile (on INT-03 WASI p2) |S2 |planned
451-
(blocked by #485)
464+
(#485 FS slice unblocked 2026-09-21; remaining: native-preview2
465+
clocks/cli/sockets + a real server profile)
452466
|INT-11 |Browser host parity (`affine-js` loader + `affinescript-dom`
453467
reconciler end-to-end) |S2 |**CLOSED 2026-07-25**
454468
|INT-12 |typed-wasm convergence fixtures |S1 |planned (Stage E;
@@ -512,7 +526,10 @@ link:specs/TYPED-WASM-ROADMAP.adoc[TYPED-WASM-ROADMAP] (Tranches B/C/D)
512526
== Update protocol
513527

514528
* One PR per ledger unit; `Refs #N` (never `Closes` on the #175 epic — only
515-
the owner closes it).
529+
the owner closes it). Residual follow-ups after the original 8 children
530+
are #485/#486/#487/#56 — do not re-open #175 to track them. Owner may
531+
close #175 once those residuals are accepted; GitHub write is a PAT
532+
capability, not a ledger action.
516533
* Every capability-affecting PR updates `CAPABILITY-MATRIX.adoc` *and* this
517534
ledger in the same change; `STATE.a2ml` mirrors after.
518535
* `dune runtest --force` must stay green (baseline 260, 2026-05-19).

0 commit comments

Comments
 (0)