Feat: add context to builder

This commit is contained in:
Jonathan Kelley committed 2021-03-03 23:06:11 -05:00
1 parent fcd68e61d2
commit cf16090838
8 files changed
+144 -98

No files matched your search

+1 -1
View File
@@ -59,7 +59,7 @@ impl ToTokens for HtmlRender {
// create a lazy tree that accepts a bump allocator // create a lazy tree that accepts a bump allocator
let final_tokens = quote! { let final_tokens = quote! {
move |ctx| { move |ctx| {
let bump = ctx.bump(); let bump = ctx.bump;
#new_toks #new_toks
} }
+1 -1
View File
@@ -73,7 +73,7 @@ impl ToTokens for RsxRender {
// create a lazy tree that accepts a bump allocator // create a lazy tree that accepts a bump allocator
let final_tokens = quote! { let final_tokens = quote! {
move |ctx| { move |ctx| {
let bump = ctx.bump(); let bump = ctx.bump;
#new_toks #new_toks
} }
}; };
+5 -5
View File
@@ -78,17 +78,17 @@ impl<'a> Context<'a> {
/// ctx.render(lazy_tree) /// 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 { let ctx = NodeCtx {
bump: self.bump, bump: self.bump,
idx: 0.into(), idx: 0.into(),
scope: self.scope, scope: self.scope,
}; };
todo!(); // todo!();
// let safe_nodes = lazy_nodes(&ctx); let safe_nodes = lazy_nodes(&ctx);
// let unsafe_nodes = unsafe { std::mem::transmute::<VNode<'a>, VNode<'static>>(safe_nodes) }; let unsafe_nodes = unsafe { std::mem::transmute::<VNode<'a>, VNode<'static>>(safe_nodes) };
// self.final_nodes.deref().borrow_mut().replace(unsafe_nodes); self.final_nodes.deref().borrow_mut().replace(unsafe_nodes);
DomTree {} DomTree {}
} }
+21 -19
View File
@@ -19,13 +19,13 @@ use bumpalo::Bump;
/// function for building `<div>` elements or the `button` function for building /// function for building `<div>` elements or the `button` function for building
/// `<button>` elements. /// `<button>` elements.
#[derive(Debug)] #[derive(Debug)]
pub struct ElementBuilder<'a, Listeners, Attributes, Children> pub struct ElementBuilder<'a, 'b, Listeners, Attributes, Children>
where where
Listeners: 'a + AsRef<[Listener<'a>]>, Listeners: 'a + AsRef<[Listener<'a>]>,
Attributes: 'a + AsRef<[Attribute<'a>]>, Attributes: 'a + AsRef<[Attribute<'a>]>,
Children: 'a + AsRef<[VNode<'a>]>, Children: 'a + AsRef<[VNode<'a>]>,
{ {
ctx: &'a NodeCtx<'a>, ctx: &'b NodeCtx<'a>,
key: NodeKey, key: NodeKey,
tag_name: &'a str, tag_name: &'a str,
listeners: Listeners, listeners: Listeners,
@@ -34,9 +34,10 @@ where
namespace: Option<&'a str>, namespace: Option<&'a str>,
} }
impl<'a> impl<'a, 'b>
ElementBuilder< ElementBuilder<
'a, 'a,
'b,
bumpalo::collections::Vec<'a, Listener<'a>>, bumpalo::collections::Vec<'a, Listener<'a>>,
bumpalo::collections::Vec<'a, Attribute<'a>>, bumpalo::collections::Vec<'a, Attribute<'a>>,
bumpalo::collections::Vec<'a, VNode<'a>>, bumpalo::collections::Vec<'a, VNode<'a>>,
@@ -65,9 +66,9 @@ impl<'a>
/// let my_element_builder = ElementBuilder::new(&b, tag_name); /// let my_element_builder = ElementBuilder::new(&b, tag_name);
/// # fn flip_coin() -> bool { true } /// # 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 { // pub fn new<B>(ctx: &'a mut NodeCtx<'a>, tag_name: &'a str) -> Self {
let bump = ctx.bump(); let bump = ctx.bump;
ElementBuilder { ElementBuilder {
ctx, ctx,
key: NodeKey::NONE, 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 where
Listeners: 'a + AsRef<[Listener<'a>]>, Listeners: 'a + AsRef<[Listener<'a>]>,
Attributes: 'a + AsRef<[Attribute<'a>]>, Attributes: 'a + AsRef<[Attribute<'a>]>,
@@ -114,7 +116,7 @@ where
/// .finish(); /// .finish();
/// ``` /// ```
#[inline] #[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 where
L: 'a + AsRef<[Listener<'a>]>, L: 'a + AsRef<[Listener<'a>]>,
{ {
@@ -153,7 +155,7 @@ where
/// .finish(); /// .finish();
/// ``` /// ```
#[inline] #[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 where
A: 'a + AsRef<[Attribute<'a>]>, A: 'a + AsRef<[Attribute<'a>]>,
{ {
@@ -192,7 +194,7 @@ where
/// .finish(); /// .finish();
/// ``` /// ```
#[inline] #[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 where
C: 'a + AsRef<[VNode<'a>]>, C: 'a + AsRef<[VNode<'a>]>,
{ {
@@ -290,17 +292,17 @@ where
/// ``` /// ```
#[inline] #[inline]
pub fn finish(self) -> VNode<'a> { 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 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 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(); let attributes: &'a [Attribute<'a>] = attributes.as_ref();
VNode::element( VNode::element(
self.ctx.bump(), self.ctx.bump,
self.key, self.key,
self.tag_name, self.tag_name,
listeners, listeners,
@@ -311,8 +313,8 @@ where
} }
} }
impl<'a, Attributes, Children> impl<'a, 'b, Attributes, Children>
ElementBuilder<'a, bumpalo::collections::Vec<'a, Listener<'a>>, Attributes, Children> ElementBuilder<'a, 'b, bumpalo::collections::Vec<'a, Listener<'a>>, Attributes, Children>
where where
Attributes: 'a + AsRef<[Attribute<'a>]>, Attributes: 'a + AsRef<[Attribute<'a>]>,
Children: 'a + AsRef<[VNode<'a>]>, Children: 'a + AsRef<[VNode<'a>]>,
@@ -355,8 +357,8 @@ where
} }
} }
impl<'a, Listeners, Children> impl<'a, 'b, Listeners, Children>
ElementBuilder<'a, Listeners, bumpalo::collections::Vec<'a, Attribute<'a>>, Children> ElementBuilder<'a, 'b, Listeners, bumpalo::collections::Vec<'a, Attribute<'a>>, Children>
where where
Listeners: 'a + AsRef<[Listener<'a>]>, Listeners: 'a + AsRef<[Listener<'a>]>,
Children: 'a + AsRef<[VNode<'a>]>, Children: 'a + AsRef<[VNode<'a>]>,
@@ -414,8 +416,8 @@ where
} }
} }
impl<'a, Listeners, Attributes> impl<'a, 'b, Listeners, Attributes>
ElementBuilder<'a, Listeners, Attributes, bumpalo::collections::Vec<'a, VNode<'a>>> ElementBuilder<'a, 'b, Listeners, Attributes, bumpalo::collections::Vec<'a, VNode<'a>>>
where where
Listeners: 'a + AsRef<[Listener<'a>]>, Listeners: 'a + AsRef<[Listener<'a>]>,
Attributes: 'a + AsRef<[Attribute<'a>]>, Attributes: 'a + AsRef<[Attribute<'a>]>,
+71 -37
View File
@@ -24,49 +24,90 @@ use bumpalo::Bump;
use crate::innerlude::{Listener, ScopeIdx}; use crate::innerlude::{Listener, ScopeIdx};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
/// The `Edit` represents a single modifcation of the renderer tree. /// The `Edit` represents a single modifcation of the renderer tree.
///
///
///
///
///
///
///
///
/// todo@ jon: allow serde to be optional /// todo@ jon: allow serde to be optional
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub enum Edit<'d> { pub enum Edit<'d> {
SetText { text: &'d str }, SetText {
text: &'d str,
},
RemoveSelfAndNextSiblings {}, RemoveSelfAndNextSiblings {},
ReplaceWith, ReplaceWith,
SetAttribute { name: &'d str, value: &'d str }, SetAttribute {
RemoveAttribute { name: &'d str }, name: &'d str,
PushReverseChild { n: u32 }, value: &'d str,
PopPushChild { n: u32 }, },
RemoveAttribute {
name: &'d str,
},
PushReverseChild {
n: u32,
},
PopPushChild {
n: u32,
},
Pop, Pop,
AppendChild, AppendChild,
CreateTextNode { text: &'d str }, CreateTextNode {
CreateElement { tag_name: &'d str }, text: &'d str,
NewEventListener { event_type: &'d str, s: ScopeIdx }, },
UpdateEventListener { event_type: &'d str, s: ScopeIdx }, CreateElement {
RemoveEventListener { event_type: &'d str }, tag_name: &'d str,
CreateElementNs { tag_name: &'d str, ns: &'d str }, },
SaveChildrenToTemporaries { temp: u32, start: u32, end: u32 },
PushChild { n: u32 }, CreateElementNs {
PushTemporary { temp: u32 }, tag_name: &'d str,
ns: &'d str,
},
SaveChildrenToTemporaries {
temp: u32,
start: u32,
end: u32,
},
PushChild {
n: u32,
},
PushTemporary {
temp: u32,
},
InsertBefore, InsertBefore,
PopPushReverseChild { n: u32 }, PopPushReverseChild {
RemoveChild { n: u32 }, n: u32,
SetClass { class_name: &'d str }, },
RemoveChild {
n: u32,
},
SetClass {
class_name: &'d str,
},
// push a known node on to the stack // 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 // 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 // Remove the current top of the stack from the known nodes
RemoveKnown, 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>>; 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) { pub fn new_event_listener(&mut self, event: &'a str, scope: ScopeIdx, id: usize) {
debug_assert!(self.traversal_is_committed()); debug_assert!(self.traversal_is_committed());
self.emitter.push(Edit::NewEventListener { self.emitter.push(Edit::NewListener { event, scope, id });
event_type: event,
s: scope,
});
// log::debug!("emit: new_event_listener({:?})", listener); // log::debug!("emit: new_event_listener({:?})", listener);
} }
@@ -332,16 +370,12 @@ impl<'a> EditMachine<'a> {
return; return;
} }
self.emitter.push(Edit::NewEventListener { self.emitter.push(Edit::NewListener { event, scope, id });
event_type: event,
s: scope,
});
} }
pub fn remove_event_listener(&mut self, event: &'a str) { pub fn remove_event_listener(&mut self, event: &'a str) {
debug_assert!(self.traversal_is_committed()); debug_assert!(self.traversal_is_committed());
self.emitter self.emitter.push(Edit::RemoveListener { event });
.push(Edit::RemoveEventListener { event_type: event });
// debug!("emit: remove_event_listener({:?})", event); // debug!("emit: remove_event_listener({:?})", event);
} }
+8 -4
View File
@@ -277,11 +277,15 @@ mod tests {
use crate::prelude::format_args_f; use crate::prelude::format_args_f;
static ListenerTest: FC<()> = |ctx, props| { static ListenerTest: FC<()> = |ctx, props| {
ctx.render(html! { ctx.render(move |c| {
<div onclick={|_| println!("Hell owlrld")}> //
"hello" builder::ElementBuilder::new(c, "div").finish()
</div>
}) })
// ctx.render(html! {
// <div onclick={|_| println!("Hell owlrld")}>
// "hello"
// </div>
// })
}; };
#[test] #[test]
+10 -9
View File
@@ -15,15 +15,16 @@ fn main() {
static App: FC<()> = |ctx, _| { static App: FC<()> = |ctx, _| {
log::info!("Ran component"); log::info!("Ran component");
use dioxus::builder::*; use dioxus::builder::*;
ctx.render(|b| { todo!()
div(b) // ctx.render(|b| {
.child(text("hello")) // div(b)
.listeners([on(b, "click", |_| { // .child(text("hello"))
// // .listeners([on(b, "click", |_| {
log::info!("button1 clicked!"); // //
})]) // log::info!("button1 clicked!");
.finish() // })])
}) // .finish()
// })
// ctx.render(html! { // ctx.render(html! {
// <div onclick={move |_| log::info!("button1 clicked!")}> // <div onclick={move |_| log::info!("button1 clicked!")}>
// "Hello" // "Hello"
+27 -22
View File
@@ -1,6 +1,10 @@
use std::{borrow::Borrow, fmt::Debug, sync::Arc}; 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 fxhash::FxHashMap;
use log::debug; use log::debug;
use wasm_bindgen::{closure::Closure, JsCast}; 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) { if let Some(entry) = self.listeners.get_mut(event) {
entry.0 += 1; entry.0 += 1;
} else { } else {
@@ -75,15 +79,15 @@ impl EventDelegater {
let typ = event.type_(); let typ = event.type_();
let gi_id = target let gi_id: Option<usize> = target
.get_attribute(&format!("dioxus-giid-{}", typ)) .get_attribute(&format!("dioxus-giid-{}", typ))
.and_then(|v| v.parse().ok()); .and_then(|v| v.parse().ok());
let gi_gen = target let gi_gen: Option<u64> = target
.get_attribute(&format!("dioxus-gigen-{}", typ)) .get_attribute(&format!("dioxus-gigen-{}", typ))
.and_then(|v| v.parse().ok()); .and_then(|v| v.parse().ok());
let li_idx = target let li_idx: Option<usize> = target
.get_attribute(&format!("dioxus-lidx-{}", typ)) .get_attribute(&format!("dioxus-lidx-{}", typ))
.and_then(|v| v.parse().ok()); .and_then(|v| v.parse().ok());
@@ -91,11 +95,8 @@ impl EventDelegater {
// Call the trigger // Call the trigger
trigger.0.as_ref()(EventTrigger::new( trigger.0.as_ref()(EventTrigger::new(
virtual_event_from_websys_event(event), virtual_event_from_websys_event(event),
CbIdx { scope,
gi_gen, li_idx,
gi_id,
listener_idx: li_idx,
},
)); ));
} }
}) as Box<dyn FnMut(&Event)>); }) as Box<dyn FnMut(&Event)>);
@@ -342,7 +343,7 @@ impl PatchMachine {
} }
// 11 // 11
Edit::NewEventListener { event_type, idx } => { Edit::NewListener { event, id, scope } => {
// attach the correct attributes to the element // attach the correct attributes to the element
// these will be used by accessing the event's target // these will be used by accessing the event's target
// This ensures we only ever have one handler attached to the root, but decide // 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); // debug!("adding attributes: {}, {}", a, b);
let CbIdx { // let CbIdx {
gi_id, // gi_id,
gi_gen, // gi_gen,
listener_idx: lidx, // listener_idx: lidx,
} = idx; // } = 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(); .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(); .unwrap();
el.set_attribute(&format!("dioxus-lidx-{}", event_type), &lidx.to_string()) el.set_attribute(&format!("dioxus-lidx-{}", event), &id.to_string())
.unwrap(); .unwrap();
self.events.add_listener(event_type, idx); self.events.add_listener(event, scope);
} }
// 12 // 12
Edit::UpdateEventListener { event_type, idx } => { Edit::UpdateListener { event, scope, id } => {
// update our internal mapping, and then modify the attribute // update our internal mapping, and then modify the attribute
if let Some(el) = self.stack.top().dyn_ref::<Element>() { if let Some(el) = self.stack.top().dyn_ref::<Element>() {
@@ -391,7 +393,7 @@ impl PatchMachine {
} }
// 13 // 13
Edit::RemoveEventListener { event_type } => { Edit::RemoveListener { event: event_type } => {
if let Some(el) = self.stack.top().dyn_ref::<Element>() { if let Some(el) = self.stack.top().dyn_ref::<Element>() {
// el.remove_event_listener_with_callback( // el.remove_event_listener_with_callback(
// event_type, // event_type,
@@ -474,6 +476,9 @@ impl PatchMachine {
el.set_class_name(class_name); el.set_class_name(class_name);
} }
} }
Edit::TraverseToKnown { node } => {}
Edit::MakeKnown { node } => {}
Edit::RemoveKnown => {}
} }
} }