feat: context api overhaul
This commit is contained in:
1 parent
11a45c8ef0
commit
a61daf220d
44 files changed
+812
-621
No files matched your search
@@ -8,13 +8,12 @@ use std::{
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
/// An ID representing an ongoing suspended component
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub struct SuspenseId(pub usize);
|
||||
pub(crate) struct SuspenseId(pub usize);
|
||||
|
||||
pub type SuspenseContext = Rc<SuspenseBoundary>;
|
||||
|
||||
/// Essentially a fiber in React
|
||||
pub struct SuspenseBoundary {
|
||||
/// A boundary in the VirtualDom that captures all suspended components below it
|
||||
pub struct SuspenseContext {
|
||||
pub(crate) id: ScopeId,
|
||||
pub(crate) waiting_on: RefCell<HashSet<SuspenseId>>,
|
||||
pub(crate) mutations: RefCell<Mutations<'static>>,
|
||||
@@ -22,7 +21,8 @@ pub struct SuspenseBoundary {
|
||||
pub(crate) created_on_stack: Cell<usize>,
|
||||
}
|
||||
|
||||
impl SuspenseBoundary {
|
||||
impl SuspenseContext {
|
||||
/// Create a new boundary for suspense
|
||||
pub fn new(id: ScopeId) -> Self {
|
||||
Self {
|
||||
id,
|
||||
@@ -35,11 +35,11 @@ impl SuspenseBoundary {
|
||||
}
|
||||
|
||||
pub(crate) struct SuspenseLeaf {
|
||||
pub id: SuspenseId,
|
||||
pub scope_id: ScopeId,
|
||||
pub tx: futures_channel::mpsc::UnboundedSender<SchedulerMsg>,
|
||||
pub notified: Cell<bool>,
|
||||
pub task: *mut dyn Future<Output = Element<'static>>,
|
||||
pub(crate) id: SuspenseId,
|
||||
pub(crate) scope_id: ScopeId,
|
||||
pub(crate) tx: futures_channel::mpsc::UnboundedSender<SchedulerMsg>,
|
||||
pub(crate) notified: Cell<bool>,
|
||||
pub(crate) task: *mut dyn Future<Output = Element<'static>>,
|
||||
}
|
||||
|
||||
impl RcWake for SuspenseLeaf {
|
||||
|
||||
@@ -4,6 +4,10 @@ use std::cell::RefCell;
|
||||
use std::future::Future;
|
||||
use std::{pin::Pin, rc::Rc};
|
||||
|
||||
/// A task's unique identifier.
|
||||
///
|
||||
/// `TaskId` is a `usize` that is unique across the entire VirtualDOM and across time. TaskIDs will never be reused
|
||||
/// once a Task has been completed.
|
||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub struct TaskId(pub usize);
|
||||
|
||||
@@ -2,9 +2,9 @@ use futures_util::FutureExt;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use crate::{
|
||||
factory::RenderReturn,
|
||||
innerlude::{Mutation, Mutations, SuspenseContext},
|
||||
TaskId, VNode, VirtualDom,
|
||||
nodes::RenderReturn,
|
||||
ScopeId, TaskId, VNode, VirtualDom,
|
||||
};
|
||||
|
||||
use super::{waker::RcWake, SuspenseId};
|
||||
@@ -14,7 +14,7 @@ impl VirtualDom {
|
||||
///
|
||||
/// This is precise, meaning we won't poll every task, just tasks that have woken up as notified to use by the
|
||||
/// queue
|
||||
pub fn handle_task_wakeup(&mut self, id: TaskId) {
|
||||
pub(crate) fn handle_task_wakeup(&mut self, id: TaskId) {
|
||||
let mut tasks = self.scheduler.tasks.borrow_mut();
|
||||
let task = &tasks[id.0];
|
||||
|
||||
@@ -31,7 +31,15 @@ impl VirtualDom {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_suspense_wakeup(&mut self, id: SuspenseId) {
|
||||
pub(crate) fn acquire_suspense_boundary<'a>(&self, id: ScopeId) -> &'a SuspenseContext {
|
||||
let ct = self.scopes[id.0]
|
||||
.consume_context::<SuspenseContext>()
|
||||
.unwrap();
|
||||
|
||||
unsafe { &*(ct as *const SuspenseContext) }
|
||||
}
|
||||
|
||||
pub(crate) fn handle_suspense_wakeup(&mut self, id: SuspenseId) {
|
||||
println!("suspense notified");
|
||||
|
||||
let leaf = self
|
||||
@@ -56,9 +64,8 @@ impl VirtualDom {
|
||||
// we should attach them to that component and then render its children
|
||||
// continue rendering the tree until we hit yet another suspended component
|
||||
if let Poll::Ready(new_nodes) = as_pinned_mut.poll_unpin(&mut cx) {
|
||||
let fiber = &self.scopes[leaf.scope_id.0]
|
||||
.consume_context::<SuspenseContext>()
|
||||
.unwrap();
|
||||
// safety: we're not going to modify the suspense context but we don't want to make a clone of it
|
||||
let fiber = self.acquire_suspense_boundary(leaf.scope_id);
|
||||
|
||||
println!("ready pool");
|
||||
|
||||
|
||||
Reference in new issue
Block a user