Skip to content

Commit 8b242b8

Browse files
committed
fix: return type of Timeout/Interval accepts both number and NodeJS.Timeout
1 parent c6f71d8 commit 8b242b8

File tree

3 files changed

+125
-13
lines changed

3 files changed

+125
-13
lines changed

crates/timers/src/callback.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@ extern "C" {
99
type GlobalThis;
1010

1111
#[wasm_bindgen(method, js_name = "setTimeout", catch)]
12-
fn set_timeout(this: &GlobalThis, handler: &Function, timeout: i32) -> Result<i32, JsValue>;
12+
fn set_timeout(this: &GlobalThis, handler: &Function, timeout: i32) -> Result<JsValue, JsValue>;
1313

1414
#[wasm_bindgen(method, js_name = "setInterval", catch)]
15-
fn set_interval(this: &GlobalThis, handler: &Function, timeout: i32) -> Result<i32, JsValue>;
15+
fn set_interval(this: &GlobalThis, handler: &Function, timeout: i32) -> Result<JsValue, JsValue>;
1616

1717
#[wasm_bindgen(method, js_name = "clearTimeout")]
18-
fn clear_timeout(this: &GlobalThis, handle: i32);
18+
fn clear_timeout(this: &GlobalThis, handle: JsValue);
1919

2020
#[wasm_bindgen(method, js_name = "clearInterval")]
21-
fn clear_interval(this: &GlobalThis, handle: i32);
21+
fn clear_interval(this: &GlobalThis, handle: JsValue);
2222
}
2323

2424
/// A scheduled timeout.
@@ -30,15 +30,15 @@ extern "C" {
3030
#[derive(Debug)]
3131
#[must_use = "timeouts cancel on drop; either call `forget` or `drop` explicitly"]
3232
pub struct Timeout {
33-
id: Option<i32>,
33+
id: Option<JsValue>,
3434
closure: Option<Closure<dyn FnMut()>>,
3535
}
3636

3737
impl Drop for Timeout {
3838
/// Disposes of the timeout, dually cancelling this timeout by calling
3939
/// `clearTimeout` directly.
4040
fn drop(&mut self) {
41-
if let Some(id) = self.id {
41+
if let Some(id) = self.id.take() {
4242
let global = js_sys::global().unchecked_into::<GlobalThis>();
4343
global.clear_timeout(id);
4444
}
@@ -95,7 +95,7 @@ impl Timeout {
9595
/// // Do stuff...
9696
/// }).forget();
9797
/// ```
98-
pub fn forget(mut self) -> i32 {
98+
pub fn forget(mut self) -> JsValue {
9999
let id = self.id.take().unwrap_throw();
100100
self.closure.take().unwrap_throw().forget();
101101
id
@@ -135,15 +135,15 @@ impl Timeout {
135135
#[derive(Debug)]
136136
#[must_use = "intervals cancel on drop; either call `forget` or `drop` explicitly"]
137137
pub struct Interval {
138-
id: Option<i32>,
138+
id: Option<JsValue>,
139139
closure: Option<Closure<dyn FnMut()>>,
140140
}
141141

142142
impl Drop for Interval {
143143
/// Disposes of the interval, dually cancelling this interval by calling
144144
/// `clearInterval` directly.
145145
fn drop(&mut self) {
146-
if let Some(id) = self.id {
146+
if let Some(id) = self.id.take() {
147147
let global = js_sys::global().unchecked_into::<GlobalThis>();
148148
global.clear_interval(id);
149149
}
@@ -198,7 +198,7 @@ impl Interval {
198198
/// // Do stuff...
199199
/// }).forget();
200200
/// ```
201-
pub fn forget(mut self) -> i32 {
201+
pub fn forget(mut self) -> JsValue {
202202
let id = self.id.take().unwrap_throw();
203203
self.closure.take().unwrap_throw().forget();
204204
id

crates/timers/tests/node.rs

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#![cfg(all(target_family = "wasm", feature = "futures"))]
2+
3+
use futures_channel::{mpsc, oneshot};
4+
use futures_util::{
5+
future::{select, Either, FutureExt},
6+
stream::StreamExt,
7+
};
8+
use gloo_timers::{
9+
callback::{Interval, Timeout},
10+
future::{sleep, IntervalStream, TimeoutFuture},
11+
};
12+
use std::cell::Cell;
13+
use std::rc::Rc;
14+
use std::time::Duration;
15+
use wasm_bindgen_test::*;
16+
17+
#[wasm_bindgen_test]
18+
async fn timeout() {
19+
let (sender, receiver) = oneshot::channel();
20+
Timeout::new(1, || sender.send(()).unwrap()).forget();
21+
receiver.await.unwrap();
22+
}
23+
24+
#[wasm_bindgen_test]
25+
async fn timeout_cancel() {
26+
let cell = Rc::new(Cell::new(false));
27+
28+
let t = Timeout::new(1, {
29+
let cell = cell.clone();
30+
move || {
31+
cell.set(true);
32+
panic!("should have been cancelled");
33+
}
34+
});
35+
t.cancel();
36+
37+
let (sender, receiver) = oneshot::channel();
38+
39+
Timeout::new(2, move || {
40+
sender.send(()).unwrap();
41+
assert_eq!(cell.get(), false);
42+
})
43+
.forget();
44+
45+
receiver.await.unwrap();
46+
}
47+
48+
#[wasm_bindgen_test]
49+
async fn timeout_future() {
50+
TimeoutFuture::new(1).await;
51+
}
52+
53+
#[wasm_bindgen_test]
54+
async fn timeout_future_cancel() {
55+
let cell = Rc::new(Cell::new(false));
56+
57+
let a = TimeoutFuture::new(1).map({
58+
let cell = cell.clone();
59+
move |_| {
60+
assert_eq!(cell.get(), false);
61+
1
62+
}
63+
});
64+
65+
let b = TimeoutFuture::new(2).map({
66+
let cell = cell.clone();
67+
move |_| {
68+
cell.set(true);
69+
2u32
70+
}
71+
});
72+
73+
let (who, other) = match select(a, b).await {
74+
Either::Left(x) => x,
75+
Either::Right(_) => panic!("Timer for 2 ms finished before timer for 1 ms"),
76+
};
77+
assert_eq!(who, 1);
78+
// Drop `b` so that its timer is canceled.
79+
drop(other);
80+
TimeoutFuture::new(3).await;
81+
// We should never have fired `b`'s timer.
82+
assert_eq!(cell.get(), false);
83+
}
84+
85+
#[wasm_bindgen_test]
86+
async fn interval() {
87+
let (mut sender, receiver) = mpsc::channel(1);
88+
let i = Interval::new(1, move || {
89+
if !sender.is_closed() {
90+
sender.try_send(()).unwrap()
91+
}
92+
});
93+
94+
let results: Vec<_> = receiver.take(5).collect().await;
95+
drop(i);
96+
assert_eq!(results.len(), 5);
97+
}
98+
99+
#[wasm_bindgen_test]
100+
async fn interval_cancel() {
101+
let i = Interval::new(10, move || {
102+
panic!("This should never be called");
103+
});
104+
i.cancel();
105+
106+
// This keeps us live for long enough that if any erroneous Interval callbacks fired, we'll have seen them.
107+
sleep(Duration::from_millis(100)).await;
108+
}
109+
110+
#[wasm_bindgen_test]
111+
async fn interval_stream() {
112+
let results: Vec<_> = IntervalStream::new(1).take(5).collect().await;
113+
assert_eq!(results.len(), 5);
114+
}

crates/timers/tests/web.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
//! Test suite for the Web and headless browsers.
2-
3-
#![cfg(all(target_arch = "wasm32", feature = "futures"))]
1+
#![cfg(all(target_family = "wasm", feature = "futures"))]
42

53
use futures_channel::{mpsc, oneshot};
64
use futures_util::{

0 commit comments

Comments
 (0)