Skip to content

Commit e9a3fa3

Browse files
authored
Merge pull request #57 from samcday/fix-timers-interval
gloo-timers: don't consume callback in Interval closure
2 parents 5fc8523 + 7749e20 commit e9a3fa3

File tree

2 files changed

+28
-28
lines changed

2 files changed

+28
-28
lines changed

crates/timers/src/callback.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,7 @@ impl Interval {
150150
where
151151
F: 'static + FnMut(),
152152
{
153-
let mut callback = Some(callback);
154-
let closure = Closure::wrap(Box::new(move || {
155-
let mut callback = callback.take().unwrap_throw();
156-
callback();
157-
}) as Box<FnMut()>);
153+
let closure = Closure::wrap(Box::new(callback) as Box<FnMut()>);
158154

159155
let id = set_interval(
160156
closure.as_ref().unchecked_ref::<js_sys::Function>(),

crates/timers/tests/web.rs

+27-23
Original file line numberDiff line numberDiff line change
@@ -91,53 +91,57 @@ fn timeout_future_cancel() -> impl Future<Item = (), Error = wasm_bindgen::JsVal
9191
#[wasm_bindgen_test(async)]
9292
fn interval() -> impl Future<Item = (), Error = wasm_bindgen::JsValue> {
9393
let (mut sender, receiver) = mpsc::channel(1);
94-
Interval::new(1, move || sender.try_send(()).unwrap()).forget();
94+
let i = Interval::new(1, move || {
95+
if !sender.is_closed() {
96+
sender.try_send(()).unwrap()
97+
}
98+
});
99+
95100
receiver
96101
.take(5)
97102
.map_err(|_| "impossible".into())
98-
.for_each(|_| Ok(()))
103+
.collect()
104+
.and_then(|results| {
105+
drop(i);
106+
assert_eq!(results.len(), 5);
107+
Ok(())
108+
})
99109
}
100110

101111
#[wasm_bindgen_test(async)]
102112
fn interval_cancel() -> impl Future<Item = (), Error = wasm_bindgen::JsValue> {
103-
let cell = Rc::new(Cell::new(false));
113+
let (mut i_sender, i_receiver) = mpsc::channel(1);
104114

105-
let i = Interval::new(1, {
106-
let cell = cell.clone();
107-
move || {
108-
cell.set(true);
109-
panic!("should have been cancelled");
110-
}
111-
});
115+
let i = Interval::new(1, move || i_sender.try_send(()).unwrap());
112116
i.cancel();
113117

118+
// This keeps us live for long enough that if any erroneous Interval callbacks fired, we'll have seen them.
114119
let (mut sender, receiver) = mpsc::channel(1);
115-
Interval::new(2, move || {
120+
Timeout::new(50, move || {
116121
sender.try_send(()).unwrap();
117-
assert_eq!(cell.get(), false);
118122
})
119123
.forget();
120124

121125
receiver
126+
.merge(i_receiver)
127+
.take(2)
122128
.map_err(|_| "impossible".into())
123-
.for_each(|_| Ok(()))
129+
.collect()
130+
.and_then(|results| {
131+
// Should only be 1 item - and that's from the timeout. Anything more means interval spuriously fired.
132+
assert_eq!(results.len(), 1);
133+
Ok(())
134+
})
124135
}
125136

126137
#[wasm_bindgen_test(async)]
127138
fn interval_stream() -> impl Future<Item = (), Error = wasm_bindgen::JsValue> {
128-
let cell = Rc::new(Cell::new(0));
129139
IntervalStream::new(1)
130140
.take(5)
131141
.map_err(|_| "impossible".into())
132-
.for_each({
133-
let cell = cell.clone();
134-
move |_| {
135-
cell.set(cell.get() + 1);
136-
Ok(())
137-
}
138-
})
139-
.and_then(move |_| {
140-
assert_eq!(cell.get(), 5);
142+
.collect()
143+
.and_then(|results| {
144+
assert_eq!(results.len(), 5);
141145
Ok(())
142146
})
143147
}

0 commit comments

Comments
 (0)