|
@@ -5,7 +5,7 @@ use bumpalo::boxed::Box as BumpBox;
|
|
use bumpalo::Bump;
|
|
use bumpalo::Bump;
|
|
use std::{
|
|
use std::{
|
|
any::{Any, TypeId},
|
|
any::{Any, TypeId},
|
|
- cell::{Cell, RefCell},
|
|
|
|
|
|
+ cell::{Cell, RefCell, UnsafeCell},
|
|
fmt::Arguments,
|
|
fmt::Arguments,
|
|
future::Future,
|
|
future::Future,
|
|
};
|
|
};
|
|
@@ -46,7 +46,7 @@ pub struct VNode<'a> {
|
|
|
|
|
|
/// The IDs for the roots of this template - to be used when moving the template around and removing it from
|
|
/// The IDs for the roots of this template - to be used when moving the template around and removing it from
|
|
/// the actual Dom
|
|
/// the actual Dom
|
|
- pub root_ids: bumpalo::collections::Vec<'a, Cell<Option<ElementId>>>,
|
|
|
|
|
|
+ pub root_ids: BoxedCellSlice,
|
|
|
|
|
|
/// The dynamic parts of the template
|
|
/// The dynamic parts of the template
|
|
pub dynamic_nodes: &'a [DynamicNode<'a>],
|
|
pub dynamic_nodes: &'a [DynamicNode<'a>],
|
|
@@ -55,13 +55,106 @@ pub struct VNode<'a> {
|
|
pub dynamic_attrs: &'a [Attribute<'a>],
|
|
pub dynamic_attrs: &'a [Attribute<'a>],
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// Saftey: There is no way to get references to the internal data of this struct so no refrences will be invalidated by mutating the data with a immutable reference (The same principle behind Cell)
|
|
|
|
+#[derive(Debug, Default)]
|
|
|
|
+pub struct BoxedCellSlice(UnsafeCell<Option<Box<[ElementId]>>>);
|
|
|
|
+
|
|
|
|
+impl Clone for BoxedCellSlice {
|
|
|
|
+ fn clone(&self) -> Self {
|
|
|
|
+ Self(UnsafeCell::new(unsafe { (*self.0.get()).clone() }))
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl BoxedCellSlice {
|
|
|
|
+ pub fn last(&self) -> Option<ElementId> {
|
|
|
|
+ unsafe {
|
|
|
|
+ (*self.0.get())
|
|
|
|
+ .as_ref()
|
|
|
|
+ .and_then(|inner| inner.as_ref().last().copied())
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub fn get(&self, idx: usize) -> Option<ElementId> {
|
|
|
|
+ unsafe {
|
|
|
|
+ (*self.0.get())
|
|
|
|
+ .as_ref()
|
|
|
|
+ .and_then(|inner| inner.as_ref().get(idx).copied())
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub unsafe fn get_unchecked(&self, idx: usize) -> Option<ElementId> {
|
|
|
|
+ (*self.0.get())
|
|
|
|
+ .as_ref()
|
|
|
|
+ .and_then(|inner| inner.as_ref().get(idx).copied())
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub fn set(&self, idx: usize, new: ElementId) {
|
|
|
|
+ unsafe {
|
|
|
|
+ if let Some(inner) = &mut *self.0.get() {
|
|
|
|
+ inner[idx] = new;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub fn intialize(&self, contents: Box<[ElementId]>) {
|
|
|
|
+ unsafe {
|
|
|
|
+ *self.0.get() = Some(contents);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub fn transfer(&self, other: &Self) {
|
|
|
|
+ unsafe {
|
|
|
|
+ *self.0.get() = (*other.0.get()).take();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub fn len(&self) -> usize {
|
|
|
|
+ unsafe {
|
|
|
|
+ (*self.0.get())
|
|
|
|
+ .as_ref()
|
|
|
|
+ .map(|inner| inner.len())
|
|
|
|
+ .unwrap_or(0)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<'a> IntoIterator for &'a BoxedCellSlice {
|
|
|
|
+ type Item = ElementId;
|
|
|
|
+
|
|
|
|
+ type IntoIter = BoxedCellSliceIter<'a>;
|
|
|
|
+
|
|
|
|
+ fn into_iter(self) -> Self::IntoIter {
|
|
|
|
+ BoxedCellSliceIter {
|
|
|
|
+ index: 0,
|
|
|
|
+ borrow: self,
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+pub struct BoxedCellSliceIter<'a> {
|
|
|
|
+ index: usize,
|
|
|
|
+ borrow: &'a BoxedCellSlice,
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl Iterator for BoxedCellSliceIter<'_> {
|
|
|
|
+ type Item = ElementId;
|
|
|
|
+
|
|
|
|
+ fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
+ let result = self.borrow.get(self.index);
|
|
|
|
+ if result.is_some() {
|
|
|
|
+ self.index += 1;
|
|
|
|
+ }
|
|
|
|
+ result
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
impl<'a> VNode<'a> {
|
|
impl<'a> VNode<'a> {
|
|
/// Create a template with no nodes that will be skipped over during diffing
|
|
/// Create a template with no nodes that will be skipped over during diffing
|
|
pub fn empty() -> Element<'a> {
|
|
pub fn empty() -> Element<'a> {
|
|
Some(VNode {
|
|
Some(VNode {
|
|
key: None,
|
|
key: None,
|
|
parent: None,
|
|
parent: None,
|
|
- root_ids: bumpalo::collections::Vec::new_in(&Bump::new()),
|
|
|
|
|
|
+ root_ids: BoxedCellSlice::default(),
|
|
dynamic_nodes: &[],
|
|
dynamic_nodes: &[],
|
|
dynamic_attrs: &[],
|
|
dynamic_attrs: &[],
|
|
template: Cell::new(Template {
|
|
template: Cell::new(Template {
|
|
@@ -572,7 +665,7 @@ impl<'a> IntoDynNode<'a> for &'a VNode<'a> {
|
|
DynamicNode::Fragment(_cx.bump().alloc([VNode {
|
|
DynamicNode::Fragment(_cx.bump().alloc([VNode {
|
|
parent: self.parent,
|
|
parent: self.parent,
|
|
template: self.template.clone(),
|
|
template: self.template.clone(),
|
|
- root_ids: self.root_ids,
|
|
|
|
|
|
+ root_ids: self.root_ids.clone(),
|
|
key: self.key,
|
|
key: self.key,
|
|
dynamic_nodes: self.dynamic_nodes,
|
|
dynamic_nodes: self.dynamic_nodes,
|
|
dynamic_attrs: self.dynamic_attrs,
|
|
dynamic_attrs: self.dynamic_attrs,
|