本文へ移動
cccskills
無料GitHub で公開

jco

Transpile Wado Wasm components to JS with jco, then run, debug, and benchmark them on Node. Use for anything that involves jco, Node, or a browser as the host.

日本語の概要は準備中です。原文の説明を表示しています。

wado-lang/wadoスター 119(GitHub 119 + cccskills 0)

実行スコア 未検証

インストール方法を見る

含まれるファイル(1)

  • SKILL.md10.5 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Running Wado on Node via jco

jco (bytecodealliance) transpiles a Wasm component into JS + core Wasm so it runs on a plain Wasm engine (V8/Node, browsers) instead of a Component Model runtime. Wado targets WASI P3; this doc covers what the released jco does for Wado today and what is still blocked.

TL;DR

  • Use the released npm jco as a library (scripts/jco, mise run jco-*).
  • Compile Wado with -f no-wide-arithmetic — V8 has no wide-arithmetic proposal, and float formatting / i128 emit it.
  • Run on Node 26+ — stable JSPI, no flag.
  • Compute and filesystem programs work (including float formatting). A filesystem program needs its preopen set with _setPreopens (see below).
  • Quick check: mise run jco-hello-released. Benchmark: mise run jco-bench <program.wado>.

Environment

  • Node 26+ required. Node 26 (V8 14.6) ships stable JSPI (WebAssembly.Suspending), so no flag is needed; the repo pins node = "26" in mise.toml. Node 24 needs --experimental-wasm-jspi; Node 22's older JSPI fails (WebAssembly.Suspending is not a constructor).
  • /tmp pitfall: outside the repo, node may resolve to a system Node 22 (mise activation is path-scoped). Run inside the repo, or use the pinned binary's absolute path.
  • V8 has no wide-arithmetic in any version (no flag exists). This is a V8 gap, not a jco one — handled by -f no-wide-arithmetic (see below).

Vendor-free pipeline (scripts/jco)

Released @bytecodealliance/jco as a library. transpile-released.mjs is a plain transpile() — jco's own preview3-shim serves every import a Wado program makes, and the output links to it through a node_modules symlink the script writes beside the files.

The shim writes stdout from a worker that is torn down once the event loop empties, so lines still queued when run() resolves are lost, and a runner that calls process.exit on that promise loses more. Hold the loop open for a second after run() resolves. The lines of one run can also arrive out of order.

A program that reads files needs a preopen. Set it before importing the transpiled module, mapping the guest's . to a host directory as wado run --dir <dir>::. does:

import { _setPreopens } from "@bytecodealliance/preview3-shim/filesystem";
_setPreopens({ ".": "/abs/host/dir" });
const m = await import("./out/prog.js");
await m.run.run();
await new Promise((r) => setTimeout(r, 1000));

Import the shim the output links to through its node_modules symlink. A second copy of the shim holds its own preopen table, which the program never reads.

mise tasks:

mise run jco-deps                       # npm install released jco under scripts/jco
mise run jco-transpile-released foo.wasm [out-dir]
mise run jco-hello-released             # compile + transpile + run hello on Node
mise run jco-bench <program.wado> [runs] # compile -f no-wide-arithmetic, transpile, self-time

Released jco status (verified at 1.30.0)

CapabilityStatus
Transpile (GC component)✅ works, wasi:http/service included
JSPI✅ native (Node 26 no flag; Node 24 needs the flag)
Wide-arithmetic component❌ transpile rejects it (wide arithmetic support is not enabled); even if forced, V8 rejects the opcode at runtime → use -f no-wide-arithmetic
Stdout via stream✅ jco's own shim delivers it, if the runner holds the event loop open after run() resolves
Filesystem read stream✅ reads through a preopen set with _setPreopens (zlib benchmark verified)

wide-arithmetic (-f no-wide-arithmetic)

Wado emits the Wasm wide-arithmetic proposal (i64.mul_wide_u/s, i64.add128, i64.sub128) for float formatting (core:prelude/fpfmt.wado) and i128. No V8 implements it (checked through Node 26; no flag, --wasm-staging no help), so any component containing those opcodes fails WebAssembly.compile with invalid numeric opcode: 0xfc16.

-f no-wide-arithmetic rewrites each such builtin call, before NIR, to a 32-bit-limb software form in core:rt (i64_mul_wide_u_soft and so on; wado-compiler/src/lower/wide_arith.rs). NIR and WIR then show ordinary calls, which the optimizer inlines. Compile every Node-bound Wado program with this flag — a bare println of a float needs it.

WASI shims

BA ships a preview3-shim implementing P3 cli / clocks / filesystem / http, with a browser build beside the Node one. A plain jco transpile wires it, and stdout, float formatting, wasi:random, MonotonicClock and an HTTP handle all run through it unaided. Its browser cli is unimplemented (throw new Todo()), which is why the playground keeps a hand-written one.

A hand-written clock is where precision goes missing: system-clock.now is an instant carrying sub-second nanoseconds, and get-resolution a bare duration.

Benchmarking on Node

mise run jco-bench <program.wado> [runs] compiles with -f no-wide-arithmetic, transpiles via the released pipeline, and runs the program self-timed runs times (default 3; keep the best). The benchmark programs already self-time via core:benchmark + MonotonicClock and print their own throughput line, so no host timing is needed.

JCO_PREOPEN names the host directory granted as the program's . (default: the repository root). The benchmarks read their data relative to benchmark/:

mise run jco-bench benchmark/mandelbrot/mandelbrot.wado
JCO_PREOPEN=benchmark mise run jco-bench benchmark/zlib/zlib_bench.wado
BenchmarkWado on Node (jco)Wado on wasmtime
mandelbrot~4.0 M px/s~4.2 M
sieve~150 M numbers/s~64 M (V8 ~2.3× faster)
fts~12 M conv/s—
zlib compress~65 MB/s—
zlib decompress~220 MB/s—

The Node column is mise run jco-bench <program.wado> as above; the wasmtime column is wado run -O2 <program.wado> from benchmark/, as benchmark/mise.toml runs it.

Compute throughput on V8 lands within ~5–10% of wasmtime (sieve is much faster on V8). Numbers are indicative on a noisy cloud VM; keep best-of-3.

The other filesystem benchmarks (json-{twitter,canada,catalog}, sqlite-parse, syntax-highlight, cbor) load their data the same way, outside the timed loop, but have not been run on Node yet.

Known blockers (jco / V8 gaps)

wide-arithmetic (V8)

Not jco. Handled by -f no-wide-arithmetic.

Reusing an instance (jco)

An instance serves a couple of calls, then the next suspends on a stream read whose host injection is never driven (JCO_DEBUG=1 ends at [StreamEnd#copy()] blocked). cloudflare-worker/ builds one per request.

Debugging jco runtime errors

Transpiled output is one large JS file. Useful canonical-builtin → JS mappings:

Wasm builtinjco JS functionNotes
stream.writestreamWrite()JSPI Suspending
stream.readstreamRead()JSPI Suspending
canon lower (async)_lowerImportBackwardsCompat()JSPI Suspending
task.returntaskReturn()
future.new (lift)_genStreamHostInjectFn / createReadableStreamEndhost→guest wiring

Techniques

  • Catch swallowed errors — jco's async machinery loses errors as unhandled rejections:

    process.on('unhandledRejection', e => { console.error('UNHANDLED:', e); process.exit(1); });
    
  • JCO_DEBUG=1 node run.mjs — verbose trace of every instruction/trampoline. A trailing [ComponentAsyncState#suspendTask()] with no progress = a rendezvous deadlock.

  • Inject logging by string-replacing a function header in the transpiled JS (e.g. add console.error(...) to streamRead/generatedStreamHostInject).

  • Timeout hangs: timeout 12 node run.mjs so a deadlock doesn't wedge.

Common error patterns

ErrorLikely cause
invalid numeric opcode: 0xfc16Wide-arithmetic — recompile with -f no-wide-arithmetic
WebAssembly.Suspending is not a constructorNode < 24, or Node 22 picked up outside the repo (use Node 26)
FutureReadableEnd is not definedFuture-end classes not injected (run via transpile-released.mjs)
stdout empty or missing linesThe runner exits or empties the event loop before the shim's worker flushes (wait after run())
Bare unreachable from a program that reads filesNo preopen set (_setPreopens), or a path outside it; the panic message is lost with the exit
wide arithmetic support is not enabled (transpile)Compile with -f no-wide-arithmetic; V8 cannot run the opcodes either
Hang / timeoutJSPI Suspending missing on a trampoline, or a stream rendezvous deadlock

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

コメント

ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。

まだコメントはありません。最初のコメントを書いてみませんか。

送信するとすぐに公開されます。メールアドレスや電話番号などの個人情報は書かないでください。URL は 2 つまでです。

0 / 1000 文字

このフォームは reCAPTCHA で保護されており、Google のプライバシーポリシーと利用規約が適用されます。

同じリポジトリのスキル

benchmark

無料

Measure Wado's performance or the size of the Wasm it generates, and refresh the benchmark/ and wasm-size/ README files. Use for any benchmarking or size-measurement request, whichever benchmark it names.

日本語の概要は準備中です。原文の説明を表示しています。

wado-lang/wado1192026年10月26日 更新

ci-timing

無料

Measure how long GitHub Actions jobs and steps took across past runs, and find the pull request that made CI slower. Use for any question about CI duration, a slow job, or when CI got slow.

日本語の概要は準備中です。原文の説明を表示しています。

wado-lang/wado1192026年10月26日 更新

How to answer code review feedback — a human reviewer, CodeRabbit, or any review bot. Verify the findings, report the classes they are instances of to the user before fixing, then fix the class rather than the sites named. Put design decisions to the user, then run /distill. Invoke when responding to review comments on a pull request, or to the findings of a /code-review run.

日本語の概要は準備中です。原文の説明を表示しています。

wado-lang/wado1192026年10月26日 更新

Investigate and improve code coverage for the wado-compiler crate. Use for any question about what the tests do and do not reach, dead code included.

日本語の概要は準備中です。原文の説明を表示しています。

wado-lang/wado1192026年10月26日 更新

cr

無料

Review the branch with /code-review at high, then answer the findings with /code-review-response.

日本語の概要は準備中です。原文の説明を表示しています。

wado-lang/wado1192026年10月26日 更新

debugger

無料

Use rust-gdb to inspect variables and step through code without modifying it. Prefer it over print debugging for any investigation into what the compiler is actually doing (lldb is unavailable on Claude Code Web).

日本語の概要は準備中です。原文の説明を表示しています。

wado-lang/wado1192026年10月26日 更新

wado-lang のスキルをすべて見る

このスキルの問題を報告する