Skip to content

Commit

Permalink
fix: use isactive instead
Browse files Browse the repository at this point in the history
  • Loading branch information
jkelleyrtp committed Feb 2, 2022
1 parent 79b5260 commit bf17c76
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 33 deletions.
13 changes: 7 additions & 6 deletions packages/core/src/diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ impl<'b> DiffState<'b> {
// this makes figure out when to drop the component more complicated
let new_idx = if let Some(idx) = vcomponent.scope.get() {
assert!(self.scopes.get_scope(idx).is_some());
self.scopes.set_active(idx, true);
idx
} else {
// Insert a new scope into our component list
Expand Down Expand Up @@ -963,12 +964,12 @@ impl<'b> DiffState<'b> {
self.mutations.dirty_scopes
);

if self.scope_stack.contains(&c.originator)
|| self.mutations.dirty_scopes.contains(&c.originator)
{
if self.scope_stack.contains(&c.originator) {
log::trace!("Removing component {:?}", old);

self.scopes.try_remove(scope_id).unwrap();
} else {
self.scopes.set_active(scope_id, false);
}
}
self.leave_scope();
Expand Down Expand Up @@ -1021,10 +1022,10 @@ impl<'b> DiffState<'b> {
self.remove_nodes([root], gen_muts);

// we can only remove this node if the originator is actively in our stackß
if self.scope_stack.contains(&c.originator)
|| self.mutations.dirty_scopes.contains(&c.originator)
{
if self.scope_stack.contains(&c.originator) {
self.scopes.try_remove(scope_id).unwrap();
} else {
self.scopes.set_active(scope_id, false);
}
}
self.leave_scope();
Expand Down
32 changes: 28 additions & 4 deletions packages/core/src/scopes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ impl ScopeArena {
fnptr: fc_ptr,
fnname,
originator,
active: Cell::new(true),

props: RefCell::new(Some(vcomp)),
frames: [BumpFrame::new(node_capacity), BumpFrame::new(node_capacity)],
Expand All @@ -162,7 +163,6 @@ impl ScopeArena {

generation: 0.into(),


tasks: self.tasks.clone(),
shared_contexts: Default::default(),

Expand Down Expand Up @@ -251,14 +251,16 @@ impl ScopeArena {
}

pub(crate) fn run_scope(&self, id: ScopeId) {
// todo: we *know* that this is aliased by the contents of the scope itself
let scope = unsafe { &mut *self.get_scope_raw(id).expect("could not find scope") };

assert!(scope.active.get());

// Cycle to the next frame and then reset it
// This breaks any latent references, invalidating every pointer referencing into it.
// Remove all the outdated listeners
self.ensure_drop_safety(id);

// todo: we *know* that this is aliased by the contents of the scope itself
let scope = unsafe { &mut *self.get_scope_raw(id).expect("could not find scope") };

log::trace!("running scope {:?} name: {:?}", id, scope.fnname);

// Safety:
Expand Down Expand Up @@ -382,6 +384,11 @@ impl ScopeArena {
None => None,
}
}

pub(crate) fn set_active(&self, scope_id: ScopeId, arg: bool) {
let scope = self.get_scope(scope_id).unwrap();
scope.active.set(arg);
}
}

/// Components in Dioxus use the "Context" object to interact with their lifecycle.
Expand Down Expand Up @@ -458,6 +465,7 @@ pub struct ScopeState {
pub(crate) fnptr: ComponentPtr,
pub(crate) fnname: &'static str,
pub(crate) originator: ScopeId,
pub(crate) active: Cell<bool>,

// todo: subtrees
pub(crate) is_subtree_root: Cell<bool>,
Expand Down Expand Up @@ -571,6 +579,22 @@ impl ScopeState {
self.parent_scope.map(|p| unsafe { &*p }.our_arena_idx)
}

pub fn container(&self) -> ElementId {
self.container
}

pub fn fnptr(&self) -> ComponentPtr {
self.fnptr
}

pub fn name(&self) -> &'static str {
self.fnname
}

pub fn originator(&self) -> ScopeId {
self.originator
}

/// Get the ID of this Scope within this Dioxus VirtualDOM.
///
/// This ID is not unique across Dioxus VirtualDOMs or across time. IDs will be reused when components are unmounted.
Expand Down
5 changes: 4 additions & 1 deletion packages/core/src/virtual_dom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,10 @@ impl VirtualDom {
log::debug!("dirty_scopes: {:?}", self.dirty_scopes);

if let Some(scopeid) = self.dirty_scopes.pop() {
if !ran_scopes.contains(&scopeid) {
let scope = scopes.get_scope(scopeid).unwrap();
let is_active = scope.active.get();

if !ran_scopes.contains(&scopeid) && is_active {
ran_scopes.insert(scopeid);

self.scopes.run_scope(scopeid);
Expand Down
6 changes: 4 additions & 2 deletions packages/router/src/components/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,19 @@ pub fn Route<'a>(cx: Scope<'a, RouteProps<'a>>) -> Element {
router_root.register_total_route(
route_context.total_route.clone(),
cx.scope_id(),
cx.name(),
cx.props.fallback,
);

Some(RouteInner {})
});

// log::trace!("Checking route {}", cx.props.to);

if router_root.should_render(cx.scope_id()) {
log::trace!("Route {} should render", cx.props.to);

cx.render(rsx!(&cx.props.children))
} else {
log::trace!("Route {} should not render", cx.props.to);
None
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/router/src/hooks/use_route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl UseRoute {
self.router.current_location()
}

fn path_segments(&self) -> Vec<String> {
pub fn path_segments(&self) -> Vec<String> {
let location = self.router.current_location();
let path = location.path();
if path == "/" {
Expand Down
42 changes: 23 additions & 19 deletions packages/router/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::platform::RouterProvider;
pub struct RouterService {
pub(crate) regen_route: Rc<dyn Fn(ScopeId)>,
pub(crate) pending_events: Rc<RefCell<Vec<RouteEvent>>>,
slots: Rc<RefCell<Vec<(ScopeId, String)>>>,
slots: Rc<RefCell<Vec<Slot>>>,
onchange_listeners: Rc<RefCell<HashSet<ScopeId>>>,
root_found: Rc<Cell<Option<ScopeId>>>,
cur_path_params: Rc<RefCell<HashMap<String, String>>>,
Expand All @@ -28,17 +28,10 @@ pub enum RouteEvent {
Push,
}

enum RouteSlot {
Routes {
// the partial route
partial: String,

// the total route
total: String,

// Connections to other routs
rest: Vec<RouteSlot>,
},
struct Slot {
id: ScopeId,
name: &'static str,
route: String,
}

impl RouterService {
Expand All @@ -48,7 +41,7 @@ impl RouterService {
let path = location.path();

let onchange_listeners = Rc::new(RefCell::new(HashSet::new()));
let slots: Rc<RefCell<Vec<(ScopeId, String)>>> = Default::default();
let slots: Rc<RefCell<Vec<Slot>>> = Default::default();
let pending_events: Rc<RefCell<Vec<RouteEvent>>> = Default::default();
let root_found = Rc::new(Cell::new(None));

Expand All @@ -61,8 +54,8 @@ impl RouterService {
move || {
root_found.set(None);
// checking if the route is valid is cheap, so we do it
for (slot, root) in slots.borrow_mut().iter().rev() {
regen_route(*slot);
for slot in slots.borrow_mut().iter().rev() {
regen_route(slot.id);
}

for listener in onchange_listeners.borrow_mut().iter() {
Expand Down Expand Up @@ -92,9 +85,20 @@ impl RouterService {
self.history.borrow_mut().push(route);
}

pub fn register_total_route(&self, route: String, scope: ScopeId, fallback: bool) {
pub fn register_total_route(
&self,
route: String,
scope: ScopeId,
scopename: &'static str,
fallback: bool,
) {
let clean = clean_route(route);
self.slots.borrow_mut().push((scope, clean));

self.slots.borrow_mut().push(Slot {
id: scope,
name: scopename,
route: clean,
});
}

pub fn should_render(&self, scope: ScopeId) -> bool {
Expand All @@ -110,11 +114,11 @@ impl RouterService {

let roots = self.slots.borrow();

let root = roots.iter().find(|(id, route)| id == &scope);
let root = roots.iter().find(|slot| slot.id == scope);

// fallback logic
match root {
Some((id, route)) => {
Some(Slot { id, name, route }) => {
if let Some(params) = route_matches_path(route, path) {
self.root_found.set(Some(*id));
*self.cur_path_params.borrow_mut() = params;
Expand Down

0 comments on commit bf17c76

Please sign in to comment.