diff --git a/Cargo.lock b/Cargo.lock index 973cf2d28..9ed31d418 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -446,9 +446,11 @@ dependencies = [ "sha2", "thiserror", "tokio", + "tsify-next", "uniffi", "uuid", "validator", + "wasm-bindgen", "wiremock", "zeroize", "zxcvbn", @@ -3541,6 +3543,17 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-wasm-bindgen" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + [[package]] name = "serde_derive" version = "1.0.210" @@ -4208,6 +4221,30 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "tsify-next" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f4a645dca4ee0800f5ab60ce166deba2db6a0315de795a2691e138a3d55d756" +dependencies = [ + "serde", + "serde-wasm-bindgen", + "tsify-next-macros", + "wasm-bindgen", +] + +[[package]] +name = "tsify-next-macros" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d5c06f8a51d759bb58129e30b2631739e7e1e4579fad1f30ac09a6c88e488a6" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.77", +] + [[package]] name = "typenum" version = "1.17.0" diff --git a/Cargo.toml b/Cargo.toml index 8c978819b..8dbcc2a19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,11 @@ bitwarden-send = { path = "crates/bitwarden-send", version = "=1.0.0" } bitwarden-sm = { path = "crates/bitwarden-sm", version = "=1.0.0" } bitwarden-vault = { path = "crates/bitwarden-vault", version = "=1.0.0" } +wasm-bindgen = { version = ">=0.2.91, <0.3", features = ["serde-serialize"] } +tsify-next = { version = ">=0.5.4, <0.6", features = [ + "js", +], default-features = false } + [workspace.lints.clippy] unused_async = "deny" unwrap_used = "deny" diff --git a/crates/bitwarden-core/Cargo.toml b/crates/bitwarden-core/Cargo.toml index 7059e26c3..f668b83b9 100644 --- a/crates/bitwarden-core/Cargo.toml +++ b/crates/bitwarden-core/Cargo.toml @@ -20,6 +20,7 @@ no-memory-hardening = [ ] # Disable memory hardening features uniffi = ["bitwarden-crypto/uniffi", "dep:uniffi"] # Uniffi bindings secrets = [] # Secrets manager API +wasm = ["dep:wasm-bindgen", "dep:tsify-next"] # WASM support [dependencies] base64 = ">=0.22.1, <0.23" @@ -51,8 +52,10 @@ thiserror = ">=1.0.40, <2.0" uniffi = { version = "=0.28.1", optional = true, features = ["tokio"] } uuid = { version = ">=1.3.3, <2.0", features = ["serde"] } validator = { version = "0.18.1", features = ["derive"] } +wasm-bindgen = { workspace = true, optional = true } zeroize = { version = ">=1.7.0, <2.0", features = ["derive", "aarch64"] } zxcvbn = { version = ">=3.0.1, <4.0", optional = true } +tsify-next = { workspace = true, optional = true } [target.'cfg(not(target_arch="wasm32"))'.dependencies] # By default, we use rustls as the TLS stack and rust-platform-verifier to support user-installed root certificates diff --git a/crates/bitwarden-core/src/client/client_settings.rs b/crates/bitwarden-core/src/client/client_settings.rs index bd678d131..48c03eea3 100644 --- a/crates/bitwarden-core/src/client/client_settings.rs +++ b/crates/bitwarden-core/src/client/client_settings.rs @@ -19,6 +19,11 @@ use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(default, rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "uniffi", derive(uniffi::Record))] +#[cfg_attr( + feature = "wasm", + derive(tsify_next::Tsify), + tsify(into_wasm_abi, from_wasm_abi) +)] pub struct ClientSettings { /// The identity url of the targeted Bitwarden instance. Defaults to `https://identity.bitwarden.com` pub identity_url: String, @@ -44,6 +49,11 @@ impl Default for ClientSettings { #[allow(non_camel_case_types)] #[derive(Serialize, Deserialize, Copy, Clone, Debug, JsonSchema)] #[cfg_attr(feature = "uniffi", derive(uniffi::Enum))] +#[cfg_attr( + feature = "wasm", + derive(tsify_next::Tsify), + tsify(into_wasm_abi, from_wasm_abi) +)] pub enum DeviceType { Android = 0, iOS = 1, diff --git a/crates/bitwarden-wasm-internal/Cargo.toml b/crates/bitwarden-wasm-internal/Cargo.toml index fbfdb9fab..df69015cf 100644 --- a/crates/bitwarden-wasm-internal/Cargo.toml +++ b/crates/bitwarden-wasm-internal/Cargo.toml @@ -15,7 +15,7 @@ keywords.workspace = true crate-type = ["cdylib"] [dependencies] -bitwarden = { workspace = true } +bitwarden = { workspace = true, features = ["internal", "wasm"] } console_error_panic_hook = "0.1.7" console_log = { version = "1.0.0", features = ["color"] } js-sys = "0.3.68" diff --git a/crates/bitwarden-wasm-internal/src/client.rs b/crates/bitwarden-wasm-internal/src/client.rs index fcf68fd50..994af1fcf 100644 --- a/crates/bitwarden-wasm-internal/src/client.rs +++ b/crates/bitwarden-wasm-internal/src/client.rs @@ -32,14 +32,14 @@ pub struct BitwardenClient(Rc); #[wasm_bindgen] impl BitwardenClient { #[wasm_bindgen(constructor)] - pub fn new(settings_input: Option, log_level: Option) -> Self { + pub fn new(settings: Option, log_level: Option) -> Self { console_error_panic_hook::set_once(); let log_level = convert_level(log_level.unwrap_or(LogLevel::Info)); if let Err(_e) = console_log::init_with_level(log_level) { set_max_level(log_level.to_level_filter()) } - Self(Rc::new(Client::new(Self::parse_settings(settings_input)))) + Self(Rc::new(Client::new(settings))) } /// Test method, echoes back the input @@ -54,16 +54,4 @@ impl BitwardenClient { res.text().await.map_err(|e| e.to_string()) } - - fn parse_settings(settings_input: Option) -> Option { - if let Some(input) = settings_input.as_ref() { - match serde_json::from_str(input) { - Ok(settings) => return Some(settings), - Err(e) => { - log::error!("Failed to parse settings: {}", e); - } - } - } - None - } } diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index f927564cf..b2adeaaa2 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -35,7 +35,12 @@ uniffi = [ "bitwarden-send/uniffi", "bitwarden-vault/uniffi", ] # Uniffi bindings -secrets = ["bitwarden-core/secrets", "dep:bitwarden-sm", "dep:bitwarden-generators"] # Secrets manager API +secrets = [ + "bitwarden-core/secrets", + "dep:bitwarden-sm", + "dep:bitwarden-generators", +] # Secrets manager API +wasm = ["bitwarden-core/wasm"] # WASM support [dependencies] bitwarden-api-api = { workspace = true } diff --git a/languages/js/sdk-internal/fallback.js b/languages/js/sdk-internal/fallback.js deleted file mode 100644 index 7da517d3f..000000000 --- a/languages/js/sdk-internal/fallback.js +++ /dev/null @@ -1,28 +0,0 @@ -// https://stackoverflow.com/a/47880734 -const supported = (() => { - try { - if (typeof WebAssembly === "object" && typeof WebAssembly.instantiate === "function") { - const module = new WebAssembly.Module( - Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00), - ); - if (module instanceof WebAssembly.Module) - return new WebAssembly.Instance(module) instanceof WebAssembly.Instance; - } - } catch (e) {} - return false; -})(); - -let wasm; - -if (supported) { - wasm = await import("./bitwarden_wasm_internal_bg.wasm"); -} else { - wasm = await import("./bitwarden_wasm_internal_bg.wasm.js"); -} - -import { __wbg_set_wasm } from "./bitwarden_wasm_internal_bg.js"; -__wbg_set_wasm(wasm); -export * from "./bitwarden_wasm_internal_bg.js"; - -// Expose if wasm is supported or not -export const supportsWasm = supported; diff --git a/languages/js/sdk-internal/index.js b/languages/js/sdk-internal/index.js new file mode 100644 index 000000000..863818494 --- /dev/null +++ b/languages/js/sdk-internal/index.js @@ -0,0 +1,7 @@ +import { __wbg_set_wasm } from "./bitwarden_wasm_internal_bg.js"; + +export function init(wasm) { + __wbg_set_wasm(wasm); +} + +export * from "./bitwarden_wasm_internal_bg.js"; diff --git a/languages/js/sdk-internal/package.json b/languages/js/sdk-internal/package.json index c4768dc2f..94b678141 100644 --- a/languages/js/sdk-internal/package.json +++ b/languages/js/sdk-internal/package.json @@ -15,7 +15,7 @@ "node/bitwarden_wasm_internal.js" ], "main": "node/bitwarden_wasm_internal.js", - "module": "bitwarden_wasm_internal.js", + "module": "index.js", "types": "bitwarden_wasm_internal.d.ts", "scripts": {}, "sideEffects": [