Skip to content

Commit 635a42f

Browse files
hculeaAndyTitu
andauthored
Add support for WASM targets running in a custom runtime (#83)
* Add support for injecting unix millisecond time function for non-JS WASM targets * Cleanup dependencies in WASM targets * Rename feature for better conveying the intention * Run cargo fmt and add getrandom as dev dependency * Revert feature conditional cfg in tests * Make sure wasm-pack only runs features that are compatible with wasm-bindgen --------- Co-authored-by: AndyTitu <[email protected]>
1 parent 6b4ba36 commit 635a42f

File tree

4 files changed

+43
-6
lines changed

4 files changed

+43
-6
lines changed

.github/workflows/zxcvbn.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -96,4 +96,6 @@ jobs:
9696
run: cargo build --target wasm32-unknown-unknown --tests --benches
9797

9898
- name: Run tests (wasm, all features)
99-
run: wasm-pack test --node --all-features
99+
env:
100+
ALL_WASM_BINDGEN_FEATURES: "default,ser,builder"
101+
run: wasm-pack test --node --features $ALL_WASM_BINDGEN_FEATURES

Cargo.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ regex = "1"
2222
time = { version = "0.3" }
2323

2424
[target.'cfg(target_arch = "wasm32")'.dependencies]
25-
getrandom = { version = "0.2", features = ["js"] }
25+
chrono = "0.4.38"
2626
wasm-bindgen = "0.2"
2727
web-sys = { version = "0.3", features = ["Performance"] }
2828

@@ -41,12 +41,14 @@ serde_json = "1"
4141

4242
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
4343
criterion = { version = "0.5", default-features = false }
44+
getrandom = { version = "0.2", features = ["js"] }
4445
wasm-bindgen-test = "0.3"
4546

4647
[features]
4748
default = ["builder"]
4849
ser = ["serde"]
4950
builder = ["derive_builder"]
51+
custom_wasm_env = []
5052

5153
[profile.test]
5254
opt-level = 2

src/lib.rs

+19-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#![doc = include_str!("../README.md")]
22
#![recursion_limit = "128"]
33
#![warn(missing_docs)]
4-
#![forbid(unsafe_code)]
54

65
#[macro_use]
76
#[cfg(feature = "builder")]
@@ -18,7 +17,7 @@ extern crate quickcheck;
1817

1918
pub use scoring::Score;
2019
use time_estimates::CrackTimes;
21-
#[cfg(target_arch = "wasm32")]
20+
#[cfg(all(target_arch = "wasm32", not(feature = "custom_wasm_env")))]
2221
use wasm_bindgen::prelude::wasm_bindgen;
2322

2423
pub use crate::matching::Match;
@@ -42,7 +41,7 @@ where
4241
(result, calc_time)
4342
}
4443

45-
#[cfg(target_arch = "wasm32")]
44+
#[cfg(all(target_arch = "wasm32", not(feature = "custom_wasm_env")))]
4645
#[allow(non_upper_case_globals)]
4746
fn time_scoped<F, R>(f: F) -> (R, Duration)
4847
where
@@ -61,6 +60,23 @@ where
6160
(result, calc_time)
6261
}
6362

63+
#[cfg(all(target_arch = "wasm32", feature = "custom_wasm_env"))]
64+
fn time_scoped<F, R>(f: F) -> (R, Duration)
65+
where
66+
F: FnOnce() -> R,
67+
{
68+
#[link(wasm_import_module = "zxcvbn")]
69+
extern "C" {
70+
fn unix_time_milliseconds_imported() -> u64;
71+
}
72+
let start_time = unsafe { unix_time_milliseconds_imported() };
73+
let result = f();
74+
let end_time = unsafe { unix_time_milliseconds_imported() };
75+
76+
let duration = std::time::Duration::from_millis(end_time - start_time);
77+
(result, duration)
78+
}
79+
6480
/// Contains the results of an entropy calculation
6581
#[derive(Debug, Clone)]
6682
#[cfg_attr(feature = "ser", derive(serde::Serialize))]

src/scoring.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,31 @@ lazy_static! {
7777
pub(crate) static ref REFERENCE_YEAR: i32 = time::OffsetDateTime::now_utc().year();
7878
}
7979

80-
#[cfg(target_arch = "wasm32")]
80+
#[cfg(all(target_arch = "wasm32", not(feature = "custom_wasm_env")))]
8181
lazy_static! {
8282
pub(crate) static ref REFERENCE_YEAR: i32 = web_sys::js_sys::Date::new_0()
8383
.get_full_year()
8484
.try_into()
8585
.unwrap();
8686
}
8787

88+
#[cfg(all(target_arch = "wasm32", feature = "custom_wasm_env"))]
89+
lazy_static! {
90+
pub(crate) static ref REFERENCE_YEAR: i32 = {
91+
#[link(wasm_import_module = "zxcvbn")]
92+
extern "C" {
93+
fn unix_time_milliseconds_imported() -> u64;
94+
}
95+
let unix_millis = unsafe { unix_time_milliseconds_imported() };
96+
97+
use chrono::Datelike;
98+
chrono::DateTime::<chrono::Utc>::from(
99+
std::time::SystemTime::UNIX_EPOCH + std::time::Duration::from_millis(unix_millis),
100+
)
101+
.year()
102+
};
103+
}
104+
88105
const MIN_YEAR_SPACE: i32 = 20;
89106
const BRUTEFORCE_CARDINALITY: u64 = 10;
90107
const MIN_GUESSES_BEFORE_GROWING_SEQUENCE: u64 = 10_000;

0 commit comments

Comments
 (0)