make eval copy
This commit is contained in:
1 parent
894a79d3df
commit
a789d6a64e
13 files changed
+191
-107
No files matched your search
+26
-12
@@ -1,26 +1,32 @@
|
||||
#![allow(clippy::await_holding_refcell_ref)]
|
||||
|
||||
use async_trait::async_trait;
|
||||
use dioxus_core::prelude::*;
|
||||
use std::future::{Future, IntoFuture};
|
||||
use generational_box::GenerationalBox;
|
||||
use std::future::{poll_fn, Future, IntoFuture};
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
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<Box<dyn Evaluator>, EvalError>;
|
||||
fn new_evaluator(&self, js: String) -> Result<GenerationalBox<Box<dyn Evaluator>>, EvalError>;
|
||||
}
|
||||
|
||||
/// The platform's evaluator.
|
||||
#[async_trait(?Send)]
|
||||
pub trait Evaluator {
|
||||
/// Sends a message to the evaluated JavaScript.
|
||||
fn send(&self, data: serde_json::Value) -> Result<(), EvalError>;
|
||||
/// Receive any queued messages from the evaluated JavaScript.
|
||||
async fn recv(&mut self) -> Result<serde_json::Value, EvalError>;
|
||||
fn poll_recv(
|
||||
&mut self,
|
||||
context: &mut Context<'_>,
|
||||
) -> Poll<Result<serde_json::Value, EvalError>>;
|
||||
/// Gets the return value of the JavaScript
|
||||
async fn join(&self) -> Result<serde_json::Value, EvalError>;
|
||||
fn poll_join(
|
||||
&mut self,
|
||||
context: &mut Context<'_>,
|
||||
) -> Poll<Result<serde_json::Value, EvalError>>;
|
||||
}
|
||||
|
||||
type EvalCreator = Rc<dyn Fn(&str) -> Result<UseEval, EvalError>>;
|
||||
@@ -54,28 +60,36 @@ pub fn eval(script: &str) -> Result<UseEval, EvalError> {
|
||||
|
||||
/// A wrapper around the target platform's evaluator.
|
||||
pub struct UseEval {
|
||||
evaluator: Box<dyn Evaluator + 'static>,
|
||||
evaluator: GenerationalBox<Box<dyn Evaluator>>,
|
||||
}
|
||||
|
||||
impl UseEval {
|
||||
/// Creates a new UseEval
|
||||
pub fn new(evaluator: Box<dyn Evaluator + 'static>) -> Self {
|
||||
pub fn new(evaluator: GenerationalBox<Box<dyn Evaluator + 'static>>) -> Self {
|
||||
Self { evaluator }
|
||||
}
|
||||
|
||||
/// Sends a [`serde_json::Value`] to the evaluated JavaScript.
|
||||
pub fn send(&self, data: serde_json::Value) -> Result<(), EvalError> {
|
||||
self.evaluator.send(data)
|
||||
self.evaluator.read().send(data)
|
||||
}
|
||||
|
||||
/// Gets an UnboundedReceiver to receive messages from the evaluated JavaScript.
|
||||
pub async fn recv(&mut self) -> Result<serde_json::Value, EvalError> {
|
||||
self.evaluator.recv().await
|
||||
poll_fn(|cx| match self.evaluator.try_write() {
|
||||
Ok(mut evaluator) => evaluator.poll_recv(cx),
|
||||
Err(_) => Poll::Ready(Err(EvalError::Finished)),
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
/// Gets the return value of the evaluated JavaScript.
|
||||
pub async fn join(self) -> Result<serde_json::Value, EvalError> {
|
||||
self.evaluator.join().await
|
||||
poll_fn(|cx| match self.evaluator.try_write() {
|
||||
Ok(mut evaluator) => evaluator.poll_join(cx),
|
||||
Err(_) => Poll::Ready(Err(EvalError::Finished)),
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +106,7 @@ impl IntoFuture for UseEval {
|
||||
#[derive(Debug)]
|
||||
pub enum EvalError {
|
||||
/// The platform does not support evaluating JavaScript.
|
||||
Unspported,
|
||||
Unsupported,
|
||||
|
||||
/// The provided JavaScript has already been ran.
|
||||
Finished,
|
||||
|
||||
Reference in new issue
Block a user