Feat: add context to builder

This commit is contained in:
Jonathan Kelley 2021-03-03 23:06:11 -05:00
parent fcd68e61d2
commit cf16090838
8 changed files with 144 additions and 98 deletions

View file

@ -59,7 +59,7 @@ impl ToTokens for HtmlRender {
// create a lazy tree that accepts a bump allocator
let final_tokens = quote! {
move |ctx| {
let bump = ctx.bump();
let bump = ctx.bump;
#new_toks
}

View file

@ -73,7 +73,7 @@ impl ToTokens for RsxRender {
// create a lazy tree that accepts a bump allocator
let final_tokens = quote! {
move |ctx| {
let bump = ctx.bump();
let bump = ctx.bump;
#new_toks
}
};

View file

@ -78,17 +78,17 @@ impl<'a> Context<'a> {
/// ctx.render(lazy_tree)
/// }
///```
pub fn render(self, lazy_nodes: impl FnOnce(&'a NodeCtx<'a>) -> VNode<'a> + 'a) -> DomTree {
pub fn render(self, lazy_nodes: impl FnOnce(&NodeCtx<'a>) -> VNode<'a> + 'a) -> DomTree {
let ctx = NodeCtx {
bump: self.bump,
idx: 0.into(),
scope: self.scope,
};
todo!();
// let safe_nodes = lazy_nodes(&ctx);
// todo!();
let safe_nodes = lazy_nodes(&ctx);
// let unsafe_nodes = unsafe { std::mem::transmute::<VNode<'a>, VNode<'static>>(safe_nodes) };
// self.final_nodes.deref().borrow_mut().replace(unsafe_nodes);
let unsafe_nodes = unsafe { std::mem::transmute::<VNode<'a>, VNode<'static>>(safe_nodes) };
self.final_nodes.deref().borrow_mut().replace(unsafe_nodes);
DomTree {}
}

View file

@ -19,13 +19,13 @@ use bumpalo::Bump;
/// function for building `<div>` elements or the `button` function for building
/// `<button>` elements.
#[derive(Debug)]
pub struct ElementBuilder<'a, Listeners, Attributes, Children>
pub struct ElementBuilder<'a, 'b, Listeners, Attributes, Children>
where
Listeners: 'a + AsRef<[Listener<'a>]>,
Attributes: 'a + AsRef<[Attribute<'a>]>,
Children: 'a + AsRef<[VNode<'a>]>,
{
ctx: &'a NodeCtx<'a>,
ctx: &'b NodeCtx<'a>,
key: NodeKey,
tag_name: &'a str,
listeners: Listeners,
@ -34,9 +34,10 @@ where
namespace: Option<&'a str>,
}
impl<'a>
impl<'a, 'b>
ElementBuilder<
'a,
'b,
bumpalo::collections::Vec<'a, Listener<'a>>,
bumpalo::collections::Vec<'a, Attribute<'a>>,
bumpalo::collections::Vec<'a, VNode<'a>>,
@ -65,9 +66,9 @@ impl<'a>
/// let my_element_builder = ElementBuilder::new(&b, tag_name);
/// # fn flip_coin() -> bool { true }
/// ```
pub fn new(ctx: &'a NodeCtx<'a>, tag_name: &'static str) -> Self {
pub fn new(ctx: &'b NodeCtx<'a>, tag_name: &'static str) -> Self {
// pub fn new<B>(ctx: &'a mut NodeCtx<'a>, tag_name: &'a str) -> Self {
let bump = ctx.bump();
let bump = ctx.bump;
ElementBuilder {
ctx,
key: NodeKey::NONE,
@ -80,7 +81,8 @@ impl<'a>
}
}
impl<'a, Listeners, Attributes, Children> ElementBuilder<'a, Listeners, Attributes, Children>
impl<'a, 'b, Listeners, Attributes, Children>
ElementBuilder<'a, 'b, Listeners, Attributes, Children>
where
Listeners: 'a + AsRef<[Listener<'a>]>,
Attributes: 'a + AsRef<[Attribute<'a>]>,
@ -114,7 +116,7 @@ where
/// .finish();
/// ```
#[inline]
pub fn listeners<L>(self, listeners: L) -> ElementBuilder<'a, L, Attributes, Children>
pub fn listeners<L>(self, listeners: L) -> ElementBuilder<'a, 'b, L, Attributes, Children>
where
L: 'a + AsRef<[Listener<'a>]>,
{
@ -153,7 +155,7 @@ where
/// .finish();
/// ```
#[inline]
pub fn attributes<A>(self, attributes: A) -> ElementBuilder<'a, Listeners, A, Children>
pub fn attributes<A>(self, attributes: A) -> ElementBuilder<'a, 'b, Listeners, A, Children>
where
A: 'a + AsRef<[Attribute<'a>]>,
{
@ -192,7 +194,7 @@ where
/// .finish();
/// ```
#[inline]
pub fn children<C>(self, children: C) -> ElementBuilder<'a, Listeners, Attributes, C>
pub fn children<C>(self, children: C) -> ElementBuilder<'a, 'b, Listeners, Attributes, C>
where
C: 'a + AsRef<[VNode<'a>]>,
{
@ -290,17 +292,17 @@ where
/// ```
#[inline]
pub fn finish(self) -> VNode<'a> {
let children: &'a Children = self.ctx.bump().alloc(self.children);
let children: &'a Children = self.ctx.bump.alloc(self.children);
let children: &'a [VNode<'a>] = children.as_ref();
let listeners: &'a Listeners = self.ctx.bump().alloc(self.listeners);
let listeners: &'a Listeners = self.ctx.bump.alloc(self.listeners);
let listeners: &'a [Listener<'a>] = listeners.as_ref();
let attributes: &'a Attributes = self.ctx.bump().alloc(self.attributes);
let attributes: &'a Attributes = self.ctx.bump.alloc(self.attributes);
let attributes: &'a [Attribute<'a>] = attributes.as_ref();
VNode::element(
self.ctx.bump(),
self.ctx.bump,
self.key,
self.tag_name,
listeners,
@ -311,8 +313,8 @@ where
}
}
impl<'a, Attributes, Children>
ElementBuilder<'a, bumpalo::collections::Vec<'a, Listener<'a>>, Attributes, Children>
impl<'a, 'b, Attributes, Children>
ElementBuilder<'a, 'b, bumpalo::collections::Vec<'a, Listener<'a>>, Attributes, Children>
where
Attributes: 'a + AsRef<[Attribute<'a>]>,
Children: 'a + AsRef<[VNode<'a>]>,
@ -355,8 +357,8 @@ where
}
}
impl<'a, Listeners, Children>
ElementBuilder<'a, Listeners, bumpalo::collections::Vec<'a, Attribute<'a>>, Children>
impl<'a, 'b, Listeners, Children>
ElementBuilder<'a, 'b, Listeners, bumpalo::collections::Vec<'a, Attribute<'a>>, Children>
where
Listeners: 'a + AsRef<[Listener<'a>]>,
Children: 'a + AsRef<[VNode<'a>]>,
@ -414,8 +416,8 @@ where
}
}
impl<'a, Listeners, Attributes>
ElementBuilder<'a, Listeners, Attributes, bumpalo::collections::Vec<'a, VNode<'a>>>
impl<'a, 'b, Listeners, Attributes>
ElementBuilder<'a, 'b, Listeners, Attributes, bumpalo::collections::Vec<'a, VNode<'a>>>
where
Listeners: 'a + AsRef<[Listener<'a>]>,
Attributes: 'a + AsRef<[Attribute<'a>]>,

View file

@ -24,49 +24,90 @@ use bumpalo::Bump;
use crate::innerlude::{Listener, ScopeIdx};
use serde::{Deserialize, Serialize};
/// The `Edit` represents a single modifcation of the renderer tree.
///
///
///
///
///
///
///
///
/// todo@ jon: allow serde to be optional
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum Edit<'d> {
SetText { text: &'d str },
SetText {
text: &'d str,
},
RemoveSelfAndNextSiblings {},
ReplaceWith,
SetAttribute { name: &'d str, value: &'d str },
RemoveAttribute { name: &'d str },
PushReverseChild { n: u32 },
PopPushChild { n: u32 },
SetAttribute {
name: &'d str,
value: &'d str,
},
RemoveAttribute {
name: &'d str,
},
PushReverseChild {
n: u32,
},
PopPushChild {
n: u32,
},
Pop,
AppendChild,
CreateTextNode { text: &'d str },
CreateElement { tag_name: &'d str },
NewEventListener { event_type: &'d str, s: ScopeIdx },
UpdateEventListener { event_type: &'d str, s: ScopeIdx },
RemoveEventListener { event_type: &'d str },
CreateElementNs { tag_name: &'d str, ns: &'d str },
SaveChildrenToTemporaries { temp: u32, start: u32, end: u32 },
PushChild { n: u32 },
PushTemporary { temp: u32 },
CreateTextNode {
text: &'d str,
},
CreateElement {
tag_name: &'d str,
},
CreateElementNs {
tag_name: &'d str,
ns: &'d str,
},
SaveChildrenToTemporaries {
temp: u32,
start: u32,
end: u32,
},
PushChild {
n: u32,
},
PushTemporary {
temp: u32,
},
InsertBefore,
PopPushReverseChild { n: u32 },
RemoveChild { n: u32 },
SetClass { class_name: &'d str },
PopPushReverseChild {
n: u32,
},
RemoveChild {
n: u32,
},
SetClass {
class_name: &'d str,
},
// push a known node on to the stack
TraverseToKnown { node: ScopeIdx },
TraverseToKnown {
node: ScopeIdx,
},
// Add the current top of the stack to the known nodes
MakeKnown { node: ScopeIdx },
MakeKnown {
node: ScopeIdx,
},
// Remove the current top of the stack from the known nodes
RemoveKnown,
NewListener {
event: &'d str,
scope: ScopeIdx,
id: usize,
},
UpdateListener {
event: &'d str,
scope: ScopeIdx,
id: usize,
},
RemoveListener {
event: &'d str,
},
// NewListener { event: &'d str, id: usize, s: ScopeIdx },
}
pub type EditList<'src> = Vec<Edit<'src>>;
@ -318,10 +359,7 @@ impl<'a> EditMachine<'a> {
pub fn new_event_listener(&mut self, event: &'a str, scope: ScopeIdx, id: usize) {
debug_assert!(self.traversal_is_committed());
self.emitter.push(Edit::NewEventListener {
event_type: event,
s: scope,
});
self.emitter.push(Edit::NewListener { event, scope, id });
// log::debug!("emit: new_event_listener({:?})", listener);
}
@ -332,16 +370,12 @@ impl<'a> EditMachine<'a> {
return;
}
self.emitter.push(Edit::NewEventListener {
event_type: event,
s: scope,
});
self.emitter.push(Edit::NewListener { event, scope, id });
}
pub fn remove_event_listener(&mut self, event: &'a str) {
debug_assert!(self.traversal_is_committed());
self.emitter
.push(Edit::RemoveEventListener { event_type: event });
self.emitter.push(Edit::RemoveListener { event });
// debug!("emit: remove_event_listener({:?})", event);
}

View file

@ -277,11 +277,15 @@ mod tests {
use crate::prelude::format_args_f;
static ListenerTest: FC<()> = |ctx, props| {
ctx.render(html! {
<div onclick={|_| println!("Hell owlrld")}>
"hello"
</div>
ctx.render(move |c| {
//
builder::ElementBuilder::new(c, "div").finish()
})
// ctx.render(html! {
// <div onclick={|_| println!("Hell owlrld")}>
// "hello"
// </div>
// })
};
#[test]

View file

@ -15,15 +15,16 @@ fn main() {
static App: FC<()> = |ctx, _| {
log::info!("Ran component");
use dioxus::builder::*;
ctx.render(|b| {
div(b)
.child(text("hello"))
.listeners([on(b, "click", |_| {
//
log::info!("button1 clicked!");
})])
.finish()
})
todo!()
// ctx.render(|b| {
// div(b)
// .child(text("hello"))
// .listeners([on(b, "click", |_| {
// //
// log::info!("button1 clicked!");
// })])
// .finish()
// })
// ctx.render(html! {
// <div onclick={move |_| log::info!("button1 clicked!")}>
// "Hello"

View file

@ -1,6 +1,10 @@
use std::{borrow::Borrow, fmt::Debug, sync::Arc};
use dioxus_core::events::{EventTrigger, MouseEvent, VirtualEvent};
use dioxus_core::{
events::{EventTrigger, MouseEvent, VirtualEvent},
patch::Edit,
prelude::ScopeIdx,
};
use fxhash::FxHashMap;
use log::debug;
use wasm_bindgen::{closure::Closure, JsCast};
@ -59,7 +63,7 @@ impl EventDelegater {
}
}
pub fn add_listener(&mut self, event: &str, cb: CbIdx) {
pub fn add_listener(&mut self, event: &str, scope: ScopeIdx) {
if let Some(entry) = self.listeners.get_mut(event) {
entry.0 += 1;
} else {
@ -75,15 +79,15 @@ impl EventDelegater {
let typ = event.type_();
let gi_id = target
let gi_id: Option<usize> = target
.get_attribute(&format!("dioxus-giid-{}", typ))
.and_then(|v| v.parse().ok());
let gi_gen = target
let gi_gen: Option<u64> = target
.get_attribute(&format!("dioxus-gigen-{}", typ))
.and_then(|v| v.parse().ok());
let li_idx = target
let li_idx: Option<usize> = target
.get_attribute(&format!("dioxus-lidx-{}", typ))
.and_then(|v| v.parse().ok());
@ -91,11 +95,8 @@ impl EventDelegater {
// Call the trigger
trigger.0.as_ref()(EventTrigger::new(
virtual_event_from_websys_event(event),
CbIdx {
gi_gen,
gi_id,
listener_idx: li_idx,
},
scope,
li_idx,
));
}
}) as Box<dyn FnMut(&Event)>);
@ -342,7 +343,7 @@ impl PatchMachine {
}
// 11
Edit::NewEventListener { event_type, idx } => {
Edit::NewListener { event, id, scope } => {
// attach the correct attributes to the element
// these will be used by accessing the event's target
// This ensures we only ever have one handler attached to the root, but decide
@ -362,24 +363,25 @@ impl PatchMachine {
// debug!("adding attributes: {}, {}", a, b);
let CbIdx {
gi_id,
gi_gen,
listener_idx: lidx,
} = idx;
// let CbIdx {
// gi_id,
// gi_gen,
// listener_idx: lidx,
// } = idx;
el.set_attribute(&format!("dioxus-giid-{}", event_type), &gi_id.to_string())
let (gi_id, gi_gen) = (&scope).into_raw_parts();
el.set_attribute(&format!("dioxus-giid-{}", event), &gi_id.to_string())
.unwrap();
el.set_attribute(&format!("dioxus-gigen-{}", event_type), &gi_gen.to_string())
el.set_attribute(&format!("dioxus-gigen-{}", event), &gi_gen.to_string())
.unwrap();
el.set_attribute(&format!("dioxus-lidx-{}", event_type), &lidx.to_string())
el.set_attribute(&format!("dioxus-lidx-{}", event), &id.to_string())
.unwrap();
self.events.add_listener(event_type, idx);
self.events.add_listener(event, scope);
}
// 12
Edit::UpdateEventListener { event_type, idx } => {
Edit::UpdateListener { event, scope, id } => {
// update our internal mapping, and then modify the attribute
if let Some(el) = self.stack.top().dyn_ref::<Element>() {
@ -391,7 +393,7 @@ impl PatchMachine {
}
// 13
Edit::RemoveEventListener { event_type } => {
Edit::RemoveListener { event: event_type } => {
if let Some(el) = self.stack.top().dyn_ref::<Element>() {
// el.remove_event_listener_with_callback(
// event_type,
@ -474,6 +476,9 @@ impl PatchMachine {
el.set_class_name(class_name);
}
}
Edit::TraverseToKnown { node } => {}
Edit::MakeKnown { node } => {}
Edit::RemoveKnown => {}
}
}