wip: clean it up a bit

This commit is contained in:
Jonathan Kelley committed 2021-12-21 00:58:14 -05:00
1 parent b997b8ebbb
commit fa106be1f5
6 files changed
+59 -34

No files matched your search

+39
View File
@@ -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:
-2
View File
@@ -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();
} }
} }
+8 -15
View File
@@ -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),
+10 -15
View File
@@ -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>,
} }
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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),
}; };
}); });