diff --git a/packages/core/src/nodes.rs b/packages/core/src/nodes.rs
index 197550a3b..a108f3577 100644
--- a/packages/core/src/nodes.rs
+++ b/packages/core/src/nodes.rs
@@ -312,19 +312,26 @@ pub struct VComponent<'a> {
/// Internally, this is used as a guarantee. Externally, this might be incorrect, so don't count on it.
///
/// This flag is assumed by the [`crate::Properties`] trait which is unsafe to implement
- pub static_props: bool,
+ pub(crate) static_props: bool,
/// The assigned Scope for this component
- pub scope: Cell>,
+ pub(crate) scope: Cell >,
/// The function pointer of the component, known at compile time
///
/// It is possible that components get folded at comppile time, so these shouldn't be really used as a key
- pub render_fn: *const (),
+ pub(crate) render_fn: *const (),
pub(crate) props: RefCell + 'a>>>,
}
+impl<'a> VComponent<'a> {
+ /// Get the scope that this component is mounted to
+ pub fn mounted_scope(&self) -> Option {
+ self.scope.get()
+ }
+}
+
impl<'a> std::fmt::Debug for VComponent<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("VComponent")
@@ -342,14 +349,36 @@ pub struct VText<'a> {
pub value: &'a str,
/// The ID of this node in the real DOM
- pub id: Cell>,
+ pub(crate) id: Cell >,
+}
+
+impl<'a> VText<'a> {
+ /// Create a new VText
+ pub fn new(value: &'a str) -> Self {
+ Self {
+ value,
+ id: Default::default(),
+ }
+ }
+
+ /// Get the mounted ID of this node
+ pub fn mounted_element(&self) -> Option {
+ self.id.get()
+ }
}
/// A placeholder node, used by suspense and fragments
#[derive(Debug, Default)]
pub struct VPlaceholder {
/// The ID of this node in the real DOM
- pub id: Cell>,
+ pub(crate) id: Cell >,
+}
+
+impl VPlaceholder {
+ /// Get the mounted ID of this node
+ pub fn mounted_element(&self) -> Option {
+ self.id.get()
+ }
}
/// An attribute of the TemplateNode, created at compile time
@@ -399,11 +428,34 @@ pub struct Attribute<'a> {
/// Doesn’t exist in the html spec. Used in Dioxus to denote “style” tags and other attribute groups.
pub namespace: Option<&'static str>,
- /// The element in the DOM that this attribute belongs to
- pub mounted_element: Cell,
-
/// An indication of we should always try and set the attribute. Used in controlled components to ensure changes are propagated
pub volatile: bool,
+
+ /// The element in the DOM that this attribute belongs to
+ pub(crate) mounted_element: Cell,
+}
+
+impl<'a> Attribute<'a> {
+ /// Create a new attribute
+ pub fn new(
+ name: &'a str,
+ value: AttributeValue<'a>,
+ namespace: Option<&'static str>,
+ volatile: bool,
+ ) -> Self {
+ Self {
+ name,
+ value,
+ namespace,
+ volatile,
+ mounted_element: Cell::new(ElementId::default()),
+ }
+ }
+
+ /// Get the element that this attribute is mounted to
+ pub fn mounted_element(&self) -> ElementId {
+ self.mounted_element.get()
+ }
}
/// Any of the built-in values that the Dioxus VirtualDom supports as dynamic attributes on elements
diff --git a/packages/html/src/events.rs b/packages/html/src/events.rs
index 0423e52cf..c59149493 100644
--- a/packages/html/src/events.rs
+++ b/packages/html/src/events.rs
@@ -10,15 +10,14 @@ macro_rules! impl_event {
$( #[$attr] )*
#[inline]
pub fn $name<'a, E: crate::EventReturn, T>(_cx: &'a ::dioxus_core::ScopeState, mut _f: impl FnMut(::dioxus_core::Event<$data>) -> E + 'a) -> ::dioxus_core::Attribute<'a> {
- ::dioxus_core::Attribute {
- name: stringify!($name),
- value: _cx.listener(move |e: ::dioxus_core::Event<$data>| {
+ ::dioxus_core::Attribute::new(
+ stringify!($name),
+ _cx.listener(move |e: ::dioxus_core::Event<$data>| {
_f(e).spawn(_cx);
}),
- namespace: None,
- mounted_element: Default::default(),
- volatile: false,
- }
+ None,
+ false,
+ )
}
)*
};
diff --git a/packages/native-core/tests/fuzzing.rs b/packages/native-core/tests/fuzzing.rs
index 5acdc33c0..13f8b81f6 100644
--- a/packages/native-core/tests/fuzzing.rs
+++ b/packages/native-core/tests/fuzzing.rs
@@ -217,13 +217,12 @@ fn create_random_dynamic_attr(cx: &ScopeState) -> Attribute {
// Listener(RefCell>>),
_ => unreachable!(),
};
- Attribute {
- name: Box::leak(format!("attr{}", rand::random::()).into_boxed_str()),
+ Attribute::new(
+ Box::leak(format!("attr{}", rand::random::()).into_boxed_str()),
value,
- namespace: random_ns(),
- mounted_element: Default::default(),
- volatile: rand::random(),
- }
+ random_ns(),
+ rand::random(),
+ )
}
static mut TEMPLATE_COUNT: usize = 0;
diff --git a/packages/ssr/src/renderer.rs b/packages/ssr/src/renderer.rs
index a85a3ea7e..f23e654fb 100644
--- a/packages/ssr/src/renderer.rs
+++ b/packages/ssr/src/renderer.rs
@@ -102,7 +102,7 @@ impl Renderer {
if self.skip_components {
write!(buf, "<{}><{}/>", node.name, node.name)?;
} else {
- let id = node.scope.get().unwrap();
+ let id = node.mounted_scope().unwrap();
let scope = dom.get_scope(id).unwrap();
let node = scope.root_node();
match node {
diff --git a/packages/web/src/rehydrate.rs b/packages/web/src/rehydrate.rs
index 5cc9ea57e..c7ea6d87d 100644
--- a/packages/web/src/rehydrate.rs
+++ b/packages/web/src/rehydrate.rs
@@ -1,7 +1,6 @@
use crate::dom::WebsysDom;
use dioxus_core::{
- AttributeValue, DynamicNode, ElementId, ScopeState, TemplateNode, VNode, VPlaceholder, VText,
- VirtualDom,
+ AttributeValue, DynamicNode, ElementId, ScopeState, TemplateNode, VNode, VirtualDom,
};
use dioxus_html::event_bubbles;
use wasm_bindgen::JsCast;
@@ -130,7 +129,7 @@ impl WebsysDom {
if let dioxus_core::TemplateAttribute::Dynamic { id } = attr {
let attribute = &vnode.dynamic_attrs[*id];
let value = &attribute.value;
- let id = attribute.mounted_element.get();
+ let id = attribute.mounted_element();
mounted_id = Some(id);
let name = attribute.name;
if let AttributeValue::Listener(_) = value {
@@ -211,7 +210,8 @@ impl WebsysDom {
}
}
match dynamic {
- dioxus_core::DynamicNode::Text(VText { id, .. }) => {
+ dioxus_core::DynamicNode::Text(text) => {
+ let id = text.mounted_element();
// skip comment separator before node
if cfg!(debug_assertions) {
assert!(current_child
@@ -227,7 +227,7 @@ impl WebsysDom {
set_node(
hydrated,
- id.get().ok_or(VNodeNotInitialized)?,
+ id.ok_or(VNodeNotInitialized)?,
current_child.clone()?,
);
*current_child = current_child
@@ -251,10 +251,10 @@ impl WebsysDom {
*last_node_was_static_text = false;
}
- dioxus_core::DynamicNode::Placeholder(VPlaceholder { id, .. }) => {
+ dioxus_core::DynamicNode::Placeholder(placeholder) => {
set_node(
hydrated,
- id.get().ok_or(VNodeNotInitialized)?,
+ placeholder.mounted_element().ok_or(VNodeNotInitialized)?,
current_child.clone()?,
);
*current_child = current_child
@@ -265,7 +265,7 @@ impl WebsysDom {
*last_node_was_static_text = false;
}
dioxus_core::DynamicNode::Component(comp) => {
- let scope = comp.scope.get().ok_or(VNodeNotInitialized)?;
+ let scope = comp.mounted_scope().ok_or(VNodeNotInitialized)?;
self.rehydrate_scope(
dom.get_scope(scope).unwrap(),
current_child,