|
@@ -1,15 +1,57 @@
|
|
use rustc_hash::{FxHashMap, FxHashSet};
|
|
use rustc_hash::{FxHashMap, FxHashSet};
|
|
use std::any::{Any, TypeId};
|
|
use std::any::{Any, TypeId};
|
|
use std::collections::VecDeque;
|
|
use std::collections::VecDeque;
|
|
|
|
+use std::rc::Rc;
|
|
|
|
|
|
use crate::node::{
|
|
use crate::node::{
|
|
ElementNode, FromAnyValue, NodeType, OwnedAttributeDiscription, OwnedAttributeValue,
|
|
ElementNode, FromAnyValue, NodeType, OwnedAttributeDiscription, OwnedAttributeValue,
|
|
};
|
|
};
|
|
-use crate::node_ref::{AttributeMask, NodeMask, NodeMaskBuilder};
|
|
|
|
|
|
+use crate::node_ref::{NodeMask, NodeMaskBuilder};
|
|
use crate::passes::{resolve_passes, DirtyNodeStates, TypeErasedPass};
|
|
use crate::passes::{resolve_passes, DirtyNodeStates, TypeErasedPass};
|
|
|
|
+use crate::prelude::AttributeMaskBuilder;
|
|
use crate::tree::{NodeId, Tree};
|
|
use crate::tree::{NodeId, Tree};
|
|
use crate::{FxDashSet, SendAnyMap};
|
|
use crate::{FxDashSet, SendAnyMap};
|
|
|
|
|
|
|
|
+struct NodesDirty<V: FromAnyValue + Send + Sync> {
|
|
|
|
+ passes_updated: FxHashMap<NodeId, FxHashSet<TypeId>>,
|
|
|
|
+ nodes_updated: FxHashMap<NodeId, NodeMask>,
|
|
|
|
+ passes: Rc<Box<[TypeErasedPass<V>]>>,
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<V: FromAnyValue + Send + Sync> NodesDirty<V> {
|
|
|
|
+ fn mark_dirty(&mut self, node_id: NodeId, mask: NodeMask) {
|
|
|
|
+ self.passes_updated.entry(node_id).or_default().extend(
|
|
|
|
+ self.passes
|
|
|
|
+ .iter()
|
|
|
|
+ .filter_map(|x| x.mask.overlaps(&mask).then_some(x.this_type_id)),
|
|
|
|
+ );
|
|
|
|
+ let nodes_updated = &mut self.nodes_updated;
|
|
|
|
+ if let Some(node) = nodes_updated.get_mut(&node_id) {
|
|
|
|
+ *node = node.union(&mask);
|
|
|
|
+ } else {
|
|
|
|
+ nodes_updated.insert(node_id, mask);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fn mark_parent_added_or_removed(&mut self, node_id: NodeId) {
|
|
|
|
+ let hm = self.passes_updated.entry(node_id).or_default();
|
|
|
|
+ for pass in &**self.passes {
|
|
|
|
+ if pass.parent_dependant {
|
|
|
|
+ hm.insert(pass.this_type_id);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fn mark_child_changed(&mut self, node_id: NodeId) {
|
|
|
|
+ let hm = self.passes_updated.entry(node_id).or_default();
|
|
|
|
+ for pass in &**self.passes {
|
|
|
|
+ if pass.child_dependant {
|
|
|
|
+ hm.insert(pass.this_type_id);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
/// A Dom that can sync with the VirtualDom mutations intended for use in lazy renderers.
|
|
/// A Dom that can sync with the VirtualDom mutations intended for use in lazy renderers.
|
|
/// The render state passes from parent to children and or accumulates state from children to parents.
|
|
/// The render state passes from parent to children and or accumulates state from children to parents.
|
|
/// To get started implement [crate::state::ParentDepState], [crate::state::NodeDepState], or [crate::state::ChildDepState] and call [RealDom::apply_mutations] to update the dom and [RealDom::update_state] to update the state of the nodes.
|
|
/// To get started implement [crate::state::ParentDepState], [crate::state::NodeDepState], or [crate::state::ChildDepState] and call [RealDom::apply_mutations] to update the dom and [RealDom::update_state] to update the state of the nodes.
|
|
@@ -19,9 +61,8 @@ use crate::{FxDashSet, SendAnyMap};
|
|
pub struct RealDom<V: FromAnyValue + Send + Sync = ()> {
|
|
pub struct RealDom<V: FromAnyValue + Send + Sync = ()> {
|
|
pub(crate) tree: Tree,
|
|
pub(crate) tree: Tree,
|
|
nodes_listening: FxHashMap<String, FxHashSet<NodeId>>,
|
|
nodes_listening: FxHashMap<String, FxHashSet<NodeId>>,
|
|
- pub(crate) passes: Box<[TypeErasedPass<V>]>,
|
|
|
|
- passes_updated: FxHashMap<NodeId, FxHashSet<TypeId>>,
|
|
|
|
- nodes_updated: FxHashMap<NodeId, NodeMask>,
|
|
|
|
|
|
+ pub(crate) passes: Rc<Box<[TypeErasedPass<V>]>>,
|
|
|
|
+ dirty_nodes: NodesDirty<V>,
|
|
phantom: std::marker::PhantomData<V>,
|
|
phantom: std::marker::PhantomData<V>,
|
|
}
|
|
}
|
|
|
|
|
|
@@ -53,6 +94,7 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ let passes = Rc::new(passes);
|
|
|
|
|
|
let mut passes_updated = FxHashMap::default();
|
|
let mut passes_updated = FxHashMap::default();
|
|
let mut nodes_updated = FxHashMap::default();
|
|
let mut nodes_updated = FxHashMap::default();
|
|
@@ -64,50 +106,22 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
|
|
RealDom {
|
|
RealDom {
|
|
tree,
|
|
tree,
|
|
nodes_listening: FxHashMap::default(),
|
|
nodes_listening: FxHashMap::default(),
|
|
- passes,
|
|
|
|
- passes_updated,
|
|
|
|
- nodes_updated,
|
|
|
|
|
|
+ passes: passes.clone(),
|
|
|
|
+ dirty_nodes: NodesDirty {
|
|
|
|
+ passes_updated,
|
|
|
|
+ nodes_updated,
|
|
|
|
+ passes,
|
|
|
|
+ },
|
|
phantom: std::marker::PhantomData,
|
|
phantom: std::marker::PhantomData,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- fn mark_dirty(&mut self, node_id: NodeId, mask: NodeMask) {
|
|
|
|
- self.passes_updated.entry(node_id).or_default().extend(
|
|
|
|
- self.passes
|
|
|
|
- .iter()
|
|
|
|
- .filter_map(|x| x.mask.overlaps(&mask).then_some(x.this_type_id)),
|
|
|
|
- );
|
|
|
|
- let nodes_updated = &mut self.nodes_updated;
|
|
|
|
- if let Some(node) = nodes_updated.get_mut(&node_id) {
|
|
|
|
- *node = node.union(&mask);
|
|
|
|
- } else {
|
|
|
|
- nodes_updated.insert(node_id, mask);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- fn mark_parent_added_or_removed(&mut self, node_id: NodeId) {
|
|
|
|
- let hm = self.passes_updated.entry(node_id).or_default();
|
|
|
|
- for pass in &*self.passes {
|
|
|
|
- if pass.parent_dependant {
|
|
|
|
- hm.insert(pass.this_type_id);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- fn mark_child_changed(&mut self, node_id: NodeId) {
|
|
|
|
- let hm = self.passes_updated.entry(node_id).or_default();
|
|
|
|
- for pass in &*self.passes {
|
|
|
|
- if pass.child_dependant {
|
|
|
|
- hm.insert(pass.this_type_id);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
pub fn create_node(&mut self, node: NodeType<V>, mark_dirty: bool) -> NodeMut<'_, V> {
|
|
pub fn create_node(&mut self, node: NodeType<V>, mark_dirty: bool) -> NodeMut<'_, V> {
|
|
let mut node_entry = self.tree.create_node();
|
|
let mut node_entry = self.tree.create_node();
|
|
let id = node_entry.id();
|
|
let id = node_entry.id();
|
|
if mark_dirty {
|
|
if mark_dirty {
|
|
- self.passes_updated
|
|
|
|
|
|
+ self.dirty_nodes
|
|
|
|
+ .passes_updated
|
|
.entry(id)
|
|
.entry(id)
|
|
.or_default()
|
|
.or_default()
|
|
.extend(self.passes.iter().map(|x| x.this_type_id));
|
|
.extend(self.passes.iter().map(|x| x.this_type_id));
|
|
@@ -186,8 +200,8 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
|
|
ctx: SendAnyMap,
|
|
ctx: SendAnyMap,
|
|
parallel: bool,
|
|
parallel: bool,
|
|
) -> (FxDashSet<NodeId>, FxHashMap<NodeId, NodeMask>) {
|
|
) -> (FxDashSet<NodeId>, FxHashMap<NodeId, NodeMask>) {
|
|
- let passes = std::mem::take(&mut self.passes_updated);
|
|
|
|
- let nodes_updated = std::mem::take(&mut self.nodes_updated);
|
|
|
|
|
|
+ let passes = std::mem::take(&mut self.dirty_nodes.passes_updated);
|
|
|
|
+ let nodes_updated = std::mem::take(&mut self.dirty_nodes.nodes_updated);
|
|
let dirty_nodes = DirtyNodeStates::with_passes(self.passes.iter().map(|p| p.this_type_id));
|
|
let dirty_nodes = DirtyNodeStates::with_passes(self.passes.iter().map(|p| p.this_type_id));
|
|
for (node_id, passes) in passes {
|
|
for (node_id, passes) in passes {
|
|
// remove any nodes that were created and then removed in the same mutations from the dirty nodes list
|
|
// remove any nodes that were created and then removed in the same mutations from the dirty nodes list
|
|
@@ -206,15 +220,15 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
|
|
|
|
|
|
pub fn remove(&mut self, id: NodeId) {
|
|
pub fn remove(&mut self, id: NodeId) {
|
|
if let Some(parent_id) = self.tree.parent_id(id) {
|
|
if let Some(parent_id) = self.tree.parent_id(id) {
|
|
- self.mark_child_changed(parent_id);
|
|
|
|
|
|
+ self.dirty_nodes.mark_child_changed(parent_id);
|
|
}
|
|
}
|
|
self.tree.remove(id)
|
|
self.tree.remove(id)
|
|
}
|
|
}
|
|
|
|
|
|
pub fn replace(&mut self, old: NodeId, new: NodeId) {
|
|
pub fn replace(&mut self, old: NodeId, new: NodeId) {
|
|
if let Some(parent_id) = self.tree.parent_id(old) {
|
|
if let Some(parent_id) = self.tree.parent_id(old) {
|
|
- self.mark_child_changed(parent_id);
|
|
|
|
- self.mark_parent_added_or_removed(new);
|
|
|
|
|
|
+ self.dirty_nodes.mark_child_changed(parent_id);
|
|
|
|
+ self.dirty_nodes.mark_parent_added_or_removed(new);
|
|
}
|
|
}
|
|
self.tree.replace(old, new);
|
|
self.tree.replace(old, new);
|
|
}
|
|
}
|
|
@@ -376,16 +390,11 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeImmutable<V> for NodeRef<'a, V> {
|
|
pub struct NodeMut<'a, V: FromAnyValue + Send + Sync = ()> {
|
|
pub struct NodeMut<'a, V: FromAnyValue + Send + Sync = ()> {
|
|
id: NodeId,
|
|
id: NodeId,
|
|
dom: &'a mut RealDom<V>,
|
|
dom: &'a mut RealDom<V>,
|
|
- dirty: NodeMask,
|
|
|
|
}
|
|
}
|
|
|
|
|
|
impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
|
|
impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
|
|
pub fn new(id: NodeId, dom: &'a mut RealDom<V>) -> Self {
|
|
pub fn new(id: NodeId, dom: &'a mut RealDom<V>) -> Self {
|
|
- Self {
|
|
|
|
- id,
|
|
|
|
- dom,
|
|
|
|
- dirty: NodeMask::default(),
|
|
|
|
- }
|
|
|
|
|
|
+ Self { id, dom }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -407,6 +416,7 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMutable<V> for NodeMut<'a, V> {
|
|
fn get_mut<T: Any + Sync + Send>(&mut self) -> Option<&mut T> {
|
|
fn get_mut<T: Any + Sync + Send>(&mut self) -> Option<&mut T> {
|
|
// mark the node state as dirty
|
|
// mark the node state as dirty
|
|
self.dom
|
|
self.dom
|
|
|
|
+ .dirty_nodes
|
|
.passes_updated
|
|
.passes_updated
|
|
.entry(self.id)
|
|
.entry(self.id)
|
|
.or_default()
|
|
.or_default()
|
|
@@ -417,6 +427,7 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMutable<V> for NodeMut<'a, V> {
|
|
fn insert<T: Any + Sync + Send>(&mut self, value: T) {
|
|
fn insert<T: Any + Sync + Send>(&mut self, value: T) {
|
|
// mark the node state as dirty
|
|
// mark the node state as dirty
|
|
self.dom
|
|
self.dom
|
|
|
|
+ .dirty_nodes
|
|
.passes_updated
|
|
.passes_updated
|
|
.entry(self.id)
|
|
.entry(self.id)
|
|
.or_default()
|
|
.or_default()
|
|
@@ -427,8 +438,8 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMutable<V> for NodeMut<'a, V> {
|
|
fn insert_after(&mut self, old: NodeId) {
|
|
fn insert_after(&mut self, old: NodeId) {
|
|
let id = self.id();
|
|
let id = self.id();
|
|
if let Some(parent_id) = self.dom.tree.parent_id(old) {
|
|
if let Some(parent_id) = self.dom.tree.parent_id(old) {
|
|
- self.dom.mark_child_changed(parent_id);
|
|
|
|
- self.dom.mark_parent_added_or_removed(id);
|
|
|
|
|
|
+ self.dom.dirty_nodes.mark_child_changed(parent_id);
|
|
|
|
+ self.dom.dirty_nodes.mark_parent_added_or_removed(id);
|
|
}
|
|
}
|
|
self.dom.tree.insert_after(old, id);
|
|
self.dom.tree.insert_after(old, id);
|
|
}
|
|
}
|
|
@@ -436,16 +447,20 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMutable<V> for NodeMut<'a, V> {
|
|
fn insert_before(&mut self, old: NodeId) {
|
|
fn insert_before(&mut self, old: NodeId) {
|
|
let id = self.id();
|
|
let id = self.id();
|
|
if let Some(parent_id) = self.dom.tree.parent_id(old) {
|
|
if let Some(parent_id) = self.dom.tree.parent_id(old) {
|
|
- self.dom.mark_child_changed(parent_id);
|
|
|
|
- self.dom.mark_parent_added_or_removed(id);
|
|
|
|
|
|
+ self.dom.dirty_nodes.mark_child_changed(parent_id);
|
|
|
|
+ self.dom.dirty_nodes.mark_parent_added_or_removed(id);
|
|
}
|
|
}
|
|
self.dom.tree.insert_before(old, id);
|
|
self.dom.tree.insert_before(old, id);
|
|
}
|
|
}
|
|
|
|
|
|
fn add_event_listener(&mut self, event: &str) {
|
|
fn add_event_listener(&mut self, event: &str) {
|
|
let id = self.id();
|
|
let id = self.id();
|
|
- if let NodeTypeMut::Element(mut element) = self.node_type_mut() {
|
|
|
|
- element.listeners_mut().insert(event.to_string());
|
|
|
|
|
|
+ let node_type: &mut NodeType<V> = self.dom.tree.get_mut(self.id).unwrap();
|
|
|
|
+ if let NodeType::Element(ElementNode { listeners, .. }) = node_type {
|
|
|
|
+ self.dom
|
|
|
|
+ .dirty_nodes
|
|
|
|
+ .mark_dirty(self.id, NodeMaskBuilder::new().with_listeners().build());
|
|
|
|
+ listeners.insert(event.to_string());
|
|
match self.dom.nodes_listening.get_mut(event) {
|
|
match self.dom.nodes_listening.get_mut(event) {
|
|
Some(hs) => {
|
|
Some(hs) => {
|
|
hs.insert(id);
|
|
hs.insert(id);
|
|
@@ -461,21 +476,33 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMutable<V> for NodeMut<'a, V> {
|
|
|
|
|
|
fn remove_event_listener(&mut self, event: &str) {
|
|
fn remove_event_listener(&mut self, event: &str) {
|
|
let id = self.id();
|
|
let id = self.id();
|
|
- if let NodeTypeMut::Element(mut element) = self.node_type_mut() {
|
|
|
|
- element.listeners_mut().remove(event);
|
|
|
|
|
|
+ let node_type: &mut NodeType<V> = self.dom.tree.get_mut(self.id).unwrap();
|
|
|
|
+ if let NodeType::Element(ElementNode { listeners, .. }) = node_type {
|
|
|
|
+ self.dom
|
|
|
|
+ .dirty_nodes
|
|
|
|
+ .mark_dirty(self.id, NodeMaskBuilder::new().with_listeners().build());
|
|
|
|
+ listeners.remove(event);
|
|
|
|
+
|
|
|
|
+ self.dom.nodes_listening.get_mut(event).unwrap().remove(&id);
|
|
}
|
|
}
|
|
- self.dom.nodes_listening.get_mut(event).unwrap().remove(&id);
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
|
|
impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
|
|
pub fn node_type_mut(&mut self) -> NodeTypeMut<'_, V> {
|
|
pub fn node_type_mut(&mut self) -> NodeTypeMut<'_, V> {
|
|
- let Self { id, dom, dirty } = self;
|
|
|
|
- let node_type = dom.tree.get_mut::<NodeType<V>>(*id).unwrap();
|
|
|
|
|
|
+ let Self { id, dom } = self;
|
|
|
|
+ let RealDom {
|
|
|
|
+ dirty_nodes, tree, ..
|
|
|
|
+ } = dom;
|
|
|
|
+ let node_type = tree.get_mut(*id).unwrap();
|
|
match node_type {
|
|
match node_type {
|
|
- NodeType::Element(element) => NodeTypeMut::Element(ElementNodeMut { element, dirty }),
|
|
|
|
|
|
+ NodeType::Element(element) => NodeTypeMut::Element(ElementNodeMut {
|
|
|
|
+ id: *id,
|
|
|
|
+ element,
|
|
|
|
+ dirty_nodes,
|
|
|
|
+ }),
|
|
NodeType::Text(text) => {
|
|
NodeType::Text(text) => {
|
|
- dirty.set_text();
|
|
|
|
|
|
+ dirty_nodes.mark_dirty(self.id, NodeMaskBuilder::new().with_text().build());
|
|
NodeTypeMut::Text(text)
|
|
NodeTypeMut::Text(text)
|
|
}
|
|
}
|
|
NodeType::Placeholder => NodeTypeMut::Placeholder,
|
|
NodeType::Placeholder => NodeTypeMut::Placeholder,
|
|
@@ -484,35 +511,32 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
|
|
|
|
|
|
pub fn set_type(&mut self, new: NodeType<V>) {
|
|
pub fn set_type(&mut self, new: NodeType<V>) {
|
|
*self.dom.tree.get_mut::<NodeType<V>>(self.id).unwrap() = new;
|
|
*self.dom.tree.get_mut::<NodeType<V>>(self.id).unwrap() = new;
|
|
- self.dirty = NodeMaskBuilder::ALL.build();
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-impl<V: FromAnyValue + Send + Sync> Drop for NodeMut<'_, V> {
|
|
|
|
- fn drop(&mut self) {
|
|
|
|
- let mask = std::mem::take(&mut self.dirty);
|
|
|
|
- self.dom.mark_dirty(self.id, mask);
|
|
|
|
|
|
+ self.dom
|
|
|
|
+ .dirty_nodes
|
|
|
|
+ .mark_dirty(self.id, NodeMaskBuilder::ALL.build())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-pub enum NodeTypeMut<'a, V: FromAnyValue = ()> {
|
|
|
|
|
|
+pub enum NodeTypeMut<'a, V: FromAnyValue + Send + Sync = ()> {
|
|
Element(ElementNodeMut<'a, V>),
|
|
Element(ElementNodeMut<'a, V>),
|
|
Text(&'a mut String),
|
|
Text(&'a mut String),
|
|
Placeholder,
|
|
Placeholder,
|
|
}
|
|
}
|
|
|
|
|
|
-pub struct ElementNodeMut<'a, V: FromAnyValue = ()> {
|
|
|
|
|
|
+pub struct ElementNodeMut<'a, V: FromAnyValue + Send + Sync = ()> {
|
|
|
|
+ id: NodeId,
|
|
element: &'a mut ElementNode<V>,
|
|
element: &'a mut ElementNode<V>,
|
|
- dirty: &'a mut NodeMask,
|
|
|
|
|
|
+ dirty_nodes: &'a mut NodesDirty<V>,
|
|
}
|
|
}
|
|
|
|
|
|
-impl<V: FromAnyValue> ElementNodeMut<'_, V> {
|
|
|
|
|
|
+impl<V: FromAnyValue + Send + Sync> ElementNodeMut<'_, V> {
|
|
pub fn tag(&self) -> &str {
|
|
pub fn tag(&self) -> &str {
|
|
&self.element.tag
|
|
&self.element.tag
|
|
}
|
|
}
|
|
|
|
|
|
pub fn tag_mut(&mut self) -> &mut String {
|
|
pub fn tag_mut(&mut self) -> &mut String {
|
|
- self.dirty.set_tag();
|
|
|
|
|
|
+ self.dirty_nodes
|
|
|
|
+ .mark_dirty(self.id, NodeMaskBuilder::new().with_tag().build());
|
|
&mut self.element.tag
|
|
&mut self.element.tag
|
|
}
|
|
}
|
|
|
|
|
|
@@ -521,7 +545,8 @@ impl<V: FromAnyValue> ElementNodeMut<'_, V> {
|
|
}
|
|
}
|
|
|
|
|
|
pub fn namespace_mut(&mut self) -> &mut Option<String> {
|
|
pub fn namespace_mut(&mut self) -> &mut Option<String> {
|
|
- self.dirty.set_namespace();
|
|
|
|
|
|
+ self.dirty_nodes
|
|
|
|
+ .mark_dirty(self.id, NodeMaskBuilder::new().with_namespace().build());
|
|
&mut self.element.namespace
|
|
&mut self.element.namespace
|
|
}
|
|
}
|
|
|
|
|
|
@@ -532,7 +557,12 @@ impl<V: FromAnyValue> ElementNodeMut<'_, V> {
|
|
pub fn attributes_mut(
|
|
pub fn attributes_mut(
|
|
&mut self,
|
|
&mut self,
|
|
) -> &mut FxHashMap<OwnedAttributeDiscription, OwnedAttributeValue<V>> {
|
|
) -> &mut FxHashMap<OwnedAttributeDiscription, OwnedAttributeValue<V>> {
|
|
- self.dirty.add_attributes(AttributeMask::All);
|
|
|
|
|
|
+ self.dirty_nodes.mark_dirty(
|
|
|
|
+ self.id,
|
|
|
|
+ NodeMaskBuilder::new()
|
|
|
|
+ .with_attrs(AttributeMaskBuilder::All)
|
|
|
|
+ .build(),
|
|
|
|
+ );
|
|
&mut self.element.attributes
|
|
&mut self.element.attributes
|
|
}
|
|
}
|
|
|
|
|
|
@@ -541,7 +571,12 @@ impl<V: FromAnyValue> ElementNodeMut<'_, V> {
|
|
name: OwnedAttributeDiscription,
|
|
name: OwnedAttributeDiscription,
|
|
value: OwnedAttributeValue<V>,
|
|
value: OwnedAttributeValue<V>,
|
|
) -> Option<OwnedAttributeValue<V>> {
|
|
) -> Option<OwnedAttributeValue<V>> {
|
|
- self.dirty.add_attributes(AttributeMask::single(&name.name));
|
|
|
|
|
|
+ self.dirty_nodes.mark_dirty(
|
|
|
|
+ self.id,
|
|
|
|
+ NodeMaskBuilder::new()
|
|
|
|
+ .with_attrs(AttributeMaskBuilder::Some(&[&name.name]))
|
|
|
|
+ .build(),
|
|
|
|
+ );
|
|
self.element.attributes.insert(name, value)
|
|
self.element.attributes.insert(name, value)
|
|
}
|
|
}
|
|
|
|
|
|
@@ -549,7 +584,12 @@ impl<V: FromAnyValue> ElementNodeMut<'_, V> {
|
|
&mut self,
|
|
&mut self,
|
|
name: &OwnedAttributeDiscription,
|
|
name: &OwnedAttributeDiscription,
|
|
) -> Option<OwnedAttributeValue<V>> {
|
|
) -> Option<OwnedAttributeValue<V>> {
|
|
- self.dirty.add_attributes(AttributeMask::single(&name.name));
|
|
|
|
|
|
+ self.dirty_nodes.mark_dirty(
|
|
|
|
+ self.id,
|
|
|
|
+ NodeMaskBuilder::new()
|
|
|
|
+ .with_attrs(AttributeMaskBuilder::Some(&[&name.name]))
|
|
|
|
+ .build(),
|
|
|
|
+ );
|
|
self.element.attributes.remove(name)
|
|
self.element.attributes.remove(name)
|
|
}
|
|
}
|
|
|
|
|
|
@@ -557,18 +597,18 @@ impl<V: FromAnyValue> ElementNodeMut<'_, V> {
|
|
&mut self,
|
|
&mut self,
|
|
name: &OwnedAttributeDiscription,
|
|
name: &OwnedAttributeDiscription,
|
|
) -> Option<&mut OwnedAttributeValue<V>> {
|
|
) -> Option<&mut OwnedAttributeValue<V>> {
|
|
- self.dirty.add_attributes(AttributeMask::single(&name.name));
|
|
|
|
|
|
+ self.dirty_nodes.mark_dirty(
|
|
|
|
+ self.id,
|
|
|
|
+ NodeMaskBuilder::new()
|
|
|
|
+ .with_attrs(AttributeMaskBuilder::Some(&[&name.name]))
|
|
|
|
+ .build(),
|
|
|
|
+ );
|
|
self.element.attributes.get_mut(name)
|
|
self.element.attributes.get_mut(name)
|
|
}
|
|
}
|
|
|
|
|
|
pub fn listeners(&self) -> &FxHashSet<String> {
|
|
pub fn listeners(&self) -> &FxHashSet<String> {
|
|
&self.element.listeners
|
|
&self.element.listeners
|
|
}
|
|
}
|
|
-
|
|
|
|
- pub fn listeners_mut(&mut self) -> &mut FxHashSet<String> {
|
|
|
|
- self.dirty.set_listeners();
|
|
|
|
- &mut self.element.listeners
|
|
|
|
- }
|
|
|
|
}
|
|
}
|
|
|
|
|
|
pub struct NodeMutRaw<'a, V: FromAnyValue + Send + Sync = ()> {
|
|
pub struct NodeMutRaw<'a, V: FromAnyValue + Send + Sync = ()> {
|