Run inside browser using web framework
Describe the bug Hello all, I'm trying to build a low-code development framework in Rust using the Dioxus framework where users have the option to add javascript to, for example, manipulate parts of interface or results from an API fetch.
To Reproduce First I wanted to test this with a simple web app with nothing but a textarea, a button and a span (for the output)
use boa_engine::{Context, Source};
use dioxus::prelude::*;
const FAVICON: Asset = asset!("/assets/favicon.ico");
const MAIN_CSS: Asset = asset!("/assets/main.css");
const HEADER_SVG: Asset = asset!("/assets/header.svg");
fn main() {
dioxus::launch(App);
}
#[component]
fn App() -> Element {
rsx! {
document::Link { rel: "icon", href: FAVICON }
document::Link { rel: "stylesheet", href: MAIN_CSS }
Hero {}
}
}
fn run_js(script: &str) -> String {
let mut context = Context::default();
match context.eval(Source::from_bytes(script)) {
Ok(result) => result.as_string().unwrap().to_std_string_escaped(),
Err(e) => format!("Error: {e}"),
}
}
#[component]
pub fn Hero() -> Element {
let mut script = use_signal(|| "".to_string());
let mut output = use_signal(|| "".to_string());
rsx! {
div {
h1 {"Testing Boa in Dioxus"}
textarea {
value: "{script}",
rows: "5",
cols: "50",
oninput: move |e| script.set(e.value()),
}
button {
onclick: move |_| {
let result = run_js(&script());
output.set(result);
},
"Run Script"
}
p {
strong { "Output: " }
span {"{output}"}
}
}
}
}
Here's my Cargo.toml:
[package]
name = "dxboa"
version = "0.1.0"
authors = ["Naveed Aman Pasha <[email protected]>"]
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
boa_engine = { version = "0.20.0", features = ["js", "annex-b", "experimental"] }
dioxus = { version = "0.6.0", features = [] }
[features]
default = ["web"]
web = ["dioxus/web"]
desktop = ["dioxus/desktop"]
mobile = ["dioxus/mobile"]
[profile.wasm-dev]
inherits = "dev"
opt-level = 1
[profile.server-dev]
inherits = "dev"
[profile.android-dev]
inherits = "dev"
Expected behavior It should compile and let me run javascript in the web app and show the output.
Observed Behaviour Instead I get the following error:
13:17:29 [dev] Full rebuild: triggered manually
13:17:29 [cargo] error: the wasm*-unknown-unknown targets are not supported by default, you may need to enable the "js" feature. For more information see: https://docs.rs/getrandom/#webassembly-support
--> /home/naveedpash/.cargo/registry/src/index.crates.io-6f17d22bba15001f/getrandom-0.2.15/src/lib.rs:342:9
|
342 | / compile_error!("the wasm*-unknown-unknown targets are not supported by \
343 | | default, you may need to enable the \"js\" feature. \
344 | | For more information see: \
345 | | https://docs.rs/getrandom/#webassembly-support");
| |________________________________________________________________________^
13:17:29 [cargo] error[E0433]: failed to resolve: use of undeclared crate or module `imp`
--> /home/naveedpash/.cargo/registry/src/index.crates.io-6f17d22bba15001f/getrandom-0.2.15/src/lib.rs:398:9
|
398 | imp::getrandom_inner(dest)?;
| ^^^ use of undeclared crate or module `imp`
13:17:29 [cargo] For more information about this error, try `rustc --explain E0433`.
13:17:29 [cargo] error: could not compile `getrandom` (lib) due to 2 previous errors
13:17:29 [cargo] Caused by:
13:17:29 [cargo] process didn't exit successfully: `/home/naveedpash/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/rustc --crate-name getrandom --edition=2018 /home/naveedpash/.cargo/registry/src/index.crates.io-6f17d22bba15001f/getrandom-0.2.15/src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --crate-type lib --emit=dep-info,metadata,link -C opt-level=1 -C embed-bitcode=no -C debuginfo=2 -C debug-assertions=on --cfg 'feature="std"' --check-cfg 'cfg(docsrs)' --check-cfg 'cfg(feature, values("compiler_builtins", "core", "custom", "js", "js-sys", "linux_disable_fallback", "rdrand", "rustc-dep-of-std", "std", "test-in-browser", "wasm-bindgen"))' -C metadata=1cec50e53ab3a290 -C extra-filename=-1cec50e53ab3a290 --out-dir /home/naveedpash/playgrounds/dxboa/target/wasm32-unknown-unknown/wasm-dev/deps --target wasm32-unknown-unknown -L dependency=/home/naveedpash/playgrounds/dxboa/target/wasm32-unknown-unknown/wasm-dev/deps -L dependency=/home/naveedpash/playgrounds/dxboa/target/wasm-dev/deps --extern cfg_if=/home/naveedpash/playgrounds/dxboa/target/wasm32-unknown-unknown/wasm-dev/deps/libcfg_if-5bf9827c65f43b49.rmeta --cap-lints allow` (exit status: 1)
13:17:29 [cargo] warning: build failed, waiting for other jobs to finish...
13:17:29 [dev] Build failed: Other(Cargo build failed, signaled by the compiler. Toggle tracing mode (press `t`) for more information.)
I tried following the example given in the ffi/wasm folder of this repository but still keep getting the same error...
Build environment (please complete the following information):
- OS: [e.g. Ubuntu]
- Version: [e.g. 24.04]
- Target triple: [e.g. wasm32-unknown-unknown]
- Rustc version: rustc 1.84.0 (9fc6b4312 2025-01-07)
Hello @naveedpash 👋
What you could do, is add the dependency in your Cargo.toml enabling the flag as an optional dependency, then conditionally enable it based on feature.
getrandom = { version = "0.2.16", optional = true }
# ...
web = ["dioxus/web", "getrandom/js"]
When you build the features will be unified, for more info on feature unification see: https://doc.rust-lang.org/cargo/reference/features.html#feature-unification
Ideally, the flag would be set by boa's "js" feature, will work on a PR for that with a little documentation on wasm compilation, since newer versions of getrandom (used in main branch) require some config to be set for getrandom on wasm32-unknown-unknown target