Feat: solve some issues regarding listeners
This commit is contained in:
1 parent
6084fbcd11
commit
dfaf5adee1
22 files changed
+192
-168
No files matched your search
@@ -25,7 +25,7 @@ The current `RealDom` trait lives in `dioxus_core/diff`. A version of it is prov
|
|||||||
```rust
|
```rust
|
||||||
pub trait RealDom<'a> {
|
pub trait RealDom<'a> {
|
||||||
fn handle_edit(&mut self, edit: DomEdit);
|
fn handle_edit(&mut self, edit: DomEdit);
|
||||||
fn request_available_node(&mut self) -> RealDomNode;
|
fn request_available_node(&mut self) -> ElementId;
|
||||||
fn raw_node_as_any(&self) -> &mut dyn Any;
|
fn raw_node_as_any(&self) -> &mut dyn Any;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let g = dioxus::prelude::LazyNodes::new(move |__cx: NodeFactory| {
|
||||||
|
use dioxus_elements::{GlobalAttributes, SvgAttributes};
|
||||||
|
__cx.element(
|
||||||
|
dioxus_elements::button,
|
||||||
|
__cx.bump()
|
||||||
|
.alloc([dioxus::events::on::onclick(__cx, move |_| {})]),
|
||||||
|
__cx.bump().alloc([]),
|
||||||
|
__cx.bump().alloc([]),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
+2
-1
@@ -3,7 +3,7 @@ use std::cell::Cell;
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use dioxus_core::{
|
use dioxus_core::{
|
||||||
nodes::{VElement, VText},
|
nodes::{VElement, VText},
|
||||||
RealDomNode,
|
ElementId,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@@ -33,6 +33,7 @@ const Example: FC<()> = |cx| {
|
|||||||
}
|
}
|
||||||
"h4"
|
"h4"
|
||||||
div { "h5" }
|
div { "h5" }
|
||||||
|
button { }
|
||||||
Child {}
|
Child {}
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -502,7 +502,6 @@ mod field_info {
|
|||||||
|
|
||||||
mod struct_info {
|
mod struct_info {
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::__private::ext::RepToTokensExt;
|
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::parse::Error;
|
use syn::parse::Error;
|
||||||
|
|
||||||
@@ -1095,13 +1094,6 @@ Finally, call `.build()` to create the instance of `{name}`.
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_props_impl(&self) -> TokenStream {
|
|
||||||
// SomeProps: #name
|
|
||||||
// #builder_name
|
|
||||||
// #generics_with_empty
|
|
||||||
quote! {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
|||||||
@@ -199,9 +199,12 @@ impl<const AS: HTML_OR_RSX> ToTokens for Element<AS> {
|
|||||||
tokens.append_all(quote! {
|
tokens.append_all(quote! {
|
||||||
__cx.element(
|
__cx.element(
|
||||||
dioxus_elements::#name,
|
dioxus_elements::#name,
|
||||||
__cx.bump().alloc([ #(#listeners),* ]),
|
[ #(#listeners),* ],
|
||||||
__cx.bump().alloc([ #(#attr),* ]),
|
[ #(#attr),* ],
|
||||||
__cx.bump().alloc([ #(#childs),* ]),
|
[ #(#childs),* ],
|
||||||
|
// __cx.bump().alloc([ #(#listeners),* ]),
|
||||||
|
// __cx.bump().alloc([ #(#attr),* ]),
|
||||||
|
// __cx.bump().alloc([ #(#childs),* ]),
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ use slab::Slab;
|
|||||||
// #[cfg(feature = "serialize", serde::Serialize)]
|
// #[cfg(feature = "serialize", serde::Serialize)]
|
||||||
// #[cfg(feature = "serialize", serde::Serialize)]
|
// #[cfg(feature = "serialize", serde::Serialize)]
|
||||||
#[derive(serde::Serialize, serde::Deserialize, Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(serde::Serialize, serde::Deserialize, Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
pub struct ScopeId(usize);
|
pub struct ScopeId(pub usize);
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
pub struct ElementId(usize);
|
pub struct ElementId(pub usize);
|
||||||
|
|
||||||
impl ElementId {
|
impl ElementId {
|
||||||
pub fn as_u64(self) -> u64 {
|
pub fn as_u64(self) -> u64 {
|
||||||
|
|||||||
@@ -34,12 +34,16 @@
|
|||||||
//! For all components, we employ some basic heuristics to speed up allocations and pre-size bump arenas. The heuristics are
|
//! For all components, we employ some basic heuristics to speed up allocations and pre-size bump arenas. The heuristics are
|
||||||
//! currently very rough, but will get better as time goes on. For FFI, we recommend using a bloom filter to cache strings.
|
//! currently very rough, but will get better as time goes on. For FFI, we recommend using a bloom filter to cache strings.
|
||||||
//!
|
//!
|
||||||
|
//!
|
||||||
//! ## Garbage Collection
|
//! ## Garbage Collection
|
||||||
//! ---------------------
|
//! ---------------------
|
||||||
//! Dioxus uses a passive garbage collection system to clean up old nodes once the work has been completed. This garabge
|
//! Dioxus uses a passive garbage collection system to clean up old nodes once the work has been completed. This garabge
|
||||||
//! collection is done internally once the main diffing work is complete. After the "garbage" is collected, Dioxus will then
|
//! collection is done internally once the main diffing work is complete. After the "garbage" is collected, Dioxus will then
|
||||||
//! start to re-use old keys for new nodes. This results in a passive memory management system that is very efficient.
|
//! start to re-use old keys for new nodes. This results in a passive memory management system that is very efficient.
|
||||||
//!
|
//!
|
||||||
|
//! The IDs used by the key/map are just an index into a vec. This means that Dioxus will drive the key allocation strategy
|
||||||
|
//! so the client only needs to maintain a simple list of nodes. By default, Dioxus will not manually clean up old nodes
|
||||||
|
//! for the client. As new nodes are created, old nodes will be over-written.
|
||||||
//!
|
//!
|
||||||
//! Further Reading and Thoughts
|
//! Further Reading and Thoughts
|
||||||
//! ----------------------------
|
//! ----------------------------
|
||||||
@@ -53,10 +57,9 @@ use smallvec::{smallvec, SmallVec};
|
|||||||
|
|
||||||
use std::{any::Any, borrow::Borrow};
|
use std::{any::Any, borrow::Borrow};
|
||||||
|
|
||||||
/// Instead of having handles directly over nodes, Dioxus uses simple u64s as node IDs.
|
/// Instead of having handles directly over nodes, Dioxus uses simple u32 as node IDs.
|
||||||
/// The expectation is that the underlying renderer will mainain their Nodes in something like slotmap or an ECS memory
|
/// The expectation is that the underlying renderer will mainain their Nodes in vec where the ids are the index. This allows
|
||||||
/// where indexing is very fast. For reference, the slotmap in the WebSys renderer takes about 3ns to randomly access any
|
/// for a form of passive garbage collection where nodes aren't immedately cleaned up.
|
||||||
/// node.
|
|
||||||
///
|
///
|
||||||
/// The "RealDom" abstracts over the... real dom. The RealDom trait assumes that the renderer maintains a stack of real
|
/// The "RealDom" abstracts over the... real dom. The RealDom trait assumes that the renderer maintains a stack of real
|
||||||
/// nodes as the diffing algorithm descenes through the tree. This means that whatever is on top of the stack will receive
|
/// nodes as the diffing algorithm descenes through the tree. This means that whatever is on top of the stack will receive
|
||||||
@@ -531,7 +534,7 @@ impl<'a, 'bump> DiffMachine<'a, 'bump> {
|
|||||||
// [... node]
|
// [... node]
|
||||||
//
|
//
|
||||||
// The change list stack is left unchanged.
|
// The change list stack is left unchanged.
|
||||||
fn diff_listeners(&mut self, old: &[&mut Listener<'_>], new: &[&mut Listener<'_>]) {
|
fn diff_listeners(&mut self, old: &[Listener<'_>], new: &[Listener<'_>]) {
|
||||||
if !old.is_empty() || !new.is_empty() {
|
if !old.is_empty() || !new.is_empty() {
|
||||||
// self.edits.commit_traversal();
|
// self.edits.commit_traversal();
|
||||||
}
|
}
|
||||||
@@ -721,7 +724,6 @@ impl<'a, 'bump> DiffMachine<'a, 'bump> {
|
|||||||
//
|
//
|
||||||
// Upon exiting, the change list stack is in the same state.
|
// Upon exiting, the change list stack is in the same state.
|
||||||
fn diff_keyed_children(&mut self, old: &'bump [VNode<'bump>], new: &'bump [VNode<'bump>]) {
|
fn diff_keyed_children(&mut self, old: &'bump [VNode<'bump>], new: &'bump [VNode<'bump>]) {
|
||||||
// todo!();
|
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
let mut keys = fxhash::FxHashSet::default();
|
let mut keys = fxhash::FxHashSet::default();
|
||||||
let mut assert_unique_keys = |children: &'bump [VNode<'bump>]| {
|
let mut assert_unique_keys = |children: &'bump [VNode<'bump>]| {
|
||||||
|
|||||||
@@ -4,7 +4,10 @@
|
|||||||
//! 3rd party renderers are responsible for converting their native events into these virtual event types. Events might
|
//! 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.
|
//! be heavy or need to interact through FFI, so the events themselves are designed to be lazy.
|
||||||
|
|
||||||
use std::{cell::Cell, rc::Rc};
|
use std::{
|
||||||
|
cell::{Cell, RefCell},
|
||||||
|
rc::Rc,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::innerlude::{ElementId, HeightMarker, ScopeId};
|
use crate::innerlude::{ElementId, HeightMarker, ScopeId};
|
||||||
|
|
||||||
@@ -135,7 +138,7 @@ pub mod on {
|
|||||||
//!
|
//!
|
||||||
|
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
use std::{fmt::Debug, ops::Deref, rc::Rc};
|
use std::{cell::RefCell, fmt::Debug, ops::Deref, rc::Rc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
innerlude::NodeFactory,
|
innerlude::NodeFactory,
|
||||||
@@ -183,10 +186,10 @@ pub mod on {
|
|||||||
event: stringify!($name),
|
event: stringify!($name),
|
||||||
mounted_node: Cell::new(None),
|
mounted_node: Cell::new(None),
|
||||||
scope: c.scope.our_arena_idx,
|
scope: c.scope.our_arena_idx,
|
||||||
callback: bump.alloc(move |evt: VirtualEvent| match evt {
|
callback: RefCell::new(bump.alloc(move |evt: VirtualEvent| match evt {
|
||||||
VirtualEvent::$wrapper(event) => callback(event),
|
VirtualEvent::$wrapper(event) => callback(event),
|
||||||
_ => unreachable!("Downcasted VirtualEvent to wrong event type - this is an internal bug!")
|
_ => unreachable!("Downcasted VirtualEvent to wrong event type - this is an internal bug!")
|
||||||
}),
|
})),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
|
|||||||
+37
-19
@@ -8,7 +8,7 @@ use crate::{
|
|||||||
innerlude::{empty_cell, Context, DomTree, ElementId, Properties, Scope, ScopeId, FC},
|
innerlude::{empty_cell, Context, DomTree, ElementId, Properties, Scope, ScopeId, FC},
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
cell::Cell,
|
cell::{Cell, RefCell},
|
||||||
fmt::{Arguments, Debug, Formatter},
|
fmt::{Arguments, Debug, Formatter},
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
@@ -77,7 +77,7 @@ pub struct VElement<'a> {
|
|||||||
pub namespace: Option<&'static str>,
|
pub namespace: Option<&'static str>,
|
||||||
|
|
||||||
pub static_listeners: bool,
|
pub static_listeners: bool,
|
||||||
pub listeners: &'a [&'a mut Listener<'a>],
|
pub listeners: &'a [Listener<'a>],
|
||||||
|
|
||||||
pub static_attrs: bool,
|
pub static_attrs: bool,
|
||||||
pub attributes: &'a [Attribute<'a>],
|
pub attributes: &'a [Attribute<'a>],
|
||||||
@@ -112,7 +112,7 @@ pub struct Listener<'bump> {
|
|||||||
|
|
||||||
pub mounted_node: Cell<Option<ElementId>>,
|
pub mounted_node: Cell<Option<ElementId>>,
|
||||||
|
|
||||||
pub(crate) callback: &'bump mut dyn FnMut(VirtualEvent),
|
pub(crate) callback: RefCell<&'bump mut dyn FnMut(VirtualEvent)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Virtual Components for custom user-defined components
|
/// Virtual Components for custom user-defined components
|
||||||
@@ -200,14 +200,19 @@ impl<'a> NodeFactory<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn element(
|
pub fn element<L, A, V>(
|
||||||
&self,
|
&self,
|
||||||
el: impl DioxusElement,
|
el: impl DioxusElement,
|
||||||
listeners: &'a mut [&'a mut Listener<'a>],
|
listeners: L,
|
||||||
attributes: &'a [Attribute<'a>],
|
attributes: A,
|
||||||
children: &'a [VNode<'a>],
|
children: V,
|
||||||
key: Option<&'a str>,
|
key: Option<&'a str>,
|
||||||
) -> VNode<'a> {
|
) -> VNode<'a>
|
||||||
|
where
|
||||||
|
L: 'a + AsRef<[Listener<'a>]>,
|
||||||
|
A: 'a + AsRef<[Attribute<'a>]>,
|
||||||
|
V: 'a + AsRef<[VNode<'a>]>,
|
||||||
|
{
|
||||||
self.raw_element(
|
self.raw_element(
|
||||||
el.tag_name(),
|
el.tag_name(),
|
||||||
el.namespace(),
|
el.namespace(),
|
||||||
@@ -218,26 +223,39 @@ impl<'a> NodeFactory<'a> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn raw_element(
|
pub fn raw_element<L, A, V>(
|
||||||
&self,
|
&self,
|
||||||
tag: &'static str,
|
tag: &'static str,
|
||||||
namespace: Option<&'static str>,
|
namespace: Option<&'static str>,
|
||||||
listeners: &'a mut [&'a mut Listener<'a>],
|
listeners: L,
|
||||||
attributes: &'a [Attribute],
|
attributes: A,
|
||||||
children: &'a [VNode<'a>],
|
children: V,
|
||||||
key: Option<&'a str>,
|
key: Option<&'a str>,
|
||||||
) -> VNode<'a> {
|
) -> VNode<'a>
|
||||||
|
where
|
||||||
|
L: 'a + AsRef<[Listener<'a>]>,
|
||||||
|
A: 'a + AsRef<[Attribute<'a>]>,
|
||||||
|
V: 'a + AsRef<[VNode<'a>]>,
|
||||||
|
{
|
||||||
|
let listeners: &'a L = self.bump().alloc(listeners);
|
||||||
|
let listeners = listeners.as_ref();
|
||||||
|
|
||||||
|
let attributes: &'a A = self.bump().alloc(attributes);
|
||||||
|
let attributes = attributes.as_ref();
|
||||||
|
|
||||||
|
let children: &'a V = self.bump().alloc(children);
|
||||||
|
let children = children.as_ref();
|
||||||
|
|
||||||
// We take the references directly from the bump arena
|
// We take the references directly from the bump arena
|
||||||
|
//
|
||||||
|
//
|
||||||
// TODO: this code shouldn't necessarily be here of all places
|
// TODO: this code shouldn't necessarily be here of all places
|
||||||
// It would make more sense to do this in diffing
|
// It would make more sense to do this in diffing
|
||||||
|
|
||||||
let mut queue = self.scope.listeners.borrow_mut();
|
let mut queue = self.scope.listeners.borrow_mut();
|
||||||
for listener in listeners.iter_mut() {
|
for listener in listeners.iter() {
|
||||||
let raw_listener = &mut **listener;
|
let long_listener: &Listener<'static> = unsafe { std::mem::transmute(listener) };
|
||||||
|
queue.push(long_listener as *const _)
|
||||||
let long_listener: &mut Listener<'static> =
|
|
||||||
unsafe { std::mem::transmute(raw_listener) };
|
|
||||||
queue.push(long_listener as *mut _)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VNode {
|
VNode {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use crate::innerlude::*;
|
use crate::innerlude::*;
|
||||||
|
use bumpalo::boxed::Box as BumpBox;
|
||||||
use std::{
|
use std::{
|
||||||
any::{Any, TypeId},
|
any::{Any, TypeId},
|
||||||
cell::{Cell, RefCell},
|
cell::{Cell, RefCell},
|
||||||
@@ -31,7 +32,7 @@ pub struct Scope {
|
|||||||
pub(crate) child_nodes: &'static [VNode<'static>],
|
pub(crate) child_nodes: &'static [VNode<'static>],
|
||||||
|
|
||||||
// Listeners
|
// Listeners
|
||||||
pub(crate) listeners: RefCell<Vec<*mut Listener<'static>>>,
|
pub(crate) listeners: RefCell<Vec<*const Listener<'static>>>,
|
||||||
pub(crate) listener_idx: Cell<usize>,
|
pub(crate) listener_idx: Cell<usize>,
|
||||||
|
|
||||||
// State
|
// State
|
||||||
@@ -154,7 +155,7 @@ impl Scope {
|
|||||||
let listners = self.listeners.borrow_mut();
|
let listners = self.listeners.borrow_mut();
|
||||||
|
|
||||||
let raw_listener = listners.iter().find(|lis| {
|
let raw_listener = listners.iter().find(|lis| {
|
||||||
let search = unsafe { &mut ***lis };
|
let search = unsafe { &***lis };
|
||||||
let search_id = search.mounted_node.get();
|
let search_id = search.mounted_node.get();
|
||||||
log::info!("searching listener {:#?}", search_id);
|
log::info!("searching listener {:#?}", search_id);
|
||||||
|
|
||||||
@@ -165,8 +166,9 @@ impl Scope {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if let Some(raw_listener) = raw_listener {
|
if let Some(raw_listener) = raw_listener {
|
||||||
let listener = unsafe { &mut **raw_listener };
|
let listener = unsafe { &**raw_listener };
|
||||||
(listener.callback)(event);
|
let mut cb = listener.callback.borrow_mut();
|
||||||
|
(cb)(event);
|
||||||
} else {
|
} else {
|
||||||
log::warn!("An event was triggered but there was no listener to handle it");
|
log::warn!("An event was triggered but there was no listener to handle it");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -181,8 +181,8 @@ impl VirtualDom {
|
|||||||
/// The diff machine expects the RealDom's stack to be the root of the application
|
/// The diff machine expects the RealDom's stack to be the root of the application
|
||||||
pub fn rebuild<'s>(
|
pub fn rebuild<'s>(
|
||||||
&'s mut self,
|
&'s mut self,
|
||||||
realdom: &'s mut dyn RealDom<'s>,
|
realdom: &'_ mut dyn RealDom<'s>,
|
||||||
edits: &'s mut Vec<DomEdit<'s>>,
|
edits: &'_ mut Vec<DomEdit<'s>>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut diff_machine = DiffMachine::new(edits, realdom, self.base_scope, &self.shared);
|
let mut diff_machine = DiffMachine::new(edits, realdom, self.base_scope, &self.shared);
|
||||||
|
|
||||||
@@ -355,6 +355,10 @@ impl VirtualDom {
|
|||||||
pub fn base_scope(&self) -> &Scope {
|
pub fn base_scope(&self) -> &Scope {
|
||||||
unsafe { self.shared.get_scope(self.base_scope).unwrap() }
|
unsafe { self.shared.get_scope(self.base_scope).unwrap() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_scope(&self, id: ScopeId) -> Option<&Scope> {
|
||||||
|
unsafe { self.shared.get_scope(id) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO!
|
// TODO!
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ wry = "0.11.0"
|
|||||||
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
dioxus-html = { path = "../html" }
|
||||||
tide = "0.15.0"
|
tide = "0.15.0"
|
||||||
tide-websockets = "0.3.0"
|
tide-websockets = "0.3.0"
|
||||||
async-std = { version = "1.9.0", features = ["attributes"] }
|
async-std = { version = "1.9.0", features = ["attributes"] }
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use dioxus_core as dioxus;
|
use dioxus_core as dioxus;
|
||||||
use dioxus_core::prelude::*;
|
use dioxus_core::prelude::*;
|
||||||
|
use dioxus_html as dioxus_elements;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(App, |f| f.with_maximized(true)).expect("Failed");
|
dioxus_desktop::launch(App, |f| f.with_maximized(true)).expect("Failed");
|
||||||
@@ -13,13 +14,3 @@ static App: FC<()> = |cx| {
|
|||||||
}
|
}
|
||||||
))
|
))
|
||||||
};
|
};
|
||||||
|
|
||||||
mod dioxus_elements {
|
|
||||||
use super::*;
|
|
||||||
pub struct div;
|
|
||||||
impl DioxusElement for div {
|
|
||||||
const TAG_NAME: &'static str = "div";
|
|
||||||
const NAME_SPACE: Option<&'static str> = None;
|
|
||||||
}
|
|
||||||
pub trait GlobalAttributes {}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
//! webview dom
|
//! webview dom
|
||||||
|
|
||||||
use dioxus_core::{DomEdit, RealDom, RealDomNode, ScopeId};
|
use dioxus_core::{DomEdit, RealDom};
|
||||||
use DomEdit::*;
|
|
||||||
|
|
||||||
pub struct WebviewRegistry {}
|
pub struct WebviewRegistry {}
|
||||||
|
|
||||||
@@ -35,9 +34,4 @@ impl<'bump> RealDom<'bump> for WebviewDom<'bump> {
|
|||||||
todo!()
|
todo!()
|
||||||
// self.edits.push(PushRoot { root });
|
// self.edits.push(PushRoot { root });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn request_available_node(&mut self) -> RealDomNode {
|
|
||||||
self.node_counter += 1;
|
|
||||||
RealDomNode::from_u64(self.node_counter)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -8,9 +8,7 @@
|
|||||||
this.stack = [root];
|
this.stack = [root];
|
||||||
this.listeners = {};
|
this.listeners = {};
|
||||||
this.lastNodeWasText = false;
|
this.lastNodeWasText = false;
|
||||||
this.nodes = {
|
this.nodes = [];
|
||||||
0: root
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
top() {
|
top() {
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
trait AsAttributeValue: Sized {
|
||||||
|
fn into_attribute_value<'a>(self, cx: NodeFactory<'a>) -> AttributeValue<'a>;
|
||||||
|
}
|
||||||
|
enum AttributeValue<'a> {
|
||||||
|
Int(i32),
|
||||||
|
Float(f32),
|
||||||
|
Str(&'a str),
|
||||||
|
Bool(bool),
|
||||||
|
}
|
||||||
|
impl<'b> AsAttributeValue for Arguments<'b> {
|
||||||
|
fn into_attribute_value<'a>(self, cx: NodeFactory<'a>) -> AttributeValue<'a> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl AsAttributeValue for &'static str {
|
||||||
|
fn into_attribute_value<'a>(self, cx: NodeFactory<'a>) -> AttributeValue<'a> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl AsAttributeValue for f32 {
|
||||||
|
fn into_attribute_value<'a>(self, cx: NodeFactory<'a>) -> AttributeValue<'a> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl AsAttributeValue for i32 {
|
||||||
|
fn into_attribute_value<'a>(self, cx: NodeFactory<'a>) -> AttributeValue<'a> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#![allow(non_snake_case)]
|
||||||
//! # Dioxus Namespace for HTML
|
//! # Dioxus Namespace for HTML
|
||||||
//!
|
//!
|
||||||
//! This crate provides a set of compile-time correct HTML elements that can be used with the Rsx and Html macros.
|
//! This crate provides a set of compile-time correct HTML elements that can be used with the Rsx and Html macros.
|
||||||
@@ -2100,33 +2101,3 @@ summary
|
|||||||
slot
|
slot
|
||||||
template
|
template
|
||||||
*/
|
*/
|
||||||
|
|
||||||
trait AsAttributeValue: Sized {
|
|
||||||
fn into_attribute_value<'a>(self, cx: NodeFactory<'a>) -> AttributeValue<'a>;
|
|
||||||
}
|
|
||||||
enum AttributeValue<'a> {
|
|
||||||
Int(i32),
|
|
||||||
Float(f32),
|
|
||||||
Str(&'a str),
|
|
||||||
Bool(bool),
|
|
||||||
}
|
|
||||||
impl<'b> AsAttributeValue for Arguments<'b> {
|
|
||||||
fn into_attribute_value<'a>(self, cx: NodeFactory<'a>) -> AttributeValue<'a> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl AsAttributeValue for &'static str {
|
|
||||||
fn into_attribute_value<'a>(self, cx: NodeFactory<'a>) -> AttributeValue<'a> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl AsAttributeValue for f32 {
|
|
||||||
fn into_attribute_value<'a>(self, cx: NodeFactory<'a>) -> AttributeValue<'a> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl AsAttributeValue for i32 {
|
|
||||||
fn into_attribute_value<'a>(self, cx: NodeFactory<'a>) -> AttributeValue<'a> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
//! webview dom
|
//! webview dom
|
||||||
|
|
||||||
use dioxus_core::{DomEdit, RealDom, RealDomNode, ScopeId};
|
use dioxus_core::{DomEdit, ElementId, RealDom, ScopeId};
|
||||||
use DomEdit::*;
|
use DomEdit::*;
|
||||||
|
|
||||||
pub struct WebviewRegistry {}
|
pub struct WebviewRegistry {}
|
||||||
@@ -35,9 +35,4 @@ impl<'bump> RealDom<'bump> for WebviewDom<'bump> {
|
|||||||
todo!()
|
todo!()
|
||||||
// self.edits.push(PushRoot { root });
|
// self.edits.push(PushRoot { root });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn request_available_node(&mut self) -> RealDomNode {
|
|
||||||
self.node_counter += 1;
|
|
||||||
RealDomNode::from_u64(self.node_counter)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+19
-19
@@ -21,7 +21,7 @@ pub fn render_vdom_scope(vdom: &VirtualDom, scope: ScopeId) -> Option<String> {
|
|||||||
"{:}",
|
"{:}",
|
||||||
TextRenderer {
|
TextRenderer {
|
||||||
cfg: SsrConfig::default(),
|
cfg: SsrConfig::default(),
|
||||||
root: vdom.shared.get_scope(scope).unwrap().root(),
|
root: vdom.get_scope(scope).unwrap().root(),
|
||||||
vdom: Some(vdom)
|
vdom: Some(vdom)
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
@@ -163,7 +163,7 @@ impl<'a> TextRenderer<'a> {
|
|||||||
VNodeKind::Component(vcomp) => {
|
VNodeKind::Component(vcomp) => {
|
||||||
let idx = vcomp.ass_scope.get().unwrap();
|
let idx = vcomp.ass_scope.get().unwrap();
|
||||||
if let Some(vdom) = self.vdom {
|
if let Some(vdom) = self.vdom {
|
||||||
let new_node = vdom.shared.get_scope(idx).unwrap().root();
|
let new_node = vdom.get_scope(idx).unwrap().root();
|
||||||
self.html_render(new_node, f, il + 1)?;
|
self.html_render(new_node, f, il + 1)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -260,22 +260,22 @@ mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
// #[test]
|
||||||
fn styles() {
|
// fn styles() {
|
||||||
const STLYE_APP: FC<()> = |cx| {
|
// const STLYE_APP: FC<()> = |cx| {
|
||||||
//
|
// //
|
||||||
cx.render(rsx! {
|
// cx.render(rsx! {
|
||||||
div {
|
// div {
|
||||||
style: {
|
// style: {
|
||||||
color: "blue",
|
// color: "blue",
|
||||||
font_size: "46px"
|
// font_size: "46px"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
};
|
// };
|
||||||
|
|
||||||
let mut dom = VirtualDom::new(STLYE_APP);
|
// let mut dom = VirtualDom::new(STLYE_APP);
|
||||||
dom.rebuild_in_place().expect("failed to run virtualdom");
|
// dom.rebuild_in_place().expect("failed to run virtualdom");
|
||||||
dbg!(render_vdom(&dom));
|
// dbg!(render_vdom(&dom));
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
@@ -23,7 +23,6 @@ wasm-bindgen-test = "0.3.21"
|
|||||||
once_cell = "1.8"
|
once_cell = "1.8"
|
||||||
async-channel = "1.6.1"
|
async-channel = "1.6.1"
|
||||||
anyhow = "1.0.41"
|
anyhow = "1.0.41"
|
||||||
slotmap = "1.0.3"
|
|
||||||
|
|
||||||
futures-util = "0.3.15"
|
futures-util = "0.3.15"
|
||||||
|
|
||||||
|
|||||||
+26
-25
@@ -68,36 +68,37 @@ pub async fn event_loop(mut internal_dom: VirtualDom) -> dioxus_core::error::Res
|
|||||||
|
|
||||||
log::info!("Going into event loop");
|
log::info!("Going into event loop");
|
||||||
loop {
|
loop {
|
||||||
let trigger = {
|
todo!();
|
||||||
let real_queue = websys_dom.wait_for_event();
|
// let trigger = {
|
||||||
if internal_dom.tasks.is_empty() {
|
// let real_queue = websys_dom.wait_for_event();
|
||||||
log::info!("tasks is empty, waiting for dom event to trigger soemthing");
|
// if internal_dom.tasks.is_empty() {
|
||||||
real_queue.await
|
// log::info!("tasks is empty, waiting for dom event to trigger soemthing");
|
||||||
} else {
|
// real_queue.await
|
||||||
log::info!("tasks is not empty, waiting for either tasks or event system");
|
// } else {
|
||||||
let task_queue = (&mut internal_dom.tasks).next();
|
// log::info!("tasks is not empty, waiting for either tasks or event system");
|
||||||
|
// let task_queue = (&mut internal_dom.tasks).next();
|
||||||
|
|
||||||
pin_mut!(real_queue);
|
// pin_mut!(real_queue);
|
||||||
pin_mut!(task_queue);
|
// pin_mut!(task_queue);
|
||||||
|
|
||||||
match futures_util::future::select(real_queue, task_queue).await {
|
// match futures_util::future::select(real_queue, task_queue).await {
|
||||||
futures_util::future::Either::Left((trigger, _)) => trigger,
|
// futures_util::future::Either::Left((trigger, _)) => trigger,
|
||||||
futures_util::future::Either::Right((trigger, _)) => trigger,
|
// futures_util::future::Either::Right((trigger, _)) => trigger,
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
if let Some(real_trigger) = trigger {
|
// if let Some(real_trigger) = trigger {
|
||||||
log::info!("event received");
|
// log::info!("event received");
|
||||||
|
|
||||||
internal_dom.queue_event(real_trigger)?;
|
// internal_dom.queue_event(real_trigger);
|
||||||
|
|
||||||
let mut edits = Vec::new();
|
// let mut edits = Vec::new();
|
||||||
internal_dom
|
// internal_dom
|
||||||
.progress_with_event(&mut websys_dom, &mut edits)
|
// .progress_with_event(&mut websys_dom, &mut edits)
|
||||||
.await?;
|
// .await?;
|
||||||
websys_dom.process_edits(&mut edits);
|
// websys_dom.process_edits(&mut edits);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
|
|||||||
+21
-17
@@ -5,7 +5,6 @@ use dioxus_core::{
|
|||||||
DomEdit, ElementId, ScopeId,
|
DomEdit, ElementId, ScopeId,
|
||||||
};
|
};
|
||||||
use fxhash::FxHashMap;
|
use fxhash::FxHashMap;
|
||||||
use slotmap::{DefaultKey, Key, KeyData};
|
|
||||||
use wasm_bindgen::{closure::Closure, JsCast};
|
use wasm_bindgen::{closure::Closure, JsCast};
|
||||||
use web_sys::{
|
use web_sys::{
|
||||||
window, Document, Element, Event, HtmlElement, HtmlInputElement, HtmlOptionElement, Node,
|
window, Document, Element, Event, HtmlElement, HtmlInputElement, HtmlOptionElement, Node,
|
||||||
@@ -13,7 +12,7 @@ use web_sys::{
|
|||||||
|
|
||||||
pub struct WebsysDom {
|
pub struct WebsysDom {
|
||||||
pub stack: Stack,
|
pub stack: Stack,
|
||||||
nodes: slotmap::SlotMap<DefaultKey, Node>,
|
nodes: Vec<Node>,
|
||||||
document: Document,
|
document: Document,
|
||||||
root: Element,
|
root: Element,
|
||||||
|
|
||||||
@@ -49,9 +48,9 @@ impl WebsysDom {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut nodes = slotmap::SlotMap::with_capacity(1000);
|
let mut nodes = Vec::with_capacity(1000);
|
||||||
|
|
||||||
let root_id = nodes.insert(root.clone().dyn_into::<Node>().unwrap());
|
// let root_id = nodes.insert(root.clone().dyn_into::<Node>().unwrap());
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
stack: Stack::with_capacity(10),
|
stack: Stack::with_capacity(10),
|
||||||
@@ -98,7 +97,8 @@ impl WebsysDom {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn push(&mut self, root: u64) {
|
fn push(&mut self, root: u64) {
|
||||||
let key = DefaultKey::from(KeyData::from_ffi(root));
|
// let key = DefaultKey::from(KeyData::from_ffi(root));
|
||||||
|
let key = root as usize;
|
||||||
let domnode = self.nodes.get_mut(key);
|
let domnode = self.nodes.get_mut(key);
|
||||||
|
|
||||||
let real_node: Node = match domnode {
|
let real_node: Node = match domnode {
|
||||||
@@ -203,11 +203,9 @@ impl WebsysDom {
|
|||||||
.dyn_into::<Node>()
|
.dyn_into::<Node>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let id = id as usize;
|
||||||
self.stack.push(textnode.clone());
|
self.stack.push(textnode.clone());
|
||||||
*self
|
*self.nodes.get_mut(id).unwrap() = textnode;
|
||||||
.nodes
|
|
||||||
.get_mut(DefaultKey::from(KeyData::from_ffi(id)))
|
|
||||||
.unwrap() = textnode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_element(&mut self, tag: &str, ns: Option<&'static str>, id: u64) {
|
fn create_element(&mut self, tag: &str, ns: Option<&'static str>, id: u64) {
|
||||||
@@ -226,14 +224,14 @@ impl WebsysDom {
|
|||||||
.dyn_into::<Node>()
|
.dyn_into::<Node>()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
};
|
};
|
||||||
let id = DefaultKey::from(KeyData::from_ffi(id));
|
let id = id as usize;
|
||||||
|
|
||||||
self.stack.push(el.clone());
|
self.stack.push(el.clone());
|
||||||
*self.nodes.get_mut(id).unwrap() = el;
|
*self.nodes.get_mut(id).unwrap() = el;
|
||||||
// let nid = self.node_counter.?next();
|
// let nid = self.node_counter.?next();
|
||||||
// let nid = self.nodes.insert(el).data().as_ffi();
|
// let nid = self.nodes.insert(el).data().as_ffi();
|
||||||
// log::debug!("Called [`create_element`]: {}, {:?}", tag, nid);
|
// log::debug!("Called [`create_element`]: {}, {:?}", tag, nid);
|
||||||
// RealDomNode::new(nid)
|
// ElementId::new(nid)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_event_listener(
|
fn new_event_listener(
|
||||||
@@ -257,7 +255,9 @@ impl WebsysDom {
|
|||||||
.dyn_ref::<Element>()
|
.dyn_ref::<Element>()
|
||||||
.expect(&format!("not an element: {:?}", el));
|
.expect(&format!("not an element: {:?}", el));
|
||||||
|
|
||||||
let scope_id = scope.data().as_ffi();
|
// let scope_id = scope.data().as_ffi();
|
||||||
|
let scope_id = scope.0 as u64;
|
||||||
|
|
||||||
el.set_attribute(
|
el.set_attribute(
|
||||||
&format!("dioxus-event-{}", event),
|
&format!("dioxus-event-{}", event),
|
||||||
&format!("{}.{}", scope_id, real_id),
|
&format!("{}.{}", scope_id, real_id),
|
||||||
@@ -349,10 +349,10 @@ impl WebsysDom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> dioxus_core::diff::RealDom<'a> for WebsysDom {
|
impl<'a> dioxus_core::diff::RealDom<'a> for WebsysDom {
|
||||||
// fn request_available_node(&mut self) -> RealDomNode {
|
// fn request_available_node(&mut self) -> ElementId {
|
||||||
// let key = self.nodes.insert(None);
|
// let key = self.nodes.insert(None);
|
||||||
// log::debug!("making new key: {:#?}", key);
|
// log::debug!("making new key: {:#?}", key);
|
||||||
// RealDomNode(key.data().as_ffi())
|
// ElementId(key.data().as_ffi())
|
||||||
// }
|
// }
|
||||||
|
|
||||||
fn raw_node_as_any(&self) -> &mut dyn std::any::Any {
|
fn raw_node_as_any(&self) -> &mut dyn std::any::Any {
|
||||||
@@ -588,6 +588,9 @@ fn virtual_event_from_websys_event(event: &web_sys::Event) -> VirtualEvent {
|
|||||||
// let evt: web_sys::ToggleEvent = event.clone().dyn_into().unwrap();
|
// let evt: web_sys::ToggleEvent = event.clone().dyn_into().unwrap();
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
_ => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -632,12 +635,13 @@ fn decode_trigger(event: &web_sys::Event) -> anyhow::Result<EventTrigger> {
|
|||||||
// Call the trigger
|
// Call the trigger
|
||||||
log::debug!("decoded scope_id: {}, node_id: {:#?}", gi_id, real_id);
|
log::debug!("decoded scope_id: {}, node_id: {:#?}", gi_id, real_id);
|
||||||
|
|
||||||
let triggered_scope: ScopeId = KeyData::from_ffi(gi_id).into();
|
let triggered_scope = gi_id;
|
||||||
|
// let triggered_scope: ScopeId = KeyData::from_ffi(gi_id).into();
|
||||||
log::debug!("Triggered scope is {:#?}", triggered_scope);
|
log::debug!("Triggered scope is {:#?}", triggered_scope);
|
||||||
Ok(EventTrigger::new(
|
Ok(EventTrigger::new(
|
||||||
virtual_event_from_websys_event(event),
|
virtual_event_from_websys_event(event),
|
||||||
triggered_scope,
|
ScopeId(triggered_scope as usize),
|
||||||
Some(RealDomNode::from_u64(real_id)),
|
Some(ElementId(real_id as usize)),
|
||||||
dioxus_core::events::EventPriority::High,
|
dioxus_core::events::EventPriority::High,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user