Skip to content

Commit 19df1ac

Browse files
feat: initial wasi p1 implementation
Signed-off-by: Henry <mail@henrygressmann.de>
1 parent 741955a commit 19df1ac

25 files changed

Lines changed: 2863 additions & 23 deletions

File tree

Cargo.lock

Lines changed: 291 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ publish = false
88
[workspace]
99
resolver = "3"
1010
members = ["crates/*"]
11-
default-members = [".", "crates/parser", "crates/tinywasm", "crates/types"]
11+
default-members = [".", "crates/parser", "crates/tinywasm", "crates/types", "crates/wasi"]
1212

1313
[workspace.package]
1414
version = "0.11.0-pre.0"
@@ -23,6 +23,7 @@ categories = ["compilers", "embedded", "no-std", "virtualization", "wasm"]
2323
tinywasm = { path = "crates/tinywasm", version = "0.11.0-pre.0", default-features = false }
2424
tinywasm-parser = { path = "crates/parser", version = "0.11.0-pre.0", default-features = false }
2525
tinywasm-types = { path = "crates/types", version = "0.11.0-pre.0", default-features = false }
26+
tinywasm-wasi = { path = "crates/wasi", version = "0.11.0-pre.0" }
2627

2728
anyhow = "1.0"
2829
log = "0.4"
@@ -37,6 +38,12 @@ wat = "1.259"
3738

3839
criterion = { version = "0.8", default-features = false, features = ["cargo_bench_support", "rayon"] }
3940

41+
[workspace.lints.cargo]
42+
unused_dependencies = "allow" # false-positive on libm
43+
44+
[workspace.lints.rust]
45+
unexpected_cfgs = { level = "warn", check-cfg = ["cfg(rust_analyzer)"] }
46+
4047
[[example]]
4148
name = "rust"
4249
test = false
@@ -61,12 +68,13 @@ name = "tinywasm_modes"
6168
anyhow.workspace = true
6269
criterion.workspace = true
6370
pretty_env_logger.workspace = true
64-
tinywasm = { path = "crates/tinywasm" }
71+
tinywasm = { path = "crates/tinywasm", features = ["state"] }
6572
tinywasm-parser.workspace = true
73+
tinywasm-wasi.workspace = true
6674
wat.workspace = true
6775

68-
[lints.cargo]
69-
unused_dependencies = "allow" # false-positive on libm
76+
[lints]
77+
workspace = true
7078

7179
[profile.bench]
7280
opt-level = 3

crates/cli/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ tinywasm = { workspace = true, features = [
3838
"log",
3939
"std",
4040
] }
41+
tinywasm-wasi.workspace = true
4142
wasm-testsuite = { workspace = true, optional = true }
4243
wast = { workspace = true, optional = true }
4344
wat = { workspace = true, optional = true }
@@ -52,3 +53,6 @@ default = ["wast", "wat"]
5253
tests = ["dep:serde", "dep:serde_json", "dep:wasm-testsuite", "wast"]
5354
wast = ["dep:wast"]
5455
wat = ["dep:wat"]
56+
57+
[lints]
58+
workspace = true

crates/cli/tests/cli.rs

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,116 @@ fn bare_run_requires_default_entrypoint() {
7272
.stderr(predicate::str::contains("no start function or `_start` export"));
7373
}
7474

75+
#[test]
76+
fn run_supplies_wasi_arguments() {
77+
let dir = tempdir().unwrap();
78+
let module = write_module(
79+
&dir,
80+
"args.wat",
81+
r#"(module
82+
(import "wasi_snapshot_preview1" "args_sizes_get" (func $args_sizes_get (param i32 i32) (result i32)))
83+
(import "wasi_snapshot_preview1" "proc_exit" (func $proc_exit (param i32)))
84+
(memory (export "memory") 1)
85+
(func (export "_start")
86+
i32.const 0
87+
i32.const 4
88+
call $args_sizes_get
89+
drop
90+
i32.const 0
91+
i32.load
92+
call $proc_exit))"#,
93+
);
94+
95+
Command::cargo_bin("tinywasm").unwrap().args(["run", &module, "one", "two"]).assert().code(3).stderr("");
96+
}
97+
98+
#[test]
99+
fn run_supplies_explicit_wasi_environment() {
100+
let dir = tempdir().unwrap();
101+
let module = write_module(
102+
&dir,
103+
"env.wat",
104+
r#"(module
105+
(import "wasi_snapshot_preview1" "environ_sizes_get" (func $environ_sizes_get (param i32 i32) (result i32)))
106+
(import "wasi_snapshot_preview1" "proc_exit" (func $proc_exit (param i32)))
107+
(memory (export "memory") 1)
108+
(func (export "_start")
109+
i32.const 0
110+
i32.const 4
111+
call $environ_sizes_get
112+
drop
113+
i32.const 0
114+
i32.load
115+
call $proc_exit))"#,
116+
);
117+
118+
Command::cargo_bin("tinywasm")
119+
.unwrap()
120+
.args(["run", "--env", "MODE=test", "--env", "COLOR=off", &module])
121+
.assert()
122+
.code(2)
123+
.stderr("");
124+
}
125+
126+
#[test]
127+
fn run_inherits_wasi_stdout() {
128+
let dir = tempdir().unwrap();
129+
let module = write_module(
130+
&dir,
131+
"stdout.wat",
132+
r#"(module
133+
(import "wasi_snapshot_preview1" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32)))
134+
(memory (export "memory") 1)
135+
(data (i32.const 16) "hello wasi\n")
136+
(func (export "_start")
137+
i32.const 0 i32.const 16 i32.store
138+
i32.const 4 i32.const 11 i32.store
139+
i32.const 1 i32.const 0 i32.const 1 i32.const 8
140+
call $fd_write
141+
drop))"#,
142+
);
143+
144+
Command::cargo_bin("tinywasm").unwrap().args(["run", &module]).assert().success().stdout("hello wasi\n");
145+
}
146+
147+
#[test]
148+
fn run_preopens_wasi_directory() {
149+
let dir = tempdir().unwrap();
150+
let module = write_module(
151+
&dir,
152+
"preopen.wat",
153+
r#"(module
154+
(import "wasi_snapshot_preview1" "fd_prestat_get" (func $prestat (param i32 i32) (result i32)))
155+
(import "wasi_snapshot_preview1" "proc_exit" (func $proc_exit (param i32)))
156+
(memory (export "memory") 1)
157+
(func (export "_start")
158+
i32.const 3
159+
i32.const 0
160+
call $prestat
161+
call $proc_exit))"#,
162+
);
163+
let mapping = format!("{}::/data", dir.path().display());
164+
165+
Command::cargo_bin("tinywasm").unwrap().args(["run", "--dir", &mapping, &module]).assert().success().stderr("");
166+
}
167+
168+
#[test]
169+
fn run_executes_core_start_before_wasi_start() {
170+
let dir = tempdir().unwrap();
171+
let module = write_module(
172+
&dir,
173+
"start-order.wat",
174+
r#"(module
175+
(import "wasi_snapshot_preview1" "proc_exit" (func $proc_exit (param i32)))
176+
(global $status (mut i32) (i32.const 1))
177+
(func $initialize i32.const 7 global.set $status)
178+
(start $initialize)
179+
(func (export "_start") global.get $status call $proc_exit))"#,
180+
);
181+
182+
Command::cargo_bin("tinywasm").unwrap().args(["run", &module]).assert().code(7).stderr("");
183+
}
184+
75185
#[test]
76186
fn inspect_lists_exports() {
77187
let dir = tempdir().unwrap();

crates/parser/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,5 @@ std = ["tinywasm-types/std", "wasmparser/std"]
3232
# validate WebAssembly while parsing
3333
validate = ["wasmparser/features", "wasmparser/validate"]
3434

35-
[lints.rust]
36-
unexpected_cfgs = { level = "warn", check-cfg = ["cfg(rust_analyzer)"] }
35+
[lints]
36+
workspace = true

crates/tinywasm/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,6 @@ nightly-tail-calls = []
132132
# note: for x86 backend selection, compile with x86-64-v3 target features
133133
# (for example: `RUSTFLAGS="-C target-cpu=x86-64-v3"`)
134134
simd-x86 = []
135+
136+
[lints]
137+
workspace = true

crates/types/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,6 @@ std = ["serde?/std"]
2828

2929
# support targets without native atomic CAS
3030
portable-atomic = ["dep:portable-atomic-util"]
31+
32+
[lints]
33+
workspace = true

crates/wasi/Cargo.toml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
[package]
2+
name = "tinywasm-wasi"
3+
version.workspace = true
4+
edition.workspace = true
5+
rust-version.workspace = true
6+
description = "WASI support for TinyWasm"
7+
repository.workspace = true
8+
license.workspace = true
9+
keywords = ["tinywasm", "wasi", "wasm", "webassembly"]
10+
categories = ["wasm"]
11+
publish = false
12+
13+
[dependencies]
14+
cap-fs-ext = "4.0.3"
15+
cap-std = "4.0.3"
16+
getrandom = "0.4.3"
17+
rustix = { version = "1.1.4", features = ["event", "fs", "net"] }
18+
tinywasm = { workspace = true, default-features = false, features = ["state"] }
19+
20+
[dev-dependencies]
21+
tinywasm = { workspace = true, features = ["parser", "state"] }
22+
wat.workspace = true
23+
24+
[lints]
25+
workspace = true

crates/wasi/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# tinywasm-wasi
2+
3+
Experimental WASI support for TinyWasm mainly targeting \*nix systems (Windows support is very limited). Currently unreleased.
4+
5+
Some behavior is based on the Bytecode Alliance `wasi-common` and
6+
`wasmtime-wasi` implementations.
7+
8+
## Future WASI support
9+
10+
Preview 2 and 3 are not planned for TinyWasm, we're probably going to wait for the final WASI 1.0 release and implement that instead.

crates/wasi/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
//! WASI support for TinyWasm.
2+
3+
/// WASI Preview 1
4+
pub mod p1;

0 commit comments

Comments
 (0)