eval.rs 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. #![allow(clippy::await_holding_refcell_ref)]
  2. use async_trait::async_trait;
  3. use dioxus_core::ScopeState;
  4. use dioxus_html::prelude::{EvalError, EvalProvider, Evaluator};
  5. use std::{cell::RefCell, rc::Rc};
  6. use crate::query::{Query, QueryEngine};
  7. /// Provides the DesktopEvalProvider through [`cx.provide_context`].
  8. pub fn init_eval(cx: &ScopeState) {
  9. let query = cx.consume_context::<QueryEngine>().unwrap();
  10. let provider: Rc<dyn EvalProvider> = Rc::new(DesktopEvalProvider { query });
  11. cx.provide_context(provider);
  12. }
  13. /// Reprents the desktop-target's provider of evaluators.
  14. pub struct DesktopEvalProvider {
  15. query: QueryEngine,
  16. }
  17. impl EvalProvider for DesktopEvalProvider {
  18. fn new_evaluator(&self, js: String) -> Result<Rc<dyn Evaluator>, EvalError> {
  19. Ok(Rc::new(DesktopEvaluator::new(self.query.clone(), js)))
  20. }
  21. }
  22. /// Reprents a desktop-target's JavaScript evaluator.
  23. pub(crate) struct DesktopEvaluator {
  24. query: Rc<RefCell<Query<serde_json::Value>>>,
  25. }
  26. impl DesktopEvaluator {
  27. /// Creates a new evaluator for desktop-based targets.
  28. pub fn new(query: QueryEngine, js: String) -> Self {
  29. let query = query.new_query(&js);
  30. Self {
  31. query: Rc::new(RefCell::new(query)),
  32. }
  33. }
  34. }
  35. #[async_trait(?Send)]
  36. impl Evaluator for DesktopEvaluator {
  37. /// # Panics
  38. /// This will panic if the query is currently being awaited.
  39. async fn join(&self) -> Result<serde_json::Value, EvalError> {
  40. self.query
  41. .borrow_mut()
  42. .result()
  43. .await
  44. .map_err(|e| EvalError::Communication(e.to_string()))
  45. }
  46. /// Sends a message to the evaluated JavaScript.
  47. fn send(&self, data: serde_json::Value) -> Result<(), EvalError> {
  48. if let Err(e) = self.query.borrow_mut().send(data) {
  49. return Err(EvalError::Communication(e.to_string()));
  50. }
  51. Ok(())
  52. }
  53. /// Gets an UnboundedReceiver to receive messages from the evaluated JavaScript.
  54. ///
  55. /// # Panics
  56. /// This will panic if the query is currently being awaited.
  57. async fn recv(&self) -> Result<serde_json::Value, EvalError> {
  58. self.query
  59. .borrow_mut()
  60. .recv()
  61. .await
  62. .map_err(|e| EvalError::Communication(e.to_string()))
  63. }
  64. }