-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Expand file tree
/
Copy patharena.rs
More file actions
147 lines (122 loc) · 4.55 KB
/
Copy patharena.rs
File metadata and controls
147 lines (122 loc) · 4.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
use crate::innerlude::{NoOpMutations, ScopeOrder};
use crate::{ScopeId, virtual_dom::VirtualDom};
/// An Element's unique identifier.
///
/// `ElementId` is a `usize` that is unique across the entire VirtualDOM - but not unique across time. If a component is
/// unmounted, then the `ElementId` will be reused for a new component.
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct ElementId(pub usize);
/// An Element that can be bubbled to's unique identifier.
///
/// `BubbleId` is a `usize` that is unique across the entire VirtualDOM - but not unique across time. If a component is
/// unmounted, then the `BubbleId` will be reused for a new component.
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub(crate) struct MountId(pub(crate) usize);
impl Default for MountId {
fn default() -> Self {
Self::PLACEHOLDER
}
}
impl MountId {
pub(crate) const PLACEHOLDER: Self = Self(usize::MAX);
pub(crate) fn as_usize(self) -> Option<usize> {
if self.mounted() { Some(self.0) } else { None }
}
#[allow(unused)]
pub(crate) fn mounted(self) -> bool {
self != Self::PLACEHOLDER
}
}
#[derive(Debug, Clone, Copy)]
pub struct ElementRef {
// the pathway of the real element inside the template
pub(crate) path: ElementPath,
// The actual element
pub(crate) mount: MountId,
}
#[derive(Clone, Copy, Debug)]
pub struct ElementPath {
pub(crate) path: &'static [u8],
}
impl VirtualDom {
pub(crate) fn next_element(&mut self) -> ElementId {
let mut elements = self.runtime.elements.borrow_mut();
ElementId(elements.insert(None))
}
pub(crate) fn reclaim(&mut self, el: ElementId) {
if !self.try_reclaim(el) {
tracing::error!("cannot reclaim {:?}", el);
}
}
pub(crate) fn try_reclaim(&mut self, el: ElementId) -> bool {
// We never reclaim the unmounted elements or the root element
if el.0 == 0 || el.0 == usize::MAX {
return true;
}
let mut elements = self.runtime.elements.borrow_mut();
elements.try_remove(el.0).is_some()
}
// Drop a scope whose rendered nodes have already been removed.
pub(crate) fn drop_scope(&mut self, id: ScopeId) {
self.drop_orphaned_child_scopes(id);
let height = {
let scope = self.scopes.remove(id.0);
let context = scope.state();
context.height
};
self.dirty_scopes.remove(&ScopeOrder::new(height, id));
// If this scope was a suspense boundary, remove it from the resolved scopes
self.resolved_scopes.retain(|s| s != &id);
}
pub(crate) fn drop_orphaned_child_scopes(&mut self, parent: ScopeId) {
// Parent rendered output can be removed before every child scope has
// been dropped. Clean those children without emitting more DOM edits.
let children = self
.scopes
.iter()
.filter_map(|(idx, _)| {
let scope = ScopeId(idx);
let parent_id = self
.runtime
.try_get_state(scope)
.and_then(|scope| scope.parent_id());
(parent_id == Some(parent)).then_some(scope)
})
.collect::<Vec<_>>();
for child in children {
if !self.scopes.contains(child.0) {
continue;
}
if self.scopes[child.0].last_rendered_node.is_some() {
self.remove_component_node(None::<&mut NoOpMutations>, true, child, None);
} else {
self.drop_scope(child);
}
}
}
}
impl ElementPath {
pub(crate) fn is_descendant(&self, small: &[u8]) -> bool {
small.len() <= self.path.len() && small == &self.path[..small.len()]
}
}
#[test]
fn is_descendant() {
let event_path = ElementPath {
path: &[1, 2, 3, 4, 5],
};
assert!(event_path.is_descendant(&[1, 2, 3, 4, 5]));
assert!(event_path.is_descendant(&[1, 2, 3, 4]));
assert!(event_path.is_descendant(&[1, 2, 3]));
assert!(event_path.is_descendant(&[1, 2]));
assert!(event_path.is_descendant(&[1]));
assert!(!event_path.is_descendant(&[1, 2, 3, 4, 5, 6]));
assert!(!event_path.is_descendant(&[2, 3, 4]));
}
impl PartialEq<&[u8]> for ElementPath {
fn eq(&self, other: &&[u8]) -> bool {
self.path.eq(*other)
}
}