Latest Results
feat: wasm-buildable leo build pipeline + leo-cli-core + leo-wasm
Brings `leo build` to `wasm32-unknown-unknown` without forking the build logic. A single `handle_build` in the new
`leo-commands` crate drives both the native CLI and the new `leo-wasm` wasm-bindgen layer; the per-target differences
are pushed to two trait seams — `FileSource` (read side, in leo-span) and `ArtifactSink` (write side, in
leo-commands::build). Native passes `DiskFileSource` + `DiskSink`; wasm passes `InMemoryFileSource` + `MemorySink`.
New crates:
- `leo-commands` (renamed from `leo-cli-core`): hosts the per-command `handle_*` cores shared between the CLI and the
wasm bindings. Today only `build` is hosted; `run` / `test` / `execute` / `deploy` will follow.
- `leo-wasm`: thin wasm-bindgen shim with a single `build(files_json, root, env_json, network_deps_json) -> String`
entry that materializes the JSON file map into an `InMemoryFileSource`, calls `handle_build`, then JSON-shapes the
artifacts the `MemorySink` collected.
Read-side abstraction (`FileSource` in `leo-span`):
- `DiskFileSource` / `InMemoryFileSource` / `OverlayFileSource` cover real-disk, JSON-staged in-memory, and editor
overlay scenarios. LSP gets `RecordingFileSource` + `SingleFileSource`.
- Required methods: `read_file`, `list_leo_files`, `is_file`, `is_dir`, `canonicalize`, `list_files_recursive`.
`exists` has a default derived from `is_file || is_dir`.
- All entry points take `&dyn FileSource` (not generic) to avoid monomorphization across the compiler / package /
commands / fmt / lsp call chains.
Write-side abstraction (`ArtifactSink` in `leo-commands::build`):
- `DiskSink` writes through to disk and auto-creates parent dirs; `MemorySink` collects writes in an `IndexMap` using
`RefCell` (single-threaded by design; `!Send` would be a compile error for a future threaded caller).
- `remove_file` / `remove_dir_all` / `exists` cover the build's pre-clean step for stale interface ABIs.
snarkVM target-gating:
- The full snarkVM umbrella stays native-only across `compiler`, `parser`, `passes`, `package`. The slim
`snarkvm-console` + `snarkvm-synthesizer-program` subsets are pulled in via leo-ast's `snarkvm_wasm` shim, with
`extern crate leo_ast as snarkvm` in the three consumer crates so existing `use snarkvm::prelude::*` lines compile
unchanged on both targets.
- The compiler's `pub mod run` (snarkVM `Process` execution surface — run/test/deploy) stays native-only via the mod
declaration in `compiler/src/lib.rs`.
- Native-only registry / network fetchers moved into `crates/package/src/native.rs` (mod-gated in lib.rs).
- The LSP-only package/manifest-driven import-stub loader moved into `crates/compiler/src/import_stubs.rs`, similarly
mod-gated.
Network and workspace dependencies on wasm:
- `Location::Network` deps: callers stage bytecode via `network_deps_json` (`{"name.aleo": "<bytecode>"}`). The wasm
shim stages each entry under `<root>/__wasm_deps__/<bare>/<name>.aleo` and rewrites matching `Location::Network`
entries in every manifest to `Location::Local` pointing at the staged path. Unsupplied deps hard-error from the
build core with a clear message.
- `Location::Workspace` deps: `Workspace::from_directory`, `Workspace::discover`, `WorkspaceManifest::read_from_file`,
and `resolve_workspace_dependency` all gained `_with_file_source` counterparts. Glob expansion in
`expand_member_pattern` runs through `FileSource::list_files_recursive` + `glob::Pattern::matches_with`, so the
filesystem-bound `glob::glob` crate is no longer on the production path. `Workspace::is_member` /
`auto_register_member` / `initialize_skeleton` stay native-only (real disk reads / writes).
Other refactors:
- Drops the hand-rolled `.aleo` import scanner; `parse_dependencies_from_aleo` runs the real snarkVM parser on both
targets via the slim wasm shim.
- `max_program_size` switched from a workspace constant to a per-network function that forwards to snarkVM's
`LATEST_MAX_PROGRAM_SIZE` helper; threaded through every consumer.
- `Package::from_directory[_with_tests]_with_file_source` grew `home_path` / `endpoint` / `network_retries` so
`load_package` in `leo-commands::build` collapses to one function (no cfg gate).
- `handle_build`'s `validate: bool` parameter dropped; inferred from `cfg!(not(target_arch = "wasm32"))`.
- `ArtifactSink::write` auto-creates parent dirs, removing the per-callsite `ensure_parent_dir` calls.
- `MemorySink` uses `RefCell` instead of `Mutex` (single-threaded build; `.unwrap()` removed).
Tests: 10 unit tests in `leo-wasm::build` (manifest rewrite, key normalization, staged paths, dev-dependency coverage)
and 3 integration tests in `leo-commands::build::tests` (full `handle_build` over `InMemoryFileSource` + `MemorySink`,
fail-closed for unsupplied network deps, workspace glob expansion + member resolution through in-memory file source).
All 13 run under plain `cargo test` on native — no wasm-bindgen-test infra needed.mohammadfawaz/leo-wasm-build Latest Branches
0%
mohammadfawaz/abi-interface-compat 0%
fix/write-transforming-assert-reconstruction +1%
mohammadfawaz/leo-wasm-build © 2026 CodSpeed Technology