feat: context api overhaul

This commit is contained in:
Jonathan Kelley committed 2022-12-02 16:24:49 -08:00
1 parent 11a45c8ef0
commit a61daf220d
44 files changed
+812 -621

No files matched your search

+11 -11
View File
@@ -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
View File
@@ -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);
+14 -7
View File
@@ -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");