Skip to content

Commit

Permalink
fix assigning ids on elements with dynamic attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
ealmloff committed Jun 6, 2024
1 parent ab1d474 commit 18cc74d
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 16 deletions.
36 changes: 24 additions & 12 deletions packages/core/src/diff/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -626,12 +626,17 @@ impl VNode {
// nodes in an iterator of (dynamic_node_index, path)
#[cfg(not(debug_assertions))]
let nodes_sorted = template.node_paths.iter().copied().enumerate();
#[cfg(not(debug_assertions))]
let attrs_sorted = template.attr_paths.iter().copied().enumerate().peekable();

// If this is a debug build, we need to check that the paths are in the correct order because hot reloading can cause scrambled states
#[cfg(debug_assertions)]
let nodes_sorted = sort_bfs(template.node_paths).into_iter();
#[cfg(debug_assertions)]
let attrs_sorted = sort_bfs(template.attr_paths).into_iter();

let mut nodes = nodes_sorted.peekable();
let mut attrs = attrs_sorted.peekable();

// Get the mounted id of this block
// At this point, we should have already mounted the block
Expand Down Expand Up @@ -676,6 +681,10 @@ impl VNode {
dom,
to.as_deref_mut(),
);
// Now write out any attributes we need
if let Some(to) = to.as_deref_mut() {
self.write_attrs(mount, &mut attrs, root_idx as u8, dom, to);
}
}

// This creates one node on the stack
Expand All @@ -685,11 +694,6 @@ impl VNode {
})
.sum();

// Now write out any attributes we need
if let Some(to) = to {
self.write_attrs(mount, dom, to);
}

// And return the number of nodes we created on the stack
nodes_created
}
Expand Down Expand Up @@ -794,15 +798,23 @@ impl VNode {
/// }
/// }
/// ```
fn write_attrs(&self, mount: MountId, dom: &mut VirtualDom, to: &mut impl WriteMutations) {
let template = self.template.get();
///
/// IMPORTANT: This function assumes that root node is the top node on the stack
fn write_attrs(
&self,
mount: MountId,
dynamic_attrbiutes_iter: &mut Peekable<impl Iterator<Item = (usize, &'static [u8])>>,
root_idx: u8,
dom: &mut VirtualDom,
to: &mut impl WriteMutations,
) {
let mut last_path = None;
for (attribute_idx, (attribute, attribute_path)) in self
.dynamic_attrs
.iter()
.zip(template.attr_paths.iter())
.enumerate()
// Only take nodes that are under this root node
let from_root_node = |(_, path): &(usize, &[u8])| path.first() == Some(&root_idx);
while let Some((attribute_idx, attribute_path)) =
dynamic_attrbiutes_iter.next_if(from_root_node)
{
let attribute = &self.dynamic_attrs[attribute_idx];
let id = match last_path {
// If the last path was exactly the same, we can reuse the id
Some((path, id)) if path == attribute_path => id,
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/virtual_dom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -865,7 +865,7 @@ impl VirtualDom {

for attr in attrs.iter() {
// Remove the "on" prefix if it exists, TODO, we should remove this and settle on one
if &attr.name[2..] == name && target_path.is_decendant(&this_path) {
if attr.name.get(2..) == Some(name) && target_path.is_decendant(&this_path) {
listeners.push(&attr.value);

// Break if this is the exact target element.
Expand Down Expand Up @@ -923,7 +923,7 @@ impl VirtualDom {
for attr in attr.iter() {
// Remove the "on" prefix if it exists, TODO, we should remove this and settle on one
// Only call the listener if this is the exact target element.
if &attr.name[2..] == name && target_path == this_path {
if attr.name.get(2..) == Some(name) && target_path == this_path {
if let AttributeValue::Listener(listener) = &attr.value {
self.runtime.rendering.set(false);
listener.call(uievent.clone());
Expand Down
4 changes: 2 additions & 2 deletions packages/fullstack/src/html_storage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,11 @@ fn serialized_and_deserializes() {
let mut storage = HTMLData::default();
storage.push(&data);
println!("serialized size: {}", storage.data[0].len());
let mut as_string = Vec::new();
let mut as_string = String::new();
serde_to_writable(&data, &mut as_string).unwrap();
println!("compressed size: {}", as_string.len());

let decoded: Vec<Data> = deserialize::serde_from_bytes(&as_string).unwrap();
let decoded: Vec<Data> = deserialize::serde_from_bytes(as_string.as_bytes()).unwrap();
assert_eq!(data, decoded);
}
}
Expand Down

0 comments on commit 18cc74d

Please sign in to comment.