Web: fix ControlFlow::WaitUntil to never wake up **before** the given time (#3133)
This commit is contained in:
parent
0363be4776
commit
fac6110cb6
2 changed files with 40 additions and 2 deletions
|
|
@ -29,6 +29,7 @@ And please only add new entries to the top of this list, right below the `# Unre
|
||||||
- **Breaking:** remove `DeviceEvent::Text`.
|
- **Breaking:** remove `DeviceEvent::Text`.
|
||||||
- On Android, fix `DeviceId` to contain device id's.
|
- On Android, fix `DeviceId` to contain device id's.
|
||||||
- Add `Window::set_blur` to request a blur behind the window; implemented on Wayland for now.
|
- Add `Window::set_blur` to request a blur behind the window; implemented on Wayland for now.
|
||||||
|
- On Web, fix `ControlFlow::WaitUntil` to never wake up **before** the given time.
|
||||||
|
|
||||||
# 0.29.1-beta
|
# 0.29.1-beta
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,15 @@ impl Schedule {
|
||||||
options.signal(&controller.signal());
|
options.signal(&controller.signal());
|
||||||
|
|
||||||
if let Some(duration) = duration {
|
if let Some(duration) = duration {
|
||||||
options.delay(duration.as_millis() as f64);
|
// `Duration::as_millis()` always rounds down (because of truncation), we want to round
|
||||||
|
// up instead. This makes sure that the we never wake up **before** the given time.
|
||||||
|
let duration = duration
|
||||||
|
.as_secs()
|
||||||
|
.checked_mul(1000)
|
||||||
|
.and_then(|secs| secs.checked_add(duration_millis_ceil(duration).into()))
|
||||||
|
.unwrap_or(u64::MAX);
|
||||||
|
|
||||||
|
options.delay(duration as f64);
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
|
|
@ -121,9 +129,24 @@ impl Schedule {
|
||||||
.expect("Failed to send message")
|
.expect("Failed to send message")
|
||||||
});
|
});
|
||||||
let handle = if let Some(duration) = duration {
|
let handle = if let Some(duration) = duration {
|
||||||
|
// `Duration::as_millis()` always rounds down (because of truncation), we want to round
|
||||||
|
// up instead. This makes sure that the we never wake up **before** the given time.
|
||||||
|
let duration = duration
|
||||||
|
.as_secs()
|
||||||
|
.try_into()
|
||||||
|
.ok()
|
||||||
|
.and_then(|secs: i32| secs.checked_mul(1000))
|
||||||
|
.and_then(|secs: i32| {
|
||||||
|
let millis: i32 = duration_millis_ceil(duration)
|
||||||
|
.try_into()
|
||||||
|
.expect("millis are somehow bigger then 1K");
|
||||||
|
secs.checked_add(millis)
|
||||||
|
})
|
||||||
|
.unwrap_or(i32::MAX);
|
||||||
|
|
||||||
window.set_timeout_with_callback_and_timeout_and_arguments_0(
|
window.set_timeout_with_callback_and_timeout_and_arguments_0(
|
||||||
timeout_closure.as_ref().unchecked_ref(),
|
timeout_closure.as_ref().unchecked_ref(),
|
||||||
duration.as_millis() as i32,
|
duration,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
window.set_timeout_with_callback(timeout_closure.as_ref().unchecked_ref())
|
window.set_timeout_with_callback(timeout_closure.as_ref().unchecked_ref())
|
||||||
|
|
@ -160,6 +183,20 @@ impl Drop for Schedule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Replace with `u32::div_ceil()` when we hit Rust v1.73.
|
||||||
|
fn duration_millis_ceil(duration: Duration) -> u32 {
|
||||||
|
let micros = duration.subsec_micros();
|
||||||
|
|
||||||
|
// From <https://doc.rust-lang.org/1.73.0/src/core/num/uint_macros.rs.html#2086-2094>.
|
||||||
|
let d = micros / 1000;
|
||||||
|
let r = micros % 1000;
|
||||||
|
if r > 0 && 1000 > 0 {
|
||||||
|
d + 1
|
||||||
|
} else {
|
||||||
|
d
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn has_scheduler_support(window: &web_sys::Window) -> bool {
|
fn has_scheduler_support(window: &web_sys::Window) -> bool {
|
||||||
thread_local! {
|
thread_local! {
|
||||||
static SCHEDULER_SUPPORT: OnceCell<bool> = OnceCell::new();
|
static SCHEDULER_SUPPORT: OnceCell<bool> = OnceCell::new();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue