본문으로 건너뛰기
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 / 1,000자

이 양식은 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의 스킬 모두 보기

이 스킬의 문제 신고