feat: update root props
This commit is contained in:
1 parent
c321532a6c
commit
fac2e56ed6
9 files changed
+96
-55
No files matched your search
Vendored
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"rust-analyzer.inlayHints.enable": false
|
"rust-analyzer.inlayHints.enable": true
|
||||||
}
|
}
|
||||||
@@ -67,12 +67,6 @@ impl ActiveFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn finished_frame_mut(&mut self) -> &mut BumpFrame {
|
|
||||||
match self.generation.get() & 1 == 1 {
|
|
||||||
true => &mut self.frames[0],
|
|
||||||
false => &mut self.frames[1],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// Give out our self-referential item with our own borrowed lifetime
|
/// Give out our self-referential item with our own borrowed lifetime
|
||||||
pub fn fin_head<'b>(&'b self) -> &'b VNode<'b> {
|
pub fn fin_head<'b>(&'b self) -> &'b VNode<'b> {
|
||||||
let cur_head = &self.finished_frame().head_node;
|
let cur_head = &self.finished_frame().head_node;
|
||||||
|
|||||||
+20
-20
@@ -633,16 +633,16 @@ pub mod on {
|
|||||||
DownArrow = 40,
|
DownArrow = 40,
|
||||||
Insert = 45,
|
Insert = 45,
|
||||||
Delete = 46,
|
Delete = 46,
|
||||||
_0 = 48,
|
Num0 = 48,
|
||||||
_1 = 49,
|
Num1 = 49,
|
||||||
_2 = 50,
|
Num2 = 50,
|
||||||
_3 = 51,
|
Num3 = 51,
|
||||||
_4 = 52,
|
Num4 = 52,
|
||||||
_5 = 53,
|
Num5 = 53,
|
||||||
_6 = 54,
|
Num6 = 54,
|
||||||
_7 = 55,
|
Num7 = 55,
|
||||||
_8 = 56,
|
Num8 = 56,
|
||||||
_9 = 57,
|
Num9 = 57,
|
||||||
A = 65,
|
A = 65,
|
||||||
B = 66,
|
B = 66,
|
||||||
C = 67,
|
C = 67,
|
||||||
@@ -738,16 +738,16 @@ pub mod on {
|
|||||||
40 => DownArrow,
|
40 => DownArrow,
|
||||||
45 => Insert,
|
45 => Insert,
|
||||||
46 => Delete,
|
46 => Delete,
|
||||||
48 => _0,
|
48 => Num0,
|
||||||
49 => _1,
|
49 => Num1,
|
||||||
50 => _2,
|
50 => Num2,
|
||||||
51 => _3,
|
51 => Num3,
|
||||||
52 => _4,
|
52 => Num4,
|
||||||
53 => _5,
|
53 => Num5,
|
||||||
54 => _6,
|
54 => Num6,
|
||||||
55 => _7,
|
55 => Num7,
|
||||||
56 => _8,
|
56 => Num8,
|
||||||
57 => _9,
|
57 => Num9,
|
||||||
65 => A,
|
65 => A,
|
||||||
66 => B,
|
66 => B,
|
||||||
67 => C,
|
67 => C,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::{
|
|||||||
cell::{Cell, RefCell, UnsafeCell},
|
cell::{Cell, RefCell, UnsafeCell},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct HookList {
|
pub(crate) struct HookList {
|
||||||
vals: RefCell<Vec<InnerHook<Box<dyn Any>>>>,
|
vals: RefCell<Vec<InnerHook<Box<dyn Any>>>>,
|
||||||
idx: Cell<usize>,
|
idx: Cell<usize>,
|
||||||
}
|
}
|
||||||
@@ -20,6 +20,7 @@ impl Default for HookList {
|
|||||||
struct InnerHook<T> {
|
struct InnerHook<T> {
|
||||||
cell: UnsafeCell<T>,
|
cell: UnsafeCell<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> InnerHook<T> {
|
impl<T> InnerHook<T> {
|
||||||
fn new(new: T) -> Self {
|
fn new(new: T) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -27,6 +28,7 @@ impl<T> InnerHook<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HookList {
|
impl HookList {
|
||||||
pub(crate) fn next<T: 'static>(&self) -> Option<&mut T> {
|
pub(crate) fn next<T: 'static>(&self) -> Option<&mut T> {
|
||||||
self.vals.borrow().get(self.idx.get()).and_then(|inn| {
|
self.vals.borrow().get(self.idx.get()).and_then(|inn| {
|
||||||
|
|||||||
+15
-16
@@ -3,11 +3,11 @@
|
|||||||
//! This module contains all the low-level built-in hooks that require 1st party support to work.
|
//! This module contains all the low-level built-in hooks that require 1st party support to work.
|
||||||
//!
|
//!
|
||||||
//! Hooks:
|
//! Hooks:
|
||||||
//! - use_hook
|
//! - [`use_hook`]
|
||||||
//! - use_state_provider
|
//! - [`use_state_provider`]
|
||||||
//! - use_state_consumer
|
//! - [`use_state_consumer`]
|
||||||
//! - use_task
|
//! - [`use_task`]
|
||||||
//! - use_suspense
|
//! - [`use_suspense`]
|
||||||
|
|
||||||
use crate::innerlude::*;
|
use crate::innerlude::*;
|
||||||
use futures_util::FutureExt;
|
use futures_util::FutureExt;
|
||||||
@@ -53,15 +53,7 @@ where
|
|||||||
(true, true) => {}
|
(true, true) => {}
|
||||||
|
|
||||||
// Needs to be initialized
|
// Needs to be initialized
|
||||||
(false, false) => {
|
(false, false) => cx.add_shared_state(init()),
|
||||||
log::debug!("Initializing context...");
|
|
||||||
cx.add_shared_state(init());
|
|
||||||
log::info!(
|
|
||||||
"There are now {} shared contexts for scope {:?}",
|
|
||||||
cx.scope.shared_contexts.borrow().len(),
|
|
||||||
cx.scope.our_arena_idx,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => debug_assert!(false, "Cannot initialize two contexts of the same type"),
|
_ => debug_assert!(false, "Cannot initialize two contexts of the same type"),
|
||||||
};
|
};
|
||||||
@@ -205,7 +197,10 @@ where
|
|||||||
|
|
||||||
cx.render(LazyNodes::new(|f| {
|
cx.render(LazyNodes::new(|f| {
|
||||||
let bump = f.bump();
|
let bump = f.bump();
|
||||||
let g: &dyn FnOnce(SuspendedContext<'src>) -> DomTree<'src> =
|
|
||||||
|
use bumpalo::boxed::Box as BumpBox;
|
||||||
|
|
||||||
|
let f: &mut dyn FnMut(SuspendedContext<'src>) -> DomTree<'src> =
|
||||||
bump.alloc(move |sus| {
|
bump.alloc(move |sus| {
|
||||||
let val = value.borrow();
|
let val = value.borrow();
|
||||||
|
|
||||||
@@ -218,11 +213,12 @@ where
|
|||||||
|
|
||||||
user_callback(sus, out)
|
user_callback(sus, out)
|
||||||
});
|
});
|
||||||
|
let callback = unsafe { BumpBox::from_raw(f) };
|
||||||
|
|
||||||
VNode::Suspended(bump.alloc(VSuspended {
|
VNode::Suspended(bump.alloc(VSuspended {
|
||||||
dom_id: empty_cell(),
|
dom_id: empty_cell(),
|
||||||
task_id: hook.handle.our_id,
|
task_id: hook.handle.our_id,
|
||||||
callback: RefCell::new(Some(g)),
|
callback: RefCell::new(Some(callback)),
|
||||||
}))
|
}))
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@@ -235,10 +231,13 @@ pub(crate) struct SuspenseHook {
|
|||||||
pub handle: TaskHandle,
|
pub handle: TaskHandle,
|
||||||
pub value: Rc<RefCell<Option<Box<dyn Any>>>>,
|
pub value: Rc<RefCell<Option<Box<dyn Any>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type SuspendedCallback = Box<dyn for<'a> Fn(SuspendedContext<'a>) -> DomTree<'a>>;
|
type SuspendedCallback = Box<dyn for<'a> Fn(SuspendedContext<'a>) -> DomTree<'a>>;
|
||||||
|
|
||||||
pub struct SuspendedContext<'a> {
|
pub struct SuspendedContext<'a> {
|
||||||
pub(crate) inner: Context<'a, ()>,
|
pub(crate) inner: Context<'a, ()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> SuspendedContext<'src> {
|
impl<'src> SuspendedContext<'src> {
|
||||||
pub fn render<F: FnOnce(NodeFactory<'src>) -> VNode<'src>>(
|
pub fn render<F: FnOnce(NodeFactory<'src>) -> VNode<'src>>(
|
||||||
self,
|
self,
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ pub(crate) mod innerlude {
|
|||||||
pub use crate::diff_stack::*;
|
pub use crate::diff_stack::*;
|
||||||
pub use crate::events::*;
|
pub use crate::events::*;
|
||||||
pub use crate::heuristics::*;
|
pub use crate::heuristics::*;
|
||||||
pub use crate::hooklist::*;
|
pub(crate) use crate::hooklist::*;
|
||||||
pub use crate::hooks::*;
|
pub use crate::hooks::*;
|
||||||
pub use crate::mutations::*;
|
pub use crate::mutations::*;
|
||||||
pub use crate::nodes::*;
|
pub use crate::nodes::*;
|
||||||
|
|||||||
@@ -283,7 +283,8 @@ pub struct VComponent<'src> {
|
|||||||
pub struct VSuspended<'a> {
|
pub struct VSuspended<'a> {
|
||||||
pub task_id: u64,
|
pub task_id: u64,
|
||||||
pub dom_id: Cell<Option<ElementId>>,
|
pub dom_id: Cell<Option<ElementId>>,
|
||||||
pub(crate) callback: RefCell<Option<&'a dyn FnOnce(SuspendedContext<'a>) -> DomTree<'a>>>,
|
pub(crate) callback:
|
||||||
|
RefCell<Option<BumpBox<'a, dyn FnMut(SuspendedContext<'a>) -> DomTree<'a>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This struct provides an ergonomic API to quickly build VNodes.
|
/// This struct provides an ergonomic API to quickly build VNodes.
|
||||||
@@ -518,7 +519,7 @@ impl<'a> NodeFactory<'a> {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_component_caller<'g, P: 'g>(
|
pub(crate) fn create_component_caller<'g, P: 'g>(
|
||||||
component: FC<P>,
|
component: FC<P>,
|
||||||
raw_props: *const (),
|
raw_props: *const (),
|
||||||
) -> Rc<dyn for<'r> Fn(&'r Scope) -> DomTree<'r>> {
|
) -> Rc<dyn for<'r> Fn(&'r Scope) -> DomTree<'r>> {
|
||||||
@@ -530,12 +531,8 @@ impl<'a> NodeFactory<'a> {
|
|||||||
props: safe_props,
|
props: safe_props,
|
||||||
scope: scp,
|
scope: scp,
|
||||||
};
|
};
|
||||||
|
|
||||||
let res = component(cx);
|
let res = component(cx);
|
||||||
|
unsafe { std::mem::transmute(res) }
|
||||||
let g2 = unsafe { std::mem::transmute(res) };
|
|
||||||
|
|
||||||
g2
|
|
||||||
});
|
});
|
||||||
unsafe { std::mem::transmute::<_, Captured<'static>>(caller) }
|
unsafe { std::mem::transmute::<_, Captured<'static>>(caller) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,8 +36,7 @@ pub struct Scope {
|
|||||||
// Listeners
|
// Listeners
|
||||||
pub(crate) listeners: RefCell<Vec<*const Listener<'static>>>,
|
pub(crate) listeners: RefCell<Vec<*const Listener<'static>>>,
|
||||||
pub(crate) borrowed_props: RefCell<Vec<*const VComponent<'static>>>,
|
pub(crate) borrowed_props: RefCell<Vec<*const VComponent<'static>>>,
|
||||||
|
pub(crate) suspended_nodes: RefCell<HashMap<u64, *const VSuspended<'static>>>,
|
||||||
pub(crate) suspended_nodes: RefCell<HashMap<u64, *const VNode<'static>>>,
|
|
||||||
|
|
||||||
// State
|
// State
|
||||||
pub(crate) hooks: HookList,
|
pub(crate) hooks: HookList,
|
||||||
@@ -146,7 +145,7 @@ impl Scope {
|
|||||||
///
|
///
|
||||||
/// Refrences to hook data can only be stored in listeners and component props. During diffing, we make sure to log
|
/// Refrences to hook data can only be stored in listeners and component props. During diffing, we make sure to log
|
||||||
/// all listeners and borrowed props so we can clear them here.
|
/// all listeners and borrowed props so we can clear them here.
|
||||||
fn ensure_drop_safety(&mut self, pool: &ResourcePool) {
|
pub(crate) fn ensure_drop_safety(&mut self, pool: &ResourcePool) {
|
||||||
// make sure all garabge is collected before trying to proceed with anything else
|
// make sure all garabge is collected before trying to proceed with anything else
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
self.pending_garbage.borrow().is_empty(),
|
self.pending_garbage.borrow().is_empty(),
|
||||||
@@ -220,6 +219,26 @@ impl Scope {
|
|||||||
unsafe { self.child_nodes.shorten_lifetime() }
|
unsafe { self.child_nodes.shorten_lifetime() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn call_suspended_node<'a>(&'a self, task: u64) {
|
||||||
|
let g = self.suspended_nodes.borrow_mut();
|
||||||
|
|
||||||
|
if let Some(suspended) = g.get(&task) {
|
||||||
|
let sus: &'a VSuspended<'static> = unsafe { &**suspended };
|
||||||
|
let sus: &'a VSuspended<'a> = unsafe { std::mem::transmute(sus) };
|
||||||
|
|
||||||
|
let bump = self.frames.wip_frame();
|
||||||
|
let mut cb = sus.callback.borrow_mut();
|
||||||
|
let mut _cb = cb.take().unwrap();
|
||||||
|
let cx: SuspendedContext<'a> = SuspendedContext {
|
||||||
|
inner: Context {
|
||||||
|
props: &(),
|
||||||
|
scope: &self,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let n: DomTree<'a> = (_cb)(cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn consume_garbage(&self) -> Vec<&VNode> {
|
pub fn consume_garbage(&self) -> Vec<&VNode> {
|
||||||
self.pending_garbage
|
self.pending_garbage
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ use futures_util::{Future, FutureExt};
|
|||||||
use std::{
|
use std::{
|
||||||
any::{Any, TypeId},
|
any::{Any, TypeId},
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
|
rc::Rc,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// An integrated virtual node system that progresses events and diffs UI trees.
|
/// An integrated virtual node system that progresses events and diffs UI trees.
|
||||||
@@ -39,6 +40,8 @@ pub struct VirtualDom {
|
|||||||
|
|
||||||
base_scope: ScopeId,
|
base_scope: ScopeId,
|
||||||
|
|
||||||
|
root_fc: Box<dyn Any>,
|
||||||
|
|
||||||
root_prop_type: std::any::TypeId,
|
root_prop_type: std::any::TypeId,
|
||||||
|
|
||||||
root_props: Pin<Box<dyn std::any::Any>>,
|
root_props: Pin<Box<dyn std::any::Any>>,
|
||||||
@@ -120,6 +123,7 @@ impl VirtualDom {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
root_fc: Box::new(root),
|
||||||
base_scope,
|
base_scope,
|
||||||
scheduler,
|
scheduler,
|
||||||
root_props: _root_props,
|
root_props: _root_props,
|
||||||
@@ -135,6 +139,32 @@ impl VirtualDom {
|
|||||||
self.scheduler.pool.get_scope(id)
|
self.scheduler.pool.get_scope(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Update the root props of this VirtualDOM.
|
||||||
|
///
|
||||||
|
/// This method retuns None if the old props could not be removed. The entire VirtualDOM will be rebuilt immediately,
|
||||||
|
/// so calling this method will block the main thread until computation is done.
|
||||||
|
pub fn update_root_props<'s, P: 'static>(&'s mut self, root_props: P) -> Option<Mutations<'s>> {
|
||||||
|
let root_scope = self.scheduler.pool.get_scope_mut(self.base_scope).unwrap();
|
||||||
|
root_scope.ensure_drop_safety(&self.scheduler.pool);
|
||||||
|
|
||||||
|
let mut _root_props: Pin<Box<dyn Any>> = Box::pin(root_props);
|
||||||
|
let _root_prop_type = TypeId::of::<P>();
|
||||||
|
|
||||||
|
if let Some(props_ptr) = _root_props.downcast_ref::<P>().map(|p| p as *const P) {
|
||||||
|
std::mem::swap(&mut self.root_props, &mut _root_props);
|
||||||
|
|
||||||
|
let root = *self.root_fc.downcast_ref::<FC<P>>().unwrap();
|
||||||
|
|
||||||
|
let new_caller = NodeFactory::create_component_caller(root, props_ptr as *const _);
|
||||||
|
|
||||||
|
root_scope.update_scope_dependencies(new_caller, ScopeChildren(&[]));
|
||||||
|
|
||||||
|
Some(self.rebuild())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Performs a *full* rebuild of the virtual dom, returning every edit required to generate the actual dom rom scratch
|
/// Performs a *full* rebuild of the virtual dom, returning every edit required to generate the actual dom rom scratch
|
||||||
///
|
///
|
||||||
/// The diff machine expects the RealDom's stack to be the root of the application
|
/// The diff machine expects the RealDom's stack to be the root of the application
|
||||||
|
|||||||
Reference in new issue
Block a user