Skip to content

Commit

Permalink
Let wasm-bindgen to the caching for us
Browse files Browse the repository at this point in the history
  • Loading branch information
daxpedda committed Dec 8, 2024
1 parent ba1e6a7 commit 3db4c30
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 111 deletions.
6 changes: 2 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ serde = ["dep:serde"]
std = [
"wasm-bindgen/std",
"js-sys/std",
"once_cell/std",
"serde?/std",
"wasm-bindgen-test/std",
"getrandom/std",
Expand All @@ -32,10 +31,9 @@ std = [
]

[target.'cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))'.dependencies]
js-sys = { version = "0.3.73", default-features = false }
once_cell = { version = "1.12.0", default-features = false }
js-sys = { version = "0.3.75", default-features = false }
serde = { version = "1.0.0", optional = true, default-features = false }
wasm-bindgen = { version = "0.2.96", default-features = false }
wasm-bindgen = { version = "0.2.98", default-features = false }

[dev-dependencies]
wasm-bindgen-test = { version = "0.3", default-features = false }
Expand Down
18 changes: 12 additions & 6 deletions src/time/instant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
use core::ops::{Add, AddAssign, Sub, SubAssign};
use core::time::Duration;

use super::js::PERFORMANCE;
#[cfg(target_feature = "atomics")]
use super::js::Origin;
use super::js::Performance;
use super::js::TIME_ORIGIN;

/// See [`std::time::Instant`].
#[cfg_attr(
Expand All @@ -37,10 +37,16 @@ impl Instant {
)]
#[must_use]
pub fn now() -> Self {
#[cfg(not(target_feature = "atomics"))]
let now = Performance::now();
#[cfg(target_feature = "atomics")]
let now = Performance::now() + Origin::get();
let now = PERFORMANCE.with(|performance| {
let performance = performance
.as_ref()
.expect("`Performance` object not found");

#[cfg(not(target_feature = "atomics"))]
return performance.now();
#[cfg(target_feature = "atomics")]
TIME_ORIGIN.with(|origin| performance.now() + origin)
});

Self(time_stamp_to_duration(now))
}
Expand Down
110 changes: 9 additions & 101 deletions src/time/js.rs
Original file line number Diff line number Diff line change
@@ -1,114 +1,22 @@
//! Bindings to the JS API.
#[cfg(not(feature = "std"))]
use once_cell::unsync::Lazy;
use wasm_bindgen::prelude::wasm_bindgen;
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).
type JsPerformance;
pub(super) type Performance;

/// Holds the [`Performance`](https://developer.mozilla.org/en-US/docs/Web/API/Performance) object.
#[wasm_bindgen(thread_local_v2, js_namespace = globalThis, js_name = performance)]
pub(super) static PERFORMANCE: Option<Performance>;

/// Binding to [`Performance.now()`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now).
#[wasm_bindgen(method)]
fn now(this: &JsPerformance) -> f64;
pub(super) fn now(this: &Performance) -> f64;

/// Binding to [`Performance.timeOrigin`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/timeOrigin).
/// Holds the [`Performance.timeOrigin`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/timeOrigin).
#[cfg(target_feature = "atomics")]
#[wasm_bindgen(method, getter, js_name = timeOrigin)]
fn time_origin(this: &JsPerformance) -> f64;
}

/// Cached [`Performance` object](https://developer.mozilla.org/en-US/docs/Web/API/Performance).
pub(super) struct Performance;

impl Performance {
/// Create the [`Performance` object](https://developer.mozilla.org/en-US/docs/Web/API/Performance).
fn init() -> JsPerformance {
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()
}
}

/// Access to the underlying [`Performance` object](https://developer.mozilla.org/en-US/docs/Web/API/Performance).
#[cfg(feature = "std")]
fn with<R>(fun: impl FnOnce(&JsPerformance) -> R) -> R {
thread_local! {
static PERFORMANCE: JsPerformance = Performance::init();
}

PERFORMANCE.with(fun)
}

/// Access to the underlying [`Performance` object](https://developer.mozilla.org/en-US/docs/Web/API/Performance).
#[cfg(not(feature = "std"))]
fn with<R>(fun: impl FnOnce(&JsPerformance) -> R) -> R {
/// `Send + Sync` wrapper for [`Lazy`].
struct Wrapper<T>(T);

#[cfg(not(target_feature = "atomics"))]
#[allow(clippy::non_send_fields_in_send_ty, unsafe_code)]
// SAFETY: only when no threads are supported.
unsafe impl<T> Send for Wrapper<T> {}
#[cfg(not(target_feature = "atomics"))]
#[allow(clippy::non_send_fields_in_send_ty, unsafe_code)]
// SAFETY: only when no threads are supported.
unsafe impl<T> Sync for Wrapper<T> {}

/// Cached [`Performance` object](https://developer.mozilla.org/en-US/docs/Web/API/Performance).
#[cfg_attr(target_feature = "atomics", thread_local)]
static PERFORMANCE: Wrapper<Lazy<JsPerformance>> = Wrapper(Lazy::new(Performance::init));

#[allow(unsafe_code)]
fun(&PERFORMANCE.0)
}

/// Calls [`Performance.now()`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now).
pub(super) fn now() -> f64 {
Self::with(JsPerformance::now)
}
}

/// Cached [`Performance.timeOrigin`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/timeOrigin).
#[cfg(target_feature = "atomics")]
pub(super) struct Origin;

#[cfg(target_feature = "atomics")]
impl Origin {
/// Get [`Performance.timeOrigin`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/timeOrigin).
fn init() -> f64 {
Performance::with(JsPerformance::time_origin)
}

/// Returns [`Performance.timeOrigin`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/timeOrigin).
#[cfg(feature = "std")]
pub(super) fn get() -> f64 {
thread_local! {
static ORIGIN: f64 = Origin::init();
}

ORIGIN.with(|origin| *origin)
}

/// Returns [`Performance.timeOrigin`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/timeOrigin).
#[cfg(not(feature = "std"))]
pub(super) fn get() -> f64 {
#[thread_local]
static ORIGIN: Lazy<f64> = Lazy::new(Origin::init);

*ORIGIN
}
#[wasm_bindgen(thread_local_v2, js_namespace = ["globalThis", "performance"], js_name = timeOrigin)]
pub(super) static TIME_ORIGIN: f64;
}

0 comments on commit 3db4c30

Please sign in to comment.