1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#[cfg(feature = "experimental-hydrate")]
pub mod hydrate;
pub mod render;
use std::cell::RefCell;
use std::hash::{Hash, Hasher};
use std::ptr;
use std::rc::Rc;
use ahash::AHashSet;
thread_local! {
static TASKS: RefCell<AHashSet<Task>> = RefCell::new(AHashSet::new());
}
#[derive(Clone)]
pub struct Task {
callback: Rc<dyn Fn() -> bool>,
}
impl Task {
pub fn new(callback: impl Fn() -> bool + 'static) -> Self {
Self {
callback: Rc::new(callback),
}
}
pub fn abort(&self) {
TASKS.with(|tasks| {
tasks.borrow_mut().remove(self);
});
}
}
impl Hash for Task {
fn hash<H: Hasher>(&self, state: &mut H) {
Rc::as_ptr(&self.callback).hash(state);
}
}
impl PartialEq for Task {
fn eq(&self, other: &Self) -> bool {
ptr::eq::<()>(
Rc::as_ptr(&self.callback).cast(),
Rc::as_ptr(&other.callback).cast(),
)
}
}
impl Eq for Task {}
#[cfg(feature = "dom")]
pub(crate) fn run_tasks() {
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
let f = Rc::new(RefCell::new(None::<Closure<dyn Fn()>>));
let g = Rc::clone(&f);
*g.borrow_mut() = Some(Closure::wrap(Box::new(move || {
TASKS.with(|tasks| {
let task_list = (*tasks.borrow()).clone();
for task in task_list {
if !(task.callback)() {
tasks.borrow_mut().remove(&task);
}
}
if tasks.borrow().is_empty() {
let callback = f.take();
drop(callback);
} else {
web_sys::window()
.unwrap_throw()
.request_animation_frame(
f.borrow().as_ref().unwrap_throw().as_ref().unchecked_ref(),
)
.unwrap_throw();
}
});
})));
web_sys::window()
.unwrap_throw()
.request_animation_frame(g.borrow().as_ref().unwrap_throw().as_ref().unchecked_ref())
.unwrap_throw();
}
#[cfg(not(feature = "dom"))]
pub(crate) fn run_tasks() {
}
pub fn loop_raf(task: Task) {
TASKS.with(|tasks| {
if tasks.borrow().is_empty() {
run_tasks();
}
tasks.borrow_mut().insert(task);
});
}