ソースを参照

Use zero cost option instead of null pointers

Evan Almloff 2 年 前
コミット
09da9c04a8
2 ファイル変更10 行追加7 行削除
  1. 8 5
      packages/core/src/arena.rs
  2. 2 2
      packages/core/src/virtual_dom.rs

+ 8 - 5
packages/core/src/arena.rs

@@ -1,3 +1,5 @@
+use std::ptr::NonNull;
+
 use crate::{
     nodes::RenderReturn, nodes::VNode, virtual_dom::VirtualDom, AttributeValue, DynamicNode,
     ScopeId,
@@ -17,7 +19,7 @@ pub(crate) struct ElementRef {
     pub path: ElementPath,
 
     // The actual template
-    pub template: *const VNode<'static>,
+    pub template: Option<NonNull<VNode<'static>>>,
 }
 
 #[derive(Clone, Copy)]
@@ -27,9 +29,9 @@ pub enum ElementPath {
 }
 
 impl ElementRef {
-    pub(crate) fn null() -> Self {
+    pub(crate) fn none() -> Self {
         Self {
-            template: std::ptr::null_mut(),
+            template: None,
             path: ElementPath::Root(0),
         }
     }
@@ -48,7 +50,7 @@ impl VirtualDom {
         let entry = self.elements.vacant_entry();
         let id = entry.key();
 
-        entry.insert(ElementRef::null());
+        entry.insert(ElementRef::none());
         ElementId(id)
     }
 
@@ -57,7 +59,8 @@ impl VirtualDom {
         let id = entry.key();
 
         entry.insert(ElementRef {
-            template: template as *const _ as *mut _,
+            // We know this is non-null because it comes from a reference
+            template: Some(unsafe { NonNull::new_unchecked(template as *const _ as *mut _) }),
             path,
         });
         ElementId(id)

+ 2 - 2
packages/core/src/virtual_dom.rs

@@ -282,7 +282,7 @@ impl VirtualDom {
         root.provide_context(Rc::new(ErrorBoundary::new(ScopeId(0))));
 
         // the root element is always given element ID 0 since it's the container for the entire tree
-        dom.elements.insert(ElementRef::null());
+        dom.elements.insert(ElementRef::none());
 
         dom
     }
@@ -387,7 +387,7 @@ impl VirtualDom {
         // Loop through each dynamic attribute in this template before moving up to the template's parent.
         while let Some(el_ref) = parent_path {
             // safety: we maintain references of all vnodes in the element slab
-            let template = unsafe { &*el_ref.template };
+            let template = unsafe { el_ref.template.unwrap().as_ref() };
             let node_template = template.template.get();
             let target_path = el_ref.path;