feat: diffing works on desktop!
This commit is contained in:
1 parent
30ef225812
commit
20f9957fbe
10 files changed
+176
-166
No files matched your search
@@ -19,6 +19,19 @@ pub struct SuspenseBoundary {
|
||||
pub waiting_on: RefCell<HashSet<SuspenseId>>,
|
||||
pub mutations: RefCell<Mutations<'static>>,
|
||||
pub placeholder: Cell<Option<ElementId>>,
|
||||
|
||||
// whenever the suspense resolves, we call this onresolve function
|
||||
// this lets us do things like putting up a loading spinner
|
||||
//
|
||||
// todo: we need a way of controlling whether or not a component hides itself but still processes changes
|
||||
// If we run into suspense, we perform a diff, so its important that the old elements are still around.
|
||||
//
|
||||
// When the timer expires, I imagine a container could hide the elements and show the spinner. This, however,
|
||||
// can not be
|
||||
pub onresolve: Option<Box<dyn FnOnce()>>,
|
||||
|
||||
/// Called when
|
||||
pub onstart: Option<Box<dyn FnOnce()>>,
|
||||
}
|
||||
|
||||
impl SuspenseBoundary {
|
||||
@@ -28,6 +41,8 @@ impl SuspenseBoundary {
|
||||
waiting_on: Default::default(),
|
||||
mutations: RefCell::new(Mutations::new(0)),
|
||||
placeholder: Cell::new(None),
|
||||
onresolve: None,
|
||||
onstart: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use super::{waker::RcWake, Scheduler, SchedulerMsg};
|
||||
use crate::ScopeId;
|
||||
use std::cell::RefCell;
|
||||
use std::future::Future;
|
||||
use std::task::Context;
|
||||
use std::{cell::UnsafeCell, pin::Pin, rc::Rc, task::Poll};
|
||||
use std::{pin::Pin, rc::Rc, task::Poll};
|
||||
|
||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
@@ -10,23 +11,19 @@ pub struct TaskId(pub usize);
|
||||
|
||||
/// the task itself is the waker
|
||||
pub(crate) struct LocalTask {
|
||||
pub id: TaskId,
|
||||
pub scope: ScopeId,
|
||||
pub tx: futures_channel::mpsc::UnboundedSender<SchedulerMsg>,
|
||||
|
||||
// todo: use rc and weak, or the bump slab instead of unsafecell
|
||||
pub task: UnsafeCell<Pin<Box<dyn Future<Output = ()> + 'static>>>,
|
||||
id: TaskId,
|
||||
tx: futures_channel::mpsc::UnboundedSender<SchedulerMsg>,
|
||||
task: RefCell<Pin<Box<dyn Future<Output = ()> + 'static>>>,
|
||||
}
|
||||
|
||||
impl LocalTask {
|
||||
pub fn progress(self: &Rc<Self>) -> bool {
|
||||
/// Poll this task and return whether or not it is complete
|
||||
pub(super) fn progress(self: &Rc<Self>) -> bool {
|
||||
let waker = self.waker();
|
||||
let mut cx = Context::from_waker(&waker);
|
||||
|
||||
// safety: the waker owns its task and everythig is single threaded
|
||||
let fut = unsafe { &mut *self.task.get() };
|
||||
|
||||
match Pin::new(fut).poll(&mut cx) {
|
||||
match self.task.borrow_mut().as_mut().poll(&mut cx) {
|
||||
Poll::Ready(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
@@ -34,6 +31,15 @@ impl LocalTask {
|
||||
}
|
||||
|
||||
impl Scheduler {
|
||||
/// Start a new future on the same thread as the rest of the VirtualDom.
|
||||
///
|
||||
/// This future will not contribute to suspense resolving, so you should primarily use this for reacting to changes
|
||||
/// and long running tasks.
|
||||
///
|
||||
/// Whenever the component that owns this future is dropped, the future will be dropped as well.
|
||||
///
|
||||
/// Spawning a future onto the root scope will cause it to be dropped when the root component is dropped - which
|
||||
/// will only occur when the VirtuaalDom itself has been dropped.
|
||||
pub fn spawn(&self, scope: ScopeId, task: impl Future<Output = ()> + 'static) -> TaskId {
|
||||
let mut tasks = self.tasks.borrow_mut();
|
||||
let entry = tasks.vacant_entry();
|
||||
@@ -42,7 +48,7 @@ impl Scheduler {
|
||||
entry.insert(Rc::new(LocalTask {
|
||||
id: task_id,
|
||||
tx: self.sender.clone(),
|
||||
task: UnsafeCell::new(Box::pin(task)),
|
||||
task: RefCell::new(Box::pin(task)),
|
||||
scope,
|
||||
}));
|
||||
|
||||
@@ -53,9 +59,11 @@ impl Scheduler {
|
||||
task_id
|
||||
}
|
||||
|
||||
// drops the future
|
||||
/// Drop the future with the given TaskId
|
||||
///
|
||||
/// This does nto abort the task, so you'll want to wrap it in an aborthandle if that's important to you
|
||||
pub fn remove(&self, id: TaskId) {
|
||||
//
|
||||
self.tasks.borrow_mut().remove(id.0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@ use std::task::{Context, Poll};
|
||||
use crate::{
|
||||
factory::RenderReturn,
|
||||
innerlude::{Mutation, Mutations, SuspenseContext},
|
||||
ScopeId, TaskId, VNode, VirtualDom,
|
||||
TaskId, VNode, VirtualDom,
|
||||
};
|
||||
|
||||
use super::{waker::RcWake, SuspenseId, SuspenseLeaf};
|
||||
use super::{waker::RcWake, SuspenseId};
|
||||
|
||||
impl VirtualDom {
|
||||
/// Handle notifications by tasks inside the scheduler
|
||||
|
||||
Reference in new issue
Block a user