Bläddra i källkod

wrap the web eval result in a compatability layer

Evan Almloff 2 år sedan
förälder
incheckning
35bebbf0cb
2 ändrade filer med 45 tillägg och 15 borttagningar
  1. 1 1
      packages/web/src/lib.rs
  2. 44 14
      packages/web/src/util.rs

+ 1 - 1
packages/web/src/lib.rs

@@ -57,7 +57,7 @@
 use std::rc::Rc;
 
 pub use crate::cfg::Config;
-pub use crate::util::use_eval;
+pub use crate::util::{use_eval, EvalResult};
 use dioxus_core::prelude::Component;
 use dioxus_core::SchedulerMsg;
 use dioxus_core::VirtualDom;

+ 44 - 14
packages/web/src/util.rs

@@ -1,6 +1,9 @@
 //! Utilities specific to websys
 
-use std::str::FromStr;
+use std::{
+    future::{IntoFuture, Ready},
+    str::FromStr,
+};
 
 use dioxus_core::*;
 use serde::de::Error;
@@ -19,24 +22,51 @@ use serde_json::Value;
 ///
 /// The closure will panic if the provided script is not valid JavaScript code
 /// or if it returns an uncaught error.
-pub fn use_eval<S: std::string::ToString>(
-    cx: &ScopeState,
-) -> &dyn Fn(S) -> Result<Value, serde_json::Error> {
+pub fn use_eval<S: std::string::ToString>(cx: &ScopeState) -> &dyn Fn(S) -> EvalResult {
     cx.use_hook(|| {
         |script: S| {
             let body = script.to_string();
-            if let Ok(value) =
-                js_sys::Function::new_no_args(&body).call0(&wasm_bindgen::JsValue::NULL)
-            {
-                if let Ok(stringified) = js_sys::JSON::stringify(&value) {
-                    let string: String = stringified.into();
-                    Value::from_str(&string)
+            EvalResult {
+                value: if let Ok(value) =
+                    js_sys::Function::new_no_args(&body).call0(&wasm_bindgen::JsValue::NULL)
+                {
+                    if let Ok(stringified) = js_sys::JSON::stringify(&value) {
+                        if !stringified.is_undefined() && stringified.is_valid_utf16() {
+                            let string: String = stringified.into();
+                            Value::from_str(&string)
+                        } else {
+                            Err(serde_json::Error::custom("Failed to stringify result"))
+                        }
+                    } else {
+                        Err(serde_json::Error::custom("Failed to stringify result"))
+                    }
                 } else {
-                    Err(serde_json::Error::custom("Failed to stringify result"))
-                }
-            } else {
-                Err(serde_json::Error::custom("Failed to execute script"))
+                    Err(serde_json::Error::custom("Failed to execute script"))
+                },
             }
         }
     })
 }
+
+/// A wrapper around the result of a JavaScript evaluation.
+/// This implements IntoFuture to be compatible with the desktop renderer's EvalResult.
+pub struct EvalResult {
+    value: Result<Value, serde_json::Error>,
+}
+
+impl EvalResult {
+    /// Get the result of the Javascript execution.
+    pub fn get(self) -> Result<Value, serde_json::Error> {
+        self.value
+    }
+}
+
+impl IntoFuture for EvalResult {
+    type Output = Result<Value, serde_json::Error>;
+
+    type IntoFuture = Ready<Result<Value, serde_json::Error>>;
+
+    fn into_future(self) -> Self::IntoFuture {
+        std::future::ready(self.value)
+    }
+}