1
0
Эх сурвалжийг харах

feat: more suspended nodes!

Jonathan Kelley 4 жил өмнө
parent
commit
de9f61b

+ 12 - 19
examples/async.rs

@@ -21,25 +21,18 @@ const ENDPOINT: &str = "https://dog.ceo/api/breeds/image/random";
 
 static App: FC<()> = |cx| {
     let mut count = use_state(cx, || 0);
-    let mut fut = cx.use_hook(
-        move || {
-            Box::pin(async {
-                //
-                let mut tick = 0;
-                loop {
-                    async_std::task::sleep(Duration::from_millis(250)).await;
-                    log::debug!("ticking forward... {}", tick);
-                    tick += 1;
-                    // match surf::get(ENDPOINT).recv_json::<DogApi>().await {
-                    //     Ok(_) => (),
-                    //     Err(_) => (),
-                    // }
-                }
-            }) as Pin<Box<dyn Future<Output = ()> + 'static>>
-        },
-        |h| h,
-        |_| {},
-    );
+    let mut fut = Box::pin(async {
+        let mut tick: i32 = 0;
+        loop {
+            async_std::task::sleep(Duration::from_millis(250)).await;
+            log::debug!("ticking forward... {}", tick);
+            tick += 1;
+            // match surf::get(ENDPOINT).recv_json::<DogApi>().await {
+            //     Ok(_) => (),
+            //     Err(_) => (),
+            // }
+        }
+    });
 
     cx.submit_task(fut);
 

+ 5 - 7
notes/SUSPENSE.md

@@ -17,13 +17,11 @@ for more general tasks, we need some way of submitting a future or task into som
 
 ```rust
 
-let task = use_hook(|| {
-    // create the future
-}, || {
-    update the future if it needs to be updated
-}, || {
-
-});
+let task = use_hook(
+    || { /* */ }, 
+    || { /* update the future if it needs to be updated */ }, 
+    || {}
+);
 cx.poll_future()
 // let recoil_event_loop = cx.use_task(move |_| async move {
 //     loop {

+ 2 - 2
packages/atoms/src/lib.rs

@@ -392,7 +392,7 @@ mod hooks {
     ) -> &'a Rc<dyn Fn(T)> {
         let api = use_recoil_api(cx);
         cx.use_hook(
-            move || {
+            move |_| {
                 let api = api.clone();
                 let raw_id = writable.static_id();
                 Rc::new(move |new_val| {
@@ -423,7 +423,7 @@ mod hooks {
 
         let api = use_recoil_api(cx);
         cx.use_hook(
-            move || {
+            move |_| {
                 let mut api = api.as_ref().borrow_mut();
 
                 let update = cx.schedule_update();

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

@@ -5,7 +5,7 @@ fn main() {}
 const App: FC<()> = |cx| {
     // create a new future
     let _fut = cx.use_hook(
-        || {
+        |_| {
             //
             async { loop {} }
             // Box::pin(async { loop {} }) as Pin<Box<dyn Future<Output = ()>>>

+ 79 - 19
packages/core/src/context.rs

@@ -1,7 +1,9 @@
 use crate::innerlude::*;
 
+use bumpalo::Bump;
 use futures_util::FutureExt;
 
+use std::any::Any;
 use std::marker::PhantomData;
 
 use std::{
@@ -134,13 +136,13 @@ impl<'src, P> Context<'src, P> {
     where
         State: 'static,
         Output: 'src,
-        Init: FnOnce() -> State,
+        Init: FnOnce(usize) -> State,
         Run: FnOnce(&'src mut State) -> Output,
         Cleanup: FnOnce(State),
     {
         // If the idx is the same as the hook length, then we need to add the current hook
         if self.scope.hooks.at_end() {
-            let new_state = initializer();
+            let new_state = initializer(self.scope.hooks.len());
             self.scope.hooks.push(new_state);
         }
 
@@ -172,7 +174,7 @@ Any function prefixed with "use" should not be called conditionally.
         let ty = TypeId::of::<T>();
 
         let is_initialized = self.use_hook(
-            || false,
+            |_| false,
             |s| {
                 let i = s.clone();
                 *s = true;
@@ -208,7 +210,7 @@ Any function prefixed with "use" should not be called conditionally.
         }
 
         self.use_hook(
-            move || UseContextHook {
+            move |_| UseContextHook {
                 par: None as Option<Rc<T>>,
                 we: None as Option<Weak<T>>,
             },
@@ -299,10 +301,9 @@ Any function prefixed with "use" should not be called conditionally.
     /// Awaits the given task, forcing the component to re-render when the value is ready.
     ///
     ///
-    pub fn use_task<Out, Fut, Init>(
-        &self,
-        task_initializer: Init,
-    ) -> (&TaskHandle, &mut Option<Out>)
+    ///
+    ///
+    pub fn use_task<Out, Fut, Init>(&self, task_initializer: Init) -> (&TaskHandle, &Option<Out>)
     where
         Out: 'static,
         Fut: Future<Output = Out> + 'static,
@@ -315,7 +316,7 @@ Any function prefixed with "use" should not be called conditionally.
 
         // whenever the task is complete, save it into th
         self.use_hook(
-            move || {
+            move |hook_idx| {
                 let task_fut = task_initializer();
 
                 let task_dump = Rc::new(RefCell::new(None));
@@ -328,7 +329,7 @@ Any function prefixed with "use" should not be called conditionally.
                     *slot.as_ref().borrow_mut() = Some(output);
                     update();
                     EventTrigger {
-                        event: VirtualEvent::FiberEvent,
+                        event: VirtualEvent::AsyncEvent { hook_idx },
                         originator,
                         priority: EventPriority::Low,
                         real_node_id: None,
@@ -344,12 +345,20 @@ Any function prefixed with "use" should not be called conditionally.
                 if let Some(val) = hook.task_dump.as_ref().borrow_mut().take() {
                     hook.value = Some(val);
                 }
-                (&TaskHandle { _p: PhantomData }, &mut hook.value)
+                (&TaskHandle { _p: PhantomData }, &hook.value)
             },
             |_| {},
         )
     }
+}
+
+pub(crate) struct SuspenseHook {
+    pub value: Rc<RefCell<Option<Box<dyn Any>>>>,
+    pub callback: SuspendedCallback,
+}
+type SuspendedCallback = Box<dyn for<'a> Fn(SuspendedContext<'a>) -> VNode<'a>>;
 
+impl<'src, P> Context<'src, P> {
     /// Asynchronously render new nodes once the given future has completed.
     ///
     /// # Easda
@@ -360,18 +369,67 @@ Any function prefixed with "use" should not be called conditionally.
     /// # Example
     ///
     ///
-    pub fn use_suspense<Out, Fut: 'static>(
+    pub fn use_suspense<Out, Fut, Cb>(
         &'src self,
-        _task_initializer: impl FnOnce() -> Fut,
-        _callback: impl FnOnce(SuspendedContext, Out) -> VNode<'src> + 'src,
+        task_initializer: impl FnOnce() -> Fut,
+        user_callback: Cb,
     ) -> VNode<'src>
     where
-        Out: 'src,
-        Fut: Future<Output = Out>,
+        Fut: Future<Output = Out> + 'static,
+        Out: 'static,
+        Cb: for<'a> Fn(SuspendedContext<'a>, &Out) -> VNode<'a> + 'static,
     {
-        // self.use_hook(|| , runner, cleanup)
+        self.use_hook(
+            move |hook_idx| {
+                let value = Rc::new(RefCell::new(None));
 
-        todo!()
+                let slot = value.clone();
+                let callback: SuspendedCallback = Box::new(move |ctx: SuspendedContext| {
+                    let v: std::cell::Ref<Option<Box<dyn Any>>> = slot.as_ref().borrow();
+                    let v: &dyn Any = v.as_ref().unwrap().as_ref();
+                    let real_val = v.downcast_ref::<Out>().unwrap();
+                    user_callback(ctx, real_val)
+                });
+
+                let originator = self.scope.arena_idx.clone();
+                let task_fut = task_initializer();
+
+                let slot = value.clone();
+                self.submit_task(Box::pin(task_fut.then(move |output| async move {
+                    // When the new value arrives, set the hooks internal slot
+                    // Dioxus will call the user's callback to generate new nodes outside of the diffing system
+                    *slot.borrow_mut() = Some(Box::new(output) as Box<dyn Any>);
+                    EventTrigger {
+                        event: VirtualEvent::SuspenseEvent { hook_idx },
+                        originator,
+                        priority: EventPriority::Low,
+                        real_node_id: None,
+                    }
+                })));
+
+                SuspenseHook { value, callback }
+            },
+            move |hook| {
+                match hook.value.borrow().as_ref() {
+                    Some(val) => {
+                        let cx = SuspendedContext {
+                            bump: &self.scope.cur_frame().bump,
+                        };
+                        (&hook.callback)(cx)
+                    }
+                    None => {
+                        //
+                        VNode {
+                            dom_id: RealDomNode::empty_cell(),
+                            key: None,
+                            kind: VNodeKind::Suspended,
+                        }
+                    }
+                }
+                //
+            },
+            |_| {},
+        )
     }
 }
 
@@ -379,4 +437,6 @@ pub struct TaskHandle<'src> {
     _p: PhantomData<&'src ()>,
 }
 #[derive(Clone)]
-pub struct SuspendedContext {}
+pub struct SuspendedContext<'a> {
+    pub bump: &'a Bump,
+}

+ 6 - 2
packages/core/src/diff.rs

@@ -77,7 +77,8 @@ use DomEdit::*;
 impl<'real, 'bump> DomEditor<'real, 'bump> {
     // Navigation
     pub(crate) fn push(&mut self, root: RealDomNode) {
-        self.edits.push(PushRoot { root });
+        let id = root.as_u64();
+        self.edits.push(PushRoot { id });
     }
     pub(crate) fn pop(&mut self) {
         self.edits.push(PopRoot {});
@@ -105,6 +106,7 @@ impl<'real, 'bump> DomEditor<'real, 'bump> {
 
     // Create
     pub(crate) fn create_text_node(&mut self, text: &'bump str, id: RealDomNode) {
+        let id = id.as_u64();
         self.edits.push(CreateTextNode { text, id });
     }
     pub(crate) fn create_element(
@@ -113,6 +115,7 @@ impl<'real, 'bump> DomEditor<'real, 'bump> {
         ns: Option<&'static str>,
         id: RealDomNode,
     ) {
+        let id = id.as_u64();
         match ns {
             Some(ns) => self.edits.push(CreateElementNs { id, ns, tag }),
             None => self.edits.push(CreateElement { id, tag }),
@@ -121,6 +124,7 @@ impl<'real, 'bump> DomEditor<'real, 'bump> {
 
     // placeholders are nodes that don't get rendered but still exist as an "anchor" in the real dom
     pub(crate) fn create_placeholder(&mut self, id: RealDomNode) {
+        let id = id.as_u64();
         self.edits.push(CreatePlaceholder { id });
     }
 
@@ -136,7 +140,7 @@ impl<'real, 'bump> DomEditor<'real, 'bump> {
             scope,
             event,
             idx: element_id,
-            node: realnode,
+            node: realnode.as_u64(),
         });
     }
     pub(crate) fn remove_event_listener(&mut self, event: &'static str) {

+ 16 - 9
packages/core/src/events.rs

@@ -4,8 +4,6 @@
 //! 3rd party renderers are responsible for converting their native events into these virtual event types. Events might
 //! be heavy or need to interact through FFI, so the events themselves are designed to be lazy.
 
-
-
 use crate::innerlude::{RealDomNode, ScopeIdx};
 
 #[derive(Debug)]
@@ -24,10 +22,10 @@ pub struct EventTrigger {
 }
 
 impl EventTrigger {
-    pub fn new_from_task(originator: ScopeIdx) -> Self {
+    pub fn new_from_task(originator: ScopeIdx, hook_idx: usize) -> Self {
         Self {
             originator,
-            event: VirtualEvent::FiberEvent,
+            event: VirtualEvent::AsyncEvent { hook_idx },
             priority: EventPriority::Low,
             real_node_id: None,
         }
@@ -103,11 +101,18 @@ pub enum VirtualEvent {
     MouseEvent(on::MouseEvent),
     PointerEvent(on::PointerEvent),
 
-    // Whenever a task is ready (complete) Dioxus produces this "FiberEvent"
-    FiberEvent,
-
     // image event has conflicting method types
     // ImageEvent(event_data::ImageEvent),
+
+    // Whenever a task is ready (complete) Dioxus produces this "AsyncEvent"
+    //
+    // Async events don't necessarily propagate into a scope being ran. It's up to the event itself
+    // to force an update for itself.
+    AsyncEvent { hook_idx: usize },
+
+    // These are more intrusive than the rest
+    SuspenseEvent { hook_idx: usize },
+
     OtherEvent,
 }
 
@@ -159,10 +164,12 @@ pub mod on {
 
                 $(
                     $(#[$method_attr])*
-                    pub fn $name<'a, F: FnMut($wrapper) + 'a>(
+                    pub fn $name<'a, F>(
                         c: NodeFactory<'a>,
                         mut callback: F,
-                    ) -> Listener<'a> {
+                    ) -> Listener<'a>
+                        where F: FnMut($wrapper) + 'a
+                    {
                         let bump = &c.bump();
                         Listener {
                             event: stringify!($name),

+ 22 - 2
packages/core/src/hooklist.rs

@@ -29,8 +29,20 @@ impl<T> InnerHook<T> {
 }
 
 impl HookList {
-    pub(crate) fn push<T: 'static>(&self, new: T) {
-        self.vals.push(InnerHook::new(Box::new(new)))
+    /// Unsafely get a mutable reference to any of the hooks
+    ///
+    /// This is unsafe because an &mut T might be aliased if the hook data is already borrowed/in use in the component
+    ///
+    /// This method should be reserved for internal methods that are guaranteed that this hook is not aliased anyhwere
+    /// inside the component body, or outside into children components.
+    ///
+    /// This method is currently used only by the suspense system whose hook implementation guarantees that all &T is dropped
+    /// before the suspense handler is ran.
+    pub(crate) unsafe fn get_mut<T: 'static>(&self, idx: usize) -> Option<&mut T> {
+        self.vals.get(idx).and_then(|inn| {
+            let raw_box = unsafe { &mut *inn.cell.get() };
+            raw_box.downcast_mut::<T>()
+        })
     }
 
     pub(crate) fn next<T: 'static>(&self) -> Option<&mut T> {
@@ -41,9 +53,17 @@ impl HookList {
         })
     }
 
+    #[inline]
+    pub(crate) fn push<T: 'static>(&self, new: T) {
+        self.vals.push(InnerHook::new(Box::new(new)))
+    }
+
     /// This resets the internal iterator count
     /// It's okay that we've given out each hook, but now we have the opportunity to give it out again
     /// Therefore, resetting is cosudered unsafe
+    ///
+    /// This should only be ran by Dioxus itself before "running scope".
+    /// Dioxus knows how to descened through the tree to prevent mutable aliasing.
     pub(crate) unsafe fn reset(&mut self) {
         self.idx.set(0);
     }

+ 1 - 1
packages/core/src/scope.rs

@@ -177,7 +177,7 @@ impl Scope {
             ..
         } = trigger;
 
-        if let &VirtualEvent::FiberEvent = &event {
+        if let &VirtualEvent::AsyncEvent { .. } = &event {
             log::info!("arrived a fiber event");
             return Ok(());
         }

+ 7 - 7
packages/core/src/serialize.rs

@@ -7,7 +7,7 @@
 //!
 //!
 
-use crate::{innerlude::ScopeIdx, RealDomNode};
+use crate::innerlude::ScopeIdx;
 use serde::{Deserialize, Serialize};
 
 /// A `DomEdit` represents a serialzied form of the VirtualDom's trait-based API. This allows streaming edits across the
@@ -16,7 +16,7 @@ use serde::{Deserialize, Serialize};
 #[serde(tag = "type")]
 pub enum DomEdit<'bump> {
     PushRoot {
-        root: RealDomNode,
+        id: u64,
     },
     PopRoot,
     AppendChildren {
@@ -29,24 +29,24 @@ pub enum DomEdit<'bump> {
     RemoveAllChildren,
     CreateTextNode {
         text: &'bump str,
-        id: RealDomNode,
+        id: u64,
     },
     CreateElement {
         tag: &'bump str,
-        id: RealDomNode,
+        id: u64,
     },
     CreateElementNs {
         tag: &'bump str,
-        id: RealDomNode,
+        id: u64,
         ns: &'static str,
     },
     CreatePlaceholder {
-        id: RealDomNode,
+        id: u64,
     },
     NewEventListener {
         event: &'static str,
         scope: ScopeIdx,
-        node: RealDomNode,
+        node: u64,
         idx: usize,
     },
     RemoveEventListener {

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

@@ -4,7 +4,7 @@ use std::{
 };
 
 use futures_util::StreamExt;
-use slotmap::{DefaultKey, KeyData};
+use slotmap::{DefaultKey, Key, KeyData};
 
 use crate::innerlude::*;
 
@@ -66,13 +66,16 @@ impl RealDomNode {
         let key: DefaultKey = data.into();
         Self(key)
     }
+    pub fn empty_cell() -> Cell<Self> {
+        Cell::new(Self::empty())
+    }
     pub fn from_u64(id: u64) -> Self {
         let data = KeyData::from_ffi(id);
         let key: DefaultKey = data.into();
         Self(key)
     }
-    pub fn empty_cell() -> Cell<Self> {
-        Cell::new(Self::empty())
+    pub fn as_u64(&self) -> u64 {
+        self.0.data().as_ffi()
     }
 }
 

+ 23 - 4
packages/core/src/virtual_dom.rs

@@ -297,10 +297,29 @@ impl VirtualDom {
         match &trigger.event {
             VirtualEvent::OtherEvent => todo!(),
 
-            // Fiber events
-            // VirtualEvent::FiberEvent => {
-            //     //
-            // }
+            // Nothing yet
+            VirtualEvent::AsyncEvent { .. } => {}
+
+            // Suspense Events! A component's suspended node is updated
+            VirtualEvent::SuspenseEvent { hook_idx } => {
+                let scope = self.components.try_get_mut(trigger.originator).unwrap();
+
+                // safety: we are sure that there are no other references to the inner content of this hook
+                let hook = unsafe { scope.hooks.get_mut::<SuspenseHook>(*hook_idx) }.unwrap();
+
+                let cx = SuspendedContext {
+                    bump: &scope.cur_frame().bump,
+                };
+
+                // generate the new node!
+                let callback: VNode<'s> = (&hook.callback)(cx);
+
+                // diff that node with the node that was originally suspended!
+
+                // hook.callback;
+
+                //
+            }
 
             // This is the "meat" of our cooperative scheduler
             // As updates flow in, we re-evalute the event queue and decide if we should be switching the type of work

+ 1 - 1
packages/hooks/src/usestate.rs

@@ -54,7 +54,7 @@ pub fn use_state<'a, 'c, T: 'static, F: FnOnce() -> T, P>(
     initial_state_fn: F,
 ) -> UseState<T> {
     cx.use_hook(
-        move || UseStateInner {
+        move |_| UseStateInner {
             current_val: initial_state_fn(),
             callback: cx.schedule_update(),
             wip: Rc::new(RefCell::new(None)),

+ 432 - 22
packages/html/src/lib.rs

@@ -112,95 +112,505 @@ pub trait GlobalAttributes {
         translate;
     }
     style_trait_methods! {
+        /// Specifies the alignment of flexible container's items within the flex container.
+        align_content: "align-content",
+
+        /// Specifies the default alignment for items within the flex container.
+        align_items: "align-items",
+
+        /// Specifies the alignment for selected items within the flex container.
+        align_self: "align-self",
+
+        /// Specifies the keyframe_based animations.
+        animation: "animation",
+
+        /// Specifies when the animation will start.
+        animation_delay: "animation-delay",
+
+        /// Specifies whether the animation should play in reverse on alternate cycles or not.
+        animation_direction: "animation-direction",
+
+        /// Specifies the number of seconds or milliseconds an animation should take to complete one cycle
+        animation_duration: "animation-duration",
+
+        /// Specifies how a CSS animation should apply styles to its target before and after it is executing
+        animation_fill_mode: "animation-fill-mode",
+
+        /// Specifies the number of times an animation cycle should be played before stopping.
+        animation_iteration_count: "animation-iteration-count",
+
+        /// Specifies the name of @keyframes defined animations that should be applied to the selected element
+        animation_name: "animation-name",
+
+        /// Specifies whether the animation is running or paused.
+        animation_play_state: "animation-play-state",
+
+        /// Specifies how a CSS animation should progress over the duration of each cycle.
+        animation_timing_function: "animation-timing-function",
+
+        /// Specifies whether or not the "back" side of a transformed element is visible when facing the user.
+        backface_visibility: "backface-visibility",
+
+
+        /// Defines a variety of background properties within one declaration.
         background: "background",
+
+        /// Specify whether the background image is fixed in the viewport or scrolls.
         background_attachment: "background-attachment",
+        /// Specifies the painting area of the background.
+        background_clip: "background-clip",
 
-        /// ## Definition and Usage
-        ///
-        /// The background-color property sets the background color of an element.
-        ///
-        /// The background of an element is the total size of the element, including padding and border (but not the margin).
-        ///
-        /// Tip: Use a background color and a text color that makes the text easy to read.
-        ///
-        /// ## Example
-        ///
-        /// ```
-        /// body {
-        ///     style: {
-        ///         background_color: "coral"
-        ///     }
-        /// }
-        /// ```
+
+        /// Defines an element's background color.
         background_color: "background-color",
+
+        /// Defines an element's background image.
         background_image: "background-image",
+        /// Specifies the positioning area of the background images.
+        background_origin: "background-origin",
+
+
+        /// Defines the origin of a background image.
         background_position: "background-position",
+
+        /// Specify whether/how the background image is tiled.
         background_repeat: "background-repeat",
+        /// Specifies the size of the background images.
+        background_size: "background-size",
+
+
+        /// Sets the width, style, and color for all four sides of an element's border.
         border: "border",
+
+        /// Sets the width, style, and color of the bottom border of an element.
         border_bottom: "border-bottom",
+
+        /// Sets the color of the bottom border of an element.
         border_bottom_color: "border-bottom-color",
+        /// Defines the shape of the bottom_left border corner of an element.
+        border_bottom_left_radius: "border-bottom-left-radius",
+
+        /// Defines the shape of the bottom_right border corner of an element.
+        border_bottom_right_radius: "border-bottom-right-radius",
+
+
+        /// Sets the style of the bottom border of an element.
         border_bottom_style: "border-bottom-style",
+
+        /// Sets the width of the bottom border of an element.
         border_bottom_width: "border-bottom-width",
+
+        /// Specifies whether table cell borders are connected or separated.
+        border_collapse: "border-collapse",
+
+        /// Sets the color of the border on all the four sides of an element.
         border_color: "border-color",
+        /// Specifies how an image is to be used in place of the border styles.
+        border_image: "border-image",
+
+        /// Specifies the amount by which the border image area extends beyond the border box.
+        border_image_outset: "border-image-outset",
+
+        /// Specifies whether the image_border should be repeated, rounded or stretched.
+        border_image_repeat: "border-image-repeat",
+
+        /// Specifies the inward offsets of the image_border.
+        border_image_slice: "border-image-slice",
+
+        /// Specifies the location of the image to be used as a border.
+        border_image_source: "border-image-source",
+
+        /// Specifies the width of the image_border.
+        border_image_width: "border-image-width",
+
+
+        /// Sets the width, style, and color of the left border of an element.
         border_left: "border-left",
+
+        /// Sets the color of the left border of an element.
         border_left_color: "border-left-color",
+
+        /// Sets the style of the left border of an element.
         border_left_style: "border-left-style",
+
+        /// Sets the width of the left border of an element.
         border_left_width: "border-left-width",
+        /// Defines the shape of the border corners of an element.
+        border_radius: "border-radius",
+
+
+        /// Sets the width, style, and color of the right border of an element.
         border_right: "border-right",
+
+        /// Sets the color of the right border of an element.
         border_right_color: "border-right-color",
+
+        /// Sets the style of the right border of an element.
         border_right_style: "border-right-style",
+
+        /// Sets the width of the right border of an element.
         border_right_width: "border-right-width",
+
+        /// Sets the spacing between the borders of adjacent table cells.
+        border_spacing: "border-spacing",
+
+        /// Sets the style of the border on all the four sides of an element.
         border_style: "border-style",
+
+        /// Sets the width, style, and color of the top border of an element.
         border_top: "border-top",
+
+        /// Sets the color of the top border of an element.
         border_top_color: "border-top-color",
+        /// Defines the shape of the top_left border corner of an element.
+        border_top_left_radius: "border-top-left-radius",
+
+        /// Defines the shape of the top_right border corner of an element.
+        border_top_right_radius: "border-top-right-radius",
+
+
+        /// Sets the style of the top border of an element.
         border_top_style: "border-top-style",
+
+        /// Sets the width of the top border of an element.
         border_top_width: "border-top-width",
+
+        /// Sets the width of the border on all the four sides of an element.
         border_width: "border-width",
+
+        /// Specify the location of the bottom edge of the positioned element.
+        bottom: "bottom",
+        /// Applies one or more drop_shadows to the element's box.
+        box_shadow: "box-shadow",
+
+        /// Alter the default CSS box model.
+        box_sizing: "box-sizing",
+
+
+        /// Specify the position of table's caption.
+        caption_side: "caption-side",
+
+        /// Specifies the placement of an element in relation to floating elements.
         clear: "clear",
+
+        /// Defines the clipping region.
         clip: "clip",
+
+        /// Specify the color of the text of an element.
         color: "color",
+        /// Specifies the number of columns in a multi_column element.
+        column_count: "column-count",
+
+        /// Specifies how columns will be filled.
+        column_fill: "column-fill",
+
+        /// Specifies the gap between the columns in a multi_column element.
+        column_gap: "column-gap",
+
+        /// Specifies a straight line, or "rule", to be drawn between each column in a multi_column element.
+        column_rule: "column-rule",
+
+        /// Specifies the color of the rules drawn between columns in a multi_column layout.
+        column_rule_color: "column-rule-color",
+
+        /// Specifies the style of the rule drawn between the columns in a multi_column layout.
+        column_rule_style: "column-rule-style",
+
+        /// Specifies the width of the rule drawn between the columns in a multi_column layout.
+        column_rule_width: "column-rule-width",
+
+        /// Specifies how many columns an element spans across in a multi_column layout.
+        column_span: "column-span",
+
+        /// Specifies the optimal width of the columns in a multi_column element.
+        column_width: "column-width",
+
+        /// A shorthand property for setting column_width and column_count properties.
+        columns: "columns",
+
+
+        /// Inserts generated content.
+        content: "content",
+
+        /// Increments one or more counter values.
+        counter_increment: "counter-increment",
+
+        /// Creates or resets one or more counters.
+        counter_reset: "counter-reset",
+
+        /// Specify the type of cursor.
         cursor: "cursor",
+
+        /// Define the text direction/writing direction.
+        direction: "direction",
+
+        /// Specifies how an element is displayed onscreen.
         display: "display",
-        filter: "filter",
-        css_float: "css-float",
+
+        /// Show or hide borders and backgrounds of empty table cells.
+        empty_cells: "empty-cells",
+        /// Specifies the components of a flexible length.
+        flex: "flex",
+
+        /// Specifies the initial main size of the flex item.
+        flex_basis: "flex-basis",
+
+        /// Specifies the direction of the flexible items.
+        flex_direction: "flex-direction",
+
+        /// A shorthand property for the flex_direction and the flex_wrap properties.
+        flex_flow: "flex-flow",
+
+        /// Specifies how the flex item will grow relative to the other items inside the flex container.
+        flex_grow: "flex-grow",
+
+        /// Specifies how the flex item will shrink relative to the other items inside the flex container
+        flex_shrink: "flex-shrink",
+
+        /// Specifies whether the flexible items should wrap or not.
+        flex_wrap: "flex-wrap",
+
+
+        /// Specifies whether or not a box should float.
+        float: "float",
+
+        /// Defines a variety of font properties within one declaration.
         font: "font",
+
+        /// Defines a list of fonts for element.
         font_family: "font-family",
+
+        /// Defines the font size for the text.
         font_size: "font-size",
+        /// Preserves the readability of text when font fallback occurs.
+        font_size_adjust: "font-size-adjust",
+
+        /// Selects a normal, condensed, or expanded face from a font.
+        font_stretch: "font-stretch",
+
+
+        /// Defines the font style for the text.
+        font_style: "font-style",
+
+        /// Specify the font variant.
         font_variant: "font-variant",
+
+        /// Specify the font weight of the text.
         font_weight: "font-weight",
+
+        /// Specify the height of an element.
         height: "height",
+        /// Specifies how flex items are aligned along the main axis of the flex container after any flexible lengths and auto margins have been resolved.
+        justify_content: "auto margins have been resolved.",
+
+
+        /// Specify the location of the left edge of the positioned element.
         left: "left",
+
+        /// Sets the extra spacing between letters.
         letter_spacing: "letter-spacing",
+
+        /// Sets the height between lines of text.
         line_height: "line-height",
+
+        /// Defines the display style for a list and list elements.
         list_style: "list-style",
+
+        /// Specifies the image to be used as a list_item marker.
         list_style_image: "list-style-image",
+
+        /// Specifies the position of the list_item marker.
         list_style_position: "list-style-position",
+
+        /// Specifies the marker style for a list_item.
         list_style_type: "list-style-type",
+
+        /// Sets the margin on all four sides of the element.
         margin: "margin",
+
+        /// Sets the bottom margin of the element.
         margin_bottom: "margin-bottom",
+
+        /// Sets the left margin of the element.
         margin_left: "margin-left",
+
+        /// Sets the right margin of the element.
         margin_right: "margin-right",
+
+        /// Sets the top margin of the element.
         margin_top: "margin-top",
+
+        /// Specify the maximum height of an element.
+        max_height: "max-height",
+
+        /// Specify the maximum width of an element.
+        max_width: "max-width",
+
+        /// Specify the minimum height of an element.
+        min_height: "min-height",
+
+        /// Specify the minimum width of an element.
+        min_width: "min-width",
+        /// Specifies the transparency of an element.
+        opacity: "opacity",
+
+        /// Specifies the order in which a flex items are displayed and laid out within a flex container.
+        order: "order",
+
+
+        /// Sets the width, style, and color for all four sides of an element's outline.
+        outline: "outline",
+
+        /// Sets the color of the outline.
+        outline_color: "outline-color",
+        /// Set the space between an outline and the border edge of an element.
+        outline_offset: "outline-offset",
+
+
+        /// Sets a style for an outline.
+        outline_style: "outline-style",
+
+        /// Sets the width of the outline.
+        outline_width: "outline-width",
+
+        /// Specifies the treatment of content that overflows the element's box.
         overflow: "overflow",
+        /// Specifies the treatment of content that overflows the element's box horizontally.
+        overflow_x: "overflow-x",
+
+        /// Specifies the treatment of content that overflows the element's box vertically.
+        overflow_y: "overflow-y",
+
+
+        /// Sets the padding on all four sides of the element.
         padding: "padding",
+
+        /// Sets the padding to the bottom side of an element.
         padding_bottom: "padding-bottom",
+
+        /// Sets the padding to the left side of an element.
         padding_left: "padding-left",
+
+        /// Sets the padding to the right side of an element.
         padding_right: "padding-right",
+
+        /// Sets the padding to the top side of an element.
         padding_top: "padding-top",
+
+        /// Insert a page breaks after an element.
         page_break_after: "page-break-after",
+
+        /// Insert a page breaks before an element.
         page_break_before: "page-break-before",
+
+        /// Insert a page breaks inside an element.
+        page_break_inside: "page-break-inside",
+        /// Defines the perspective from which all child elements of the object are viewed.
+        perspective: "perspective",
+
+        /// Defines the origin (the vanishing point for the 3D space) for the perspective property.
+        perspective_origin: "perspective-origin",
+
+
+        /// Specifies how an element is positioned.
         position: "position",
-        stroke_dasharray: "stroke-dasharray",
-        stroke_dashoffset: "stroke-dashoffset",
+
+        /// Specifies quotation marks for embedded quotations.
+        quotes: "quotes",
+        /// Specifies whether or not an element is resizable by the user.
+        resize: "resize",
+
+
+        /// Specify the location of the right edge of the positioned element.
+        right: "right",
+        /// Specifies the length of the tab character.
+        tab_size: "tab-size",
+
+        /// Specifies a table layout algorithm.
+        table_layout: "table-layout",
+
+        /// Sets the horizontal alignment of inline content.
         text_align: "text-align",
+        /// Specifies how the last line of a block or a line right before a forced line break is aligned when  is justify.",
+        text_align_last: "text-align-last",
+
+        /// Specifies the decoration added to text.
         text_decoration: "text-decoration",
+        /// Specifies the color of the text_decoration_line.
+        text_decoration_color: "text-decoration-color",
+
+        /// Specifies what kind of line decorations are added to the element.
+        text_decoration_line: "text-decoration-line",
+
+        /// Specifies the style of the lines specified by the text_decoration_line property
+        text_decoration_style: "text-decoration-style",
+
+
+        /// Indent the first line of text.
         text_indent: "text-indent",
+        /// Specifies the justification method to use when the text_align property is set to justify.
+        text_justify: "text-justify",
+
+        /// Specifies how the text content will be displayed, when it overflows the block containers.
+        text_overflow: "text-overflow",
+
+        /// Applies one or more shadows to the text content of an element.
+        text_shadow: "text-shadow",
+
+
+        /// Transforms the case of the text.
         text_transform: "text-transform",
+
+        /// Specify the location of the top edge of the positioned element.
         top: "top",
+        /// Applies a 2D or 3D transformation to an element.
+        transform: "transform",
+
+        /// Defines the origin of transformation for an element.
+        transform_origin: "transform-origin",
+
+        /// Specifies how nested elements are rendered in 3D space.
+        transform_style: "transform-style",
+
+        /// Defines the transition between two states of an element.
+        transition: "transition",
+
+        /// Specifies when the transition effect will start.
+        transition_delay: "transition-delay",
+
+        /// Specifies the number of seconds or milliseconds a transition effect should take to complete.
+        transition_duration: "transition-duration",
+
+        /// Specifies the names of the CSS properties to which a transition effect should be applied.
+        transition_property: "transition-property",
+
+        /// Specifies the speed curve of the transition effect.
+        transition_timing_function: "transition-timing-function",
+
+
+        /// Sets the vertical positioning of an element relative to the current text baseline.
         vertical_align: "vertical-align",
+
+        /// Specifies whether or not an element is visible.
         visibility: "visibility",
+
+        /// Specifies how white space inside the element is handled.
+        white_space: "white-space",
+
+        /// Specify the width of an element.
         width: "width",
-        z_index: "z-index",
+        /// Specifies how to break lines within words.
+        word_break: "word-break",
+
+
+        /// Sets the spacing between words.
+        word_spacing: "word-spacing",
+        /// Specifies whether to break words when the content overflows the boundaries of its container.
+        word_wrap: "word-wrap",
+
+        /// Specifies a layering or stacking order for positioned elements.
+        z_index	: "z-index	",
+
     }
     aria_trait_methods! {
         aria_current: "aria-current",

+ 9 - 10
packages/web/examples/async_web.rs

@@ -32,34 +32,33 @@ struct DogApi {
 const ENDPOINT: &str = "https://dog.ceo/api/breeds/image/random/";
 
 static App: FC<()> = |cx| {
-    // let mut count = use_state(cx, || 0);
     let state = use_state(cx, || 0);
-    let set_val = state.setter();
 
-    let (tas, g) = cx.use_task(|| async move {
-        set_val(10);
-        surf::get(ENDPOINT).recv_json::<DogApi>().await
-    });
+    let request = cx.use_task(|| surf::get(ENDPOINT).recv_json::<DogApi>()).1;
 
-    let dog_node = match g.as_ref().and_then(|f| f.as_ref().ok()) {
-        Some(res) => rsx!(in cx, img { src: "{res.message}" }),
-        None => rsx!(in cx, div { "No doggos for you :(" }),
+    let dog_node = if let Some(Ok(res)) = request {
+        rsx!(in cx, img { src: "{res.message}" })
+    } else {
+        rsx!(in cx, div { "No doggos for you :(" })
     };
 
     cx.render(rsx! {
         div {
+            style: {
+                align_items: "center"
+            }
             section { class: "py-12 px-4 text-center"
                 div { class: "w-full max-w-2xl mx-auto"
                     span { class: "text-sm font-semibold"
                         "count: {state}"
                     }
+                    br {}
                     div {
                         button {
                             onclick: move |_| state.set(state + 1)
                             "incr"
                         }
                         br {}
-                        br {}
                         button {
                             onclick: move |_| state.set(state - 1)
                             "decr"

+ 3 - 0
packages/web/examples/blah.rs

@@ -28,6 +28,9 @@ static App: FC<()> = |cx| {
     let mut state = use_state(cx, || 0);
     cx.render(rsx! {
         div {
+            style: {
+                align_items: "center"
+            }
             section { class: "py-12 px-4 text-center"
                 div { class: "w-full max-w-2xl mx-auto"
                     span { class: "text-sm font-semibold"

+ 2 - 17
packages/web/src/lib.rs

@@ -99,8 +99,6 @@ impl WebsysRenderer {
 
             if let Some(real_trigger) = trigger {
                 log::info!("event received");
-                // let root_node = body_element.first_child().unwrap();
-                // websys_dom.stack.push(root_node.clone());
 
                 self.internal_dom.queue_event(real_trigger)?;
 
@@ -110,23 +108,10 @@ impl WebsysRenderer {
                     .await?;
                 websys_dom.process_edits(&mut edits);
             }
-
-            // let t2 = self.internal_dom.tasks.next();
-            // futures::select! {
-            //     trigger = t1 => {
-            //         log::info!("event received");
-            //         let root_node = body_element.first_child().unwrap();
-            //         websys_dom.stack.push(root_node.clone());
-            //         self.internal_dom
-            //             .progress_with_event(&mut websys_dom, trigger)?;
-            //     },
-            //     () = t2 => {}
-            // };
         }
-        // while let Some(trigger) = websys_dom.wait_for_event().await {
-        // }
 
-        Ok(()) // should actually never return from this, should be an error, rustc just cant see it
+        // should actually never return from this, should be an error, rustc just cant see it
+        Ok(())
     }
 }
 

+ 14 - 19
packages/web/src/new.rs

@@ -74,7 +74,7 @@ impl WebsysDom {
         for edit in edits.drain(..) {
             log::info!("Handling edit: {:#?}", edit);
             match edit {
-                DomEdit::PushRoot { root } => self.push(root),
+                DomEdit::PushRoot { id: root } => self.push(root),
                 DomEdit::PopRoot => self.pop(),
                 DomEdit::AppendChildren { many } => self.append_children(many),
                 DomEdit::ReplaceWith { many } => self.replace_with(many),
@@ -97,8 +97,8 @@ impl WebsysDom {
             }
         }
     }
-    fn push(&mut self, root: RealDomNode) {
-        let key = root.0;
+    fn push(&mut self, root: u64) {
+        let key = DefaultKey::from(KeyData::from_ffi(root));
         let domnode = self.nodes.get_mut(key);
 
         let domnode = domnode.unwrap().as_mut().unwrap();
@@ -186,10 +186,10 @@ impl WebsysDom {
         todo!()
     }
 
-    fn create_placeholder(&mut self, id: RealDomNode) {
+    fn create_placeholder(&mut self, id: u64) {
         self.create_element("pre", None, id)
     }
-    fn create_text_node(&mut self, text: &str, id: RealDomNode) {
+    fn create_text_node(&mut self, text: &str, id: u64) {
         // let nid = self.node_counter.next();
 
         let textnode = self
@@ -199,18 +199,13 @@ impl WebsysDom {
             .unwrap();
 
         self.stack.push(textnode.clone());
-        let mut slot = self.nodes.get_mut(id.0).unwrap();
-        *slot = Some(textnode);
-
-        // let nid = self.nodes.insert(textnode);
-        // let nid = nid.data().as_ffi();
-
-        // log::debug!("Called [`create_text_node`]: {}, {}", text, nid);
-
-        // RealDomNode::new(nid)
+        *self
+            .nodes
+            .get_mut(DefaultKey::from(KeyData::from_ffi(id)))
+            .unwrap() = Some(textnode);
     }
 
-    fn create_element(&mut self, tag: &str, ns: Option<&'static str>, id: RealDomNode) {
+    fn create_element(&mut self, tag: &str, ns: Option<&'static str>, id: u64) {
         let tag = wasm_bindgen::intern(tag);
         let el = match ns {
             Some(ns) => self
@@ -226,10 +221,10 @@ impl WebsysDom {
                 .dyn_into::<Node>()
                 .unwrap(),
         };
+        let id = DefaultKey::from(KeyData::from_ffi(id));
 
         self.stack.push(el.clone());
-        let mut slot = self.nodes.get_mut(id.0).unwrap();
-        *slot = Some(el);
+        *self.nodes.get_mut(id).unwrap() = Some(el);
         // let nid = self.node_counter.?next();
         // let nid = self.nodes.insert(el).data().as_ffi();
         // log::debug!("Called [`create_element`]: {}, {:?}", tag, nid);
@@ -241,7 +236,7 @@ impl WebsysDom {
         event: &'static str,
         scope: ScopeIdx,
         _element_id: usize,
-        real_id: RealDomNode,
+        real_id: u64,
     ) {
         let (_on, event) = event.split_at(2);
         let event = wasm_bindgen::intern(event);
@@ -260,7 +255,7 @@ impl WebsysDom {
         let scope_id = scope.data().as_ffi();
         el.set_attribute(
             &format!("dioxus-event-{}", event),
-            &format!("{}.{}", scope_id, real_id.0.data().as_ffi()),
+            &format!("{}.{}", scope_id, real_id),
         )
         .unwrap();
 

+ 1 - 1
src/lib.rs

@@ -108,7 +108,7 @@
 //! fn my_hook<'a>(cx: &impl Scoped<'a>) -> &'a String {
 //!     cx.use_hook(
 //!         // Initializer stores a value
-//!         || String::new("stored_data"),
+//!         |hook_idx| String::new("stored_data"),
 //!           
 //!         // Runner returns the hook value every time the component is rendered
 //!         |hook| &*hook,

+ 0 - 0
wip.md