diff --git a/embassy-time/src/driver_wasm.rs b/embassy-time/src/driver_wasm.rs index 492a9ee2ab..3fbf5422bc 100644 --- a/embassy-time/src/driver_wasm.rs +++ b/embassy-time/src/driver_wasm.rs @@ -45,22 +45,34 @@ embassy_time_driver::time_driver_impl!(static DRIVER: TimeDriver = TimeDriver { alarms: UninitCell::uninit(), }); +#[cfg(feature = "panic_on_webworker")] +thread_local! { + static CHECK_THREAD: Once = Once::new(); +} + impl TimeDriver { fn ensure_init(&self) { self.once.call_once(|| unsafe { self.alarms.write(Mutex::new([ALARM_NEW; ALARM_COUNT])); - #[cfg(feature = "panic_on_webworker")] - assert!(!is_web_worker_thread(), "Timer currently has issues on Web Workers: https://github.com/embassy-rs/embassy/issues/3313"); + }); + #[cfg(feature = "panic_on_webworker")] + CHECK_THREAD.with(|val| { + val.call_once(|| { + assert!( + !is_web_worker_thread(), + "Timer currently has issues on Web Workers: https://github.com/embassy-rs/embassy/issues/3313" + ); + }) }); } } impl Driver for TimeDriver { - fn now(&self) -> u64 { - self.ensure_init(); - // this is calibrated with timeOrigin. - now_as_calibrated_timestamp().as_micros() as u64 - } + fn now(&self) -> u64 { + self.ensure_init(); + // this is calibrated with timeOrigin. + now_as_calibrated_timestamp().as_micros() as u64 + } unsafe fn allocate_alarm(&self) -> Option { let id = self.alarm_count.fetch_update(Ordering::AcqRel, Ordering::Acquire, |x| { @@ -138,7 +150,9 @@ impl UninitCell { } fn is_web_worker_thread() -> bool { - js_sys::eval("typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope").unwrap().is_truthy() + js_sys::eval("typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope") + .unwrap() + .is_truthy() } // ---------------- taken from web-time/js.rs @@ -147,48 +161,47 @@ use wasm_bindgen::{JsCast, JsValue}; #[wasm_bindgen] extern "C" { - /// Type for the [global object](https://developer.mozilla.org/en-US/docs/Glossary/Global_object). - type Global; - - /// Returns the [`Performance`](https://developer.mozilla.org/en-US/docs/Web/API/Performance) object. - #[wasm_bindgen(method, getter)] - fn performance(this: &Global) -> JsValue; - - /// Type for the [`Performance` object](https://developer.mozilla.org/en-US/docs/Web/API/Performance). - pub(super) type Performance; - - /// Binding to [`Performance.now()`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now). - #[wasm_bindgen(method)] - pub(super) fn now(this: &Performance) -> f64; - - /// Binding to [`Performance.timeOrigin`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/timeOrigin). - #[cfg(target_feature = "atomics")] - #[wasm_bindgen(method, getter, js_name = timeOrigin)] - pub(super) fn time_origin(this: &Performance) -> f64; + /// Type for the [global object](https://developer.mozilla.org/en-US/docs/Glossary/Global_object). + type Global; + + /// Returns the [`Performance`](https://developer.mozilla.org/en-US/docs/Web/API/Performance) object. + #[wasm_bindgen(method, getter)] + fn performance(this: &Global) -> JsValue; + + /// Type for the [`Performance` object](https://developer.mozilla.org/en-US/docs/Web/API/Performance). + pub(super) type Performance; + + /// Binding to [`Performance.now()`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now). + #[wasm_bindgen(method)] + pub(super) fn now(this: &Performance) -> f64; + + /// Binding to [`Performance.timeOrigin`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/timeOrigin). + #[cfg(target_feature = "atomics")] + #[wasm_bindgen(method, getter, js_name = timeOrigin)] + pub(super) fn time_origin(this: &Performance) -> f64; } thread_local! { - pub(super) static PERFORMANCE: Performance = { - let global: Global = js_sys::global().unchecked_into(); - let performance = global.performance(); - - if performance.is_undefined() { - panic!("`Performance` object not found") - } else { - performance.unchecked_into() - } - }; -} + pub(super) static PERFORMANCE: Performance = { + let global: Global = js_sys::global().unchecked_into(); + let performance = global.performance(); + if performance.is_undefined() { + panic!("`Performance` object not found") + } else { + performance.unchecked_into() + } + }; +} // ---------------- taken from web-time/instant.rs thread_local! { - static ORIGIN: f64 = PERFORMANCE.with(Performance::time_origin); + static ORIGIN: f64 = PERFORMANCE.with(Performance::time_origin); } -/// This will get a Duration from a synchronized start point, whether in webworkers or the main browser thread. -/// +/// This will get a Duration from a synchronized start point, whether in webworkers or the main browser thread. +/// /// # Panics /// /// This call will panic if the [`Performance` object] was not found, e.g. @@ -198,10 +211,10 @@ thread_local! { /// [worklet]: https://developer.mozilla.org/en-US/docs/Web/API/Worklet #[must_use] pub fn now_as_calibrated_timestamp() -> core::time::Duration { - let now = PERFORMANCE.with(|performance| { - return ORIGIN.with(|origin| performance.now() + origin); - }); - time_stamp_to_duration(now) + let now = PERFORMANCE.with(|performance| { + return ORIGIN.with(|origin| performance.now() + origin); + }); + time_stamp_to_duration(now) } /// Converts a `DOMHighResTimeStamp` to a [`Duration`]. @@ -210,12 +223,8 @@ pub fn now_as_calibrated_timestamp() -> core::time::Duration { /// /// Keep in mind that like [`Duration::from_secs_f64()`] this doesn't do perfect /// rounding. -#[allow( - clippy::as_conversions, - clippy::cast_possible_truncation, - clippy::cast_sign_loss -)] +#[allow(clippy::as_conversions, clippy::cast_possible_truncation, clippy::cast_sign_loss)] fn time_stamp_to_duration(time_stamp: f64) -> core::time::Duration { - core::time::Duration::from_millis(time_stamp.trunc() as u64) - + core::time::Duration::from_nanos((time_stamp.fract() * 1.0e6).round() as u64) + core::time::Duration::from_millis(time_stamp.trunc() as u64) + + core::time::Duration::from_nanos((time_stamp.fract() * 1.0e6).round() as u64) }