Skip to content

Commit 91b7868

Browse files
authored
Merge pull request #44 from golemcloud/special-method-for-pollable
Generating a promise() function for Pollable
2 parents 502d6e9 + 21a9dda commit 91b7868

13 files changed

Lines changed: 607 additions & 0 deletions

File tree

crates/wasm-rquickjs/src/imports.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,27 @@ fn generate_import_module(
332332
}
333333
}
334334

335+
let mut special_methods = Vec::new();
336+
if resource_name == "pollable"
337+
&& &import.name == "poll"
338+
&& import
339+
.package_name
340+
.as_ref()
341+
.map(|p| format!("{}:{}", p.namespace, p.name))
342+
== Some("wasi:io".to_string())
343+
{
344+
special_methods.push(quote! {
345+
pub async fn promise(&mut self) -> () {
346+
let js_state = crate::internal::get_js_state();
347+
let reactor = js_state.reactor.borrow().clone().unwrap();
348+
349+
let pollable = self.inner.take().expect("Resource has already been disposed");
350+
let pollable: wasi::io::poll::Pollable = unsafe { wasi::io::poll::Pollable::from_handle(pollable.take_handle()) };
351+
reactor.wait_for(pollable).await;
352+
}
353+
});
354+
}
355+
335356
let rquickjs_class =
336357
generate_rquickjs_class_module(resource_name, &resource_name_ident, &resource_name_lit);
337358

@@ -354,6 +375,8 @@ fn generate_import_module(
354375
pub fn __dispose(&mut self) {
355376
let _ = self.inner.take();
356377
}
378+
379+
#(#special_methods)*
357380
}
358381

359382
impl<'js> rquickjs::IntoJs<'js> for #bindgen_path {

examples/pollable/src/pollable.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
import * as poll from 'wasi:io/poll@0.2.3';
3+
import * as monotonicClock from 'wasi:clocks/monotonic-clock@0.2.3';
4+
5+
export const test = async () => {
6+
let nanos = BigInt(2 * 1000 * 1000 * 1000);
7+
let pollable = monotonicClock.subscribeDuration(nanos)
8+
let before = monotonicClock.now();
9+
await pollable.promise();
10+
let after = monotonicClock.now();
11+
return after - before;
12+
};
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package wasi:clocks@0.2.3;
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.2.0)
11+
interface monotonic-clock {
12+
@since(version = 0.2.0)
13+
use wasi:io/poll@0.2.3.{pollable};
14+
15+
/// An instant in time, in nanoseconds. An instant is relative to an
16+
/// unspecified initial value, and can only be compared to instances from
17+
/// the same monotonic-clock.
18+
@since(version = 0.2.0)
19+
type instant = u64;
20+
21+
/// A duration of time, in nanoseconds.
22+
@since(version = 0.2.0)
23+
type duration = u64;
24+
25+
/// Read the current value of the clock.
26+
///
27+
/// The clock is monotonic, therefore calling this function repeatedly will
28+
/// produce a sequence of non-decreasing values.
29+
@since(version = 0.2.0)
30+
now: func() -> instant;
31+
32+
/// Query the resolution of the clock. Returns the duration of time
33+
/// corresponding to a clock tick.
34+
@since(version = 0.2.0)
35+
resolution: func() -> duration;
36+
37+
/// Create a `pollable` which will resolve once the specified instant
38+
/// has occurred.
39+
@since(version = 0.2.0)
40+
subscribe-instant: func(
41+
when: instant,
42+
) -> pollable;
43+
44+
/// Create a `pollable` that will resolve after the specified duration has
45+
/// elapsed from the time this function is invoked.
46+
@since(version = 0.2.0)
47+
subscribe-duration: func(
48+
when: duration,
49+
) -> pollable;
50+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package wasi:clocks@0.2.3;
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.2.3;
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.2.0)
17+
interface wall-clock {
18+
/// A time and date in seconds plus nanoseconds.
19+
@since(version = 0.2.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.2.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.2.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.2.3;
2+
3+
@since(version = 0.2.0)
4+
world imports {
5+
@since(version = 0.2.0)
6+
import monotonic-clock;
7+
@since(version = 0.2.0)
8+
import wall-clock;
9+
@unstable(feature = clocks-timezone)
10+
import timezone;
11+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package wasi:io@0.2.3;
2+
3+
@since(version = 0.2.0)
4+
interface error {
5+
/// A resource which represents some error information.
6+
///
7+
/// The only method provided by this resource is `to-debug-string`,
8+
/// which provides some human-readable information about the error.
9+
///
10+
/// In the `wasi:io` package, this resource is returned through the
11+
/// `wasi:io/streams/stream-error` type.
12+
///
13+
/// To provide more specific error information, other interfaces may
14+
/// offer functions to "downcast" this error into more specific types. For example,
15+
/// errors returned from streams derived from filesystem types can be described using
16+
/// the filesystem's own error-code type. This is done using the function
17+
/// `wasi:filesystem/types/filesystem-error-code`, which takes a `borrow<error>`
18+
/// parameter and returns an `option<wasi:filesystem/types/error-code>`.
19+
///
20+
/// The set of functions which can "downcast" an `error` into a more
21+
/// concrete type is open.
22+
@since(version = 0.2.0)
23+
resource error {
24+
/// Returns a string that is suitable to assist humans in debugging
25+
/// this error.
26+
///
27+
/// WARNING: The returned string should not be consumed mechanically!
28+
/// It may change across platforms, hosts, or other implementation
29+
/// details. Parsing this string is a major platform-compatibility
30+
/// hazard.
31+
@since(version = 0.2.0)
32+
to-debug-string: func() -> string;
33+
}
34+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package wasi:io@0.2.3;
2+
3+
/// A poll API intended to let users wait for I/O events on multiple handles
4+
/// at once.
5+
@since(version = 0.2.0)
6+
interface poll {
7+
/// `pollable` represents a single I/O event which may be ready, or not.
8+
@since(version = 0.2.0)
9+
resource pollable {
10+
11+
/// Return the readiness of a pollable. This function never blocks.
12+
///
13+
/// Returns `true` when the pollable is ready, and `false` otherwise.
14+
@since(version = 0.2.0)
15+
ready: func() -> bool;
16+
17+
/// `block` returns immediately if the pollable is ready, and otherwise
18+
/// blocks until ready.
19+
///
20+
/// This function is equivalent to calling `poll.poll` on a list
21+
/// containing only this pollable.
22+
@since(version = 0.2.0)
23+
block: func();
24+
}
25+
26+
/// Poll for completion on a set of pollables.
27+
///
28+
/// This function takes a list of pollables, which identify I/O sources of
29+
/// interest, and waits until one or more of the events is ready for I/O.
30+
///
31+
/// The result `list<u32>` contains one or more indices of handles in the
32+
/// argument list that is ready for I/O.
33+
///
34+
/// This function traps if either:
35+
/// - the list is empty, or:
36+
/// - the list contains more elements than can be indexed with a `u32` value.
37+
///
38+
/// A timeout can be implemented by adding a pollable from the
39+
/// wasi-clocks API to the list.
40+
///
41+
/// This function does not return a `result`; polling in itself does not
42+
/// do any I/O so it doesn't fail. If any of the I/O sources identified by
43+
/// the pollables has an error, it is indicated by marking the source as
44+
/// being ready for I/O.
45+
@since(version = 0.2.0)
46+
poll: func(in: list<borrow<pollable>>) -> list<u32>;
47+
}

0 commit comments

Comments
 (0)