Repository navigation
Deno-ESM emit target + Deno-FS stdlib bindings (enable TS→AffineScript for Deno I/O modules) #122
Description
Motivation
Estate TS-elimination (RSR: no TypeScript in the Tier-1 estate) requires migrating Deno I/O modules, not just wasm-pure logic and VS Code extensions. Concrete blocked consumer: hyperpolymath/ubicity src/storage.ts (async ExperienceStorage class, Deno FS effects, consumed as ESM ./storage.js by ~6 .js modules) and src/wasm-bridge.ts (Deno.readFile + WebAssembly.instantiate glue). The antipattern-check gate correctly flags these as genuine violations; they cannot be migrated today.
Gap analysis
Available today (per #35, Phases 1–3, lib/codegen_node.ml):
- ✅ wasm expression core (Int/Bool/struct/enum/match)
- ✅ Node-CJS
.cjsshim wrapping compiled wasm - ✅ vscode FFI bindings (
stdlib/Vscode.affine, handle-table adapter)
Missing for Deno I/O module migration:
- Deno-ESM emit target — emit an ES module (
.js,import/export) consumable by a Deno runtime, distinct from the Node-CJS.cjspath. Output-extension dispatch like the existing.cjsroute. stdlib/Deno.affineFS bindings —pub extern fnleaves forDeno.readTextFile/writeTextFile/readDir/stat/remove,ensureDir(@std/fs),join(@std/path),Deno.errors.NotFounddiscrimination. JS-side adapter mirroring thepackages/affine-vscode/mod.jshandle/readString pattern.- Async-extern ABI —
storage.tsisasync/Promise-returning. Depends on / extends Async-extern ABI: bind withProgress + LanguageClient.sendRequest #103 (async-extern ABI). Required before any Deno FS binding is callable. - Class/object ESM emission —
ExperienceStorageis an instantiable class with private fields; emit must expose a constructable object whose methods bridge to wasm + the JS adapter.
Scope
In: the four capabilities above + a migration of ubicity's two files as the proving harness. Out: non-Deno runtimes; experimental nextgen-languages; vscode work (covered by #35/#63/#104).
Acceptance criteria
-
affinescriptemits a Deno-ESM module from.affine(dispatched by output ext) -
stdlib/Deno.affinecovers the FS/path surface listed above, with JS adapter - async-extern path (Async-extern ABI: bind withProgress + LanguageClient.sendRequest #103) sufficient for Promise-returning FS calls
- ubicity
storage.affine+wasm-bridge.affinecompile to drop-in./storage.js/./wasm-bridge.js; ubicitydeno task test+antipattern-checkgreen; no.tsinsrc/
Relations
Refs #35 (builds on its codegen_node.ml/shim infra). Refs #103 (async-extern prerequisite). Motivating consumer: hyperpolymath/ubicity. Surfaced during the 2026-05-16 estate PR sweep.
Activity
feat(codegen-deno/typecheck): consumer-migration primitives + ++ disa…
feat: Deno-ESM target + grammar-v2 build-out (Refs #122) (#123)
fix(typecheck): make len/show truly polymorphic schemes (Refs #122) (#…
Eliminate all src/*.ts (Closes #30; Refs affinescript#122) (#31)
fix(codegen-deno): async-context IIFE wrappers (Refs #122) (#126)
fix: plain clone works fully + Deno container (Refs affinescript#122)
hyperpolymath commentedon May 16, 2026
Spec satisfied by #123/#125/#126; consumer proven by
ubicity#31/#33 (44/44 in-container). Mutually agreed complete.
fix(test/codegen-node): correct false-positive in vscode-off-by-defau…
fix(stdlib): seed Some/None/Ok/Err builtins so stdlib/string.affine r…
fix(resolve): remove b895374 Some/None/Ok/Err seed; resolve imports r…