wip: clean it up a bit
This commit is contained in:
1 parent
b997b8ebbb
commit
fa106be1f5
6 files changed
+59
-34
No files matched your search
@@ -4,6 +4,45 @@ This is the core crate for the Dioxus Virtual DOM. This README will focus on the
|
|||||||
|
|
||||||
To build new apps with Dioxus or to extend the ecosystem with new hooks or components, use the higher-level `dioxus` crate with the appropriate feature flags.
|
To build new apps with Dioxus or to extend the ecosystem with new hooks or components, use the higher-level `dioxus` crate with the appropriate feature flags.
|
||||||
|
|
||||||
|
|
||||||
|
```rust
|
||||||
|
fn app(cx: Scope<()>) -> Element {
|
||||||
|
cx.render(rsx!(
|
||||||
|
div { "hello world" }
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut renderer = SomeRenderer::new();
|
||||||
|
|
||||||
|
|
||||||
|
// Creating a new virtualdom from a component
|
||||||
|
let mut dom = VirtualDom::new(app);
|
||||||
|
|
||||||
|
// Patching the renderer with the changes to draw the screen
|
||||||
|
let edits = dom.rebuild();
|
||||||
|
renderer.apply(edits);
|
||||||
|
|
||||||
|
// Injecting events
|
||||||
|
dom.handle_message(SchedulerMsg::UserEvent());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
## Internals
|
## Internals
|
||||||
|
|
||||||
Dioxus-core builds off the many frameworks that came before it. Notably, Dioxus borrows these concepts:
|
Dioxus-core builds off the many frameworks that came before it. Notably, Dioxus borrows these concepts:
|
||||||
|
|||||||
@@ -1295,8 +1295,6 @@ impl<'bump> DiffState<'bump> {
|
|||||||
let scope_id = c.scope.get().unwrap();
|
let scope_id = c.scope.get().unwrap();
|
||||||
let root = self.scopes.root_node(scope_id);
|
let root = self.scopes.root_node(scope_id);
|
||||||
self.remove_nodes(Some(root), gen_muts);
|
self.remove_nodes(Some(root), gen_muts);
|
||||||
|
|
||||||
log::debug!("Destroying scope {:?}", scope_id);
|
|
||||||
self.scopes.try_remove(scope_id).unwrap();
|
self.scopes.try_remove(scope_id).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,13 +123,6 @@ impl ScopeArena {
|
|||||||
debug_assert!(any_item.is_none());
|
debug_assert!(any_item.is_none());
|
||||||
} else {
|
} else {
|
||||||
// else create a new scope
|
// else create a new scope
|
||||||
let (node_capacity, hook_capacity) = self
|
|
||||||
.heuristics
|
|
||||||
.borrow()
|
|
||||||
.get(&fc_ptr)
|
|
||||||
.map(|h| (h.node_arena_size, h.hook_arena_size))
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
self.scopes.borrow_mut().insert(
|
self.scopes.borrow_mut().insert(
|
||||||
new_scope_id,
|
new_scope_id,
|
||||||
self.bump.alloc(ScopeState::new(
|
self.bump.alloc(ScopeState::new(
|
||||||
@@ -139,8 +132,11 @@ impl ScopeArena {
|
|||||||
self.sender.clone(),
|
self.sender.clone(),
|
||||||
parent_scope,
|
parent_scope,
|
||||||
vcomp,
|
vcomp,
|
||||||
node_capacity,
|
self.heuristics
|
||||||
hook_capacity,
|
.borrow()
|
||||||
|
.get(&fc_ptr)
|
||||||
|
.map(|h| (h.node_arena_size, h.hook_arena_size))
|
||||||
|
.unwrap_or_default(),
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -437,19 +433,16 @@ impl ScopeState {
|
|||||||
sender: UnboundedSender<SchedulerMsg>,
|
sender: UnboundedSender<SchedulerMsg>,
|
||||||
parent_scope: Option<*mut ScopeState>,
|
parent_scope: Option<*mut ScopeState>,
|
||||||
vcomp: Box<dyn AnyProps>,
|
vcomp: Box<dyn AnyProps>,
|
||||||
node_capacity: usize,
|
(node_capacity, hook_capacity): (usize, usize),
|
||||||
hook_capacity: usize,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let frames = [BumpFrame::new(node_capacity), BumpFrame::new(node_capacity)];
|
|
||||||
|
|
||||||
ScopeState {
|
ScopeState {
|
||||||
sender,
|
sender,
|
||||||
container,
|
container,
|
||||||
our_arena_idx,
|
our_arena_idx,
|
||||||
parent_scope,
|
parent_scope,
|
||||||
props: RefCell::new(Some(vcomp)),
|
|
||||||
height,
|
height,
|
||||||
frames,
|
props: RefCell::new(Some(vcomp)),
|
||||||
|
frames: [BumpFrame::new(node_capacity), BumpFrame::new(node_capacity)],
|
||||||
|
|
||||||
// todo: subtrees
|
// todo: subtrees
|
||||||
subtree: Cell::new(0),
|
subtree: Cell::new(0),
|
||||||
|
|||||||
@@ -345,11 +345,10 @@ impl VirtualDom {
|
|||||||
|
|
||||||
pub fn process_message(&mut self, msg: SchedulerMsg) {
|
pub fn process_message(&mut self, msg: SchedulerMsg) {
|
||||||
match msg {
|
match msg {
|
||||||
// just keep looping, the task is now saved but we should actually poll it
|
|
||||||
SchedulerMsg::NewTask(id) => {
|
SchedulerMsg::NewTask(id) => {
|
||||||
self.scopes.pending_futures.borrow_mut().insert(id);
|
self.scopes.pending_futures.borrow_mut().insert(id);
|
||||||
}
|
}
|
||||||
SchedulerMsg::UiEvent(event) => {
|
SchedulerMsg::Event(event) => {
|
||||||
if let Some(element) = event.element {
|
if let Some(element) = event.element {
|
||||||
self.scopes.call_listener_with_bubbling(event, element);
|
self.scopes.call_listener_with_bubbling(event, element);
|
||||||
}
|
}
|
||||||
@@ -640,6 +639,7 @@ impl VirtualDom {
|
|||||||
(create.mutations, edit.mutations)
|
(create.mutations, edit.mutations)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Scopes and ScopeArenas are never dropped internally.
|
Scopes and ScopeArenas are never dropped internally.
|
||||||
An app will always occupy as much memory as its biggest form.
|
An app will always occupy as much memory as its biggest form.
|
||||||
@@ -662,9 +662,6 @@ should we build a vcomponent for the root?
|
|||||||
|
|
||||||
- 1: Use remove_nodes to use the ensure_drop_safety pathway to safely drop the tree
|
- 1: Use remove_nodes to use the ensure_drop_safety pathway to safely drop the tree
|
||||||
- 2: Drop the ScopeState itself
|
- 2: Drop the ScopeState itself
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
impl Drop for VirtualDom {
|
impl Drop for VirtualDom {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
@@ -684,27 +681,26 @@ impl Drop for VirtualDom {
|
|||||||
|
|
||||||
// make sure there are no "live" components
|
// make sure there are no "live" components
|
||||||
for (_, scopeptr) in self.scopes.scopes.get_mut().drain() {
|
for (_, scopeptr) in self.scopes.scopes.get_mut().drain() {
|
||||||
|
// safety: all scopes were made in the bump's allocator
|
||||||
|
// They are never dropped until now. The only way to drop is through Box.
|
||||||
let scope = unsafe { bumpalo::boxed::Box::from_raw(scopeptr) };
|
let scope = unsafe { bumpalo::boxed::Box::from_raw(scopeptr) };
|
||||||
drop(scope);
|
drop(scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
for scopeptr in self.scopes.free_scopes.get_mut().drain(..) {
|
for scopeptr in self.scopes.free_scopes.get_mut().drain(..) {
|
||||||
|
// safety: all scopes were made in the bump's allocator
|
||||||
|
// They are never dropped until now. The only way to drop is through Box.
|
||||||
let mut scope = unsafe { bumpalo::boxed::Box::from_raw(scopeptr) };
|
let mut scope = unsafe { bumpalo::boxed::Box::from_raw(scopeptr) };
|
||||||
scope.reset();
|
scope.reset();
|
||||||
drop(scope);
|
drop(scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Safety: all refereneces to this caller have been dropped
|
|
||||||
// the pointer is still valid since we haven't moved it since the virtualdom was created
|
|
||||||
// ensure the root component's caller is dropped
|
|
||||||
// drop(unsafe { Box::from_raw(self.caller) });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum SchedulerMsg {
|
pub enum SchedulerMsg {
|
||||||
// events from the host
|
// events from the host
|
||||||
UiEvent(UserEvent),
|
Event(UserEvent),
|
||||||
|
|
||||||
// setstate
|
// setstate
|
||||||
Immediate(ScopeId),
|
Immediate(ScopeId),
|
||||||
@@ -746,20 +742,19 @@ pub enum SchedulerMsg {
|
|||||||
/// ```
|
/// ```
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct UserEvent {
|
pub struct UserEvent {
|
||||||
/// The originator of the event trigger
|
/// The originator of the event trigger if available
|
||||||
pub scope_id: Option<ScopeId>,
|
pub scope_id: Option<ScopeId>,
|
||||||
|
|
||||||
|
/// The priority of the event to be scheduled around ongoing work
|
||||||
pub priority: EventPriority,
|
pub priority: EventPriority,
|
||||||
|
|
||||||
/// The optional real node associated with the trigger
|
/// The optional real node associated with the trigger
|
||||||
pub element: Option<ElementId>,
|
pub element: Option<ElementId>,
|
||||||
|
|
||||||
/// The event type IE "onclick" or "onmouseover"
|
/// The event type IE "onclick" or "onmouseover"
|
||||||
///
|
|
||||||
/// The name that the renderer will use to mount the listener.
|
|
||||||
pub name: &'static str,
|
pub name: &'static str,
|
||||||
|
|
||||||
/// Event Data
|
/// The event data to be passed onto the event handler
|
||||||
pub data: Arc<dyn Any + Send + Sync>,
|
pub data: Arc<dyn Any + Send + Sync>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ impl DesktopController {
|
|||||||
"user_event" => {
|
"user_event" => {
|
||||||
let event = events::trigger_from_serialized(req.params.unwrap());
|
let event = events::trigger_from_serialized(req.params.unwrap());
|
||||||
log::debug!("User event: {:?}", event);
|
log::debug!("User event: {:?}", event);
|
||||||
sender.unbounded_send(SchedulerMsg::UiEvent(event)).unwrap();
|
sender.unbounded_send(SchedulerMsg::Event(event)).unwrap();
|
||||||
}
|
}
|
||||||
"initialize" => {
|
"initialize" => {
|
||||||
is_ready.store(true, std::sync::atomic::Ordering::Relaxed);
|
is_ready.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||||
|
|||||||
@@ -300,7 +300,7 @@ impl WebsysDom {
|
|||||||
// "Result" cannot be received from JS
|
// "Result" cannot be received from JS
|
||||||
// Instead, we just build and immediately execute a closure that returns result
|
// Instead, we just build and immediately execute a closure that returns result
|
||||||
match decode_trigger(event) {
|
match decode_trigger(event) {
|
||||||
Ok(synthetic_event) => trigger.as_ref()(SchedulerMsg::UiEvent(synthetic_event)),
|
Ok(synthetic_event) => trigger.as_ref()(SchedulerMsg::Event(synthetic_event)),
|
||||||
Err(e) => log::error!("Error decoding Dioxus event attribute. {:#?}", e),
|
Err(e) => log::error!("Error decoding Dioxus event attribute. {:#?}", e),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in new issue
Block a user