wrap the web eval result in a compatability layer

This commit is contained in:
Evan Almloff 2022-12-08 10:57:09 -06:00
parent e863ef29b8
commit 35bebbf0cb
2 changed files with 45 additions and 15 deletions

View file

@ -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;

View file

@ -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)
}
}