feat: enable children properly
This commit is contained in:
1 parent
dbb981d500
commit
b997b8ebbb
10 files changed
+128
-131
No files matched your search
@@ -17,7 +17,7 @@ pub fn format_args_f(input: TokenStream) -> TokenStream {
|
||||
.into()
|
||||
}
|
||||
|
||||
#[proc_macro_derive(Props, attributes(builder))]
|
||||
#[proc_macro_derive(Props, attributes(props))]
|
||||
pub fn derive_typed_builder(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let input = parse_macro_input!(input as syn::DeriveInput);
|
||||
match props::impl_my_derive(&input) {
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
//! However, it has been adopted to fit the Dioxus Props builder pattern.
|
||||
//!
|
||||
//! For dioxus, we make a few changes:
|
||||
//! - automatically implement Into<Option> on the setters (IE the strip setter option)
|
||||
//! - automatically implement a default of none for optional fields (those explicitly wrapped with Option<T>)
|
||||
//! - [ ] automatically implement Into<Option> on the setters (IE the strip setter option)
|
||||
//! - [ ] automatically implement a default of none for optional fields (those explicitly wrapped with Option<T>)
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
|
||||
@@ -194,6 +194,14 @@ mod field_info {
|
||||
field_defaults: FieldBuilderAttr,
|
||||
) -> Result<FieldInfo, Error> {
|
||||
if let Some(ref name) = field.ident {
|
||||
let mut builder_attr = field_defaults.with(&field.attrs)?;
|
||||
|
||||
// children field is automatically defaulted to None
|
||||
if name == "children" {
|
||||
builder_attr.default =
|
||||
Some(syn::parse(quote!(Default::default()).into()).unwrap());
|
||||
}
|
||||
|
||||
Ok(FieldInfo {
|
||||
ordinal,
|
||||
name,
|
||||
@@ -202,7 +210,7 @@ mod field_info {
|
||||
proc_macro2::Span::call_site(),
|
||||
),
|
||||
ty: &field.ty,
|
||||
builder_attr: field_defaults.with(&field.attrs)?,
|
||||
builder_attr,
|
||||
})
|
||||
} else {
|
||||
Err(Error::new(field.span(), "Nameless field in struct"))
|
||||
@@ -285,7 +293,7 @@ mod field_info {
|
||||
pub fn with(mut self, attrs: &[syn::Attribute]) -> Result<Self, Error> {
|
||||
let mut skip_tokens = None;
|
||||
for attr in attrs {
|
||||
if path_to_single_string(&attr.path).as_deref() != Some("builder") {
|
||||
if path_to_single_string(&attr.path).as_deref() != Some("props") {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -316,7 +324,7 @@ mod field_info {
|
||||
if self.setter.skip && self.default.is_none() {
|
||||
return Err(Error::new_spanned(
|
||||
skip_tokens.unwrap(),
|
||||
"#[builder(skip)] must be accompanied by default or default_code",
|
||||
"#[props(skip)] must be accompanied by default or default_code",
|
||||
));
|
||||
}
|
||||
|
||||
@@ -325,6 +333,7 @@ mod field_info {
|
||||
|
||||
pub fn apply_meta(&mut self, expr: syn::Expr) -> Result<(), Error> {
|
||||
match expr {
|
||||
// #[props(default = "...")]
|
||||
syn::Expr::Assign(assign) => {
|
||||
let name = expr_to_single_string(&assign.left)
|
||||
.ok_or_else(|| Error::new_spanned(&assign.left, "Expected identifier"))?;
|
||||
@@ -356,6 +365,8 @@ mod field_info {
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
// uh not sure
|
||||
syn::Expr::Path(path) => {
|
||||
let name = path_to_single_string(&path.path)
|
||||
.ok_or_else(|| Error::new_spanned(&path, "Expected identifier"))?;
|
||||
@@ -371,6 +382,8 @@ mod field_info {
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
syn::Expr::Call(call) => {
|
||||
let subsetting_name = if let syn::Expr::Path(path) = &*call.func {
|
||||
path_to_single_string(&path.path)
|
||||
@@ -398,6 +411,7 @@ mod field_info {
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
syn::Expr::Unary(syn::ExprUnary {
|
||||
op: syn::UnOp::Not(_),
|
||||
expr,
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_core as dioxus;
|
||||
use dioxus_core_macro::*;
|
||||
use dioxus_html as dioxus_elements;
|
||||
|
||||
fn main() {
|
||||
let mut dom = VirtualDom::new(parent);
|
||||
let edits = dom.rebuild();
|
||||
dbg!(edits);
|
||||
}
|
||||
|
||||
fn parent(cx: Scope<()>) -> Element {
|
||||
let value = cx.use_hook(|_| String::new(), |f| f);
|
||||
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
child(
|
||||
name: value,
|
||||
h1 {"hi"}
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Props)]
|
||||
struct ChildProps<'a> {
|
||||
name: &'a str,
|
||||
children: Element<'a>,
|
||||
}
|
||||
|
||||
fn child<'a>(cx: Scope<'a, ChildProps<'a>>) -> Element {
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
"it's nested {cx.props.name}"
|
||||
{&cx.props.children}
|
||||
}
|
||||
})
|
||||
}
|
||||
+23
-25
@@ -88,8 +88,6 @@
|
||||
//! More info on how to improve this diffing algorithm:
|
||||
//! - https://hacks.mozilla.org/2019/03/fast-bump-allocated-virtual-doms-with-rust-and-wasm/
|
||||
|
||||
use std::borrow::BorrowMut;
|
||||
|
||||
use crate::innerlude::*;
|
||||
use fxhash::{FxHashMap, FxHashSet};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
@@ -295,7 +293,7 @@ impl<'bump> DiffState<'bump> {
|
||||
for child in el.children.iter() {
|
||||
num_on_stack += self.push_all_nodes(child);
|
||||
}
|
||||
self.mutations.push_root(el.dom_id.get().unwrap());
|
||||
self.mutations.push_root(el.id.get().unwrap());
|
||||
|
||||
num_on_stack + 1
|
||||
}
|
||||
@@ -351,7 +349,7 @@ impl<'bump> DiffState<'bump> {
|
||||
let real_id = self.scopes.reserve_node(node);
|
||||
|
||||
self.mutations.create_text_node(vtext.text, real_id);
|
||||
vtext.dom_id.set(Some(real_id));
|
||||
vtext.id.set(Some(real_id));
|
||||
self.stack.add_child_count(1);
|
||||
}
|
||||
|
||||
@@ -359,20 +357,20 @@ impl<'bump> DiffState<'bump> {
|
||||
let real_id = self.scopes.reserve_node(node);
|
||||
|
||||
self.mutations.create_placeholder(real_id);
|
||||
anchor.dom_id.set(Some(real_id));
|
||||
anchor.id.set(Some(real_id));
|
||||
|
||||
self.stack.add_child_count(1);
|
||||
}
|
||||
|
||||
fn create_element_node(&mut self, element: &'bump VElement<'bump>, node: &'bump VNode<'bump>) {
|
||||
let VElement {
|
||||
tag_name,
|
||||
tag: tag_name,
|
||||
listeners,
|
||||
attributes,
|
||||
children,
|
||||
namespace,
|
||||
dom_id,
|
||||
parent_id,
|
||||
id: dom_id,
|
||||
parent: parent_id,
|
||||
..
|
||||
} = element;
|
||||
|
||||
@@ -479,9 +477,9 @@ impl<'bump> DiffState<'bump> {
|
||||
}
|
||||
(Element(old), Element(new)) => self.diff_element_nodes(old, new, old_node, new_node),
|
||||
(Placeholder(old), Placeholder(new)) => {
|
||||
if let Some(root) = old.dom_id.get() {
|
||||
if let Some(root) = old.id.get() {
|
||||
self.scopes.update_node(new_node, root);
|
||||
new.dom_id.set(Some(root))
|
||||
new.id.set(Some(root))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -515,13 +513,13 @@ impl<'bump> DiffState<'bump> {
|
||||
_old_node: &'bump VNode<'bump>,
|
||||
new_node: &'bump VNode<'bump>,
|
||||
) {
|
||||
if let Some(root) = old.dom_id.get() {
|
||||
if let Some(root) = old.id.get() {
|
||||
if old.text != new.text {
|
||||
self.mutations.set_text(new.text, root.as_u64());
|
||||
}
|
||||
self.scopes.update_node(new_node, root);
|
||||
|
||||
new.dom_id.set(Some(root));
|
||||
new.id.set(Some(root));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -532,13 +530,13 @@ impl<'bump> DiffState<'bump> {
|
||||
old_node: &'bump VNode<'bump>,
|
||||
new_node: &'bump VNode<'bump>,
|
||||
) {
|
||||
let root = old.dom_id.get().unwrap();
|
||||
let root = old.id.get().unwrap();
|
||||
|
||||
// If the element type is completely different, the element needs to be re-rendered completely
|
||||
// This is an optimization React makes due to how users structure their code
|
||||
//
|
||||
// This case is rather rare (typically only in non-keyed lists)
|
||||
if new.tag_name != old.tag_name || new.namespace != old.namespace {
|
||||
if new.tag != old.tag || new.namespace != old.namespace {
|
||||
// maybe make this an instruction?
|
||||
// issue is that we need the "vnode" but this method only has the velement
|
||||
self.stack.push_nodes_created(0);
|
||||
@@ -551,8 +549,8 @@ impl<'bump> DiffState<'bump> {
|
||||
|
||||
self.scopes.update_node(new_node, root);
|
||||
|
||||
new.dom_id.set(Some(root));
|
||||
new.parent_id.set(old.parent_id.get());
|
||||
new.id.set(Some(root));
|
||||
new.parent.set(old.parent.get());
|
||||
|
||||
// todo: attributes currently rely on the element on top of the stack, but in theory, we only need the id of the
|
||||
// element to modify its attributes.
|
||||
@@ -1182,9 +1180,9 @@ impl<'bump> DiffState<'bump> {
|
||||
|
||||
loop {
|
||||
match &search_node.take().unwrap() {
|
||||
VNode::Text(t) => break t.dom_id.get(),
|
||||
VNode::Element(t) => break t.dom_id.get(),
|
||||
VNode::Placeholder(t) => break t.dom_id.get(),
|
||||
VNode::Text(t) => break t.id.get(),
|
||||
VNode::Element(t) => break t.id.get(),
|
||||
VNode::Placeholder(t) => break t.id.get(),
|
||||
VNode::Fragment(frag) => {
|
||||
search_node = frag.children.last();
|
||||
}
|
||||
@@ -1209,9 +1207,9 @@ impl<'bump> DiffState<'bump> {
|
||||
let scope_id = el.scope.get().unwrap();
|
||||
search_node = Some(self.scopes.root_node(scope_id));
|
||||
}
|
||||
VNode::Text(t) => break t.dom_id.get(),
|
||||
VNode::Element(t) => break t.dom_id.get(),
|
||||
VNode::Placeholder(t) => break t.dom_id.get(),
|
||||
VNode::Text(t) => break t.id.get(),
|
||||
VNode::Element(t) => break t.id.get(),
|
||||
VNode::Placeholder(t) => break t.id.get(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1263,7 +1261,7 @@ impl<'bump> DiffState<'bump> {
|
||||
match node {
|
||||
VNode::Text(t) => {
|
||||
// this check exists because our null node will be removed but does not have an ID
|
||||
if let Some(id) = t.dom_id.get() {
|
||||
if let Some(id) = t.id.get() {
|
||||
self.scopes.collect_garbage(id);
|
||||
|
||||
if gen_muts {
|
||||
@@ -1272,7 +1270,7 @@ impl<'bump> DiffState<'bump> {
|
||||
}
|
||||
}
|
||||
VNode::Placeholder(a) => {
|
||||
let id = a.dom_id.get().unwrap();
|
||||
let id = a.id.get().unwrap();
|
||||
self.scopes.collect_garbage(id);
|
||||
|
||||
if gen_muts {
|
||||
@@ -1280,7 +1278,7 @@ impl<'bump> DiffState<'bump> {
|
||||
}
|
||||
}
|
||||
VNode::Element(e) => {
|
||||
let id = e.dom_id.get().unwrap();
|
||||
let id = e.id.get().unwrap();
|
||||
|
||||
if gen_muts {
|
||||
self.mutations.remove(id.as_u64());
|
||||
|
||||
@@ -16,7 +16,6 @@ pub(crate) mod innerlude {
|
||||
pub use crate::mutations::*;
|
||||
pub use crate::nodes::*;
|
||||
pub use crate::scopes::*;
|
||||
pub(crate) use crate::scopes::*;
|
||||
pub use crate::virtual_dom::*;
|
||||
|
||||
/// An [`Element`] is a possibly-none [`VNode`] created by calling `render` on [`Scope`] or [`ScopeState`].
|
||||
|
||||
+27
-80
@@ -141,9 +141,9 @@ impl<'src> VNode<'src> {
|
||||
/// Returns None if the VNode is not mounted, or if the VNode cannot be presented by a mounted ID (Fragment/Component)
|
||||
pub fn try_mounted_id(&self) -> Option<ElementId> {
|
||||
match &self {
|
||||
VNode::Text(el) => el.dom_id.get(),
|
||||
VNode::Element(el) => el.dom_id.get(),
|
||||
VNode::Placeholder(el) => el.dom_id.get(),
|
||||
VNode::Text(el) => el.id.get(),
|
||||
VNode::Element(el) => el.id.get(),
|
||||
VNode::Placeholder(el) => el.id.get(),
|
||||
VNode::Fragment(_) => None,
|
||||
VNode::Component(_) => None,
|
||||
}
|
||||
@@ -176,7 +176,7 @@ impl Debug for VNode<'_> {
|
||||
match &self {
|
||||
VNode::Element(el) => s
|
||||
.debug_struct("VNode::VElement")
|
||||
.field("name", &el.tag_name)
|
||||
.field("name", &el.tag)
|
||||
.field("key", &el.key)
|
||||
.field("attrs", &el.attributes)
|
||||
.field("children", &el.children)
|
||||
@@ -187,7 +187,6 @@ impl Debug for VNode<'_> {
|
||||
write!(s, "VNode::VFragment {{ children: {:?} }}", frag.children)
|
||||
}
|
||||
VNode::Component(comp) => write!(s, "VNode::VComponent {{ fc: {:?}}}", comp.user_fc),
|
||||
// VNode::Component(comp) => write!(s, "VNode::VComponent {{ fc: {:?}}}", comp.user_fc),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -216,13 +215,13 @@ fn empty_cell() -> Cell<Option<ElementId>> {
|
||||
|
||||
/// A placeholder node only generated when Fragments don't have any children.
|
||||
pub struct VPlaceholder {
|
||||
pub dom_id: Cell<Option<ElementId>>,
|
||||
pub id: Cell<Option<ElementId>>,
|
||||
}
|
||||
|
||||
/// A bump-allocated string slice and metadata.
|
||||
pub struct VText<'src> {
|
||||
pub text: &'src str,
|
||||
pub dom_id: Cell<Option<ElementId>>,
|
||||
pub id: Cell<Option<ElementId>>,
|
||||
pub is_static: bool,
|
||||
}
|
||||
|
||||
@@ -238,11 +237,11 @@ pub struct VFragment<'src> {
|
||||
|
||||
/// An element like a "div" with children, listeners, and attributes.
|
||||
pub struct VElement<'a> {
|
||||
pub tag_name: &'static str,
|
||||
pub tag: &'static str,
|
||||
pub namespace: Option<&'static str>,
|
||||
pub key: Option<&'a str>,
|
||||
pub dom_id: Cell<Option<ElementId>>,
|
||||
pub parent_id: Cell<Option<ElementId>>,
|
||||
pub id: Cell<Option<ElementId>>,
|
||||
pub parent: Cell<Option<ElementId>>,
|
||||
pub listeners: &'a [Listener<'a>],
|
||||
pub attributes: &'a [Attribute<'a>],
|
||||
pub children: &'a [VNode<'a>],
|
||||
@@ -251,11 +250,11 @@ pub struct VElement<'a> {
|
||||
impl Debug for VElement<'_> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("VElement")
|
||||
.field("tag_name", &self.tag_name)
|
||||
.field("tag_name", &self.tag)
|
||||
.field("namespace", &self.namespace)
|
||||
.field("key", &self.key)
|
||||
.field("dom_id", &self.dom_id)
|
||||
.field("parent_id", &self.parent_id)
|
||||
.field("id", &self.id)
|
||||
.field("parent", &self.parent)
|
||||
.field("listeners", &self.listeners.len())
|
||||
.field("attributes", &self.attributes)
|
||||
.field("children", &self.children)
|
||||
@@ -363,20 +362,13 @@ pub struct VComponent<'src> {
|
||||
}
|
||||
|
||||
pub(crate) struct VComponentProps<P> {
|
||||
// Props start local
|
||||
// If they are static, then they can get promoted onto the heap
|
||||
pub render_fn: Component<P>,
|
||||
pub props: P,
|
||||
pub memo: unsafe fn(&P, &P) -> bool,
|
||||
pub props: P,
|
||||
}
|
||||
|
||||
pub trait AnyProps {
|
||||
fn as_ptr(&self) -> *const ();
|
||||
fn release(&self);
|
||||
fn replace_heap(&self, new: Box<dyn Any>);
|
||||
|
||||
// move the props from the bump arena onto the heap
|
||||
fn promote(&self);
|
||||
fn render<'a>(&'a self, bump: &'a ScopeState) -> Element<'a>;
|
||||
unsafe fn memoize(&self, other: &dyn AnyProps) -> bool;
|
||||
}
|
||||
@@ -384,16 +376,9 @@ pub trait AnyProps {
|
||||
impl<P> AnyProps for VComponentProps<P> {
|
||||
fn as_ptr(&self) -> *const () {
|
||||
&self.props as *const _ as *const ()
|
||||
// // todo: maybe move this into an enum
|
||||
// let heap_props = self.heap_props.borrow();
|
||||
// if let Some(b) = heap_props.as_ref() {
|
||||
// b.as_ref() as *const _ as *const ()
|
||||
// } else {
|
||||
// let local_props = self.local_props.borrow();
|
||||
// local_props.as_ref().unwrap() as *const _ as *const ()
|
||||
// }
|
||||
}
|
||||
|
||||
// Safety:
|
||||
// this will downcat the other ptr as our swallowed type!
|
||||
// you *must* make this check *before* calling this method
|
||||
// if your functions are not the same, then you will downcast a pointer into a different type (UB)
|
||||
@@ -403,41 +388,9 @@ impl<P> AnyProps for VComponentProps<P> {
|
||||
(self.memo)(real_us, real_other)
|
||||
}
|
||||
|
||||
fn release(&self) {
|
||||
panic!("don't release props anymore");
|
||||
// if let Some(heap_props) = self.heap_props.borrow_mut().take() {
|
||||
// dbg!("releasing heap");
|
||||
// drop(heap_props)
|
||||
// } else if let Some(local_props) = self.local_props.borrow_mut().take() {
|
||||
// dbg!("releasing local");
|
||||
// drop(local_props)
|
||||
// } else {
|
||||
// dbg!("trying to do a double release");
|
||||
// }
|
||||
}
|
||||
|
||||
fn promote(&self) {
|
||||
panic!("don't promote props anymore");
|
||||
// dbg!("promoting props");
|
||||
// if let Some(props) = self.local_props.borrow_mut().take() {
|
||||
// let mut heap_slot = self.heap_props.borrow_mut();
|
||||
// *heap_slot = Some(Box::new(props));
|
||||
// }
|
||||
}
|
||||
|
||||
fn render<'a>(&'a self, scope: &'a ScopeState) -> Element<'a> {
|
||||
let props: &P = &self.props;
|
||||
let inline_props = unsafe { std::mem::transmute::<&P, &P>(props) };
|
||||
|
||||
(self.render_fn)(Scope {
|
||||
scope,
|
||||
props: inline_props,
|
||||
})
|
||||
}
|
||||
|
||||
fn replace_heap(&self, new: Box<dyn Any>) {
|
||||
// let new = new.downcast::<P>().unwrap();
|
||||
// self.heap_props.borrow_mut().replace(new);
|
||||
let props = unsafe { std::mem::transmute::<&P, &P>(&self.props) };
|
||||
(self.render_fn)(Scope { scope, props })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,7 +416,7 @@ impl<'a> NodeFactory<'a> {
|
||||
/// Directly pass in text blocks without the need to use the format_args macro.
|
||||
pub fn static_text(&self, text: &'static str) -> VNode<'a> {
|
||||
VNode::Text(self.bump.alloc(VText {
|
||||
dom_id: empty_cell(),
|
||||
id: empty_cell(),
|
||||
text,
|
||||
is_static: true,
|
||||
}))
|
||||
@@ -492,7 +445,7 @@ impl<'a> NodeFactory<'a> {
|
||||
VNode::Text(self.bump.alloc(VText {
|
||||
text,
|
||||
is_static,
|
||||
dom_id: empty_cell(),
|
||||
id: empty_cell(),
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -545,14 +498,14 @@ impl<'a> NodeFactory<'a> {
|
||||
let key = key.map(|f| self.raw_text(f).0);
|
||||
|
||||
VNode::Element(self.bump.alloc(VElement {
|
||||
tag_name,
|
||||
tag: tag_name,
|
||||
key,
|
||||
namespace,
|
||||
listeners,
|
||||
attributes,
|
||||
children,
|
||||
dom_id: empty_cell(),
|
||||
parent_id: empty_cell(),
|
||||
id: empty_cell(),
|
||||
parent: empty_cell(),
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -621,9 +574,7 @@ impl<'a> NodeFactory<'a> {
|
||||
}
|
||||
|
||||
if nodes.is_empty() {
|
||||
VNode::Placeholder(self.bump.alloc(VPlaceholder {
|
||||
dom_id: empty_cell(),
|
||||
}))
|
||||
VNode::Placeholder(self.bump.alloc(VPlaceholder { id: empty_cell() }))
|
||||
} else {
|
||||
VNode::Fragment(VFragment {
|
||||
children: nodes.into_bump_slice(),
|
||||
@@ -643,9 +594,7 @@ impl<'a> NodeFactory<'a> {
|
||||
}
|
||||
|
||||
if nodes.is_empty() {
|
||||
VNode::Placeholder(self.bump.alloc(VPlaceholder {
|
||||
dom_id: empty_cell(),
|
||||
}))
|
||||
VNode::Placeholder(self.bump.alloc(VPlaceholder { id: empty_cell() }))
|
||||
} else {
|
||||
let children = nodes.into_bump_slice();
|
||||
|
||||
@@ -686,9 +635,9 @@ impl<'a> NodeFactory<'a> {
|
||||
}
|
||||
|
||||
if nodes.is_empty() {
|
||||
Some(VNode::Placeholder(self.bump.alloc(VPlaceholder {
|
||||
dom_id: empty_cell(),
|
||||
})))
|
||||
Some(VNode::Placeholder(
|
||||
self.bump.alloc(VPlaceholder { id: empty_cell() }),
|
||||
))
|
||||
} else {
|
||||
let children = nodes.into_bump_slice();
|
||||
|
||||
@@ -766,9 +715,7 @@ impl<'a> IntoVNode<'a> for Option<LazyNodes<'a, '_>> {
|
||||
fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a> {
|
||||
match self {
|
||||
Some(lazy) => lazy.call(cx),
|
||||
None => VNode::Placeholder(cx.bump.alloc(VPlaceholder {
|
||||
dom_id: empty_cell(),
|
||||
})),
|
||||
None => VNode::Placeholder(cx.bump.alloc(VPlaceholder { id: empty_cell() })),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,11 +44,11 @@ impl ScopeArena {
|
||||
// this will *never* show up in the diffing process
|
||||
// todo: figure out why this is necessary. i forgot. whoops.
|
||||
let el = bump.alloc(VElement {
|
||||
tag_name: "root",
|
||||
tag: "root",
|
||||
namespace: None,
|
||||
key: None,
|
||||
dom_id: Cell::new(Some(ElementId(0))),
|
||||
parent_id: Default::default(),
|
||||
id: Cell::new(Some(ElementId(0))),
|
||||
parent: Default::default(),
|
||||
listeners: &[],
|
||||
attributes: &[],
|
||||
children: &[],
|
||||
@@ -279,7 +279,7 @@ impl ScopeArena {
|
||||
let node = frame
|
||||
.bump
|
||||
.alloc(VNode::Placeholder(frame.bump.alloc(VPlaceholder {
|
||||
dom_id: Default::default(),
|
||||
id: Default::default(),
|
||||
})));
|
||||
frame.node.set(unsafe { extend_vnode(node) });
|
||||
}
|
||||
@@ -310,7 +310,7 @@ impl ScopeArena {
|
||||
}
|
||||
}
|
||||
|
||||
cur_el = real_el.parent_id.get();
|
||||
cur_el = real_el.parent.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -869,7 +869,7 @@ impl BumpFrame {
|
||||
|
||||
let node = &*bump.alloc(VText {
|
||||
text: "placeholdertext",
|
||||
dom_id: Default::default(),
|
||||
id: Default::default(),
|
||||
is_static: false,
|
||||
});
|
||||
let node = bump.alloc(VNode::Text(unsafe { std::mem::transmute(node) }));
|
||||
@@ -881,7 +881,7 @@ impl BumpFrame {
|
||||
self.bump.reset();
|
||||
let node = self.bump.alloc(VText {
|
||||
text: "placeholdertext",
|
||||
dom_id: Default::default(),
|
||||
id: Default::default(),
|
||||
is_static: false,
|
||||
});
|
||||
let node = self
|
||||
|
||||
@@ -109,14 +109,14 @@ fn components_generate() {
|
||||
*render_phase += 1;
|
||||
|
||||
cx.render(match *render_phase {
|
||||
0 => rsx!("Text0"),
|
||||
1 => rsx!(div {}),
|
||||
2 => rsx!("Text2"),
|
||||
3 => rsx!(Child {}),
|
||||
4 => rsx!({ None as Option<()> }),
|
||||
5 => rsx!("text 3"),
|
||||
6 => rsx!({ (0..2).map(|f| rsx!("text {f}")) }),
|
||||
7 => rsx!(Child {}),
|
||||
1 => rsx!("Text0"),
|
||||
2 => rsx!(div {}),
|
||||
3 => rsx!("Text2"),
|
||||
4 => rsx!(Child {}),
|
||||
5 => rsx!({ None as Option<()> }),
|
||||
6 => rsx!("text 3"),
|
||||
7 => rsx!({ (0..2).map(|f| rsx!("text {f}")) }),
|
||||
8 => rsx!(Child {}),
|
||||
_ => todo!(),
|
||||
})
|
||||
};
|
||||
@@ -220,7 +220,6 @@ fn components_generate() {
|
||||
|
||||
#[test]
|
||||
fn component_swap() {
|
||||
// simple_logger::init();
|
||||
static App: Component<()> = |cx| {
|
||||
let render_phase = cx.use_hook(|_| 0, |f| f);
|
||||
*render_phase += 1;
|
||||
|
||||
@@ -132,7 +132,7 @@ impl DesktopController {
|
||||
runtime.block_on(async move {
|
||||
// LocalSet::new().block_on(&runtime, async move {
|
||||
let mut dom =
|
||||
VirtualDom::new_with_props_and_scheduler(root, props, sender, receiver);
|
||||
VirtualDom::new_with_props_and_scheduler(root, props, (sender, receiver));
|
||||
|
||||
let edits = dom.rebuild();
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ impl<'a> TextRenderer<'a, '_> {
|
||||
}
|
||||
}
|
||||
|
||||
write!(f, "<{}", el.tag_name)?;
|
||||
write!(f, "<{}", el.tag)?;
|
||||
|
||||
let mut inner_html = None;
|
||||
let mut attr_iter = el.attributes.iter().peekable();
|
||||
@@ -233,7 +233,7 @@ impl<'a> TextRenderer<'a, '_> {
|
||||
}
|
||||
}
|
||||
|
||||
write!(f, "</{}>", el.tag_name)?;
|
||||
write!(f, "</{}>", el.tag)?;
|
||||
if self.cfg.newline {
|
||||
writeln!(f)?;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user