Skip to content

Commit 171a532

Browse files
committed
feat(wasi): add support for wasi:[email protected]
Signed-off-by: Roman Volosatovs <[email protected]>
1 parent 38c0f34 commit 171a532

28 files changed

+535
-32
lines changed

Cargo.lock

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

ci/vendor-wit.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ make_vendor "wasi" "
4444
4545
4646
47+
4748
"
4849

4950
make_vendor "wasi-http" "
@@ -55,6 +56,7 @@ make_vendor "wasi-http" "
5556
5657
5758
59+
5860
"
5961

6062
make_vendor "wasi-config" "config@f4d699b"

crates/test-programs/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@ anyhow = { workspace = true, features = ['std'] }
1515
wasi = "0.11.0"
1616
wasi-nn = "0.6.0"
1717
wit-bindgen = { workspace = true, features = ['default'] }
18+
wit-bindgen-rt = "0.37"
1819
libc = { workspace = true }
1920
getrandom = "0.2.9"
2021
futures = { workspace = true, default-features = false, features = ['alloc'] }
2122
url = { workspace = true }
2223
sha2 = "0.10.2"
2324
base64 = "0.21.0"
25+
tokio = { workspace = true, features = ["macros"] }

crates/test-programs/src/bin/preview2_sleep.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use test_programs::wasi::clocks::monotonic_clock;
1+
use test_programs::wasi::clocks0_2_3::monotonic_clock;
22

33
fn main() {
44
sleep_10ms();
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
use core::future::Future as _;
2+
use core::pin::pin;
3+
use core::ptr;
4+
use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
5+
6+
use test_programs::wasi::clocks0_3_0::monotonic_clock;
7+
8+
// Adapted from https://github.com/rust-lang/rust/blob/cd805f09ffbfa3896c8f50a619de9b67e1d9f3c3/library/core/src/task/wake.rs#L63-L77
9+
// TODO: Replace by `Waker::noop` once MSRV is raised to 1.85
10+
const NOOP_RAW_WAKER: RawWaker = {
11+
const VTABLE: RawWakerVTable = RawWakerVTable::new(
12+
// Cloning just returns a new no-op raw waker
13+
|_| NOOP_RAW_WAKER,
14+
// `wake` does nothing
15+
|_| {},
16+
// `wake_by_ref` does nothing
17+
|_| {},
18+
// Dropping does nothing as we don't allocate anything
19+
|_| {},
20+
);
21+
RawWaker::new(ptr::null(), &VTABLE)
22+
};
23+
24+
const NOOP_WAKER: &'static Waker = &unsafe { Waker::from_raw(NOOP_RAW_WAKER) };
25+
26+
#[tokio::main(flavor = "current_thread")]
27+
async fn main() {
28+
sleep_10ms().await;
29+
sleep_0ms();
30+
sleep_backwards_in_time();
31+
}
32+
33+
async fn sleep_10ms() {
34+
let dur = 10_000_000;
35+
monotonic_clock::wait_until(monotonic_clock::now() + dur).await;
36+
monotonic_clock::wait_for(dur).await;
37+
}
38+
39+
fn sleep_0ms() {
40+
let mut cx = Context::from_waker(NOOP_WAKER);
41+
42+
assert_eq!(
43+
pin!(monotonic_clock::wait_until(monotonic_clock::now())).poll(&mut cx),
44+
Poll::Ready(()),
45+
"waiting until now() is ready immediately",
46+
);
47+
assert_eq!(
48+
pin!(monotonic_clock::wait_for(0)).poll(&mut cx),
49+
Poll::Ready(()),
50+
"waiting for 0 is ready immediately",
51+
);
52+
}
53+
54+
fn sleep_backwards_in_time() {
55+
let mut cx = Context::from_waker(NOOP_WAKER);
56+
57+
assert_eq!(
58+
pin!(monotonic_clock::wait_until(monotonic_clock::now() - 1)).poll(&mut cx),
59+
Poll::Ready(()),
60+
"waiting until instant which has passed is ready immediately",
61+
);
62+
}

crates/test-programs/src/lib.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ wit_bindgen::generate!({
1313
include wasi:config/[email protected];
1414
include wasi:keyvalue/[email protected];
1515
16+
include wasi:clocks/[email protected];
1617
include wasi:random/[email protected];
1718
}
1819
",
@@ -23,6 +24,12 @@ wit_bindgen::generate!({
2324
],
2425
world: "wasmtime:test/test",
2526
features: ["cli-exit-with-code"],
27+
async: {
28+
imports: [
29+
"wasi:clocks/[email protected]#wait-for",
30+
"wasi:clocks/[email protected]#wait-until",
31+
],
32+
},
2633
generate_all,
2734
});
2835

@@ -42,8 +49,8 @@ pub mod proxy {
4249
"wasi:cli/[email protected]": crate::wasi::cli::stdout,
4350
"wasi:cli/[email protected]": crate::wasi::cli::stderr,
4451
"wasi:cli/[email protected]": crate::wasi::cli::stdin,
45-
"wasi:clocks/[email protected]": crate::wasi::clocks::monotonic_clock,
46-
"wasi:clocks/[email protected]": crate::wasi::clocks::wall_clock,
52+
"wasi:clocks/[email protected]": crate::wasi::clocks0_2_3::monotonic_clock,
53+
"wasi:clocks/[email protected]": crate::wasi::clocks0_2_3::wall_clock,
4754
},
4855
});
4956
}

crates/test-programs/src/sockets.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::wasi::clocks::monotonic_clock;
1+
use crate::wasi::clocks0_2_3::monotonic_clock;
22
use crate::wasi::io::poll::{self, Pollable};
33
use crate::wasi::io::streams::{InputStream, OutputStream, StreamError};
44
use crate::wasi::random0_2_3 as random;

crates/wasi-http/src/bindings.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ pub mod sync {
6262
"wasi:http": crate::bindings::http, // http is in this crate
6363
"wasi:io": wasmtime_wasi::bindings::sync::io, // io is sync
6464
"wasi:random": wasmtime_wasi::bindings::random0_2_3, // use correct `wasi:random`
65+
"wasi:clocks": wasmtime_wasi::bindings::clocks0_2_3, // use correct `wasi:clocks`
6566
"wasi": wasmtime_wasi::bindings, // everything else
6667
},
6768
require_store_data_send: true,

crates/wasi-http/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -286,8 +286,8 @@ where
286286
{
287287
let io_closure = type_annotate_io::<T, _>(|t| wasmtime_wasi::IoImpl(t));
288288
let closure = type_annotate_wasi::<T, _>(|t| wasmtime_wasi::WasiImpl(wasmtime_wasi::IoImpl(t)));
289-
wasmtime_wasi::bindings::clocks::wall_clock::add_to_linker_get_host(l, closure)?;
290-
wasmtime_wasi::bindings::clocks::monotonic_clock::add_to_linker_get_host(l, closure)?;
289+
wasmtime_wasi::bindings::clocks0_2_3::wall_clock::add_to_linker_get_host(l, closure)?;
290+
wasmtime_wasi::bindings::clocks0_2_3::monotonic_clock::add_to_linker_get_host(l, closure)?;
291291
wasmtime_wasi::bindings::io::poll::add_to_linker_get_host(l, io_closure)?;
292292
wasmtime_wasi::bindings::io::error::add_to_linker_get_host(l, io_closure)?;
293293
wasmtime_wasi::bindings::io::streams::add_to_linker_get_host(l, io_closure)?;
@@ -385,8 +385,8 @@ where
385385
let io_closure = type_annotate_io::<T, _>(|t| wasmtime_wasi::IoImpl(t));
386386
let closure = type_annotate_wasi::<T, _>(|t| wasmtime_wasi::WasiImpl(wasmtime_wasi::IoImpl(t)));
387387

388-
wasmtime_wasi::bindings::clocks::wall_clock::add_to_linker_get_host(l, closure)?;
389-
wasmtime_wasi::bindings::clocks::monotonic_clock::add_to_linker_get_host(l, closure)?;
388+
wasmtime_wasi::bindings::clocks0_2_3::wall_clock::add_to_linker_get_host(l, closure)?;
389+
wasmtime_wasi::bindings::clocks0_2_3::monotonic_clock::add_to_linker_get_host(l, closure)?;
390390
wasmtime_wasi::bindings::sync::io::poll::add_to_linker_get_host(l, io_closure)?;
391391
wasmtime_wasi::bindings::sync::io::streams::add_to_linker_get_host(l, io_closure)?;
392392
wasmtime_wasi::bindings::io::error::add_to_linker_get_host(l, io_closure)?;
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package wasi:clocks@0.3.0;
2+
/// WASI Monotonic Clock is a clock API intended to let users measure elapsed
3+
/// time.
4+
///
5+
/// It is intended to be portable at least between Unix-family platforms and
6+
/// Windows.
7+
///
8+
/// A monotonic clock is a clock which has an unspecified initial value, and
9+
/// successive reads of the clock will produce non-decreasing values.
10+
@since(version = 0.3.0)
11+
interface monotonic-clock {
12+
/// An instant in time, in nanoseconds. An instant is relative to an
13+
/// unspecified initial value, and can only be compared to instances from
14+
/// the same monotonic-clock.
15+
@since(version = 0.3.0)
16+
type instant = u64;
17+
18+
/// A duration of time, in nanoseconds.
19+
@since(version = 0.3.0)
20+
type duration = u64;
21+
22+
/// Read the current value of the clock.
23+
///
24+
/// The clock is monotonic, therefore calling this function repeatedly will
25+
/// produce a sequence of non-decreasing values.
26+
@since(version = 0.3.0)
27+
now: func() -> instant;
28+
29+
/// Query the resolution of the clock. Returns the duration of time
30+
/// corresponding to a clock tick.
31+
@since(version = 0.3.0)
32+
resolution: func() -> duration;
33+
34+
/// Wait until the specified instant has occurred.
35+
@since(version = 0.3.0)
36+
wait-until: func(
37+
when: instant,
38+
);
39+
40+
/// Wait for the specified duration has elapsed.
41+
@since(version = 0.3.0)
42+
wait-for: func(
43+
how-long: duration,
44+
);
45+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package wasi:clocks@0.3.0;
2+
3+
@unstable(feature = clocks-timezone)
4+
interface timezone {
5+
@unstable(feature = clocks-timezone)
6+
use wall-clock.{datetime};
7+
8+
/// Return information needed to display the given `datetime`. This includes
9+
/// the UTC offset, the time zone name, and a flag indicating whether
10+
/// daylight saving time is active.
11+
///
12+
/// If the timezone cannot be determined for the given `datetime`, return a
13+
/// `timezone-display` for `UTC` with a `utc-offset` of 0 and no daylight
14+
/// saving time.
15+
@unstable(feature = clocks-timezone)
16+
display: func(when: datetime) -> timezone-display;
17+
18+
/// The same as `display`, but only return the UTC offset.
19+
@unstable(feature = clocks-timezone)
20+
utc-offset: func(when: datetime) -> s32;
21+
22+
/// Information useful for displaying the timezone of a specific `datetime`.
23+
///
24+
/// This information may vary within a single `timezone` to reflect daylight
25+
/// saving time adjustments.
26+
@unstable(feature = clocks-timezone)
27+
record timezone-display {
28+
/// The number of seconds difference between UTC time and the local
29+
/// time of the timezone.
30+
///
31+
/// The returned value will always be less than 86400 which is the
32+
/// number of seconds in a day (24*60*60).
33+
///
34+
/// In implementations that do not expose an actual time zone, this
35+
/// should return 0.
36+
utc-offset: s32,
37+
38+
/// The abbreviated name of the timezone to display to a user. The name
39+
/// `UTC` indicates Coordinated Universal Time. Otherwise, this should
40+
/// reference local standards for the name of the time zone.
41+
///
42+
/// In implementations that do not expose an actual time zone, this
43+
/// should be the string `UTC`.
44+
///
45+
/// In time zones that do not have an applicable name, a formatted
46+
/// representation of the UTC offset may be returned, such as `-04:00`.
47+
name: string,
48+
49+
/// Whether daylight saving time is active.
50+
///
51+
/// In implementations that do not expose an actual time zone, this
52+
/// should return false.
53+
in-daylight-saving-time: bool,
54+
}
55+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package wasi:clocks@0.3.0;
2+
/// WASI Wall Clock is a clock API intended to let users query the current
3+
/// time. The name "wall" makes an analogy to a "clock on the wall", which
4+
/// is not necessarily monotonic as it may be reset.
5+
///
6+
/// It is intended to be portable at least between Unix-family platforms and
7+
/// Windows.
8+
///
9+
/// A wall clock is a clock which measures the date and time according to
10+
/// some external reference.
11+
///
12+
/// External references may be reset, so this clock is not necessarily
13+
/// monotonic, making it unsuitable for measuring elapsed time.
14+
///
15+
/// It is intended for reporting the current date and time for humans.
16+
@since(version = 0.3.0)
17+
interface wall-clock {
18+
/// A time and date in seconds plus nanoseconds.
19+
@since(version = 0.3.0)
20+
record datetime {
21+
seconds: u64,
22+
nanoseconds: u32,
23+
}
24+
25+
/// Read the current value of the clock.
26+
///
27+
/// This clock is not monotonic, therefore calling this function repeatedly
28+
/// will not necessarily produce a sequence of non-decreasing values.
29+
///
30+
/// The returned timestamps represent the number of seconds since
31+
/// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch],
32+
/// also known as [Unix Time].
33+
///
34+
/// The nanoseconds field of the output is always less than 1000000000.
35+
///
36+
/// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16
37+
/// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time
38+
@since(version = 0.3.0)
39+
now: func() -> datetime;
40+
41+
/// Query the resolution of the clock.
42+
///
43+
/// The nanoseconds field of the output is always less than 1000000000.
44+
@since(version = 0.3.0)
45+
resolution: func() -> datetime;
46+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package wasi:clocks@0.3.0;
2+
3+
@since(version = 0.3.0)
4+
world imports {
5+
@since(version = 0.3.0)
6+
import monotonic-clock;
7+
@since(version = 0.3.0)
8+
import wall-clock;
9+
@unstable(feature = clocks-timezone)
10+
import timezone;
11+
}

crates/wasi-preview1-component-adapter/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
)]
1515
#![expect(clippy::allow_attributes, reason = "crate not migrated yet")]
1616

17-
use crate::bindings::wasi::clocks::{monotonic_clock, wall_clock};
17+
use crate::bindings::wasi::clocks0_2_3::{monotonic_clock, wall_clock};
1818
use crate::bindings::wasi::io::poll;
1919
use crate::bindings::wasi::io::streams;
2020
use crate::bindings::wasi::random0_2_3::random;

0 commit comments

Comments
 (0)