Skip to content

Commit

Permalink
actually warn on web workers
Browse files Browse the repository at this point in the history
  • Loading branch information
9SMTM6 committed Sep 7, 2024
1 parent fe148f2 commit c9974b4
Showing 1 changed file with 60 additions and 51 deletions.
111 changes: 60 additions & 51 deletions embassy-time/src/driver_wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<AlarmHandle> {
let id = self.alarm_count.fetch_update(Ordering::AcqRel, Ordering::Acquire, |x| {
Expand Down Expand Up @@ -138,7 +150,9 @@ impl<T: Copy> UninitCell<T> {
}

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
Expand All @@ -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.
Expand All @@ -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`].
Expand All @@ -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)
}

0 comments on commit c9974b4

Please sign in to comment.