Browse Source

add a noop evaluator to the ssr renderer

Evan Almloff 1 year ago
parent
commit
b9554fd744

+ 1 - 0
packages/fullstack/examples/axum-hello-world/src/main.rs

@@ -24,6 +24,7 @@ fn app(cx: Scope<AppProps>) -> Element {
 
     let mut count = use_state(cx, || 0);
     let text = use_state(cx, || "...".to_string());
+    let eval = use_eval(cx);
 
     cx.render(rsx! {
         div {

+ 2 - 0
packages/fullstack/src/render.rs

@@ -45,6 +45,8 @@ impl SsrRendererPool {
                         .expect("couldn't spawn runtime")
                         .block_on(async move {
                             let mut vdom = VirtualDom::new_with_props(component, props);
+                            // Make sure the evaluator is initialized
+                            dioxus_ssr::eval::init_eval(vdom.base_scope());
                             let mut to = WriteBuffer { buffer: Vec::new() };
                             // before polling the future, we need to set the context
                             let prev_context =

+ 3 - 0
packages/ssr/Cargo.toml

@@ -10,6 +10,7 @@ keywords = ["dom", "ui", "gui", "react", "ssr"]
 
 [dependencies]
 dioxus-core = { workspace = true, features = ["serialize"] }
+dioxus-html = { workspace = true }
 askama_escape = "0.10.3"
 thiserror = "1.0.23"
 rustc-hash = "1.1.0"
@@ -17,6 +18,8 @@ lru = "0.10.0"
 tracing = { workspace = true }
 http = "0.2.9"
 tokio = { version = "1.28", features = ["full"], optional = true }
+async-trait = "0.1.58"
+serde_json = { version = "1.0" }
 
 [dev-dependencies]
 dioxus = { workspace = true }

+ 42 - 0
packages/ssr/src/eval.rs

@@ -0,0 +1,42 @@
+use async_trait::async_trait;
+use dioxus_core::ScopeState;
+use dioxus_html::prelude::{EvalError, EvalProvider, Evaluator};
+use std::rc::Rc;
+
+/// Provides the SSREvalProvider through [`cx.provide_context`].
+pub fn init_eval(cx: &ScopeState) {
+    let provider: Rc<dyn EvalProvider> = Rc::new(SSREvalProvider {});
+    cx.provide_context(provider);
+}
+
+/// Reprents the ssr-target's provider of evaluators.
+pub struct SSREvalProvider;
+impl EvalProvider for SSREvalProvider {
+    fn new_evaluator(&self, _: String) -> Result<Rc<dyn Evaluator>, EvalError> {
+        Ok(Rc::new(SSREvaluator) as Rc<dyn Evaluator + 'static>)
+    }
+}
+
+/// Represents a ssr-target's JavaScript evaluator.
+pub struct SSREvaluator;
+
+// In ssr rendering we never run or resolve evals.
+#[async_trait(?Send)]
+impl Evaluator for SSREvaluator {
+    /// Runs the evaluated JavaScript.
+    async fn join(&self) -> Result<serde_json::Value, EvalError> {
+        std::future::pending::<()>().await;
+        unreachable!()
+    }
+
+    /// Sends a message to the evaluated JavaScript.
+    fn send(&self, _el: serde_json::Value) -> Result<(), EvalError> {
+        Ok(())
+    }
+
+    /// Gets an UnboundedReceiver to receive messages from the evaluated JavaScript.
+    async fn recv(&self) -> Result<serde_json::Value, EvalError> {
+        std::future::pending::<()>().await;
+        unreachable!()
+    }
+}

+ 1 - 0
packages/ssr/src/incremental.rs

@@ -81,6 +81,7 @@ impl IncrementalRenderer {
         let mut html_buffer = WriteBuffer { buffer: Vec::new() };
         {
             let mut vdom = VirtualDom::new_with_props(comp, props);
+            crate::eval::init_eval(vdom.base_scope());
             rebuild_with(&mut vdom).await;
 
             renderer.render_before_body(&mut *html_buffer)?;

+ 2 - 0
packages/ssr/src/lib.rs

@@ -10,6 +10,7 @@ pub mod incremental;
 #[cfg(feature = "incremental")]
 mod incremental_cfg;
 
+pub mod eval;
 pub mod renderer;
 pub mod template;
 
@@ -42,6 +43,7 @@ pub fn render_lazy(f: LazyNodes<'_, '_>) -> String {
     };
 
     let mut dom = VirtualDom::new_with_props(lazy_app, props);
+    crate::eval::init_eval(dom.base_scope());
     _ = dom.rebuild();
 
     Renderer::new().render(&dom)