diff --git a/examples/eval.rs b/examples/eval.rs index 9e0646147..31ee813e9 100644 --- a/examples/eval.rs +++ b/examples/eval.rs @@ -25,8 +25,7 @@ fn app() -> Element { console.log(msg); return "hi from JS!"; "#, - ) - .unwrap(); + ); // Send a message to the JS code. eval.send("Hi from Rust!".into()).unwrap(); diff --git a/packages/desktop/headless_tests/events.rs b/packages/desktop/headless_tests/events.rs index 07be8be96..f9009ebe4 100644 --- a/packages/desktop/headless_tests/events.rs +++ b/packages/desktop/headless_tests/events.rs @@ -45,7 +45,7 @@ fn mock_event(id: &'static str, value: &'static str) { value, id ); - eval(&js).unwrap().await.unwrap(); + eval(&js).await.unwrap(); }); }) } diff --git a/packages/desktop/headless_tests/rendering.rs b/packages/desktop/headless_tests/rendering.rs index 0df48de07..882c70d21 100644 --- a/packages/desktop/headless_tests/rendering.rs +++ b/packages/desktop/headless_tests/rendering.rs @@ -38,7 +38,6 @@ fn use_inner_html(id: &'static str) -> Option { return element.innerHTML"#, id )) - .unwrap() .await .unwrap(); diff --git a/packages/desktop/src/eval.rs b/packages/desktop/src/eval.rs index 1a7b6aa6a..f920a508c 100644 --- a/packages/desktop/src/eval.rs +++ b/packages/desktop/src/eval.rs @@ -15,8 +15,8 @@ impl DesktopEvalProvider { } impl EvalProvider for DesktopEvalProvider { - fn new_evaluator(&self, js: String) -> Result>, EvalError> { - Ok(DesktopEvaluator::create(self.desktop_ctx.clone(), js)) + fn new_evaluator(&self, js: String) -> GenerationalBox> { + DesktopEvaluator::create(self.desktop_ctx.clone(), js) } } diff --git a/packages/html/src/eval.rs b/packages/html/src/eval.rs index 62ac1d4a2..5151750cd 100644 --- a/packages/html/src/eval.rs +++ b/packages/html/src/eval.rs @@ -1,7 +1,7 @@ #![allow(clippy::await_holding_refcell_ref)] use dioxus_core::prelude::*; -use generational_box::GenerationalBox; +use generational_box::{AnyStorage, GenerationalBox, UnsyncStorage}; use std::future::{poll_fn, Future, IntoFuture}; use std::pin::Pin; use std::rc::Rc; @@ -10,7 +10,7 @@ use std::task::{Context, Poll}; /// A struct that implements EvalProvider is sent through [`ScopeState`]'s provide_context function /// so that [`use_eval`] can provide a platform agnostic interface for evaluating JavaScript code. pub trait EvalProvider { - fn new_evaluator(&self, js: String) -> Result>, EvalError>; + fn new_evaluator(&self, js: String) -> GenerationalBox>; } /// The platform's evaluator. @@ -29,7 +29,7 @@ pub trait Evaluator { ) -> Poll>; } -type EvalCreator = Rc Result>; +type EvalCreator = Rc UseEval>; /// Get a struct that can execute any JavaScript. /// @@ -43,19 +43,45 @@ type EvalCreator = Rc Result>; pub fn eval_provider() -> EvalCreator { let eval_provider = consume_context::>(); - Rc::new(move |script: &str| { - eval_provider - .new_evaluator(script.to_string()) - .map(UseEval::new) - }) as Rc Result> + Rc::new(move |script: &str| UseEval::new(eval_provider.new_evaluator(script.to_string()))) + as Rc UseEval> } -pub fn eval(script: &str) -> Result { - let eval_provider = dioxus_core::prelude::consume_context::>(); +pub fn eval(script: &str) -> UseEval { + let eval_provider = dioxus_core::prelude::try_consume_context::>() + // Create a dummy provider that always hiccups when trying to evaluate + // That way, we can still compile and run the code without a real provider + .unwrap_or_else(|| { + struct DummyProvider; + impl EvalProvider for DummyProvider { + fn new_evaluator(&self, _js: String) -> GenerationalBox> { + UnsyncStorage::owner().insert(Box::new(DummyEvaluator)) + } + } - eval_provider - .new_evaluator(script.to_string()) - .map(UseEval::new) + struct DummyEvaluator; + impl Evaluator for DummyEvaluator { + fn send(&self, _data: serde_json::Value) -> Result<(), EvalError> { + Err(EvalError::Unsupported) + } + fn poll_recv( + &mut self, + _context: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Err(EvalError::Unsupported)) + } + fn poll_join( + &mut self, + _context: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Err(EvalError::Unsupported)) + } + } + + Rc::new(DummyProvider) as Rc + }); + + UseEval::new(eval_provider.new_evaluator(script.to_string())) } /// A wrapper around the target platform's evaluator. diff --git a/packages/liveview/src/eval.rs b/packages/liveview/src/eval.rs index e521b35dc..c7dca0c3d 100644 --- a/packages/liveview/src/eval.rs +++ b/packages/liveview/src/eval.rs @@ -18,8 +18,8 @@ pub struct DesktopEvalProvider { } impl EvalProvider for DesktopEvalProvider { - fn new_evaluator(&self, js: String) -> Result>, EvalError> { - Ok(DesktopEvaluator::create(self.query.clone(), js)) + fn new_evaluator(&self, js: String) -> GenerationalBox> { + DesktopEvaluator::create(self.query.clone(), js) } } diff --git a/packages/playwright-tests/web/src/main.rs b/packages/playwright-tests/web/src/main.rs index 787988c62..3ac275eb1 100644 --- a/packages/playwright-tests/web/src/main.rs +++ b/packages/playwright-tests/web/src/main.rs @@ -24,12 +24,11 @@ fn app() -> Element { class: "eval-button", onclick: move |_| async move { let mut eval = eval( - r#" - window.document.title = 'Hello from Dioxus Eval!'; - dioxus.send("returned eval value"); - "#, - ) - .unwrap(); + r#" + window.document.title = 'Hello from Dioxus Eval!'; + dioxus.send("returned eval value"); + "#, + ); let result = eval.recv().await; if let Ok(serde_json::Value::String(string)) = result { diff --git a/packages/ssr/src/eval.rs b/packages/ssr/src/eval.rs index c55b7167f..af9d56394 100644 --- a/packages/ssr/src/eval.rs +++ b/packages/ssr/src/eval.rs @@ -13,9 +13,9 @@ pub fn init_eval() { /// Reprents the ssr-target's provider of evaluators. pub struct SSREvalProvider; impl EvalProvider for SSREvalProvider { - fn new_evaluator(&self, _: String) -> Result>, EvalError> { + fn new_evaluator(&self, _: String) -> GenerationalBox> { let owner = UnsyncStorage::owner(); - Ok(owner.insert(Box::new(SSREvaluator) as Box)) + owner.insert(Box::new(SSREvaluator) as Box) } } diff --git a/packages/web/src/eval.rs b/packages/web/src/eval.rs index 4156a9005..cb9bc0e42 100644 --- a/packages/web/src/eval.rs +++ b/packages/web/src/eval.rs @@ -16,7 +16,7 @@ pub fn init_eval() { /// Represents the web-target's provider of evaluators. pub struct WebEvalProvider; impl EvalProvider for WebEvalProvider { - fn new_evaluator(&self, js: String) -> Result>, EvalError> { + fn new_evaluator(&self, js: String) -> GenerationalBox> { WebEvaluator::create(js) } } @@ -33,12 +33,12 @@ const PROMISE_WRAPPER: &str = r#" struct WebEvaluator { dioxus: Dioxus, channel_receiver: futures_channel::mpsc::UnboundedReceiver, - result: Option, + result: Option>, } impl WebEvaluator { /// Creates a new evaluator for web-based targets. - fn create(js: String) -> Result>, EvalError> { + fn create(js: String) -> GenerationalBox> { let (mut channel_sender, channel_receiver) = futures_channel::mpsc::unbounded(); let owner = UnsyncStorage::owner(); let invalid = owner.invalid(); @@ -69,23 +69,21 @@ impl WebEvaluator { let string: String = stringified.into(); Value::from_str(&string).map_err(|e| { EvalError::Communication(format!("Failed to parse result - {}", e)) - })? + }) } else { - return Err(EvalError::Communication( + Err(EvalError::Communication( "Failed to stringify result".into(), - )); + )) } } else { - return Err(EvalError::Communication( + Err(EvalError::Communication( "Failed to stringify result".into(), - )); + )) } } - Err(err) => { - return Err(EvalError::InvalidJs( - err.as_string().unwrap_or("unknown".to_string()), - )); - } + Err(err) => Err(EvalError::InvalidJs( + err.as_string().unwrap_or("unknown".to_string()), + )), }; invalid.set(Box::new(Self { @@ -94,7 +92,7 @@ impl WebEvaluator { result: Some(result), }) as Box); - Ok(invalid) + invalid } } @@ -105,7 +103,7 @@ impl Evaluator for WebEvaluator { _cx: &mut std::task::Context<'_>, ) -> std::task::Poll> { if let Some(result) = self.result.take() { - std::task::Poll::Ready(Ok(result)) + std::task::Poll::Ready(result) } else { std::task::Poll::Ready(Err(EvalError::Finished)) }