wip: bubbling in progress

This commit is contained in:
Jonathan Kelley committed 2021-11-11 21:34:20 -05:00
1 parent 8acdd2ea83
commit a21020ea57
15 files changed
+268 -291

No files matched your search

+47 -29
View File
@@ -54,7 +54,7 @@
//! We also employ "subtree memoization" which saves us from having to check trees which hold no dynamic content. We can
//! detect if a subtree is "static" by checking if its children are "static". Since we dive into the tree depth-first, the
//! calls to "create" propagate this information upwards. Structures like the one below are entirely static:
//! ```rust
//! ```rust, ignore
//! rsx!( div { class: "hello world", "this node is entirely static" } )
//! ```
//! Because the subtrees won't be diffed, their "real node" data will be stale (invalid), so it's up to the reconciler to
@@ -147,6 +147,7 @@ pub(crate) enum DiffInstruction<'a> {
},
PopScope,
PopElement,
}
#[derive(Debug, Clone, Copy)]
@@ -162,30 +163,32 @@ pub(crate) struct DiffStack<'bump> {
pub(crate) instructions: Vec<DiffInstruction<'bump>>,
nodes_created_stack: SmallVec<[usize; 10]>,
pub scope_stack: SmallVec<[ScopeId; 5]>,
pub element_stack: SmallVec<[ElementId; 10]>,
}
impl<'bump> DiffStack<'bump> {
pub fn new() -> Self {
fn new() -> Self {
Self {
instructions: Vec::with_capacity(1000),
nodes_created_stack: smallvec![],
scope_stack: smallvec![],
element_stack: smallvec![],
}
}
pub fn pop(&mut self) -> Option<DiffInstruction<'bump>> {
fn pop(&mut self) -> Option<DiffInstruction<'bump>> {
self.instructions.pop()
}
pub fn pop_off_scope(&mut self) {
fn pop_off_scope(&mut self) {
self.scope_stack.pop();
}
pub fn push(&mut self, instruction: DiffInstruction<'bump>) {
pub(crate) fn push(&mut self, instruction: DiffInstruction<'bump>) {
self.instructions.push(instruction)
}
pub fn create_children(&mut self, children: &'bump [VNode<'bump>], and: MountType<'bump>) {
fn create_children(&mut self, children: &'bump [VNode<'bump>], and: MountType<'bump>) {
self.nodes_created_stack.push(0);
self.instructions.push(DiffInstruction::Mount { and });
@@ -195,36 +198,36 @@ impl<'bump> DiffStack<'bump> {
}
}
pub fn push_subtree(&mut self) {
fn push_subtree(&mut self) {
self.nodes_created_stack.push(0);
self.instructions.push(DiffInstruction::Mount {
and: MountType::Append,
});
}
pub fn push_nodes_created(&mut self, count: usize) {
fn push_nodes_created(&mut self, count: usize) {
self.nodes_created_stack.push(count);
}
pub fn create_node(&mut self, node: &'bump VNode<'bump>, and: MountType<'bump>) {
pub(crate) fn create_node(&mut self, node: &'bump VNode<'bump>, and: MountType<'bump>) {
self.nodes_created_stack.push(0);
self.instructions.push(DiffInstruction::Mount { and });
self.instructions.push(DiffInstruction::Create { node });
}
pub fn add_child_count(&mut self, count: usize) {
fn add_child_count(&mut self, count: usize) {
*self.nodes_created_stack.last_mut().unwrap() += count;
}
pub fn pop_nodes_created(&mut self) -> usize {
fn pop_nodes_created(&mut self) -> usize {
self.nodes_created_stack.pop().unwrap()
}
pub fn current_scope(&self) -> Option<ScopeId> {
fn current_scope(&self) -> Option<ScopeId> {
self.scope_stack.last().copied()
}
pub fn create_component(&mut self, idx: ScopeId, node: &'bump VNode<'bump>) {
fn create_component(&mut self, idx: ScopeId, node: &'bump VNode<'bump>) {
// Push the new scope onto the stack
self.scope_stack.push(idx);
@@ -263,10 +266,13 @@ impl<'bump> DiffState<'bump> {
self.stack.add_child_count(num_on_stack);
}
DiffInstruction::PopScope => self.stack.pop_off_scope(),
DiffInstruction::PopElement => {
self.stack.element_stack.pop();
}
};
if deadline_expired() {
log::debug!("Deadline expired before we could finished!");
log::debug!("Deadline expired before we could finish!");
return false;
}
}
@@ -390,11 +396,18 @@ impl<'bump> DiffState<'bump> {
children,
namespace,
dom_id,
parent_id,
..
} = element;
let real_id = self.scopes.reserve_node(node);
// set the parent ID for event bubbling
self.stack.instructions.push(DiffInstruction::PopElement);
let parent = self.stack.element_stack.last().unwrap();
parent_id.set(Some(*parent));
// set the id of the element
let real_id = self.scopes.reserve_node(node);
self.stack.element_stack.push(real_id);
dom_id.set(Some(real_id));
self.mutations.create_element(tag_name, *namespace, real_id);
@@ -438,9 +451,11 @@ impl<'bump> DiffState<'bump> {
let caller = unsafe { std::mem::transmute(vcomponent.caller as *const _) };
let fc_ptr = vcomponent.user_fc;
let new_idx = self
.scopes
.new_with_key(fc_ptr, caller, parent_scope, height, subtree);
let container = *self.stack.element_stack.last().unwrap();
let new_idx =
self.scopes
.new_with_key(fc_ptr, caller, parent_scope, container, height, subtree);
// Actually initialize the caller's slot with the right address
vcomponent.associated_scope.set(Some(new_idx));
@@ -650,20 +665,18 @@ impl<'bump> DiffState<'bump> {
let scope = unsafe {
self.scopes
.get_scope_mut(&scope_addr)
.expect(&format!("could not find {:?}", scope_addr))
.unwrap_or_else(|| panic!("could not find {:?}", scope_addr))
};
scope.caller = unsafe { std::mem::transmute(new.caller) };
// React doesn't automatically memoize, but we do.
let props_are_the_same = old.comparator.unwrap();
if self.force_diff || !props_are_the_same(new) {
if self.scopes.run_scope(&scope_addr) {
self.diff_node(
self.scopes.wip_head(&scope_addr),
self.scopes.fin_head(&scope_addr),
);
}
if (self.force_diff || !props_are_the_same(new)) && self.scopes.run_scope(&scope_addr) {
self.diff_node(
self.scopes.wip_head(&scope_addr),
self.scopes.fin_head(&scope_addr),
);
}
self.stack.scope_stack.pop();
@@ -1206,13 +1219,19 @@ impl<'bump> DiffState<'bump> {
fn replace_node(&mut self, old: &'bump VNode<'bump>, nodes_created: usize) {
match old {
VNode::Element(el) => {
let id = old.try_mounted_id().expect(&format!("broke on {:?}", old));
let id = old
.try_mounted_id()
.unwrap_or_else(|| panic!("broke on {:?}", old));
self.mutations.replace_with(id, nodes_created as u32);
self.remove_nodes(el.children, false);
}
VNode::Text(_) | VNode::Anchor(_) | VNode::Suspended(_) => {
let id = old.try_mounted_id().expect(&format!("broke on {:?}", old));
let id = old
.try_mounted_id()
.unwrap_or_else(|| panic!("broke on {:?}", old));
self.mutations.replace_with(id, nodes_created as u32);
}
@@ -1226,7 +1245,6 @@ impl<'bump> DiffState<'bump> {
self.replace_node(node, nodes_created);
let scope_id = c.associated_scope.get().unwrap();
println!("replacing c {:?} ", scope_id);
log::debug!("Destroying scope {:?}", scope_id);
self.scopes.try_remove(&scope_id).unwrap();
}