wip: fix rebuild
This commit is contained in:
1 parent
2559740463
commit
15c31d545a
5 files changed
+207
-120
No files matched your search
+13
-11
@@ -125,11 +125,13 @@ impl<'bump> DiffState<'bump> {
|
||||
|
||||
impl<'bump> ScopeArena {
|
||||
pub fn diff_scope(&'bump self, state: &mut DiffState<'bump>, id: &ScopeId) {
|
||||
if let Some(component) = self.get_scope(id) {
|
||||
let (old, new) = (component.wip_head(), component.fin_head());
|
||||
state.stack.push(DiffInstruction::Diff { new, old });
|
||||
self.work(state, || false);
|
||||
}
|
||||
// if let Some(component) = self.get_scope(id) {
|
||||
|
||||
let (old, new) = (self.wip_head(id), self.fin_head(id));
|
||||
|
||||
state.stack.push(DiffInstruction::Diff { old, new });
|
||||
self.work(state, || false);
|
||||
// }
|
||||
}
|
||||
|
||||
/// Progress the diffing for this "fiber"
|
||||
@@ -1146,8 +1148,8 @@ impl<'bump> ScopeArena {
|
||||
}
|
||||
VNode::Component(el) => {
|
||||
let scope_id = el.associated_scope.get().unwrap();
|
||||
let scope = self.get_scope(&scope_id).unwrap();
|
||||
search_node = Some(scope.root_node());
|
||||
// let scope = self.get_scope(&scope_id).unwrap();
|
||||
search_node = Some(self.root_node(&scope_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1164,8 +1166,8 @@ impl<'bump> ScopeArena {
|
||||
}
|
||||
VNode::Component(el) => {
|
||||
let scope_id = el.associated_scope.get().unwrap();
|
||||
let scope = self.get_scope(&scope_id).unwrap();
|
||||
search_node = Some(scope.root_node());
|
||||
// let scope = self.get_scope(&scope_id).unwrap();
|
||||
search_node = Some(self.root_node(&scope_id));
|
||||
}
|
||||
VNode::Linked(link) => {
|
||||
todo!("linked")
|
||||
@@ -1249,8 +1251,8 @@ impl<'bump> ScopeArena {
|
||||
|
||||
VNode::Component(c) => {
|
||||
let scope_id = c.associated_scope.get().unwrap();
|
||||
let scope = self.get_scope(&scope_id).unwrap();
|
||||
let root = scope.root_node();
|
||||
// let scope = self.get_scope(&scope_id).unwrap();
|
||||
let root = self.root_node(&scope_id);
|
||||
self.remove_nodes(state, Some(root), gen_muts);
|
||||
|
||||
log::debug!("Destroying scope {:?}", scope_id);
|
||||
|
||||
@@ -20,7 +20,9 @@ use std::{
|
||||
///
|
||||
/// It is used during the diffing/rendering process as a runtime key into an existing set of nodes. The "render" key
|
||||
/// is essentially a unique key to guarantee safe usage of the Node.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct NodeLink {
|
||||
pub(crate) link_idx: usize,
|
||||
pub(crate) gen_id: u32,
|
||||
pub(crate) scope_id: ScopeId,
|
||||
}
|
||||
@@ -198,6 +200,7 @@ impl<'src> VNode<'src> {
|
||||
VNode::Linked(c) => VNode::Linked(NodeLink {
|
||||
gen_id: c.gen_id,
|
||||
scope_id: c.scope_id,
|
||||
link_idx: c.link_idx,
|
||||
}),
|
||||
}
|
||||
}
|
||||
@@ -207,20 +210,22 @@ impl Debug for VNode<'_> {
|
||||
fn fmt(&self, s: &mut Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
|
||||
match &self {
|
||||
VNode::Element(el) => s
|
||||
.debug_struct("VElement")
|
||||
.debug_struct("VNode::VElement")
|
||||
.field("name", &el.tag_name)
|
||||
.field("key", &el.key)
|
||||
.finish(),
|
||||
|
||||
VNode::Text(t) => write!(s, "VText {{ text: {} }}", t.text),
|
||||
VNode::Anchor(_) => write!(s, "VAnchor"),
|
||||
VNode::Text(t) => write!(s, "VNode::VText {{ text: {} }}", t.text),
|
||||
VNode::Anchor(_) => write!(s, "VNode::VAnchor"),
|
||||
|
||||
VNode::Fragment(frag) => write!(s, "VFragment {{ children: {:?} }}", frag.children),
|
||||
VNode::Suspended { .. } => write!(s, "VSuspended"),
|
||||
VNode::Component(comp) => write!(s, "VComponent {{ fc: {:?}}}", comp.user_fc),
|
||||
VNode::Fragment(frag) => {
|
||||
write!(s, "VNode::VFragment {{ children: {:?} }}", frag.children)
|
||||
}
|
||||
VNode::Suspended { .. } => write!(s, "VNode::VSuspended"),
|
||||
VNode::Component(comp) => write!(s, "VNode::VComponent {{ fc: {:?}}}", comp.user_fc),
|
||||
VNode::Linked(c) => write!(
|
||||
s,
|
||||
"VCached {{ gen_id: {}, scope_id: {:?} }}",
|
||||
"VNode::VCached {{ gen_id: {}, scope_id: {:?} }}",
|
||||
c.gen_id, c.scope_id
|
||||
),
|
||||
}
|
||||
|
||||
+54
-61
@@ -59,12 +59,16 @@ pub struct Scope {
|
||||
|
||||
pub(crate) is_subtree_root: Cell<bool>,
|
||||
|
||||
pub(crate) generation: Cell<u32>,
|
||||
|
||||
// The double-buffering situation that we will use
|
||||
pub(crate) frames: [Bump; 2],
|
||||
pub(crate) frames: [BumpFrame; 2],
|
||||
|
||||
pub(crate) old_root: RefCell<Option<NodeLink>>,
|
||||
pub(crate) new_root: RefCell<Option<NodeLink>>,
|
||||
|
||||
pub(crate) caller: *mut dyn Fn(&Scope) -> Element,
|
||||
|
||||
/*
|
||||
we care about:
|
||||
- listeners (and how to call them when an event is triggered)
|
||||
@@ -83,14 +87,6 @@ pub struct Scope {
|
||||
}
|
||||
|
||||
pub struct SelfReferentialItems<'a> {
|
||||
// nodes stored by "cx.render"
|
||||
pub(crate) cached_nodes_old: Vec<VNode<'a>>,
|
||||
pub(crate) cached_nodes_new: Vec<VNode<'a>>,
|
||||
|
||||
pub(crate) caller: &'a dyn Fn(&Scope) -> Element,
|
||||
|
||||
pub(crate) generation: Cell<u32>,
|
||||
|
||||
pub(crate) listeners: Vec<&'a Listener<'a>>,
|
||||
pub(crate) borrowed_props: Vec<&'a VComponent<'a>>,
|
||||
pub(crate) suspended_nodes: FxHashMap<u64, &'a VSuspended<'a>>,
|
||||
@@ -100,25 +96,6 @@ pub struct SelfReferentialItems<'a> {
|
||||
|
||||
// Public methods exposed to libraries and components
|
||||
impl Scope {
|
||||
/// Get the root VNode for this Scope.
|
||||
///
|
||||
/// This VNode is the "entrypoint" VNode. If the component renders multiple nodes, then this VNode will be a fragment.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// let mut dom = VirtualDom::new(|(cx, props)|cx.render(rsx!{ div {} }));
|
||||
/// dom.rebuild();
|
||||
///
|
||||
/// let base = dom.base_scope();
|
||||
///
|
||||
/// if let VNode::VElement(node) = base.root_node() {
|
||||
/// assert_eq!(node.tag_name, "div");
|
||||
/// }
|
||||
/// ```
|
||||
pub fn root_node(&self) -> &VNode {
|
||||
self.fin_head()
|
||||
}
|
||||
|
||||
/// Get the subtree ID that this scope belongs to.
|
||||
///
|
||||
/// Each component has its own subtree ID - the root subtree has an ID of 0. This ID is used by the renderer to route
|
||||
@@ -239,7 +216,7 @@ impl Scope {
|
||||
///
|
||||
/// `ScopeId` is not unique for the lifetime of the VirtualDom - a ScopeId will be reused if a component is unmounted.
|
||||
pub fn bump(&self) -> &Bump {
|
||||
&self.wip_frame()
|
||||
&self.wip_frame().bump
|
||||
}
|
||||
|
||||
/// Take a lazy VNode structure and actually build it with the context of the VDom's efficient VNode allocator.
|
||||
@@ -258,18 +235,18 @@ impl Scope {
|
||||
/// }
|
||||
///```
|
||||
pub fn render<'src>(&'src self, lazy_nodes: Option<LazyNodes<'src, '_>>) -> Option<NodeLink> {
|
||||
let bump = &self.wip_frame();
|
||||
let bump = &self.wip_frame().bump;
|
||||
let factory = NodeFactory { bump };
|
||||
let node = lazy_nodes.map(|f| f.call(factory))?;
|
||||
|
||||
self.items
|
||||
.borrow_mut()
|
||||
.cached_nodes_old
|
||||
.push(unsafe { std::mem::transmute(node) });
|
||||
let idx = self
|
||||
.wip_frame()
|
||||
.add_node(unsafe { std::mem::transmute(node) });
|
||||
|
||||
Some(NodeLink {
|
||||
gen_id: self.items.borrow().generation.get(),
|
||||
gen_id: self.generation.get(),
|
||||
scope_id: self.our_arena_idx,
|
||||
link_idx: idx,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -427,11 +404,7 @@ impl Scope {
|
||||
self.hooks.push_hook(initializer(self.hooks.len()));
|
||||
}
|
||||
|
||||
runner(self.hooks.next::<State>().expect(HOOK_ERR_MSG))
|
||||
}
|
||||
}
|
||||
|
||||
const HOOK_ERR_MSG: &str = r###"
|
||||
const HOOK_ERR_MSG: &str = r###"
|
||||
Unable to retrieve the hook that was initialized at this index.
|
||||
Consult the `rules of hooks` to understand how to use hooks properly.
|
||||
|
||||
@@ -439,29 +412,24 @@ You likely used the hook in a conditional. Hooks rely on consistent ordering bet
|
||||
Functions prefixed with "use" should never be called conditionally.
|
||||
"###;
|
||||
|
||||
runner(self.hooks.next::<State>().expect(HOOK_ERR_MSG))
|
||||
}
|
||||
}
|
||||
|
||||
// Important internal methods
|
||||
impl Scope {
|
||||
/// Give out our self-referential item with our own borrowed lifetime
|
||||
pub(crate) fn fin_head<'b>(&'b self) -> &'b VNode<'b> {
|
||||
todo!()
|
||||
// let cur_head = &self.finished_frame().head_node;
|
||||
// unsafe { std::mem::transmute::<&VNode<'static>, &VNode<'b>>(cur_head) }
|
||||
}
|
||||
|
||||
/// Give out our self-referential item with our own borrowed lifetime
|
||||
pub(crate) fn wip_head<'b>(&'b self) -> &'b VNode<'b> {
|
||||
todo!()
|
||||
// let cur_head = &self.wip_frame().head_node;
|
||||
// unsafe { std::mem::transmute::<&VNode<'static>, &VNode<'b>>(cur_head) }
|
||||
}
|
||||
|
||||
/// The "work in progress frame" represents the frame that is currently being worked on.
|
||||
pub(crate) fn wip_frame(&self) -> &Bump {
|
||||
todo!()
|
||||
// match self.cur_generation.get() & 1 == 0 {
|
||||
// true => &self.frames[0],
|
||||
// false => &self.frames[1],
|
||||
// }
|
||||
pub(crate) fn wip_frame(&self) -> &BumpFrame {
|
||||
match self.generation.get() & 1 == 0 {
|
||||
true => &self.frames[0],
|
||||
false => &self.frames[1],
|
||||
}
|
||||
}
|
||||
pub(crate) fn fin_frame(&self) -> &BumpFrame {
|
||||
match self.generation.get() & 1 == 1 {
|
||||
true => &self.frames[0],
|
||||
false => &self.frames[1],
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn reset_wip_frame(&self) {
|
||||
@@ -469,8 +437,10 @@ impl Scope {
|
||||
let bump = self.wip_frame() as *const _ as *mut Bump;
|
||||
let g = &mut *bump;
|
||||
g.reset();
|
||||
}
|
||||
|
||||
// self.wip_frame_mut().bump.reset()
|
||||
pub fn cycle_frame(&self) {
|
||||
self.generation.set(self.generation.get() + 1);
|
||||
}
|
||||
|
||||
/// A safe wrapper around calling listeners
|
||||
@@ -528,3 +498,26 @@ impl Scope {
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BumpFrame {
|
||||
pub bump: Bump,
|
||||
pub nodes: RefCell<Vec<VNode<'static>>>,
|
||||
}
|
||||
impl BumpFrame {
|
||||
pub fn new() -> Self {
|
||||
let bump = Bump::new();
|
||||
|
||||
let node = &*bump.alloc(VText {
|
||||
text: "asd",
|
||||
dom_id: Default::default(),
|
||||
is_static: false,
|
||||
});
|
||||
let nodes = RefCell::new(vec![VNode::Text(unsafe { std::mem::transmute(node) })]);
|
||||
Self { bump, nodes }
|
||||
}
|
||||
fn add_node(&self, node: VNode<'static>) -> usize {
|
||||
let mut nodes = self.nodes.borrow_mut();
|
||||
nodes.push(node);
|
||||
nodes.len() - 1
|
||||
}
|
||||
}
|
||||
+109
-33
@@ -1,5 +1,8 @@
|
||||
use slab::Slab;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::{
|
||||
borrow::BorrowMut,
|
||||
cell::{Cell, RefCell},
|
||||
};
|
||||
|
||||
use bumpalo::{boxed::Box as BumpBox, Bump};
|
||||
use futures_channel::mpsc::UnboundedSender;
|
||||
@@ -22,6 +25,7 @@ pub(crate) struct ScopeArena {
|
||||
bump: Bump,
|
||||
scopes: Vec<*mut Scope>,
|
||||
free_scopes: Vec<ScopeId>,
|
||||
nodes: RefCell<Slab<*const VNode<'static>>>,
|
||||
pub(crate) sender: UnboundedSender<SchedulerMsg>,
|
||||
}
|
||||
|
||||
@@ -31,7 +35,7 @@ impl ScopeArena {
|
||||
bump: Bump::new(),
|
||||
scopes: Vec::new(),
|
||||
free_scopes: Vec::new(),
|
||||
|
||||
nodes: RefCell::new(Slab::new()),
|
||||
sender,
|
||||
}
|
||||
}
|
||||
@@ -55,41 +59,49 @@ impl ScopeArena {
|
||||
todo!("override the scope contents");
|
||||
id
|
||||
} else {
|
||||
let id = ScopeId(self.scopes.len());
|
||||
let scope_id = ScopeId(self.scopes.len());
|
||||
|
||||
// cast off the lifetime
|
||||
let caller = unsafe { std::mem::transmute(caller) };
|
||||
let old_root = NodeLink {
|
||||
link_idx: 0,
|
||||
gen_id: 0,
|
||||
scope_id,
|
||||
};
|
||||
let new_root = NodeLink {
|
||||
link_idx: 0,
|
||||
gen_id: 0,
|
||||
scope_id,
|
||||
};
|
||||
|
||||
let new_scope = Scope {
|
||||
sender: self.sender.clone(),
|
||||
parent_scope,
|
||||
our_arena_idx: id,
|
||||
our_arena_idx: scope_id,
|
||||
height,
|
||||
subtree: Cell::new(subtree),
|
||||
is_subtree_root: Cell::new(false),
|
||||
frames: [Bump::default(), Bump::default()],
|
||||
frames: [BumpFrame::new(), BumpFrame::new()],
|
||||
|
||||
hooks: Default::default(),
|
||||
shared_contexts: Default::default(),
|
||||
caller,
|
||||
generation: 0.into(),
|
||||
|
||||
old_root: RefCell::new(Some(old_root)),
|
||||
new_root: RefCell::new(Some(new_root)),
|
||||
// old_root: RefCell::new(Some(old_root)),
|
||||
// new_root: RefCell::new(None),
|
||||
items: RefCell::new(SelfReferentialItems {
|
||||
listeners: Default::default(),
|
||||
borrowed_props: Default::default(),
|
||||
suspended_nodes: Default::default(),
|
||||
tasks: Default::default(),
|
||||
pending_effects: Default::default(),
|
||||
cached_nodes_old: Default::default(),
|
||||
generation: Default::default(),
|
||||
cached_nodes_new: Default::default(),
|
||||
caller,
|
||||
}),
|
||||
old_root: todo!(),
|
||||
new_root: todo!(),
|
||||
};
|
||||
|
||||
let stable = self.bump.alloc(new_scope);
|
||||
self.scopes.push(stable);
|
||||
id
|
||||
scope_id
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,8 +110,20 @@ impl ScopeArena {
|
||||
}
|
||||
|
||||
pub fn reserve_node(&self, node: &VNode) -> ElementId {
|
||||
todo!()
|
||||
// self.node_reservations.insert(id);
|
||||
let mut els = self.nodes.borrow_mut();
|
||||
let entry = els.vacant_entry();
|
||||
let key = entry.key();
|
||||
let id = ElementId(key);
|
||||
let node = node as *const _;
|
||||
let node = unsafe { std::mem::transmute(node) };
|
||||
entry.insert(node);
|
||||
id
|
||||
|
||||
// let nodes = self.nodes.borrow_mut();
|
||||
// let id = nodes.insert(());
|
||||
// let node_id = ElementId(id);
|
||||
// node = Some(node_id);
|
||||
// node_id
|
||||
}
|
||||
|
||||
pub fn collect_garbage(&self, id: ElementId) {
|
||||
@@ -177,38 +201,90 @@ impl ScopeArena {
|
||||
// - We've dropped all references to the wip bump frame with "ensure_drop_safety"
|
||||
unsafe { scope.reset_wip_frame() };
|
||||
|
||||
let mut items = scope.items.borrow_mut();
|
||||
{
|
||||
let mut items = scope.items.borrow_mut();
|
||||
|
||||
// just forget about our suspended nodes while we're at it
|
||||
items.suspended_nodes.clear();
|
||||
// just forget about our suspended nodes while we're at it
|
||||
items.suspended_nodes.clear();
|
||||
|
||||
// guarantee that we haven't screwed up - there should be no latent references anywhere
|
||||
debug_assert!(items.listeners.is_empty());
|
||||
debug_assert!(items.suspended_nodes.is_empty());
|
||||
debug_assert!(items.borrowed_props.is_empty());
|
||||
// guarantee that we haven't screwed up - there should be no latent references anywhere
|
||||
debug_assert!(items.listeners.is_empty());
|
||||
debug_assert!(items.suspended_nodes.is_empty());
|
||||
debug_assert!(items.borrowed_props.is_empty());
|
||||
|
||||
log::debug!("Borrowed stuff is successfully cleared");
|
||||
log::debug!("Borrowed stuff is successfully cleared");
|
||||
|
||||
// temporarily cast the vcomponent to the right lifetime
|
||||
// let vcomp = scope.load_vcomp();
|
||||
// temporarily cast the vcomponent to the right lifetime
|
||||
// let vcomp = scope.load_vcomp();
|
||||
}
|
||||
|
||||
let render: &dyn Fn(&Scope) -> Element = todo!();
|
||||
let render: &dyn Fn(&Scope) -> Element = unsafe { &*scope.caller };
|
||||
|
||||
// Todo: see if we can add stronger guarantees around internal bookkeeping and failed component renders.
|
||||
scope.wip_frame().nodes.borrow_mut().clear();
|
||||
if let Some(key) = render(scope) {
|
||||
// todo!("attach the niode");
|
||||
// let new_head = builder.into_vnode(NodeFactory {
|
||||
// bump: &scope.frames.wip_frame().bump,
|
||||
// });
|
||||
// log::debug!("Render is successful");
|
||||
dbg!(key);
|
||||
|
||||
dbg!(&scope.wip_frame().nodes.borrow_mut());
|
||||
// let mut old = scope.old_root.borrow_mut();
|
||||
// let mut new = scope.new_root.borrow_mut();
|
||||
|
||||
// let new_old = new.clone();
|
||||
// *old = new_old;
|
||||
// *new = Some(key);
|
||||
|
||||
// dbg!(&old);
|
||||
// dbg!(&new);
|
||||
|
||||
// the user's component succeeded. We can safely cycle to the next frame
|
||||
// scope.frames.wip_frame_mut().head_node = unsafe { std::mem::transmute(new_head) };
|
||||
// scope.frames.cycle_frame();
|
||||
scope.cycle_frame();
|
||||
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn wip_head(&self, id: &ScopeId) -> &VNode {
|
||||
let scope = self.get_scope(id).unwrap();
|
||||
let wip_frame = scope.wip_frame();
|
||||
let nodes = wip_frame.nodes.borrow();
|
||||
let node = nodes.get(0).unwrap();
|
||||
unsafe { std::mem::transmute(node) }
|
||||
// let root = scope.old_root.borrow();
|
||||
// let link = root.as_ref().unwrap();
|
||||
// dbg!(link);
|
||||
|
||||
// // for now, components cannot pass portals through each other
|
||||
// assert_eq!(link.scope_id, *id);
|
||||
// // assert_eq!(link.gen_id, scope.generation.get() - 1);
|
||||
|
||||
// // let items = scope.items.borrow();
|
||||
// let nodes = scope.wip_frame().nodes.borrow();
|
||||
// let node = nodes.get(link.link_idx).unwrap();
|
||||
// unsafe { std::mem::transmute(node) }
|
||||
}
|
||||
|
||||
pub fn fin_head(&self, id: &ScopeId) -> &VNode {
|
||||
let scope = self.get_scope(id).unwrap();
|
||||
let wip_frame = scope.fin_frame();
|
||||
let nodes = wip_frame.nodes.borrow();
|
||||
let node = nodes.get(0).unwrap();
|
||||
unsafe { std::mem::transmute(node) }
|
||||
// let scope = self.get_scope(id).unwrap();
|
||||
// let root = scope.new_root.borrow();
|
||||
// let link = root.as_ref().unwrap();
|
||||
|
||||
// // for now, components cannot pass portals through each other
|
||||
// assert_eq!(link.scope_id, *id);
|
||||
// // assert_eq!(link.gen_id, scope.generation.get());
|
||||
|
||||
// let nodes = scope.fin_frame().nodes.borrow();
|
||||
// let node = nodes.get(link.link_idx).unwrap();
|
||||
// unsafe { std::mem::transmute(node) }
|
||||
}
|
||||
pub fn root_node(&self, id: &ScopeId) -> &VNode {
|
||||
self.wip_head(id)
|
||||
}
|
||||
}
|
||||
@@ -384,8 +384,10 @@ impl VirtualDom {
|
||||
log::debug!("about to run scope {:?}", scopeid);
|
||||
|
||||
if self.scopes.run_scope(&scopeid) {
|
||||
let scope = self.scopes.get_scope(&scopeid).unwrap();
|
||||
let (old, new) = (scope.wip_head(), scope.fin_head());
|
||||
let (old, new) = (
|
||||
self.scopes.wip_head(&scopeid),
|
||||
self.scopes.fin_head(&scopeid),
|
||||
);
|
||||
diff_state.stack.scope_stack.push(scopeid);
|
||||
diff_state.stack.push(DiffInstruction::Diff { new, old });
|
||||
}
|
||||
@@ -438,13 +440,20 @@ impl VirtualDom {
|
||||
/// apply_edits(edits);
|
||||
/// ```
|
||||
pub fn rebuild(&mut self) -> Mutations {
|
||||
// todo: I think we need to append a node or something
|
||||
// diff_machine
|
||||
// .stack
|
||||
// .create_node(cur_component.frames.fin_head(), MountType::Append);
|
||||
let mut diff_machine = DiffState::new(Mutations::new());
|
||||
|
||||
let scope = self.base_scope;
|
||||
self.hard_diff(&scope).unwrap()
|
||||
let scope_id = self.base_scope;
|
||||
if self.scopes.run_scope(&scope_id) {
|
||||
diff_machine
|
||||
.stack
|
||||
.create_node(self.scopes.fin_head(&scope_id), MountType::Append);
|
||||
|
||||
diff_machine.stack.scope_stack.push(scope_id);
|
||||
|
||||
self.scopes.work(&mut diff_machine, || false);
|
||||
}
|
||||
|
||||
diff_machine.mutations
|
||||
}
|
||||
|
||||
/// Compute a manual diff of the VirtualDOM between states.
|
||||
@@ -491,6 +500,8 @@ impl VirtualDom {
|
||||
|
||||
self.scopes.diff_scope(&mut diff_machine, scope_id);
|
||||
|
||||
dbg!(&diff_machine.mutations);
|
||||
|
||||
Some(diff_machine.mutations)
|
||||
} else {
|
||||
None
|
||||
|
||||
Reference in new issue
Block a user