mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-09-21 14:52:02 +00:00
feat: update root props
This commit is contained in:
parent
c321532a6c
commit
fac2e56ed6
9 changed files with 96 additions and 55 deletions
2
packages/core/.vscode/settings.json
vendored
2
packages/core/.vscode/settings.json
vendored
|
@ -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
|
||||
pub fn fin_head<'b>(&'b self) -> &'b VNode<'b> {
|
||||
let cur_head = &self.finished_frame().head_node;
|
||||
|
|
|
@ -633,16 +633,16 @@ pub mod on {
|
|||
DownArrow = 40,
|
||||
Insert = 45,
|
||||
Delete = 46,
|
||||
_0 = 48,
|
||||
_1 = 49,
|
||||
_2 = 50,
|
||||
_3 = 51,
|
||||
_4 = 52,
|
||||
_5 = 53,
|
||||
_6 = 54,
|
||||
_7 = 55,
|
||||
_8 = 56,
|
||||
_9 = 57,
|
||||
Num0 = 48,
|
||||
Num1 = 49,
|
||||
Num2 = 50,
|
||||
Num3 = 51,
|
||||
Num4 = 52,
|
||||
Num5 = 53,
|
||||
Num6 = 54,
|
||||
Num7 = 55,
|
||||
Num8 = 56,
|
||||
Num9 = 57,
|
||||
A = 65,
|
||||
B = 66,
|
||||
C = 67,
|
||||
|
@ -738,16 +738,16 @@ pub mod on {
|
|||
40 => DownArrow,
|
||||
45 => Insert,
|
||||
46 => Delete,
|
||||
48 => _0,
|
||||
49 => _1,
|
||||
50 => _2,
|
||||
51 => _3,
|
||||
52 => _4,
|
||||
53 => _5,
|
||||
54 => _6,
|
||||
55 => _7,
|
||||
56 => _8,
|
||||
57 => _9,
|
||||
48 => Num0,
|
||||
49 => Num1,
|
||||
50 => Num2,
|
||||
51 => Num3,
|
||||
52 => Num4,
|
||||
53 => Num5,
|
||||
54 => Num6,
|
||||
55 => Num7,
|
||||
56 => Num8,
|
||||
57 => Num9,
|
||||
65 => A,
|
||||
66 => B,
|
||||
67 => C,
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::{
|
|||
cell::{Cell, RefCell, UnsafeCell},
|
||||
};
|
||||
|
||||
pub struct HookList {
|
||||
pub(crate) struct HookList {
|
||||
vals: RefCell<Vec<InnerHook<Box<dyn Any>>>>,
|
||||
idx: Cell<usize>,
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ impl Default for HookList {
|
|||
struct InnerHook<T> {
|
||||
cell: UnsafeCell<T>,
|
||||
}
|
||||
|
||||
impl<T> InnerHook<T> {
|
||||
fn new(new: T) -> Self {
|
||||
Self {
|
||||
|
@ -27,6 +28,7 @@ impl<T> InnerHook<T> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HookList {
|
||||
pub(crate) fn next<T: 'static>(&self) -> Option<&mut T> {
|
||||
self.vals.borrow().get(self.idx.get()).and_then(|inn| {
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
//! This module contains all the low-level built-in hooks that require 1st party support to work.
|
||||
//!
|
||||
//! Hooks:
|
||||
//! - use_hook
|
||||
//! - use_state_provider
|
||||
//! - use_state_consumer
|
||||
//! - use_task
|
||||
//! - use_suspense
|
||||
//! - [`use_hook`]
|
||||
//! - [`use_state_provider`]
|
||||
//! - [`use_state_consumer`]
|
||||
//! - [`use_task`]
|
||||
//! - [`use_suspense`]
|
||||
|
||||
use crate::innerlude::*;
|
||||
use futures_util::FutureExt;
|
||||
|
@ -53,15 +53,7 @@ where
|
|||
(true, true) => {}
|
||||
|
||||
// Needs to be initialized
|
||||
(false, false) => {
|
||||
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,
|
||||
);
|
||||
}
|
||||
(false, false) => cx.add_shared_state(init()),
|
||||
|
||||
_ => debug_assert!(false, "Cannot initialize two contexts of the same type"),
|
||||
};
|
||||
|
@ -205,7 +197,10 @@ where
|
|||
|
||||
cx.render(LazyNodes::new(|f| {
|
||||
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| {
|
||||
let val = value.borrow();
|
||||
|
||||
|
@ -218,11 +213,12 @@ where
|
|||
|
||||
user_callback(sus, out)
|
||||
});
|
||||
let callback = unsafe { BumpBox::from_raw(f) };
|
||||
|
||||
VNode::Suspended(bump.alloc(VSuspended {
|
||||
dom_id: empty_cell(),
|
||||
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 value: Rc<RefCell<Option<Box<dyn Any>>>>,
|
||||
}
|
||||
|
||||
type SuspendedCallback = Box<dyn for<'a> Fn(SuspendedContext<'a>) -> DomTree<'a>>;
|
||||
|
||||
pub struct SuspendedContext<'a> {
|
||||
pub(crate) inner: Context<'a, ()>,
|
||||
}
|
||||
|
||||
impl<'src> SuspendedContext<'src> {
|
||||
pub fn render<F: FnOnce(NodeFactory<'src>) -> VNode<'src>>(
|
||||
self,
|
||||
|
|
|
@ -38,7 +38,7 @@ pub(crate) mod innerlude {
|
|||
pub use crate::diff_stack::*;
|
||||
pub use crate::events::*;
|
||||
pub use crate::heuristics::*;
|
||||
pub use crate::hooklist::*;
|
||||
pub(crate) use crate::hooklist::*;
|
||||
pub use crate::hooks::*;
|
||||
pub use crate::mutations::*;
|
||||
pub use crate::nodes::*;
|
||||
|
|
|
@ -283,7 +283,8 @@ pub struct VComponent<'src> {
|
|||
pub struct VSuspended<'a> {
|
||||
pub task_id: u64,
|
||||
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.
|
||||
|
@ -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>,
|
||||
raw_props: *const (),
|
||||
) -> Rc<dyn for<'r> Fn(&'r Scope) -> DomTree<'r>> {
|
||||
|
@ -530,12 +531,8 @@ impl<'a> NodeFactory<'a> {
|
|||
props: safe_props,
|
||||
scope: scp,
|
||||
};
|
||||
|
||||
let res = component(cx);
|
||||
|
||||
let g2 = unsafe { std::mem::transmute(res) };
|
||||
|
||||
g2
|
||||
unsafe { std::mem::transmute(res) }
|
||||
});
|
||||
unsafe { std::mem::transmute::<_, Captured<'static>>(caller) }
|
||||
}
|
||||
|
|
|
@ -36,8 +36,7 @@ pub struct Scope {
|
|||
// Listeners
|
||||
pub(crate) listeners: RefCell<Vec<*const Listener<'static>>>,
|
||||
pub(crate) borrowed_props: RefCell<Vec<*const VComponent<'static>>>,
|
||||
|
||||
pub(crate) suspended_nodes: RefCell<HashMap<u64, *const VNode<'static>>>,
|
||||
pub(crate) suspended_nodes: RefCell<HashMap<u64, *const VSuspended<'static>>>,
|
||||
|
||||
// State
|
||||
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
|
||||
/// 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
|
||||
debug_assert!(
|
||||
self.pending_garbage.borrow().is_empty(),
|
||||
|
@ -220,6 +219,26 @@ impl Scope {
|
|||
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> {
|
||||
self.pending_garbage
|
||||
.borrow_mut()
|
||||
|
|
|
@ -23,6 +23,7 @@ use futures_util::{Future, FutureExt};
|
|||
use std::{
|
||||
any::{Any, TypeId},
|
||||
pin::Pin,
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
/// An integrated virtual node system that progresses events and diffs UI trees.
|
||||
|
@ -39,6 +40,8 @@ pub struct VirtualDom {
|
|||
|
||||
base_scope: ScopeId,
|
||||
|
||||
root_fc: Box<dyn Any>,
|
||||
|
||||
root_prop_type: std::any::TypeId,
|
||||
|
||||
root_props: Pin<Box<dyn std::any::Any>>,
|
||||
|
@ -120,6 +123,7 @@ impl VirtualDom {
|
|||
});
|
||||
|
||||
Self {
|
||||
root_fc: Box::new(root),
|
||||
base_scope,
|
||||
scheduler,
|
||||
root_props: _root_props,
|
||||
|
@ -135,6 +139,32 @@ impl VirtualDom {
|
|||
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
|
||||
///
|
||||
/// The diff machine expects the RealDom's stack to be the root of the application
|
||||
|
|
Loading…
Reference in a new issue