Explorar el Código

Feat: listeners now have scope information

Jonathan Kelley hace 4 años
padre
commit
fcd68e61d2

+ 1 - 1
packages/core-macro/src/htm.rs

@@ -149,7 +149,7 @@ impl ToTokens for ToToksCtx<&Element> {
         // let ctx = self.ctx;
         // let ctx = self.ctx;
         let name = &self.inner.name;
         let name = &self.inner.name;
         tokens.append_all(quote! {
         tokens.append_all(quote! {
-            dioxus::builder::#name(bump)
+            dioxus::builder::ElementBuilder::new(ctx, "#name")
         });
         });
         for attr in self.inner.attrs.iter() {
         for attr in self.inner.attrs.iter() {
             self.recurse(attr).to_tokens(tokens);
             self.recurse(attr).to_tokens(tokens);

+ 1 - 1
packages/core-macro/src/rsxt.rs

@@ -146,7 +146,7 @@ impl ToTokens for ToToksCtx<&Element> {
         // // let ctx = self.ctx;
         // // let ctx = self.ctx;
         let name = &self.inner.name;
         let name = &self.inner.name;
         tokens.append_all(quote! {
         tokens.append_all(quote! {
-            dioxus::builder::#name(bump)
+            dioxus::builder::ElementBuilder::new(ctx, "#name")
         });
         });
         for attr in self.inner.attrs.iter() {
         for attr in self.inner.attrs.iter() {
             self.recurse(attr).to_tokens(tokens);
             self.recurse(attr).to_tokens(tokens);

+ 89 - 89
packages/core/examples/alternative.rs

@@ -1,93 +1,93 @@
-//! An alternative function syntax
-//!
+// //! An alternative function syntax
+// //!
 
 
-use bumpalo::Bump;
-use dioxus_core::prelude::VNode;
+// use bumpalo::Bump;
+// use dioxus_core::prelude::VNode;
 
 
 fn main() {}
 fn main() {}
 
 
-struct Context2<'a, P> {
-    _props: &'a P, // _p: PhantomData<&'a ()>,
-    rops: &'a P,   // _p: PhantomData<&'a ()>,
-}
-impl<'a, P> Context2<'a, P> {
-    fn render(self, _f: impl FnOnce(&'a Bump) -> VNode<'a>) -> DTree {
-        DTree {}
-    }
-
-    fn props(&self) -> &'a P {
-        todo!()
-    }
-
-    pub fn use_hook<'scope, InternalHookState: 'static, Output: 'a>(
-        &'scope self,
-        _initializer: impl FnOnce() -> InternalHookState,
-        _runner: impl FnOnce(&'a mut InternalHookState) -> Output,
-        _cleanup: impl FnOnce(InternalHookState),
-    ) -> Output {
-        todo!()
-    }
-}
-
-trait Properties {}
-
-struct DTree;
-// type FC2<'a, T: 'a> = fn(Context2<T>) -> DTree;
-fn virtual_child<'a, T: 'a>(_bump: &'a Bump, _props: T, _f: FC2<T>) -> VNode<'a> {
-    todo!()
-}
-
-struct Props {
-    c: String,
-}
-
-fn Example(ctx: Context2<Props>) -> DTree {
-    let val = use_state(&ctx, || String::from("asd"));
-    let props = ctx.props();
-
-    ctx.render(move |b| {
-        dioxus_core::nodebuilder::div(b)
-            .child(dioxus_core::nodebuilder::text(props.c.as_str()))
-            .child(virtual_child(b, Props2 { a: val }, AltChild))
-            .finish()
-    })
-}
-
-// #[fc]
-fn Example2(ctx: Context2<()>, name: &str, _blah: &str) -> DTree {
-    let val = use_state(&ctx, || String::from("asd"));
-
-    ctx.render(move |b| {
-        dioxus_core::nodebuilder::div(b)
-            .child(dioxus_core::nodebuilder::text(name))
-            .child(virtual_child(b, Props2 { a: val }, AltChild))
-            .finish()
-    })
-}
-
-type FC2<'a, T> = fn(Context2<T>) -> DTree;
-
-// still works if you don't take any references in your props (ie, something copy or cloneable)
-static CHILD: FC2<Props2> = |_ctx: Context2<Props2>| {
-    //
-    todo!()
-};
-
-struct Props2<'a> {
-    a: &'a String,
-}
-impl Properties for Props2<'_> {}
-
-fn AltChild(ctx: Context2<Props2>) -> DTree {
-    ctx.render(|_b| {
-        //
-        todo!()
-    })
-}
-
-fn use_state<'a, 'c, P, T: 'static, F: FnOnce() -> T>(
-    _ctx: &'_ Context2<'a, P>,
-    _initial_state_fn: F,
-) -> &'a T {
-    todo!()
-}
+// struct Context2<'a, P> {
+//     _props: &'a P, // _p: PhantomData<&'a ()>,
+//     rops: &'a P,   // _p: PhantomData<&'a ()>,
+// }
+// impl<'a, P> Context2<'a, P> {
+//     fn render(self, _f: impl FnOnce(&'a Bump) -> VNode<'a>) -> DTree {
+//         DTree {}
+//     }
+
+//     fn props(&self) -> &'a P {
+//         todo!()
+//     }
+
+//     pub fn use_hook<'scope, InternalHookState: 'static, Output: 'a>(
+//         &'scope self,
+//         _initializer: impl FnOnce() -> InternalHookState,
+//         _runner: impl FnOnce(&'a mut InternalHookState) -> Output,
+//         _cleanup: impl FnOnce(InternalHookState),
+//     ) -> Output {
+//         todo!()
+//     }
+// }
+
+// trait Properties {}
+
+// struct DTree;
+// // type FC2<'a, T: 'a> = fn(Context2<T>) -> DTree;
+// fn virtual_child<'a, T: 'a>(_bump: &'a Bump, _props: T, _f: FC2<T>) -> VNode<'a> {
+//     todo!()
+// }
+
+// struct Props {
+//     c: String,
+// }
+
+// fn Example(ctx: Context2<Props>) -> DTree {
+//     let val = use_state(&ctx, || String::from("asd"));
+//     let props = ctx.props();
+
+//     ctx.render(move |b| {
+//         dioxus_core::nodebuilder::div(b)
+//             .child(dioxus_core::nodebuilder::text(props.c.as_str()))
+//             .child(virtual_child(b, Props2 { a: val }, AltChild))
+//             .finish()
+//     })
+// }
+
+// // #[fc]
+// fn Example2(ctx: Context2<()>, name: &str, _blah: &str) -> DTree {
+//     let val = use_state(&ctx, || String::from("asd"));
+
+//     ctx.render(move |ctx| {
+//         dioxus_core::builder::ElementBuilder::new(b, "div")
+//             .child(dioxus_core::nodebuilder::text(name))
+//             .child(virtual_child(b, Props2 { a: val }, AltChild))
+//             .finish()
+//     })
+// }
+
+// type FC2<'a, T> = fn(Context2<T>) -> DTree;
+
+// // still works if you don't take any references in your props (ie, something copy or cloneable)
+// static CHILD: FC2<Props2> = |_ctx: Context2<Props2>| {
+//     //
+//     todo!()
+// };
+
+// struct Props2<'a> {
+//     a: &'a String,
+// }
+// impl Properties for Props2<'_> {}
+
+// fn AltChild(ctx: Context2<Props2>) -> DTree {
+//     ctx.render(|_b| {
+//         //
+//         todo!()
+//     })
+// }
+
+// fn use_state<'a, 'c, P, T: 'static, F: FnOnce() -> T>(
+//     _ctx: &'_ Context2<'a, P>,
+//     _initial_state_fn: F,
+// ) -> &'a T {
+//     todo!()
+// }

+ 2 - 2
packages/core/examples/borrowed.rs

@@ -22,12 +22,12 @@ fn app(ctx: Context, props: &Props) -> DomTree {
     let (f, setter) = use_state(&ctx, || 0);
     let (f, setter) = use_state(&ctx, || 0);
 
 
     ctx.render(move |b| {
     ctx.render(move |b| {
-        let mut root = builder::div(b);
+        let mut root = builder::ElementBuilder::new(b, "div");
         for child in &props.items {
         for child in &props.items {
             // notice that the child directly borrows from our vec
             // notice that the child directly borrows from our vec
             // this makes lists very fast (simply views reusing lifetimes)
             // this makes lists very fast (simply views reusing lifetimes)
             root = root.child(builder::virtual_child(
             root = root.child(builder::virtual_child(
-                b,
+                b.bump,
                 ChildProps {
                 ChildProps {
                     item: child,
                     item: child,
                     item_handler: setter,
                     item_handler: setter,

+ 1 - 2
packages/core/examples/contextapi.rs

@@ -1,4 +1,3 @@
-use builder::button;
 use dioxus_core::prelude::*;
 use dioxus_core::prelude::*;
 
 
 fn main() {}
 fn main() {}
@@ -15,7 +14,7 @@ static Example: FC<Props> = |ctx, props| {
     let value = ctx.use_context(|c: &SomeContext| c.items.last().unwrap());
     let value = ctx.use_context(|c: &SomeContext| c.items.last().unwrap());
 
 
     ctx.render(move |bump| {
     ctx.render(move |bump| {
-        button(bump)
+        builder::ElementBuilder::new(bump, "button")
             .on("click", move |_| {
             .on("click", move |_| {
                 println!("Value is {}", props.name);
                 println!("Value is {}", props.name);
                 println!("Value is {}", value.as_str());
                 println!("Value is {}", value.as_str());

+ 1 - 1
packages/core/examples/nested.rs

@@ -13,7 +13,7 @@ static Header: FC<()> = |ctx, props| {
     let handler1 = move || println!("Value is {}", inner.current());
     let handler1 = move || println!("Value is {}", inner.current());
 
 
     ctx.render(|bump| {
     ctx.render(|bump| {
-        builder::div(bump)
+        builder::ElementBuilder::new(bump, "div")
             .child(VNode::Component(VComponent::new(
             .child(VNode::Component(VComponent::new(
                 Bottom,
                 Bottom,
                 //
                 //

+ 589 - 0
packages/core/old/builderconstructors.rs

@@ -0,0 +1,589 @@
+// we don't want to necessarily adhere to the spec for dioxus core
+// 3rd party libs can implement their own builders if they want
+
+// macro_rules! builder_constructors {
+//     ( $(
+//         $(#[$attr:meta])*
+//         $name:ident;
+//     )* ) => {
+//         $(
+//             $(#[$attr])*
+//             #[inline]
+//             pub fn $name<'a, B>(
+//                 bump: B,
+//             ) -> ElementBuilder<
+//                 'a,
+//                 bumpalo::collections::Vec<'a, Listener<'a>>,
+//                 bumpalo::collections::Vec<'a, Attribute<'a>>,
+//                 bumpalo::collections::Vec<'a, VNode<'a>>,
+//             >
+//             where
+//                 B: Into<&'a Bump>
+//             {
+//                 ElementBuilder::new(bump, stringify!($name))
+//             }
+//         )*
+//     };
+//     ( $(
+//         $(#[$attr:meta])*
+//         $name:ident <> $namespace:tt;
+//     )* ) => {
+//         $(
+//             $(#[$attr])*
+//             #[inline]
+//             pub fn $name<'a>(
+//                 bump: &'a Bump,
+//             ) -> ElementBuilder<
+//                 'a,
+//                 bumpalo::collections::Vec<'a, Listener<'a>>,
+//                 bumpalo::collections::Vec<'a, Attribute<'a>>,
+//                 bumpalo::collections::Vec<'a, VNode<'a>>,
+//             > {
+//                 let builder = ElementBuilder::new(bump, stringify!($name));
+//                 builder.namespace(Some($namespace))
+//             }
+//         )*
+//     }
+// }
+
+// // Organized in the same order as
+// // https://developer.mozilla.org/en-US/docs/Web/HTML/Element
+// //
+// // Does not include obsolete elements.
+// builder_constructors! {
+//     // Document metadata
+
+//     /// Build a
+//     /// [`<base>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base)
+//     /// element.
+//     base;
+//     /// Build a
+//     /// [`<head>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head)
+//     /// element.
+//     head;
+//     /// Build a
+//     /// [`<link>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link)
+//     /// element.
+//     link;
+//     /// Build a
+//     /// [`<meta>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta)
+//     /// element.
+//     meta;
+//     /// Build a
+//     /// [`<style>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/style)
+//     /// element.
+//     style;
+//     /// Build a
+//     /// [`<title>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/title)
+//     /// element.
+//     title;
+
+//     // Sectioning root
+
+//     /// Build a
+//     /// [`<body>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/body)
+//     /// element.
+//     body;
+
+//     // Content sectioning
+
+//     /// Build a
+//     /// [`<address>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/address)
+//     /// element.
+//     address;
+//     /// Build a
+//     /// [`<article>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/article)
+//     /// element.
+//     article;
+//     /// Build a
+//     /// [`<aside>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/aside)
+//     /// element.
+//     aside;
+//     /// Build a
+//     /// [`<footer>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/footer)
+//     /// element.
+//     footer;
+//     /// Build a
+//     /// [`<header>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/header)
+//     /// element.
+//     header;
+//     /// Build a
+//     /// [`<h1>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h1)
+//     /// element.
+//     h1;
+//     /// Build a
+//     /// [`<h2>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h2)
+//     /// element.
+//     h2;
+//     /// Build a
+//     /// [`<h3>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h3)
+//     /// element.
+//     h3;
+//     /// Build a
+//     /// [`<h4>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h4)
+//     /// element.
+//     h4;
+//     /// Build a
+//     /// [`<h5>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h5)
+//     /// element.
+//     h5;
+//     /// Build a
+//     /// [`<h6>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h6)
+//     /// element.
+//     h6;
+//     /// Build a
+//     /// [`<hgroup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hgroup)
+//     /// element.
+//     hgroup;
+//     /// Build a
+//     /// [`<main>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/main)
+//     /// element.
+//     main;
+//     /// Build a
+//     /// [`<nav>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/nav)
+//     /// element.
+//     nav;
+//     /// Build a
+//     /// [`<section>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/section)
+//     /// element.
+//     section;
+
+//     // Text content
+
+//     /// Build a
+//     /// [`<blockquote>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote)
+//     /// element.
+//     blockquote;
+//     /// Build a
+//     /// [`<dd>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dd)
+//     /// element.
+//     dd;
+//     /// Build a
+//     /// [`<div>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div)
+//     /// element.
+//     div;
+//     /// Build a
+//     /// [`<dl>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl)
+//     /// element.
+//     dl;
+//     /// Build a
+//     /// [`<dt>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dt)
+//     /// element.
+//     dt;
+//     /// Build a
+//     /// [`<figcaption>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figcaption)
+//     /// element.
+//     figcaption;
+//     /// Build a
+//     /// [`<figure>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figure)
+//     /// element.
+//     figure;
+//     /// Build a
+//     /// [`<hr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hr)
+//     /// element.
+//     hr;
+//     /// Build a
+//     /// [`<li>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/li)
+//     /// element.
+//     li;
+//     /// Build a
+//     /// [`<ol>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ol)
+//     /// element.
+//     ol;
+//     /// Build a
+//     /// [`<p>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/p)
+//     /// element.
+//     p;
+//     /// Build a
+//     /// [`<pre>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/pre)
+//     /// element.
+//     pre;
+//     /// Build a
+//     /// [`<ul>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ul)
+//     /// element.
+//     ul;
+
+//     // Inline text semantics
+
+//     /// Build a
+//     /// [`<a>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a)
+//     /// element.
+//     a;
+//     /// Build a
+//     /// [`<abbr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/abbr)
+//     /// element.
+//     abbr;
+//     /// Build a
+//     /// [`<b>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/b)
+//     /// element.
+//     b;
+//     /// Build a
+//     /// [`<bdi>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdi)
+//     /// element.
+//     bdi;
+//     /// Build a
+//     /// [`<bdo>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdo)
+//     /// element.
+//     bdo;
+//     /// Build a
+//     /// [`<br>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/br)
+//     /// element.
+//     br;
+//     /// Build a
+//     /// [`<cite>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/cite)
+//     /// element.
+//     cite;
+//     /// Build a
+//     /// [`<code>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/code)
+//     /// element.
+//     code;
+//     /// Build a
+//     /// [`<data>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/data)
+//     /// element.
+//     data;
+//     /// Build a
+//     /// [`<dfn>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dfn)
+//     /// element.
+//     dfn;
+//     /// Build a
+//     /// [`<em>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/em)
+//     /// element.
+//     em;
+//     /// Build a
+//     /// [`<i>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/i)
+//     /// element.
+//     i;
+//     /// Build a
+//     /// [`<kbd>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/kbd)
+//     /// element.
+//     kbd;
+//     /// Build a
+//     /// [`<mark>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/mark)
+//     /// element.
+//     mark;
+//     /// Build a
+//     /// [`<q>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/q)
+//     /// element.
+//     q;
+//     /// Build a
+//     /// [`<rb>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rb)
+//     /// element.
+//     rb;
+//     /// Build a
+//     /// [`<rp>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rp)
+//     /// element.
+//     rp;
+//     /// Build a
+//     /// [`<rt>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rt)
+//     /// element.
+//     rt;
+//     /// Build a
+//     /// [`<rtc>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rtc)
+//     /// element.
+//     rtc;
+//     /// Build a
+//     /// [`<ruby>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ruby)
+//     /// element.
+//     ruby;
+//     /// Build a
+//     /// [`<s>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/s)
+//     /// element.
+//     s;
+//     /// Build a
+//     /// [`<samp>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/samp)
+//     /// element.
+//     samp;
+//     /// Build a
+//     /// [`<small>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/small)
+//     /// element.
+//     small;
+//     /// Build a
+//     /// [`<span>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/span)
+//     /// element.
+//     span;
+//     /// Build a
+//     /// [`<strong>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/strong)
+//     /// element.
+//     strong;
+//     /// Build a
+//     /// [`<sub>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sub)
+//     /// element.
+//     sub;
+//     /// Build a
+//     /// [`<sup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sup)
+//     /// element.
+//     sup;
+//     /// Build a
+//     /// [`<time>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time)
+//     /// element.
+//     time;
+//     /// Build a
+//     /// [`<u>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/u)
+//     /// element.
+//     u;
+//     /// Build a
+//     /// [`<var>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/var)
+//     /// element.
+//     var;
+//     /// Build a
+//     /// [`<wbr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/wbr)
+//     /// element.
+//     wbr;
+
+//     // Image and multimedia
+
+//     /// Build a
+//     /// [`<area>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/area)
+//     /// element.
+//     area;
+//     /// Build a
+//     /// [`<audio>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio)
+//     /// element.
+//     audio;
+//     /// Build a
+//     /// [`<img>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img)
+//     /// element.
+//     img;
+//     /// Build a
+//     /// [`<map>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/map)
+//     /// element.
+//     map;
+//     /// Build a
+//     /// [`<track>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/track)
+//     /// element.
+//     track;
+//     /// Build a
+//     /// [`<video>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video)
+//     /// element.
+//     video;
+
+//     // Embedded content
+
+//     /// Build a
+//     /// [`<embed>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/embed)
+//     /// element.
+//     embed;
+//     /// Build a
+//     /// [`<iframe>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe)
+//     /// element.
+//     iframe;
+//     /// Build a
+//     /// [`<object>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/object)
+//     /// element.
+//     object;
+//     /// Build a
+//     /// [`<param>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/param)
+//     /// element.
+//     param;
+//     /// Build a
+//     /// [`<picture>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture)
+//     /// element.
+//     picture;
+//     /// Build a
+//     /// [`<source>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source)
+//     /// element.
+//     source;
+
+//     // Scripting
+
+//     /// Build a
+//     /// [`<canvas>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas)
+//     /// element.
+//     canvas;
+//     /// Build a
+//     /// [`<noscript>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/noscript)
+//     /// element.
+//     noscript;
+//     /// Build a
+//     /// [`<script>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script)
+//     /// element.
+//     script;
+
+//     // Demarcating edits
+
+//     /// Build a
+//     /// [`<del>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/del)
+//     /// element.
+//     del;
+//     /// Build a
+//     /// [`<ins>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ins)
+//     /// element.
+//     ins;
+
+//     // Table content
+
+//     /// Build a
+//     /// [`<caption>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/caption)
+//     /// element.
+//     caption;
+//     /// Build a
+//     /// [`<col>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/col)
+//     /// element.
+//     col;
+//     /// Build a
+//     /// [`<colgroup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/colgroup)
+//     /// element.
+//     colgroup;
+//     /// Build a
+//     /// [`<table>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table)
+//     /// element.
+//     table;
+//     /// Build a
+//     /// [`<tbody>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tbody)
+//     /// element.
+//     tbody;
+//     /// Build a
+//     /// [`<td>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td)
+//     /// element.
+//     td;
+//     /// Build a
+//     /// [`<tfoot>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tfoot)
+//     /// element.
+//     tfoot;
+//     /// Build a
+//     /// [`<th>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/th)
+//     /// element.
+//     th;
+//     /// Build a
+//     /// [`<thead>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/thead)
+//     /// element.
+//     thead;
+//     /// Build a
+//     /// [`<tr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tr)
+//     /// element.
+//     tr;
+
+//     // Forms
+
+//     /// Build a
+//     /// [`<button>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button)
+//     /// element.
+//     button;
+//     /// Build a
+//     /// [`<datalist>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist)
+//     /// element.
+//     datalist;
+//     /// Build a
+//     /// [`<fieldset>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset)
+//     /// element.
+//     fieldset;
+//     /// Build a
+//     /// [`<form>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form)
+//     /// element.
+//     form;
+//     /// Build a
+//     /// [`<input>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input)
+//     /// element.
+//     input;
+//     /// Build a
+//     /// [`<label>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label)
+//     /// element.
+//     label;
+//     /// Build a
+//     /// [`<legend>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/legend)
+//     /// element.
+//     legend;
+//     /// Build a
+//     /// [`<meter>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meter)
+//     /// element.
+//     meter;
+//     /// Build a
+//     /// [`<optgroup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup)
+//     /// element.
+//     optgroup;
+//     /// Build a
+//     /// [`<option>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
+//     /// element.
+//     option;
+//     /// Build a
+//     /// [`<output>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/output)
+//     /// element.
+//     output;
+//     /// Build a
+//     /// [`<progress>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress)
+//     /// element.
+//     progress;
+//     /// Build a
+//     /// [`<select>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select)
+//     /// element.
+//     select;
+//     /// Build a
+//     /// [`<textarea>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea)
+//     /// element.
+//     textarea;
+
+//     // Interactive elements
+
+//     /// Build a
+//     /// [`<details>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details)
+//     /// element.
+//     details;
+//     /// Build a
+//     /// [`<dialog>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog)
+//     /// element.
+//     dialog;
+//     /// Build a
+//     /// [`<menu>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/menu)
+//     /// element.
+//     menu;
+//     /// Build a
+//     /// [`<menuitem>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/menuitem)
+//     /// element.
+//     menuitem;
+//     /// Build a
+//     /// [`<summary>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary)
+//     /// element.
+//     summary;
+
+//     // Web components
+
+//     /// Build a
+//     /// [`<slot>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot)
+//     /// element.
+//     slot;
+//     /// Build a
+//     /// [`<template>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template)
+//     /// element.
+//     template;
+// }
+
+// builder_constructors! {
+//     // SVG components
+
+//     /// Build a
+//     /// [`<svg>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/svg)
+//     /// element.
+//     svg <> "http://www.w3.org/2000/svg" ;
+//     /// Build a
+//     /// [`<path>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/path)
+//     /// element.
+//     path <> "http://www.w3.org/2000/svg";
+//     /// Build a
+//     /// [`<circle>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/circle)
+//     /// element.
+//     circle <>  "http://www.w3.org/2000/svg";
+//     /// Build a
+//     /// [`<ellipse>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/ellipse)
+//     /// element.
+//     ellipse <> "http://www.w3.org/2000/svg";
+//     /// Build a
+//     /// [`<line>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/line)
+//     /// element.
+//     line <> "http://www.w3.org/2000/svg";
+//     /// Build a
+//     /// [`<polygon>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/polygon)
+//     /// element.
+//     polygon <> "http://www.w3.org/2000/svg";
+//     /// Build a
+//     /// [`<polyline>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/polyline)
+//     /// element.
+//     polyline <> "http://www.w3.org/2000/svg";
+//     /// Build a
+//     /// [`<rect>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/rect)
+//     /// element.
+//     rect <> "http://www.w3.org/2000/svg";
+//     /// Build a
+//     /// [`<image>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/image)
+//     /// element.
+//     image <> "http://www.w3.org/2000/svg";
+// }

+ 1 - 0
packages/core/src/component.rs

@@ -48,6 +48,7 @@ mod tests {
 
 
         ctx.render(html! {
         ctx.render(html! {
             <div>
             <div>
+
             </div>
             </div>
         })
         })
     };
     };

+ 17 - 7
packages/core/src/context.rs

@@ -31,6 +31,8 @@ use std::{
 pub struct Context<'src> {
 pub struct Context<'src> {
     pub idx: AtomicUsize,
     pub idx: AtomicUsize,
 
 
+    pub scope: ScopeIdx,
+
     // Borrowed from scope
     // Borrowed from scope
     pub(crate) arena: &'src typed_arena::Arena<Hook>,
     pub(crate) arena: &'src typed_arena::Arena<Hook>,
     pub(crate) hooks: &'src RefCell<Vec<*mut Hook>>,
     pub(crate) hooks: &'src RefCell<Vec<*mut Hook>>,
@@ -76,12 +78,17 @@ impl<'a> Context<'a> {
     ///     ctx.render(lazy_tree)
     ///     ctx.render(lazy_tree)
     /// }
     /// }
     ///```
     ///```
-    pub fn render(self, lazy_nodes: impl FnOnce(NodeCtx<'a>) -> VNode<'a> + 'a) -> DomTree {
-        let ctx = NodeCtx { bump: self.bump };
-        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);
+    pub fn render(self, lazy_nodes: impl FnOnce(&'a 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);
+
+        // let unsafe_nodes = unsafe { std::mem::transmute::<VNode<'a>, VNode<'static>>(safe_nodes) };
+        // self.final_nodes.deref().borrow_mut().replace(unsafe_nodes);
         DomTree {}
         DomTree {}
     }
     }
 
 
@@ -100,8 +107,11 @@ impl<'a> Context<'a> {
 
 
 // NodeCtx is used to build VNodes in the component's memory space.
 // NodeCtx is used to build VNodes in the component's memory space.
 // This struct adds metadata to the final DomTree about listeners, attributes, and children
 // This struct adds metadata to the final DomTree about listeners, attributes, and children
+#[derive(Debug, Clone)]
 pub struct NodeCtx<'a> {
 pub struct NodeCtx<'a> {
-    bump: &'a Bump,
+    pub bump: &'a Bump,
+    pub idx: RefCell<usize>,
+    pub scope: ScopeIdx,
 }
 }
 
 
 impl NodeCtx<'_> {
 impl NodeCtx<'_> {

+ 20 - 97
packages/core/src/diff.rs

@@ -78,12 +78,6 @@ impl<'a> DiffMachine<'a> {
         new: &VNode<'a>,
         new: &VNode<'a>,
         // scope: Option<generational_arena::Index>,
         // scope: Option<generational_arena::Index>,
     ) {
     ) {
-        log::debug!("old {:#?}", old);
-        log::debug!("new {:#?}", new);
-
-        // Set it while diffing
-        // Reset it when finished diffing
-        // self.current_idx = scope;
         /*
         /*
         For each valid case, we "commit traversal", meaning we save this current position in the tree.
         For each valid case, we "commit traversal", meaning we save this current position in the tree.
         Then, we diff and queue an edit event (via chagelist). s single trees - when components show up, we save that traversal and then re-enter later.
         Then, we diff and queue an edit event (via chagelist). s single trees - when components show up, we save that traversal and then re-enter later.
@@ -98,7 +92,6 @@ impl<'a> DiffMachine<'a> {
                 }
                 }
             }
             }
 
 
-            // Definitely different, need to commit update
             (VNode::Text(_), VNode::Element(_)) => {
             (VNode::Text(_), VNode::Element(_)) => {
                 // TODO: Hook up the events properly
                 // TODO: Hook up the events properly
                 // todo!("Hook up events registry");
                 // todo!("Hook up events registry");
@@ -109,112 +102,37 @@ impl<'a> DiffMachine<'a> {
                 self.change_list.replace_with();
                 self.change_list.replace_with();
             }
             }
 
 
-            // Definitely different, need to commit update
             (VNode::Element(_), VNode::Text(_)) => {
             (VNode::Element(_), VNode::Text(_)) => {
                 self.change_list.commit_traversal();
                 self.change_list.commit_traversal();
                 self.create(new);
                 self.create(new);
-
-                // create(cached_set, self.change_list, registry, new, cached_roots);
-                // Note: text nodes cannot have event listeners, so we don't need to
-                // remove the old node's listeners from our registry her.
                 self.change_list.replace_with();
                 self.change_list.replace_with();
             }
             }
-            // compare elements
-            // if different, schedule different types of update
+
             (VNode::Element(eold), VNode::Element(enew)) => {
             (VNode::Element(eold), VNode::Element(enew)) => {
-                // log::debug!("elements are different");
                 // If the element type is completely different, the element needs to be re-rendered completely
                 // If the element type is completely different, the element needs to be re-rendered completely
                 if enew.tag_name != eold.tag_name || enew.namespace != eold.namespace {
                 if enew.tag_name != eold.tag_name || enew.namespace != eold.namespace {
                     self.change_list.commit_traversal();
                     self.change_list.commit_traversal();
-                    // create(cached_set, self.change_list, registry, new, cached_roots);
-                    // registry.remove_subtree(&old);
                     self.change_list.replace_with();
                     self.change_list.replace_with();
                     return;
                     return;
                 }
                 }
 
 
                 self.diff_listeners(eold.listeners, enew.listeners);
                 self.diff_listeners(eold.listeners, enew.listeners);
-
                 self.diff_attr(eold.attributes, enew.attributes, enew.namespace.is_some());
                 self.diff_attr(eold.attributes, enew.attributes, enew.namespace.is_some());
-
                 self.diff_children(eold.children, enew.children);
                 self.diff_children(eold.children, enew.children);
             }
             }
-            // No immediate change to dom. If props changed though, queue a "props changed" update
-            // However, mark these for a
+
             (VNode::Component(_), VNode::Component(_)) => {
             (VNode::Component(_), VNode::Component(_)) => {
                 todo!("Usage of component VNode not currently supported");
                 todo!("Usage of component VNode not currently supported");
-                //     // Both the new and old nodes are cached.
-                //     (&NodeKind::Cached(ref new), &NodeKind::Cached(ref old)) => {
-                //         cached_roots.insert(new.id);
-                //         if new.id == old.id {
-                //             // This is the same cached node, so nothing has changed!
-                //             return;
-                //         }
-                //         let (new, new_template) = cached_set.get(new.id);
-                //         let (old, old_template) = cached_set.get(old.id);
-                //         if new_template == old_template {
-                //             // If they are both using the same template, then just diff the
-                //             // subtrees.
-                //             diff(cached_set, change_list, registry, old, new, cached_roots);
-                //         } else {
-                //             // Otherwise, they are probably different enough that
-                //             // re-constructing the subtree from scratch should be faster.
-                //             // This doubly holds true if we have a new template.
-                //             change_list.commit_traversal();
-                //             create_and_replace(
-                //                 cached_set,
-                //                 change_list,
-                //                 registry,
-                //                 new_template,
-                //                 old,
-                //                 new,
-                //                 cached_roots,
-                //             );
-                //         }
-                //     }
-                // queue a lifecycle event.
-                // no change
             }
             }
 
 
-            // A component has been birthed!
-            // Queue its arrival
             (_, VNode::Component(_)) => {
             (_, VNode::Component(_)) => {
                 todo!("Usage of component VNode not currently supported");
                 todo!("Usage of component VNode not currently supported");
-                //     // Old cached node and new non-cached node. Again, assume that they are
-                //     // probably pretty different and create the new non-cached node afresh.
-                //     (_, &NodeKind::Cached(_)) => {
-                //         change_list.commit_traversal();
-                //         create(cached_set, change_list, registry, new, cached_roots);
-                //         registry.remove_subtree(&old);
-                //         change_list.replace_with();
-                //     }
-                // }
             }
             }
 
 
-            // A component was removed :(
-            // Queue its removal
             (VNode::Component(_), _) => {
             (VNode::Component(_), _) => {
-                //     // New cached node when the old node was not cached. In this scenario,
-                //     // we assume that they are pretty different, and it isn't worth diffing
-                //     // the subtrees, so we just create the new cached node afresh.
-                //     (&NodeKind::Cached(ref c), _) => {
-                //         change_list.commit_traversal();
-                //         cached_roots.insert(c.id);
-                //         let (new, new_template) = cached_set.get(c.id);
-                //         create_and_replace(
-                //             cached_set,
-                //             change_list,
-                //             registry,
-                //             new_template,
-                //             old,
-                //             new,
-                //             cached_roots,
-                //         );
-                //     }
                 todo!("Usage of component VNode not currently supported");
                 todo!("Usage of component VNode not currently supported");
             }
             }
 
 
-            // A suspended component appeared!
-            // Don't do much, just wait
             (VNode::Suspended, _) | (_, VNode::Suspended) => {
             (VNode::Suspended, _) | (_, VNode::Suspended) => {
                 // (VNode::Element(_), VNode::Suspended) => {}
                 // (VNode::Element(_), VNode::Suspended) => {}
                 // (VNode::Text(_), VNode::Suspended) => {}
                 // (VNode::Text(_), VNode::Suspended) => {}
@@ -254,17 +172,19 @@ impl<'a> DiffMachine<'a> {
                 if new_l.event == old_l.event {
                 if new_l.event == old_l.event {
                     // if let Some(scope) = self.current_idx {
                     // if let Some(scope) = self.current_idx {
                     //     let cb = CbIdx::from_gi_index(scope, l_idx);
                     //     let cb = CbIdx::from_gi_index(scope, l_idx);
-                    self.change_list.update_event_listener(event_type, cb);
+                    self.change_list
+                        .update_event_listener(event_type, new_l.scope, new_l.id);
                     // }
                     // }
 
 
                     continue 'outer1;
                     continue 'outer1;
                 }
                 }
             }
             }
 
 
-            if let Some(scope) = self.current_idx {
-                let cb = CbIdx::from_gi_index(scope, l_idx);
-                self.change_list.new_event_listener(event_type, cb);
-            }
+            // if let Some(scope) = self.current_idx {
+            // let cb = CbIdx::from_gi_index(scope, l_idx);
+            self.change_list
+                .new_event_listener(event_type, new_l.scope, new_l.id);
+            // }
         }
         }
 
 
         'outer2: for old_l in old {
         'outer2: for old_l in old {
@@ -893,14 +813,17 @@ impl<'a> DiffMachine<'a> {
                 }
                 }
 
 
                 listeners.iter().enumerate().for_each(|(id, listener)| {
                 listeners.iter().enumerate().for_each(|(id, listener)| {
-                    if let Some(index) = self.current_idx {
-                        self.change_list
-                            .new_event_listener(listener.event, CbIdx::from_gi_index(index, id));
-                    } else {
-                        // Don't panic
-                        // Used for testing
-                        log::trace!("Failed to set listener, create was not called in the context of the virtual dom");
-                    }
+                    // if let Some(index) = self.current_idx {
+                    self.change_list.new_event_listener(
+                        listener.event,
+                        listener.scope,
+                        listener.id,
+                    );
+                    // } else {
+                    // Don't panic
+                    // Used for testing
+                    //     log::trace!("Failed to set listener, create was not called in the context of the virtual dom");
+                    // }
                 });
                 });
                 // for l in listeners {
                 // for l in listeners {
                 // unsafe {
                 // unsafe {

+ 51 - 631
packages/core/src/nodebuilder.rs

@@ -3,6 +3,7 @@
 use std::ops::Deref;
 use std::ops::Deref;
 
 
 use crate::{
 use crate::{
+    context::NodeCtx,
     events::VirtualEvent,
     events::VirtualEvent,
     innerlude::VComponent,
     innerlude::VComponent,
     nodes::{Attribute, Listener, NodeKey, VNode},
     nodes::{Attribute, Listener, NodeKey, VNode},
@@ -17,14 +18,14 @@ use bumpalo::Bump;
 /// Typically constructed with element-specific constructors, eg the `div`
 /// Typically constructed with element-specific constructors, eg the `div`
 /// 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(Clone, Debug)]
+#[derive(Debug)]
 pub struct ElementBuilder<'a, Listeners, Attributes, Children>
 pub struct ElementBuilder<'a, 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>]>,
 {
 {
-    bump: &'a Bump,
+    ctx: &'a NodeCtx<'a>,
     key: NodeKey,
     key: NodeKey,
     tag_name: &'a str,
     tag_name: &'a str,
     listeners: Listeners,
     listeners: Listeners,
@@ -64,13 +65,11 @@ 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<B>(bump: B, tag_name: &'a str) -> Self
-    where
-        B: Into<&'a Bump>,
-    {
-        let bump = bump.into();
+    pub fn new(ctx: &'a 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();
         ElementBuilder {
         ElementBuilder {
-            bump,
+            ctx,
             key: NodeKey::NONE,
             key: NodeKey::NONE,
             tag_name,
             tag_name,
             listeners: bumpalo::collections::Vec::new_in(bump),
             listeners: bumpalo::collections::Vec::new_in(bump),
@@ -120,7 +119,7 @@ where
         L: 'a + AsRef<[Listener<'a>]>,
         L: 'a + AsRef<[Listener<'a>]>,
     {
     {
         ElementBuilder {
         ElementBuilder {
-            bump: self.bump,
+            ctx: self.ctx,
             key: self.key,
             key: self.key,
             tag_name: self.tag_name,
             tag_name: self.tag_name,
             listeners,
             listeners,
@@ -159,7 +158,7 @@ where
         A: 'a + AsRef<[Attribute<'a>]>,
         A: 'a + AsRef<[Attribute<'a>]>,
     {
     {
         ElementBuilder {
         ElementBuilder {
-            bump: self.bump,
+            ctx: self.ctx,
             key: self.key,
             key: self.key,
             tag_name: self.tag_name,
             tag_name: self.tag_name,
             listeners: self.listeners,
             listeners: self.listeners,
@@ -198,7 +197,7 @@ where
         C: 'a + AsRef<[VNode<'a>]>,
         C: 'a + AsRef<[VNode<'a>]>,
     {
     {
         ElementBuilder {
         ElementBuilder {
-            bump: self.bump,
+            ctx: self.ctx,
             key: self.key,
             key: self.key,
             tag_name: self.tag_name,
             tag_name: self.tag_name,
             listeners: self.listeners,
             listeners: self.listeners,
@@ -225,7 +224,7 @@ where
     #[inline]
     #[inline]
     pub fn namespace(self, namespace: Option<&'a str>) -> Self {
     pub fn namespace(self, namespace: Option<&'a str>) -> Self {
         ElementBuilder {
         ElementBuilder {
-            bump: self.bump,
+            ctx: self.ctx,
             key: self.key,
             key: self.key,
             tag_name: self.tag_name,
             tag_name: self.tag_name,
             listeners: self.listeners,
             listeners: self.listeners,
@@ -291,17 +290,17 @@ where
     /// ```
     /// ```
     #[inline]
     #[inline]
     pub fn finish(self) -> VNode<'a> {
     pub fn finish(self) -> VNode<'a> {
-        let children: &'a Children = self.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.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.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.bump,
+            self.ctx.bump(),
             self.key,
             self.key,
             self.tag_name,
             self.tag_name,
             listeners,
             listeners,
@@ -340,10 +339,18 @@ where
     /// ```
     /// ```
     #[inline]
     #[inline]
     pub fn on(mut self, event: &'static str, callback: impl Fn(VirtualEvent) + 'a) -> Self {
     pub fn on(mut self, event: &'static str, callback: impl Fn(VirtualEvent) + 'a) -> Self {
+        // todo:
+        // increment listner id from nodectx ref
+        // add listener attrs here instead of later?
         self.listeners.push(Listener {
         self.listeners.push(Listener {
             event,
             event,
-            callback: self.bump.alloc(callback),
+            callback: self.ctx.bump.alloc(callback),
+            id: *self.ctx.idx.borrow(),
+            scope: self.ctx.scope,
         });
         });
+
+        // bump the context id forward
+        *self.ctx.idx.borrow_mut() += 1;
         self
         self
     }
     }
 }
 }
@@ -435,593 +442,6 @@ where
     }
     }
 }
 }
 
 
-macro_rules! builder_constructors {
-    ( $(
-        $(#[$attr:meta])*
-        $name:ident;
-    )* ) => {
-        $(
-            $(#[$attr])*
-            #[inline]
-            pub fn $name<'a, B>(
-                bump: B,
-            ) -> ElementBuilder<
-                'a,
-                bumpalo::collections::Vec<'a, Listener<'a>>,
-                bumpalo::collections::Vec<'a, Attribute<'a>>,
-                bumpalo::collections::Vec<'a, VNode<'a>>,
-            >
-            where
-                B: Into<&'a Bump>
-            {
-                ElementBuilder::new(bump, stringify!($name))
-            }
-        )*
-    };
-    ( $(
-        $(#[$attr:meta])*
-        $name:ident <> $namespace:tt;
-    )* ) => {
-        $(
-            $(#[$attr])*
-            #[inline]
-            pub fn $name<'a>(
-                bump: &'a Bump,
-            ) -> ElementBuilder<
-                'a,
-                bumpalo::collections::Vec<'a, Listener<'a>>,
-                bumpalo::collections::Vec<'a, Attribute<'a>>,
-                bumpalo::collections::Vec<'a, VNode<'a>>,
-            > {
-                let builder = ElementBuilder::new(bump, stringify!($name));
-                builder.namespace(Some($namespace))
-            }
-        )*
-    }
-}
-
-// Organized in the same order as
-// https://developer.mozilla.org/en-US/docs/Web/HTML/Element
-//
-// Does not include obsolete elements.
-builder_constructors! {
-    // Document metadata
-
-    /// Build a
-    /// [`<base>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base)
-    /// element.
-    base;
-    /// Build a
-    /// [`<head>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head)
-    /// element.
-    head;
-    /// Build a
-    /// [`<link>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link)
-    /// element.
-    link;
-    /// Build a
-    /// [`<meta>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta)
-    /// element.
-    meta;
-    /// Build a
-    /// [`<style>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/style)
-    /// element.
-    style;
-    /// Build a
-    /// [`<title>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/title)
-    /// element.
-    title;
-
-    // Sectioning root
-
-    /// Build a
-    /// [`<body>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/body)
-    /// element.
-    body;
-
-    // Content sectioning
-
-    /// Build a
-    /// [`<address>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/address)
-    /// element.
-    address;
-    /// Build a
-    /// [`<article>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/article)
-    /// element.
-    article;
-    /// Build a
-    /// [`<aside>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/aside)
-    /// element.
-    aside;
-    /// Build a
-    /// [`<footer>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/footer)
-    /// element.
-    footer;
-    /// Build a
-    /// [`<header>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/header)
-    /// element.
-    header;
-    /// Build a
-    /// [`<h1>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h1)
-    /// element.
-    h1;
-    /// Build a
-    /// [`<h2>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h2)
-    /// element.
-    h2;
-    /// Build a
-    /// [`<h3>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h3)
-    /// element.
-    h3;
-    /// Build a
-    /// [`<h4>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h4)
-    /// element.
-    h4;
-    /// Build a
-    /// [`<h5>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h5)
-    /// element.
-    h5;
-    /// Build a
-    /// [`<h6>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h6)
-    /// element.
-    h6;
-    /// Build a
-    /// [`<hgroup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hgroup)
-    /// element.
-    hgroup;
-    /// Build a
-    /// [`<main>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/main)
-    /// element.
-    main;
-    /// Build a
-    /// [`<nav>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/nav)
-    /// element.
-    nav;
-    /// Build a
-    /// [`<section>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/section)
-    /// element.
-    section;
-
-    // Text content
-
-    /// Build a
-    /// [`<blockquote>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote)
-    /// element.
-    blockquote;
-    /// Build a
-    /// [`<dd>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dd)
-    /// element.
-    dd;
-    /// Build a
-    /// [`<div>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div)
-    /// element.
-    div;
-    /// Build a
-    /// [`<dl>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl)
-    /// element.
-    dl;
-    /// Build a
-    /// [`<dt>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dt)
-    /// element.
-    dt;
-    /// Build a
-    /// [`<figcaption>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figcaption)
-    /// element.
-    figcaption;
-    /// Build a
-    /// [`<figure>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figure)
-    /// element.
-    figure;
-    /// Build a
-    /// [`<hr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hr)
-    /// element.
-    hr;
-    /// Build a
-    /// [`<li>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/li)
-    /// element.
-    li;
-    /// Build a
-    /// [`<ol>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ol)
-    /// element.
-    ol;
-    /// Build a
-    /// [`<p>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/p)
-    /// element.
-    p;
-    /// Build a
-    /// [`<pre>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/pre)
-    /// element.
-    pre;
-    /// Build a
-    /// [`<ul>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ul)
-    /// element.
-    ul;
-
-    // Inline text semantics
-
-    /// Build a
-    /// [`<a>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a)
-    /// element.
-    a;
-    /// Build a
-    /// [`<abbr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/abbr)
-    /// element.
-    abbr;
-    /// Build a
-    /// [`<b>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/b)
-    /// element.
-    b;
-    /// Build a
-    /// [`<bdi>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdi)
-    /// element.
-    bdi;
-    /// Build a
-    /// [`<bdo>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdo)
-    /// element.
-    bdo;
-    /// Build a
-    /// [`<br>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/br)
-    /// element.
-    br;
-    /// Build a
-    /// [`<cite>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/cite)
-    /// element.
-    cite;
-    /// Build a
-    /// [`<code>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/code)
-    /// element.
-    code;
-    /// Build a
-    /// [`<data>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/data)
-    /// element.
-    data;
-    /// Build a
-    /// [`<dfn>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dfn)
-    /// element.
-    dfn;
-    /// Build a
-    /// [`<em>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/em)
-    /// element.
-    em;
-    /// Build a
-    /// [`<i>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/i)
-    /// element.
-    i;
-    /// Build a
-    /// [`<kbd>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/kbd)
-    /// element.
-    kbd;
-    /// Build a
-    /// [`<mark>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/mark)
-    /// element.
-    mark;
-    /// Build a
-    /// [`<q>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/q)
-    /// element.
-    q;
-    /// Build a
-    /// [`<rb>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rb)
-    /// element.
-    rb;
-    /// Build a
-    /// [`<rp>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rp)
-    /// element.
-    rp;
-    /// Build a
-    /// [`<rt>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rt)
-    /// element.
-    rt;
-    /// Build a
-    /// [`<rtc>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rtc)
-    /// element.
-    rtc;
-    /// Build a
-    /// [`<ruby>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ruby)
-    /// element.
-    ruby;
-    /// Build a
-    /// [`<s>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/s)
-    /// element.
-    s;
-    /// Build a
-    /// [`<samp>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/samp)
-    /// element.
-    samp;
-    /// Build a
-    /// [`<small>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/small)
-    /// element.
-    small;
-    /// Build a
-    /// [`<span>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/span)
-    /// element.
-    span;
-    /// Build a
-    /// [`<strong>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/strong)
-    /// element.
-    strong;
-    /// Build a
-    /// [`<sub>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sub)
-    /// element.
-    sub;
-    /// Build a
-    /// [`<sup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sup)
-    /// element.
-    sup;
-    /// Build a
-    /// [`<time>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time)
-    /// element.
-    time;
-    /// Build a
-    /// [`<u>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/u)
-    /// element.
-    u;
-    /// Build a
-    /// [`<var>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/var)
-    /// element.
-    var;
-    /// Build a
-    /// [`<wbr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/wbr)
-    /// element.
-    wbr;
-
-    // Image and multimedia
-
-    /// Build a
-    /// [`<area>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/area)
-    /// element.
-    area;
-    /// Build a
-    /// [`<audio>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio)
-    /// element.
-    audio;
-    /// Build a
-    /// [`<img>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img)
-    /// element.
-    img;
-    /// Build a
-    /// [`<map>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/map)
-    /// element.
-    map;
-    /// Build a
-    /// [`<track>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/track)
-    /// element.
-    track;
-    /// Build a
-    /// [`<video>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video)
-    /// element.
-    video;
-
-    // Embedded content
-
-    /// Build a
-    /// [`<embed>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/embed)
-    /// element.
-    embed;
-    /// Build a
-    /// [`<iframe>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe)
-    /// element.
-    iframe;
-    /// Build a
-    /// [`<object>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/object)
-    /// element.
-    object;
-    /// Build a
-    /// [`<param>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/param)
-    /// element.
-    param;
-    /// Build a
-    /// [`<picture>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture)
-    /// element.
-    picture;
-    /// Build a
-    /// [`<source>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source)
-    /// element.
-    source;
-
-    // Scripting
-
-    /// Build a
-    /// [`<canvas>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas)
-    /// element.
-    canvas;
-    /// Build a
-    /// [`<noscript>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/noscript)
-    /// element.
-    noscript;
-    /// Build a
-    /// [`<script>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script)
-    /// element.
-    script;
-
-    // Demarcating edits
-
-    /// Build a
-    /// [`<del>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/del)
-    /// element.
-    del;
-    /// Build a
-    /// [`<ins>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ins)
-    /// element.
-    ins;
-
-    // Table content
-
-    /// Build a
-    /// [`<caption>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/caption)
-    /// element.
-    caption;
-    /// Build a
-    /// [`<col>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/col)
-    /// element.
-    col;
-    /// Build a
-    /// [`<colgroup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/colgroup)
-    /// element.
-    colgroup;
-    /// Build a
-    /// [`<table>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table)
-    /// element.
-    table;
-    /// Build a
-    /// [`<tbody>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tbody)
-    /// element.
-    tbody;
-    /// Build a
-    /// [`<td>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td)
-    /// element.
-    td;
-    /// Build a
-    /// [`<tfoot>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tfoot)
-    /// element.
-    tfoot;
-    /// Build a
-    /// [`<th>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/th)
-    /// element.
-    th;
-    /// Build a
-    /// [`<thead>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/thead)
-    /// element.
-    thead;
-    /// Build a
-    /// [`<tr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tr)
-    /// element.
-    tr;
-
-    // Forms
-
-    /// Build a
-    /// [`<button>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button)
-    /// element.
-    button;
-    /// Build a
-    /// [`<datalist>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist)
-    /// element.
-    datalist;
-    /// Build a
-    /// [`<fieldset>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset)
-    /// element.
-    fieldset;
-    /// Build a
-    /// [`<form>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form)
-    /// element.
-    form;
-    /// Build a
-    /// [`<input>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input)
-    /// element.
-    input;
-    /// Build a
-    /// [`<label>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label)
-    /// element.
-    label;
-    /// Build a
-    /// [`<legend>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/legend)
-    /// element.
-    legend;
-    /// Build a
-    /// [`<meter>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meter)
-    /// element.
-    meter;
-    /// Build a
-    /// [`<optgroup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup)
-    /// element.
-    optgroup;
-    /// Build a
-    /// [`<option>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
-    /// element.
-    option;
-    /// Build a
-    /// [`<output>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/output)
-    /// element.
-    output;
-    /// Build a
-    /// [`<progress>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress)
-    /// element.
-    progress;
-    /// Build a
-    /// [`<select>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select)
-    /// element.
-    select;
-    /// Build a
-    /// [`<textarea>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea)
-    /// element.
-    textarea;
-
-    // Interactive elements
-
-    /// Build a
-    /// [`<details>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details)
-    /// element.
-    details;
-    /// Build a
-    /// [`<dialog>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog)
-    /// element.
-    dialog;
-    /// Build a
-    /// [`<menu>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/menu)
-    /// element.
-    menu;
-    /// Build a
-    /// [`<menuitem>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/menuitem)
-    /// element.
-    menuitem;
-    /// Build a
-    /// [`<summary>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary)
-    /// element.
-    summary;
-
-    // Web components
-
-    /// Build a
-    /// [`<slot>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot)
-    /// element.
-    slot;
-    /// Build a
-    /// [`<template>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template)
-    /// element.
-    template;
-}
-
-builder_constructors! {
-    // SVG components
-
-    /// Build a
-    /// [`<svg>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/svg)
-    /// element.
-    svg <> "http://www.w3.org/2000/svg" ;
-    /// Build a
-    /// [`<path>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/path)
-    /// element.
-    path <> "http://www.w3.org/2000/svg";
-    /// Build a
-    /// [`<circle>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/circle)
-    /// element.
-    circle <>  "http://www.w3.org/2000/svg";
-    /// Build a
-    /// [`<ellipse>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/ellipse)
-    /// element.
-    ellipse <> "http://www.w3.org/2000/svg";
-    /// Build a
-    /// [`<line>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/line)
-    /// element.
-    line <> "http://www.w3.org/2000/svg";
-    /// Build a
-    /// [`<polygon>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/polygon)
-    /// element.
-    polygon <> "http://www.w3.org/2000/svg";
-    /// Build a
-    /// [`<polyline>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/polyline)
-    /// element.
-    polyline <> "http://www.w3.org/2000/svg";
-    /// Build a
-    /// [`<rect>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/rect)
-    /// element.
-    rect <> "http://www.w3.org/2000/svg";
-    /// Build a
-    /// [`<image>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/image)
-    /// element.
-    image <> "http://www.w3.org/2000/svg";
-}
-
 /// Construct a text VNode.
 /// Construct a text VNode.
 ///
 ///
 /// This is `dioxus`'s virtual DOM equivalent of `document.createTextVNode`.
 /// This is `dioxus`'s virtual DOM equivalent of `document.createTextVNode`.
@@ -1062,33 +482,33 @@ pub fn attr<'a>(name: &'static str, value: &'a str) -> Attribute<'a> {
     Attribute { name, value }
     Attribute { name, value }
 }
 }
 
 
-/// Create an event listener.
-///
-/// `event` is the type of event to listen for, e.g. `"click"`. The `callback`
-/// is the function that will be invoked when the event occurs.
-///
-/// # Example
-///
-/// ```no_run
-/// use dioxus::{builder::*, bumpalo::Bump};
-///
-/// let b = Bump::new();
-///
-/// let listener = on(&b, "click", |root, vdom, event| {
-///     // do something when a click happens...
-/// });
-/// ```
-pub fn on<'a, 'b>(
-    // pub fn on<'a, 'b, F: 'static>(
-    bump: &'a Bump,
-    event: &'static str,
-    callback: impl Fn(VirtualEvent) + 'a,
-) -> Listener<'a> {
-    Listener {
-        event,
-        callback: bump.alloc(callback),
-    }
-}
+// /// Create an event listener.
+// ///
+// /// `event` is the type of event to listen for, e.g. `"click"`. The `callback`
+// /// is the function that will be invoked when the event occurs.
+// ///
+// /// # Example
+// ///
+// /// ```no_run
+// /// use dioxus::{builder::*, bumpalo::Bump};
+// ///
+// /// let b = Bump::new();
+// ///
+// /// let listener = on(&b, "click", |root, vdom, event| {
+// ///     // do something when a click happens...
+// /// });
+// /// ```
+// pub fn on<'a, 'b>(
+//     // pub fn on<'a, 'b, F: 'static>(
+//     bump: &'a Bump,
+//     event: &'static str,
+//     callback: impl Fn(VirtualEvent) + 'a,
+// ) -> Listener<'a> {
+//     Listener {
+//         event,
+//         callback: bump.alloc(callback),
+//     }
+// }
 
 
 pub fn virtual_child<'a, T>(_bump: &'a Bump, _props: T, _f: crate::innerlude::FC<T>) -> VNode<'a> {
 pub fn virtual_child<'a, T>(_bump: &'a Bump, _props: T, _f: crate::innerlude::FC<T>) -> VNode<'a> {
     todo!()
     todo!()

+ 6 - 3
packages/core/src/nodes.rs

@@ -97,6 +97,8 @@ mod velement {
 
 
     // use crate::{events::VirtualEvent, innerlude::CbIdx};
     // use crate::{events::VirtualEvent, innerlude::CbIdx};
 
 
+    use crate::{events::VirtualEvent, innerlude::ScopeIdx};
+
     use super::*;
     use super::*;
     use std::fmt::Debug;
     use std::fmt::Debug;
 
 
@@ -182,7 +184,8 @@ mod velement {
 
 
     pub struct ListenerHandle {
     pub struct ListenerHandle {
         pub event: &'static str,
         pub event: &'static str,
-        pub idx: CbIdx,
+        pub scope: ScopeIdx,
+        pub id: usize,
     }
     }
 
 
     /// An event listener.
     /// An event listener.
@@ -190,8 +193,8 @@ mod velement {
         /// The type of event to listen for.
         /// The type of event to listen for.
         pub(crate) event: &'static str,
         pub(crate) event: &'static str,
 
 
-        // ref to the real listener
-        // pub(crate) id: u32,
+        pub scope: ScopeIdx,
+        pub id: usize,
 
 
         // pub(crate) _i: &'bump str,
         // pub(crate) _i: &'bump str,
         // #[serde(skip_serializing, skip_deserializing, default="")]
         // #[serde(skip_serializing, skip_deserializing, default="")]

+ 34 - 51
packages/core/src/patch.rs

@@ -58,7 +58,15 @@ pub enum Edit<'d> {
     PopPushReverseChild { n: u32 },
     PopPushReverseChild { n: u32 },
     RemoveChild { n: u32 },
     RemoveChild { n: u32 },
     SetClass { class_name: &'d str },
     SetClass { class_name: &'d str },
-    PushKnown { node: ScopeIdx },
+
+    // push a known node on to the stack
+    TraverseToKnown { node: ScopeIdx },
+
+    // Add the current top of the stack to the known nodes
+    MakeKnown { node: ScopeIdx },
+
+    // Remove the current top of the stack from the known nodes
+    RemoveKnown,
 }
 }
 
 
 pub type EditList<'src> = Vec<Edit<'src>>;
 pub type EditList<'src> = Vec<Edit<'src>>;
@@ -67,7 +75,6 @@ pub struct EditMachine<'src> {
     pub traversal: Traversal,
     pub traversal: Traversal,
     next_temporary: u32,
     next_temporary: u32,
     forcing_new_listeners: bool,
     forcing_new_listeners: bool,
-
     pub emitter: EditList<'src>,
     pub emitter: EditList<'src>,
 }
 }
 
 
@@ -80,8 +87,12 @@ impl<'b> EditMachine<'b> {
             emitter: EditList::default(),
             emitter: EditList::default(),
         }
         }
     }
     }
+}
 
 
-    /// Traversal methods.
+// ===================================
+//  Traversal Methods
+// ===================================
+impl<'b> EditMachine<'b> {
     pub fn go_down(&mut self) {
     pub fn go_down(&mut self) {
         self.traversal.down();
         self.traversal.down();
     }
     }
@@ -158,6 +169,9 @@ impl<'b> EditMachine<'b> {
     }
     }
 }
 }
 
 
+// ===================================
+//  Stack methods
+// ===================================
 impl<'a> EditMachine<'a> {
 impl<'a> EditMachine<'a> {
     pub fn next_temporary(&self) -> u32 {
     pub fn next_temporary(&self) -> u32 {
         self.next_temporary
         self.next_temporary
@@ -205,11 +219,6 @@ impl<'a> EditMachine<'a> {
         self.emitter.push(Edit::InsertBefore {})
         self.emitter.push(Edit::InsertBefore {})
     }
     }
 
 
-    pub fn ensure_string(&mut self, _string: &str) -> StringKey {
-        todo!()
-        // self.strings.ensure_string(string, &self.emitter)
-    }
-
     pub fn set_text(&mut self, text: &'a str) {
     pub fn set_text(&mut self, text: &'a str) {
         debug_assert!(self.traversal_is_committed());
         debug_assert!(self.traversal_is_committed());
         // debug!("emit: set_text({:?})", text);
         // debug!("emit: set_text({:?})", text);
@@ -307,42 +316,26 @@ impl<'a> EditMachine<'a> {
         self.forcing_new_listeners = previous;
         self.forcing_new_listeners = previous;
     }
     }
 
 
-    pub fn new_event_listener(&mut self, event: &'a str, idx: CbIdx) {
+    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::NewEventListener {
             event_type: event,
             event_type: event,
-            s: idx,
+            s: scope,
         });
         });
-        // todo!("Event listener not wired up yet");
         // log::debug!("emit: new_event_listener({:?})", listener);
         // log::debug!("emit: new_event_listener({:?})", listener);
-        // let (a, b) = listener.get_callback_parts();
-        // debug_assert!(a != 0);
-        // // let event_id = self.ensure_string(listener.event);
-        // self.emitter.new_event_listener(listener.event.into(), a, b);
     }
     }
 
 
-    pub fn update_event_listener(&mut self, event: &'a str, idx: CbIdx) {
+    pub fn update_event_listener(&mut self, event: &'a str, scope: ScopeIdx, id: usize) {
         debug_assert!(self.traversal_is_committed());
         debug_assert!(self.traversal_is_committed());
         if self.forcing_new_listeners {
         if self.forcing_new_listeners {
-            self.new_event_listener(event, idx);
+            self.new_event_listener(event, scope, id);
             return;
             return;
         }
         }
 
 
         self.emitter.push(Edit::NewEventListener {
         self.emitter.push(Edit::NewEventListener {
             event_type: event,
             event_type: event,
-            s: idx,
+            s: scope,
         });
         });
-
-        // log::debug!("emit: update_event_listener({:?})", listener);
-        // // todo!("Event listener not wired up yet");
-        // let (a, b) = listener.get_callback_parts();
-        // debug_assert!(a != 0);
-        // self.emitter.push(Edit::UpdateEventListener {
-        //     event_type: listener.event.into(),
-        //     a,
-        //     b,
-        // });
-        // self.emitter.update_event_listener(event_id.into(), a, b);
     }
     }
 
 
     pub fn remove_event_listener(&mut self, event: &'a str) {
     pub fn remove_event_listener(&mut self, event: &'a str) {
@@ -350,16 +343,8 @@ impl<'a> EditMachine<'a> {
         self.emitter
         self.emitter
             .push(Edit::RemoveEventListener { event_type: event });
             .push(Edit::RemoveEventListener { event_type: event });
         // debug!("emit: remove_event_listener({:?})", event);
         // debug!("emit: remove_event_listener({:?})", event);
-        // let _event_id = self.ensure_string(event);
-        // todo!("Event listener not wired up yet");
-        // self.emitter.remove_event_listener(event_id.into());
     }
     }
 
 
-    // #[inline]
-    // pub fn has_template(&mut self, id: CacheId) -> bool {
-    //     self.templates.contains(&id)
-    // }
-
     // pub fn save_template(&mut self, id: CacheId) {
     // pub fn save_template(&mut self, id: CacheId) {
     //     debug_assert!(self.traversal_is_committed());
     //     debug_assert!(self.traversal_is_committed());
     //     debug_assert!(!self.has_template(id));
     //     debug_assert!(!self.has_template(id));
@@ -516,10 +501,8 @@ impl Traversal {
     /// Commit this traversals moves and return the optimized path from the last
     /// Commit this traversals moves and return the optimized path from the last
     /// commit.
     /// commit.
     #[inline]
     #[inline]
-    pub fn commit(&mut self) -> Moves {
-        Moves {
-            inner: self.uncommitted.drain(..),
-        }
+    pub fn commit(&mut self) -> std::vec::Drain<'_, MoveTo> {
+        self.uncommitted.drain(..)
     }
     }
 
 
     #[inline]
     #[inline]
@@ -528,18 +511,18 @@ impl Traversal {
     }
     }
 }
 }
 
 
-pub struct Moves<'a> {
-    inner: std::vec::Drain<'a, MoveTo>,
-}
+// pub struct Moves<'a> {
+//     inner: std::vec::Drain<'a, MoveTo>,
+// }
 
 
-impl Iterator for Moves<'_> {
-    type Item = MoveTo;
+// impl Iterator for Moves<'_> {
+//     type Item = MoveTo;
 
 
-    #[inline]
-    fn next(&mut self) -> Option<MoveTo> {
-        self.inner.next()
-    }
-}
+//     #[inline]
+//     fn next(&mut self) -> Option<MoveTo> {
+//         self.inner.next()
+//     }
+// }
 
 
 #[cfg(test)]
 #[cfg(test)]
 mod tests {
 mod tests {

+ 52 - 30
packages/core/src/scope.rs

@@ -45,13 +45,21 @@ pub struct Scope {
     // lying, cheating reference >:(
     // lying, cheating reference >:(
     pub props: Box<dyn std::any::Any>,
     pub props: Box<dyn std::any::Any>,
 
 
+    // our own index
+    pub myidx: ScopeIdx,
+
     // pub props_type: TypeId,
     // pub props_type: TypeId,
     pub caller: *const (),
     pub caller: *const (),
 }
 }
 
 
 impl Scope {
 impl Scope {
     // create a new scope from a function
     // create a new scope from a function
-    pub fn new<'a, P1, P2: 'static>(f: FC<P1>, props: P1, parent: Option<ScopeIdx>) -> Self {
+    pub fn new<'a, P1, P2: 'static>(
+        f: FC<P1>,
+        props: P1,
+        myidx: ScopeIdx,
+        parent: Option<ScopeIdx>,
+    ) -> Self {
         let hook_arena = typed_arena::Arena::new();
         let hook_arena = typed_arena::Arena::new();
         let hooks = RefCell::new(Vec::new());
         let hooks = RefCell::new(Vec::new());
 
 
@@ -79,6 +87,7 @@ impl Scope {
         let props = unsafe { std::mem::transmute::<_, Box<P2>>(props) };
         let props = unsafe { std::mem::transmute::<_, Box<P2>>(props) };
 
 
         Self {
         Self {
+            myidx,
             hook_arena,
             hook_arena,
             hooks,
             hooks,
             caller,
             caller,
@@ -109,6 +118,7 @@ impl Scope {
             idx: 0.into(),
             idx: 0.into(),
             _p: PhantomData {},
             _p: PhantomData {},
             final_nodes: node_slot.clone(),
             final_nodes: node_slot.clone(),
+            scope: self.myidx,
         };
         };
 
 
         unsafe {
         unsafe {
@@ -276,25 +286,34 @@ mod tests {
 
 
     #[test]
     #[test]
     fn check_listeners() -> Result<()> {
     fn check_listeners() -> Result<()> {
-        let mut scope = Scope::new::<(), ()>(ListenerTest, (), None);
-        scope.run::<()>();
+        todo!()
+        // let mut scope = Scope::new::<(), ()>(ListenerTest, (), None);
+        // scope.run::<()>();
 
 
-        let nodes = scope.new_frame();
-        dbg!(nodes);
+        // let nodes = scope.new_frame();
+        // dbg!(nodes);
 
 
-        Ok(())
+        // Ok(())
     }
     }
 
 
     #[test]
     #[test]
     fn test_scope() {
     fn test_scope() {
         let example: FC<()> = |ctx, props| {
         let example: FC<()> = |ctx, props| {
             use crate::builder::*;
             use crate::builder::*;
-            ctx.render(|ctx| div(ctx.bump()).child(text("a")).finish())
+            ctx.render(|ctx| {
+                builder::ElementBuilder::new(ctx, "div")
+                    .child(text("a"))
+                    .finish()
+            })
         };
         };
 
 
         let props = ();
         let props = ();
         let parent = None;
         let parent = None;
-        let scope = Scope::new::<(), ()>(example, props, parent);
+        let mut nodes = generational_arena::Arena::new();
+        nodes.insert_with(|f| {
+            let scope = Scope::new::<(), ()>(example, props, f, parent);
+            //
+        });
     }
     }
 
 
     #[derive(Debug)]
     #[derive(Debug)]
@@ -320,39 +339,42 @@ mod tests {
         let childprops: ExampleProps<'a> = ExampleProps { name: content };
         let childprops: ExampleProps<'a> = ExampleProps { name: content };
         // let childprops: ExampleProps<'a> = ExampleProps { name: content };
         // let childprops: ExampleProps<'a> = ExampleProps { name: content };
         ctx.render(move |ctx| {
         ctx.render(move |ctx| {
-            let b = ctx.bump();
-            div(b)
-                .child(text(props.name))
-                // .child(text(props.name))
-                .child(virtual_child::<ExampleProps>(b, childprops, child_example))
-                // .child(virtual_child::<ExampleProps<'a>>(b, childprops, CHILD))
-                // as for<'scope> fn(Context<'_>, &'scope ExampleProps<'scope>) -> DomTree
-                // |ctx, pops| todo!(),
-                // .child(virtual_child::<'a>(
-                //     b,
-                //     child_example,
-                //     ExampleProps { name: text },
-                // ))
-                .finish()
+            todo!()
+            // let b = ctx.bump();
+            // div(b)
+            //     .child(text(props.name))
+            //     // .child(text(props.name))
+            //     .child(virtual_child::<ExampleProps>(b, childprops, child_example))
+            //     // .child(virtual_child::<ExampleProps<'a>>(b, childprops, CHILD))
+            //     // as for<'scope> fn(Context<'_>, &'scope ExampleProps<'scope>) -> DomTree
+            //     // |ctx, pops| todo!(),
+            //     // .child(virtual_child::<'a>(
+            //     //     b,
+            //     //     child_example,
+            //     //     ExampleProps { name: text },
+            //     // ))
+            //     .finish()
         })
         })
     }
     }
 
 
     fn child_example<'b>(ctx: Context<'b>, props: &'b ExampleProps) -> DomTree {
     fn child_example<'b>(ctx: Context<'b>, props: &'b ExampleProps) -> DomTree {
         ctx.render(move |ctx| {
         ctx.render(move |ctx| {
-            div(ctx.bump())
-                .child(text(props.name))
-                //
-                .finish()
+            todo!()
+            // div(ctx.bump())
+            //     .child(text(props.name))
+            //     //
+            //     .finish()
         })
         })
     }
     }
 
 
     static CHILD: FC<ExampleProps> = |ctx, props: &'_ ExampleProps| {
     static CHILD: FC<ExampleProps> = |ctx, props: &'_ ExampleProps| {
         // todo!()
         // todo!()
         ctx.render(move |ctx| {
         ctx.render(move |ctx| {
-            div(ctx.bump())
-                .child(text(props.name))
-                //
-                .finish()
+            todo!()
+            // div(ctx.bump())
+            //     .child(text(props.name))
+            //     //
+            //     .finish()
         })
         })
     };
     };
     #[test]
     #[test]

+ 8 - 6
packages/core/src/virtual_dom.rs

@@ -56,7 +56,8 @@ impl VirtualDom {
         // Create a reference to the component in the arena
         // Create a reference to the component in the arena
         // Note: we are essentially running the "Mount" lifecycle event manually while the vdom doesnt yet exist
         // Note: we are essentially running the "Mount" lifecycle event manually while the vdom doesnt yet exist
         // This puts the dom in a usable state on creation, rather than being potentially invalid
         // This puts the dom in a usable state on creation, rather than being potentially invalid
-        let base_scope = components.insert(Scope::new::<_, P>(root, root_props, None));
+        let base_scope =
+            components.insert_with(|id| Scope::new::<_, P>(root, root_props, id, None));
 
 
         // evaluate the component, pushing any updates its generates into the lifecycle queue
         // evaluate the component, pushing any updates its generates into the lifecycle queue
         // todo!
         // todo!
@@ -277,11 +278,12 @@ mod tests {
     #[test]
     #[test]
     fn start_dom() {
     fn start_dom() {
         let mut dom = VirtualDom::new(|ctx, props| {
         let mut dom = VirtualDom::new(|ctx, props| {
-            ctx.render(|ctx| {
-                use crate::builder::*;
-                let bump = ctx.bump();
-                div(bump).child(text("hello,    world")).finish()
-            })
+            todo!()
+            // ctx.render(|ctx| {
+            //     use crate::builder::*;
+            //     let bump = ctx.bump();
+            //     div(bump).child(text("hello,    world")).finish()
+            // })
         });
         });
         let edits = dom.rebuild().unwrap();
         let edits = dom.rebuild().unwrap();
         println!("{:#?}", edits);
         println!("{:#?}", edits);

+ 20 - 0
packages/web/examples/query.rs

@@ -0,0 +1,20 @@
+// use dioxus_core::prelude::*;
+// use dioxus_web::WebsysRenderer;
+
+// fn main() {
+//     wasm_bindgen_futures::spawn_local(WebsysRenderer::start(Example));
+// }
+
+// fn Example(ctx: Context, props: ()) -> DomTree {
+//     let user_data = use_sql_query(&ctx, USER_DATA_QUERY);
+
+//     ctx.render(rsx! {
+//         h1 { "Hello, {username}"}
+//         button {
+//             "Delete user"
+//             onclick: move |_| user_data.delete()
+//         }
+//     })
+// }
+
+fn main() {}

+ 19 - 0
packages/web/src/old/virtual_node_test_utils.rs

@@ -139,3 +139,22 @@ mod tests {
         assert_eq!(hello_nodes.len(), 1);
         assert_eq!(hello_nodes.len(), 1);
     }
     }
 }
 }
+
+use dioxus_core::prelude::*;
+use dioxus_web::WebsysRenderer;
+
+fn main() {
+    wasm_bindgen_futures::spawn_local(WebsysRenderer::start(Example));
+}
+
+fn Component(ctx: Context, props: ()) -> DomTree {
+    let user_data = use_sql_query(&ctx, USER_DATA_QUERY);
+
+    ctx.render(rsx! {
+        h1 { "Hello, {username}"}
+        button {
+            "Delete user"
+            onclick: move |_| user_data.delete()
+        }
+    })
+}