work on intigrating state with passes
This commit is contained in:
1 parent
4812b5124a
commit
d78af904e6
5 files changed
+137
-108
No files matched your search
@@ -1,3 +1,6 @@
|
||||
use std::hash::BuildHasherDefault;
|
||||
|
||||
use rustc_hash::FxHasher;
|
||||
use tree::NodeId;
|
||||
|
||||
pub mod layout_attributes;
|
||||
@@ -10,7 +13,10 @@ pub mod tree;
|
||||
pub mod utils;
|
||||
|
||||
/// A id for a node that lives in the real dom.
|
||||
type RealNodeId = NodeId;
|
||||
pub type RealNodeId = NodeId;
|
||||
pub(crate) type FxDashMap<K, V> = dashmap::DashMap<K, V, BuildHasherDefault<FxHasher>>;
|
||||
pub(crate) type FxDashSet<K> = dashmap::DashSet<K, BuildHasherDefault<FxHasher>>;
|
||||
pub(crate) type SendAnyMap = anymap::Map<dyn anymap::any::Any + Send + Sync + 'static>;
|
||||
|
||||
/// Used in derived state macros
|
||||
#[derive(Eq, PartialEq)]
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
|
||||
use crate::tree::{NodeId, TreeView};
|
||||
use crate::{FxDashMap, FxDashSet, SendAnyMap};
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use std::collections::BTreeMap;
|
||||
use std::hash::BuildHasherDefault;
|
||||
use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign};
|
||||
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::tree::{NodeId, TreeView};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
||||
pub struct DirtyNodes {
|
||||
map: BTreeMap<u16, FxHashSet<NodeId>>,
|
||||
@@ -57,8 +55,6 @@ fn dirty_nodes() {
|
||||
assert_eq!(dirty_nodes.pop_front(), Some(NodeId(3)));
|
||||
}
|
||||
|
||||
type FxDashMap<K, V> = dashmap::DashMap<K, V, BuildHasherDefault<FxHasher>>;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct DirtyNodeStates {
|
||||
dirty: FxDashMap<NodeId, Vec<AtomicU64>>,
|
||||
@@ -167,7 +163,12 @@ pub trait Pass {
|
||||
}
|
||||
|
||||
pub trait UpwardPass<T>: Pass {
|
||||
fn pass<'a>(&self, node: &mut T, children: &mut dyn Iterator<Item = &'a mut T>) -> PassReturn;
|
||||
fn pass<'a>(
|
||||
&self,
|
||||
node: &mut T,
|
||||
children: &mut dyn Iterator<Item = &'a mut T>,
|
||||
ctx: &SendAnyMap,
|
||||
) -> PassReturn;
|
||||
}
|
||||
|
||||
fn resolve_upward_pass<T, P: UpwardPass<T> + ?Sized>(
|
||||
@@ -175,12 +176,15 @@ fn resolve_upward_pass<T, P: UpwardPass<T> + ?Sized>(
|
||||
pass: &P,
|
||||
mut dirty: DirtyNodes,
|
||||
dirty_states: &DirtyNodeStates,
|
||||
nodes_updated: &FxDashSet<NodeId>,
|
||||
ctx: &SendAnyMap,
|
||||
) {
|
||||
while let Some(id) = dirty.pop_back() {
|
||||
let (node, mut children) = tree.parent_child_mut(id).unwrap();
|
||||
let result = pass.pass(node, &mut children);
|
||||
let result = pass.pass(node, &mut children, ctx);
|
||||
drop(children);
|
||||
if result.progress || result.mark_dirty {
|
||||
nodes_updated.insert(id);
|
||||
if let Some(id) = tree.parent_id(id) {
|
||||
if result.mark_dirty {
|
||||
for dependant in pass.dependants() {
|
||||
@@ -197,7 +201,7 @@ fn resolve_upward_pass<T, P: UpwardPass<T> + ?Sized>(
|
||||
}
|
||||
|
||||
pub trait DownwardPass<T>: Pass {
|
||||
fn pass(&self, node: &mut T, parent: Option<&mut T>) -> PassReturn;
|
||||
fn pass(&self, node: &mut T, parent: Option<&mut T>, ctx: &SendAnyMap) -> PassReturn;
|
||||
}
|
||||
|
||||
fn resolve_downward_pass<T, P: DownwardPass<T> + ?Sized>(
|
||||
@@ -205,11 +209,14 @@ fn resolve_downward_pass<T, P: DownwardPass<T> + ?Sized>(
|
||||
pass: &P,
|
||||
mut dirty: DirtyNodes,
|
||||
dirty_states: &DirtyNodeStates,
|
||||
nodes_updated: &FxDashSet<NodeId>,
|
||||
ctx: &SendAnyMap,
|
||||
) {
|
||||
while let Some(id) = dirty.pop_front() {
|
||||
let (node, parent) = tree.node_parent_mut(id).unwrap();
|
||||
let result = pass.pass(node, parent);
|
||||
let result = pass.pass(node, parent, ctx);
|
||||
if result.mark_dirty || result.progress {
|
||||
nodes_updated.insert(id);
|
||||
for id in tree.children_ids(id).unwrap() {
|
||||
if result.mark_dirty {
|
||||
for dependant in pass.dependants() {
|
||||
@@ -226,7 +233,7 @@ fn resolve_downward_pass<T, P: DownwardPass<T> + ?Sized>(
|
||||
}
|
||||
|
||||
pub trait NodePass<T>: Pass {
|
||||
fn pass(&self, node: &mut T) -> bool;
|
||||
fn pass(&self, node: &mut T, ctx: &SendAnyMap) -> bool;
|
||||
}
|
||||
|
||||
fn resolve_node_pass<T, P: NodePass<T> + ?Sized>(
|
||||
@@ -234,10 +241,13 @@ fn resolve_node_pass<T, P: NodePass<T> + ?Sized>(
|
||||
pass: &P,
|
||||
mut dirty: DirtyNodes,
|
||||
dirty_states: &DirtyNodeStates,
|
||||
nodes_updated: &FxDashSet<NodeId>,
|
||||
ctx: &SendAnyMap,
|
||||
) {
|
||||
while let Some(id) = dirty.pop_back() {
|
||||
let node = tree.get_mut(id).unwrap();
|
||||
if pass.pass(node) {
|
||||
if pass.pass(node, ctx) {
|
||||
nodes_updated.insert(id);
|
||||
for dependant in pass.dependants() {
|
||||
dirty_states.insert(*dependant, id);
|
||||
}
|
||||
@@ -245,14 +255,14 @@ fn resolve_node_pass<T, P: NodePass<T> + ?Sized>(
|
||||
}
|
||||
}
|
||||
|
||||
pub enum AnyPass<T> {
|
||||
Upward(Box<dyn UpwardPass<T> + Send + Sync>),
|
||||
Downward(Box<dyn DownwardPass<T> + Send + Sync>),
|
||||
Node(Box<dyn NodePass<T> + Send + Sync>),
|
||||
pub enum AnyPass<T: 'static> {
|
||||
Upward(&'static (dyn UpwardPass<T> + Send + Sync + 'static)),
|
||||
Downward(&'static (dyn DownwardPass<T> + Send + Sync + 'static)),
|
||||
Node(&'static (dyn NodePass<T> + Send + Sync + 'static)),
|
||||
}
|
||||
|
||||
impl<T> AnyPass<T> {
|
||||
fn pass_id(&self) -> PassId {
|
||||
pub fn pass_id(&self) -> PassId {
|
||||
match self {
|
||||
Self::Upward(pass) => pass.pass_id(),
|
||||
Self::Downward(pass) => pass.pass_id(),
|
||||
@@ -260,7 +270,7 @@ impl<T> AnyPass<T> {
|
||||
}
|
||||
}
|
||||
|
||||
fn dependancies(&self) -> &'static [PassId] {
|
||||
pub fn dependancies(&self) -> &'static [PassId] {
|
||||
match self {
|
||||
Self::Upward(pass) => pass.dependancies(),
|
||||
Self::Downward(pass) => pass.dependancies(),
|
||||
@@ -281,11 +291,19 @@ impl<T> AnyPass<T> {
|
||||
tree: &mut impl TreeView<T>,
|
||||
dirty: DirtyNodes,
|
||||
dirty_states: &DirtyNodeStates,
|
||||
nodes_updated: &FxDashSet<NodeId>,
|
||||
ctx: &SendAnyMap,
|
||||
) {
|
||||
match self {
|
||||
Self::Downward(pass) => resolve_downward_pass(tree, pass.as_ref(), dirty, dirty_states),
|
||||
Self::Upward(pass) => resolve_upward_pass(tree, pass.as_ref(), dirty, dirty_states),
|
||||
Self::Node(pass) => resolve_node_pass(tree, pass.as_ref(), dirty, dirty_states),
|
||||
Self::Downward(pass) => {
|
||||
resolve_downward_pass(tree, *pass, dirty, dirty_states, nodes_updated, ctx)
|
||||
}
|
||||
Self::Upward(pass) => {
|
||||
resolve_upward_pass(tree, *pass, dirty, dirty_states, nodes_updated, ctx)
|
||||
}
|
||||
Self::Node(pass) => {
|
||||
resolve_node_pass(tree, *pass, dirty, dirty_states, nodes_updated, ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -297,11 +315,14 @@ unsafe impl<T> Sync for RawPointer<T> {}
|
||||
pub fn resolve_passes<T, Tr: TreeView<T>>(
|
||||
tree: &mut Tr,
|
||||
dirty_nodes: DirtyNodeStates,
|
||||
mut passes: Vec<AnyPass<T>>,
|
||||
) {
|
||||
mut passes: Vec<&AnyPass<T>>,
|
||||
ctx: SendAnyMap,
|
||||
) -> FxDashSet<NodeId> {
|
||||
let dirty_states = Arc::new(dirty_nodes);
|
||||
let mut resolved_passes: FxHashSet<PassId> = FxHashSet::default();
|
||||
let mut resolving = Vec::new();
|
||||
let nodes_updated = Arc::new(FxDashSet::default());
|
||||
let ctx = Arc::new(ctx);
|
||||
while !passes.is_empty() {
|
||||
let mut currently_borrowed = MemberMask::default();
|
||||
std::thread::scope(|s| {
|
||||
@@ -322,13 +343,16 @@ pub fn resolve_passes<T, Tr: TreeView<T>>(
|
||||
let tree_mut = tree as *mut _;
|
||||
let raw_ptr = RawPointer(tree_mut);
|
||||
let dirty_states = dirty_states.clone();
|
||||
let nodes_updated = nodes_updated.clone();
|
||||
let ctx = ctx.clone();
|
||||
s.spawn(move || unsafe {
|
||||
// let tree_mut: &mut Tr = &mut *raw_ptr.0;
|
||||
let raw = raw_ptr;
|
||||
// this is safe because the member_mask acts as a per-member mutex and we have verified that the pass does not overlap with any other pass
|
||||
let tree_mut: &mut Tr = &mut *raw.0;
|
||||
let mut dirty = DirtyNodes::default();
|
||||
dirty_states.all_dirty(pass_id, &mut dirty, tree_mut);
|
||||
pass.resolve(tree_mut, dirty, &dirty_states);
|
||||
pass.resolve(tree_mut, dirty, &dirty_states, &nodes_updated, &ctx);
|
||||
});
|
||||
} else {
|
||||
i += 1;
|
||||
@@ -339,14 +363,13 @@ pub fn resolve_passes<T, Tr: TreeView<T>>(
|
||||
resolved_passes.extend(resolving.iter().copied());
|
||||
resolving.clear()
|
||||
}
|
||||
std::sync::Arc::try_unwrap(nodes_updated).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn node_pass() {
|
||||
use crate::tree::{Tree, TreeLike};
|
||||
let mut tree = Tree::new(0);
|
||||
let parent = tree.root();
|
||||
println!("{:#?}", tree);
|
||||
|
||||
struct AddPass;
|
||||
impl Pass for AddPass {
|
||||
@@ -368,16 +391,17 @@ fn node_pass() {
|
||||
}
|
||||
|
||||
impl NodePass<i32> for AddPass {
|
||||
fn pass(&self, node: &mut i32) -> bool {
|
||||
fn pass(&self, node: &mut i32, _: &SendAnyMap) -> bool {
|
||||
*node += 1;
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
let passes = vec![AnyPass::Node(Box::new(AddPass))];
|
||||
let add_pass = AnyPass::Node(&AddPass);
|
||||
let passes = vec![&add_pass];
|
||||
let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
|
||||
dirty_nodes.insert(PassId(0), tree.root());
|
||||
resolve_passes(&mut tree, dirty_nodes, passes);
|
||||
resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
|
||||
|
||||
assert_eq!(tree.get(tree.root()).unwrap(), &1);
|
||||
}
|
||||
@@ -407,8 +431,7 @@ fn dependant_node_pass() {
|
||||
}
|
||||
|
||||
impl NodePass<i32> for AddPass {
|
||||
fn pass(&self, node: &mut i32) -> bool {
|
||||
println!("AddPass: {}", node);
|
||||
fn pass(&self, node: &mut i32, _: &SendAnyMap) -> bool {
|
||||
*node += 1;
|
||||
true
|
||||
}
|
||||
@@ -434,20 +457,18 @@ fn dependant_node_pass() {
|
||||
}
|
||||
}
|
||||
impl NodePass<i32> for SubtractPass {
|
||||
fn pass(&self, node: &mut i32) -> bool {
|
||||
println!("SubtractPass: {}", node);
|
||||
fn pass(&self, node: &mut i32, _: &SendAnyMap) -> bool {
|
||||
*node -= 1;
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
let passes = vec![
|
||||
AnyPass::Node(Box::new(AddPass)),
|
||||
AnyPass::Node(Box::new(SubtractPass)),
|
||||
];
|
||||
let add_pass = AnyPass::Node(&AddPass);
|
||||
let subtract_pass = AnyPass::Node(&SubtractPass);
|
||||
let passes = vec![&add_pass, &subtract_pass];
|
||||
let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
|
||||
dirty_nodes.insert(PassId(1), tree.root());
|
||||
resolve_passes(&mut tree, dirty_nodes, passes);
|
||||
resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
|
||||
|
||||
assert_eq!(*tree.get(tree.root()).unwrap(), 0);
|
||||
}
|
||||
@@ -477,7 +498,7 @@ fn independant_node_pass() {
|
||||
}
|
||||
|
||||
impl NodePass<(i32, i32)> for AddPass1 {
|
||||
fn pass(&self, node: &mut (i32, i32)) -> bool {
|
||||
fn pass(&self, node: &mut (i32, i32), _: &SendAnyMap) -> bool {
|
||||
node.0 += 1;
|
||||
true
|
||||
}
|
||||
@@ -503,20 +524,19 @@ fn independant_node_pass() {
|
||||
}
|
||||
|
||||
impl NodePass<(i32, i32)> for AddPass2 {
|
||||
fn pass(&self, node: &mut (i32, i32)) -> bool {
|
||||
fn pass(&self, node: &mut (i32, i32), _: &SendAnyMap) -> bool {
|
||||
node.1 += 1;
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
let passes = vec![
|
||||
AnyPass::Node(Box::new(AddPass1)),
|
||||
AnyPass::Node(Box::new(AddPass2)),
|
||||
];
|
||||
let add_pass1 = AnyPass::Node(&AddPass1);
|
||||
let add_pass2 = AnyPass::Node(&AddPass2);
|
||||
let passes = vec![&add_pass1, &add_pass2];
|
||||
let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
|
||||
dirty_nodes.insert(PassId(0), tree.root());
|
||||
dirty_nodes.insert(PassId(1), tree.root());
|
||||
resolve_passes(&mut tree, dirty_nodes, passes);
|
||||
resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
|
||||
|
||||
assert_eq!(tree.get(tree.root()).unwrap(), &(1, 1));
|
||||
}
|
||||
@@ -555,7 +575,7 @@ fn down_pass() {
|
||||
}
|
||||
}
|
||||
impl DownwardPass<i32> for AddPass {
|
||||
fn pass(&self, node: &mut i32, parent: Option<&mut i32>) -> PassReturn {
|
||||
fn pass(&self, node: &mut i32, parent: Option<&mut i32>, _: &SendAnyMap) -> PassReturn {
|
||||
if let Some(parent) = parent {
|
||||
*node += *parent;
|
||||
}
|
||||
@@ -566,10 +586,11 @@ fn down_pass() {
|
||||
}
|
||||
}
|
||||
|
||||
let passes = vec![AnyPass::Downward(Box::new(AddPass))];
|
||||
let add_pass = AnyPass::Downward(&AddPass);
|
||||
let passes = vec![&add_pass];
|
||||
let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
|
||||
dirty_nodes.insert(PassId(0), tree.root());
|
||||
resolve_passes(&mut tree, dirty_nodes, passes);
|
||||
resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
|
||||
|
||||
assert_eq!(tree.get(tree.root()).unwrap(), &1);
|
||||
assert_eq!(tree.get(child1).unwrap(), &2);
|
||||
@@ -616,12 +637,10 @@ fn dependant_down_pass() {
|
||||
}
|
||||
}
|
||||
impl DownwardPass<i32> for AddPass {
|
||||
fn pass(&self, node: &mut i32, parent: Option<&mut i32>) -> PassReturn {
|
||||
fn pass(&self, node: &mut i32, parent: Option<&mut i32>, _: &SendAnyMap) -> PassReturn {
|
||||
if let Some(parent) = parent {
|
||||
println!("AddPass: {} -> {}", node, *node + *parent);
|
||||
*node += *parent;
|
||||
} else {
|
||||
println!("AddPass: {}", node);
|
||||
}
|
||||
PassReturn {
|
||||
progress: true,
|
||||
@@ -649,12 +668,10 @@ fn dependant_down_pass() {
|
||||
}
|
||||
}
|
||||
impl DownwardPass<i32> for SubtractPass {
|
||||
fn pass(&self, node: &mut i32, parent: Option<&mut i32>) -> PassReturn {
|
||||
fn pass(&self, node: &mut i32, parent: Option<&mut i32>, _: &SendAnyMap) -> PassReturn {
|
||||
if let Some(parent) = parent {
|
||||
println!("SubtractPass: {} -> {}", node, *node - *parent);
|
||||
*node -= *parent;
|
||||
} else {
|
||||
println!("SubtractPass: {}", node);
|
||||
}
|
||||
PassReturn {
|
||||
progress: true,
|
||||
@@ -663,13 +680,12 @@ fn dependant_down_pass() {
|
||||
}
|
||||
}
|
||||
|
||||
let passes = vec![
|
||||
AnyPass::Downward(Box::new(AddPass)),
|
||||
AnyPass::Downward(Box::new(SubtractPass)),
|
||||
];
|
||||
let add_pass = AnyPass::Downward(&AddPass);
|
||||
let subtract_pass = AnyPass::Downward(&SubtractPass);
|
||||
let passes = vec![&add_pass, &subtract_pass];
|
||||
let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
|
||||
dirty_nodes.insert(PassId(1), tree.root());
|
||||
resolve_passes(&mut tree, dirty_nodes, passes);
|
||||
resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
|
||||
|
||||
// Tree before:
|
||||
// 1=\
|
||||
@@ -745,6 +761,7 @@ fn up_pass() {
|
||||
&self,
|
||||
node: &mut i32,
|
||||
children: &mut dyn Iterator<Item = &'a mut i32>,
|
||||
_: &SendAnyMap,
|
||||
) -> PassReturn {
|
||||
*node += children.map(|i| *i).sum::<i32>();
|
||||
PassReturn {
|
||||
@@ -754,11 +771,12 @@ fn up_pass() {
|
||||
}
|
||||
}
|
||||
|
||||
let passes = vec![AnyPass::Upward(Box::new(AddPass))];
|
||||
let add_pass = AnyPass::Upward(&AddPass);
|
||||
let passes = vec![&add_pass];
|
||||
let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
|
||||
dirty_nodes.insert(PassId(0), grandchild1);
|
||||
dirty_nodes.insert(PassId(0), grandchild2);
|
||||
resolve_passes(&mut tree, dirty_nodes, passes);
|
||||
resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
|
||||
|
||||
assert_eq!(tree.get(tree.root()).unwrap(), &2);
|
||||
assert_eq!(tree.get(child1).unwrap(), &1);
|
||||
@@ -809,6 +827,7 @@ fn dependant_up_pass() {
|
||||
&self,
|
||||
node: &mut i32,
|
||||
children: &mut dyn Iterator<Item = &'a mut i32>,
|
||||
_: &SendAnyMap,
|
||||
) -> PassReturn {
|
||||
*node += children.map(|i| *i).sum::<i32>();
|
||||
PassReturn {
|
||||
@@ -841,6 +860,7 @@ fn dependant_up_pass() {
|
||||
&self,
|
||||
node: &mut i32,
|
||||
children: &mut dyn Iterator<Item = &'a mut i32>,
|
||||
_: &SendAnyMap,
|
||||
) -> PassReturn {
|
||||
*node -= children.map(|i| *i).sum::<i32>();
|
||||
PassReturn {
|
||||
@@ -850,14 +870,13 @@ fn dependant_up_pass() {
|
||||
}
|
||||
}
|
||||
|
||||
let passes = vec![
|
||||
AnyPass::Upward(Box::new(AddPass)),
|
||||
AnyPass::Upward(Box::new(SubtractPass)),
|
||||
];
|
||||
let add_pass = AnyPass::Upward(&AddPass);
|
||||
let subtract_pass = AnyPass::Upward(&SubtractPass);
|
||||
let passes = vec![&add_pass, &subtract_pass];
|
||||
let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
|
||||
dirty_nodes.insert(PassId(1), grandchild1);
|
||||
dirty_nodes.insert(PassId(1), grandchild2);
|
||||
resolve_passes(&mut tree, dirty_nodes, passes);
|
||||
resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
|
||||
|
||||
// Tree before:
|
||||
// 0=\
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use anymap::AnyMap;
|
||||
use dioxus_core::{ElementId, Mutations};
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use std::ops::{Index, IndexMut};
|
||||
|
||||
use crate::node::{Node, NodeData, NodeType, OwnedAttributeDiscription};
|
||||
use crate::node::{Node, NodeType, OwnedAttributeDiscription};
|
||||
use crate::node_ref::{AttributeMask, NodeMask};
|
||||
use crate::passes::DirtyNodeStates;
|
||||
use crate::state::State;
|
||||
use crate::tree::{NodeId, Tree, TreeLike, TreeView};
|
||||
use crate::RealNodeId;
|
||||
use crate::{FxDashSet, RealNodeId, SendAnyMap};
|
||||
|
||||
fn mark_dirty(
|
||||
node_id: NodeId,
|
||||
@@ -96,10 +96,7 @@ impl<S: State> RealDom<S> {
|
||||
}
|
||||
|
||||
/// Updates the dom with some mutations and return a set of nodes that were updated. Pass the dirty nodes to update_state.
|
||||
pub fn apply_mutations(
|
||||
&mut self,
|
||||
mutations_vec: Vec<Mutations>,
|
||||
) -> FxHashMap<RealNodeId, NodeMask> {
|
||||
pub fn apply_mutations(&mut self, mutations_vec: Vec<Mutations>) -> DirtyNodeStates {
|
||||
let mut nodes_updated: FxHashMap<RealNodeId, NodeMask> = FxHashMap::default();
|
||||
for mutations in mutations_vec {
|
||||
for e in mutations.edits {
|
||||
@@ -346,20 +343,28 @@ impl<S: State> RealDom<S> {
|
||||
}
|
||||
}
|
||||
|
||||
// remove any nodes that were created and then removed in the same mutations from the dirty nodes list
|
||||
nodes_updated.retain(|k, _| self.tree.get(*k).is_some());
|
||||
let dirty_nodes = DirtyNodeStates::default();
|
||||
for (n, mask) in nodes_updated {
|
||||
// remove any nodes that were created and then removed in the same mutations from the dirty nodes list
|
||||
if self.tree.contains(n) {
|
||||
for (m, p) in S::MASKS.iter().zip(S::PASSES.iter()) {
|
||||
if mask.overlaps(m) {
|
||||
dirty_nodes.insert(p.pass_id(), n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nodes_updated
|
||||
dirty_nodes
|
||||
}
|
||||
|
||||
/// Update the state of the dom, after appling some mutations. This will keep the nodes in the dom up to date with their VNode counterparts.
|
||||
pub fn update_state(
|
||||
&mut self,
|
||||
nodes_updated: FxHashMap<RealNodeId, NodeMask>,
|
||||
ctx: AnyMap,
|
||||
) -> FxHashSet<RealNodeId> {
|
||||
let (mut state_tree, node_tree) = self.split();
|
||||
S::update(&nodes_updated, &mut state_tree, &node_tree, &ctx)
|
||||
nodes_updated: DirtyNodeStates,
|
||||
ctx: SendAnyMap,
|
||||
) -> FxDashSet<RealNodeId> {
|
||||
S::update(nodes_updated, &mut self.tree, ctx)
|
||||
}
|
||||
|
||||
/// Find all nodes that are listening for an event, sorted by there height in the dom progressing starting at the bottom and progressing up.
|
||||
@@ -389,19 +394,6 @@ impl<S: State> RealDom<S> {
|
||||
self.tree.root()
|
||||
}
|
||||
|
||||
pub fn split(&mut self) -> (impl TreeView<S> + '_, impl TreeView<NodeData> + '_) {
|
||||
let raw = self as *mut Self;
|
||||
// this is safe beacuse the treeview trait does not allow mutation of the position of elements, and within elements the access is disjoint.
|
||||
(
|
||||
unsafe { &mut *raw }
|
||||
.tree
|
||||
.map(|n| &n.state, |n| &mut n.state),
|
||||
unsafe { &mut *raw }
|
||||
.tree
|
||||
.map(|n| &n.node_data, |n| &mut n.node_data),
|
||||
)
|
||||
}
|
||||
|
||||
fn clone_node(&mut self, node_id: NodeId) -> RealNodeId {
|
||||
let node = self.tree.get(node_id).unwrap();
|
||||
let new_node = node.clone();
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use crate::node::NodeData;
|
||||
use crate::node::Node;
|
||||
use crate::node_ref::{NodeMask, NodeView};
|
||||
use crate::passes::{resolve_passes, AnyPass, DirtyNodeStates};
|
||||
use crate::tree::TreeView;
|
||||
use crate::RealNodeId;
|
||||
use anymap::AnyMap;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use crate::{FxDashSet, RealNodeId, SendAnyMap};
|
||||
|
||||
/// Join two sorted iterators
|
||||
pub(crate) fn union_ordered_iter<'a>(
|
||||
@@ -204,20 +203,29 @@ pub trait NodeDepState {
|
||||
fn reduce<'a>(
|
||||
&mut self,
|
||||
node: NodeView,
|
||||
siblings: <Self::DepState as ElementBorrowable>::ElementBorrowed<'a>,
|
||||
node_state: <Self::DepState as ElementBorrowable>::ElementBorrowed<'a>,
|
||||
ctx: &Self::Ctx,
|
||||
) -> bool;
|
||||
}
|
||||
|
||||
/// Do not implement this trait. It is only meant to be derived and used through [crate::real_dom::RealDom].
|
||||
pub trait State: Default + Clone {
|
||||
pub trait State: Default + Clone + 'static {
|
||||
#[doc(hidden)]
|
||||
fn update<'a, T: TreeView<Self>, T2: TreeView<NodeData>>(
|
||||
dirty: &FxHashMap<RealNodeId, NodeMask>,
|
||||
state_tree: &'a mut T,
|
||||
rdom: &'a T2,
|
||||
ctx: &AnyMap,
|
||||
) -> FxHashSet<RealNodeId>;
|
||||
const PASSES: &'static [AnyPass<Node<Self>>];
|
||||
#[doc(hidden)]
|
||||
const MASKS: &'static [NodeMask];
|
||||
|
||||
#[doc(hidden)]
|
||||
fn update<T: TreeView<Node<Self>>>(
|
||||
dirty: DirtyNodeStates,
|
||||
tree: &mut T,
|
||||
ctx: SendAnyMap,
|
||||
) -> FxDashSet<RealNodeId> {
|
||||
let set = FxDashSet::default();
|
||||
let passes = Self::PASSES.iter().collect();
|
||||
resolve_passes(tree, dirty, passes, ctx);
|
||||
set
|
||||
}
|
||||
}
|
||||
|
||||
impl ChildDepState for () {
|
||||
|
||||
@@ -73,6 +73,10 @@ pub trait TreeView<T>: Sized {
|
||||
|
||||
fn root(&self) -> NodeId;
|
||||
|
||||
fn contains(&self, id: NodeId) -> bool {
|
||||
self.get(id).is_some()
|
||||
}
|
||||
|
||||
fn get(&self, id: NodeId) -> Option<&T>;
|
||||
|
||||
fn get_unchecked(&self, id: NodeId) -> &T {
|
||||
|
||||
Reference in new issue
Block a user