mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-27 14:40:44 +00:00
wip: compiling again with runtime safety
This commit is contained in:
parent
95bd17e38f
commit
857c92f7f0
8 changed files with 461 additions and 290 deletions
|
@ -40,8 +40,6 @@ indexmap = "1.7.0"
|
|||
# Serialize the Edits for use in Webview/Liveview instances
|
||||
serde = { version = "1", features = ["derive"], optional = true }
|
||||
|
||||
serde_repr = { version = "0.1.7", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
anyhow = "1.0.42"
|
||||
dioxus-html = { path = "../html" }
|
||||
|
@ -54,7 +52,7 @@ dioxus-core-macro = { path = "../core-macro", version = "0.1.2" }
|
|||
|
||||
[features]
|
||||
default = []
|
||||
serialize = ["serde", "serde_repr"]
|
||||
serialize = ["serde"]
|
||||
debug_vdom = []
|
||||
|
||||
[[bench]]
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -34,7 +34,7 @@ impl HookList {
|
|||
///
|
||||
/// This should only be ran by Dioxus itself before "running scope".
|
||||
/// Dioxus knows how to descend through the tree to prevent mutable aliasing.
|
||||
pub(crate) unsafe fn reset(&mut self) {
|
||||
pub(crate) unsafe fn reset(&self) {
|
||||
self.idx.set(0);
|
||||
}
|
||||
|
||||
|
|
|
@ -319,7 +319,8 @@ pub struct Listener<'bump> {
|
|||
pub struct VComponent<'src> {
|
||||
pub key: Option<&'src str>,
|
||||
|
||||
pub associated_scope: Cell<Option<*mut ScopeInner>>,
|
||||
pub associated_scope: Cell<Option<ScopeId>>,
|
||||
// pub associated_scope: Cell<Option<*mut ScopeInner>>,
|
||||
|
||||
// Function pointer to the FC that was used to generate this component
|
||||
pub user_fc: *const (),
|
||||
|
|
|
@ -43,14 +43,18 @@ pub type Context<'a> = &'a ScopeInner;
|
|||
/// use case they might have.
|
||||
pub struct ScopeInner {
|
||||
// Book-keeping about our spot in the arena
|
||||
// yes, a raw pointer
|
||||
// it's bump allocated so it's stable
|
||||
// the safety of parent pointers is guaranteed by the logic in this crate
|
||||
|
||||
// safety:
|
||||
//
|
||||
// pointers to scopes are *always* valid since they are bump allocated and never freed until this scope is also freed
|
||||
pub(crate) parent_scope: Option<*mut ScopeInner>,
|
||||
|
||||
pub(crate) our_arena_idx: ScopeId,
|
||||
|
||||
pub(crate) height: u32,
|
||||
|
||||
pub(crate) subtree: Cell<u32>,
|
||||
|
||||
pub(crate) is_subtree_root: Cell<bool>,
|
||||
|
||||
// Nodes
|
||||
|
@ -100,12 +104,12 @@ impl ScopeInner {
|
|||
///
|
||||
/// This also makes sure that drop order is consistent and predictable. All resources that rely on being dropped will
|
||||
/// be dropped.
|
||||
pub(crate) fn ensure_drop_safety(&mut self) {
|
||||
pub(crate) fn ensure_drop_safety(&self) {
|
||||
// make sure we drop all borrowed props manually to guarantee that their drop implementation is called before we
|
||||
// run the hooks (which hold an &mut Reference)
|
||||
// right now, we don't drop
|
||||
self.items
|
||||
.get_mut()
|
||||
.borrow_mut()
|
||||
.borrowed_props
|
||||
.drain(..)
|
||||
.map(|li| unsafe { &*li })
|
||||
|
@ -116,9 +120,10 @@ impl ScopeInner {
|
|||
.get()
|
||||
.expect("VComponents should be associated with a valid Scope");
|
||||
|
||||
let scope = unsafe { &mut *scope_id };
|
||||
todo!("move this onto virtualdom");
|
||||
// let scope = unsafe { &mut *scope_id };
|
||||
|
||||
scope.ensure_drop_safety();
|
||||
// scope.ensure_drop_safety();
|
||||
|
||||
todo!("drop the component's props");
|
||||
// let mut drop_props = comp.drop_props.borrow_mut().take().unwrap();
|
||||
|
@ -127,7 +132,7 @@ impl ScopeInner {
|
|||
|
||||
// Now that all the references are gone, we can safely drop our own references in our listeners.
|
||||
self.items
|
||||
.get_mut()
|
||||
.borrow_mut()
|
||||
.listeners
|
||||
.drain(..)
|
||||
.map(|li| unsafe { &*li })
|
||||
|
@ -135,8 +140,8 @@ impl ScopeInner {
|
|||
}
|
||||
|
||||
/// A safe wrapper around calling listeners
|
||||
pub(crate) fn call_listener(&mut self, event: UserEvent, element: ElementId) {
|
||||
let listners = &mut self.items.get_mut().listeners;
|
||||
pub(crate) fn call_listener(&self, event: UserEvent, element: ElementId) {
|
||||
let listners = &mut self.items.borrow_mut().listeners;
|
||||
|
||||
let raw_listener = listners.iter().find(|lis| {
|
||||
let search = unsafe { &***lis };
|
||||
|
@ -191,9 +196,10 @@ impl ScopeInner {
|
|||
// }
|
||||
}
|
||||
|
||||
pub(crate) fn update_vcomp(&mut self, vcomp: &VComponent) {
|
||||
pub(crate) fn update_vcomp(&self, vcomp: &VComponent) {
|
||||
let f: *const _ = vcomp;
|
||||
self.vcomp = unsafe { std::mem::transmute(f) };
|
||||
todo!()
|
||||
// self.vcomp = unsafe { std::mem::transmute(f) };
|
||||
}
|
||||
|
||||
pub(crate) fn load_vcomp<'a>(&'a mut self) -> &'a VComponent<'a> {
|
||||
|
|
|
@ -32,8 +32,8 @@ impl ScopeArena {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self, id: &ScopeId) -> Option<&mut ScopeInner> {
|
||||
unsafe { Some(&mut *self.scopes[id.0]) }
|
||||
pub fn get_mut(&self, id: &ScopeId) -> Option<&ScopeInner> {
|
||||
unsafe { Some(&*self.scopes[id.0]) }
|
||||
}
|
||||
|
||||
pub fn new_with_key(
|
||||
|
|
|
@ -33,7 +33,9 @@ impl TestDom {
|
|||
|
||||
pub fn diff<'a>(&'a self, old: &'a VNode<'a>, new: &'a VNode<'a>) -> Mutations<'a> {
|
||||
let mutations = Mutations::new();
|
||||
let mut machine = DiffMachine::new(mutations);
|
||||
let mut machine: DiffState = todo!();
|
||||
// let mut machine = DiffState::new(mutations);
|
||||
// let mut machine = DiffState::new(mutations);
|
||||
machine.stack.push(DiffInstruction::Diff { new, old });
|
||||
machine.mutations
|
||||
}
|
||||
|
@ -41,13 +43,17 @@ impl TestDom {
|
|||
pub fn create<'a>(&'a self, left: Option<LazyNodes<'a, '_>>) -> Mutations<'a> {
|
||||
let old = self.bump.alloc(self.render_direct(left));
|
||||
|
||||
let mut machine = DiffMachine::new(Mutations::new());
|
||||
let mut machine: DiffState = todo!();
|
||||
// let mut machine = DiffState::new(Mutations::new());
|
||||
// let mut machine = DiffState::new(Mutations::new());
|
||||
|
||||
machine.stack.create_node(old, MountType::Append);
|
||||
|
||||
machine.work(&mut || false);
|
||||
todo!()
|
||||
|
||||
machine.mutations
|
||||
// machine.work(&mut || false);
|
||||
|
||||
// machine.mutations
|
||||
}
|
||||
|
||||
pub fn lazy_diff<'a>(
|
||||
|
@ -57,22 +63,26 @@ impl TestDom {
|
|||
) -> (Mutations<'a>, Mutations<'a>) {
|
||||
let (old, new) = (self.render(left), self.render(right));
|
||||
|
||||
let mut machine = DiffMachine::new(Mutations::new());
|
||||
let mut machine: DiffState = todo!();
|
||||
// let mut machine = DiffState::new(Mutations::new());
|
||||
|
||||
machine.stack.create_node(old, MountType::Append);
|
||||
|
||||
machine.work(|| false);
|
||||
let create_edits = machine.mutations;
|
||||
todo!()
|
||||
|
||||
let mut machine = DiffMachine::new(Mutations::new());
|
||||
// machine.work(|| false);
|
||||
// let create_edits = machine.mutations;
|
||||
|
||||
machine.stack.push(DiffInstruction::Diff { old, new });
|
||||
// let mut machine: DiffState = todo!();
|
||||
// // let mut machine = DiffState::new(Mutations::new());
|
||||
|
||||
machine.work(&mut || false);
|
||||
// machine.stack.push(DiffInstruction::Diff { old, new });
|
||||
|
||||
let edits = machine.mutations;
|
||||
// machine.work(&mut || false);
|
||||
|
||||
(create_edits, edits)
|
||||
// let edits = machine.mutations;
|
||||
|
||||
// (create_edits, edits)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ pub struct VirtualDom {
|
|||
// we need to keep the allocation around, but we don't necessarily use it
|
||||
_root_caller: Box<dyn Any>,
|
||||
|
||||
pub scopes: ScopeArena,
|
||||
pub(crate) scopes: ScopeArena,
|
||||
|
||||
pub receiver: UnboundedReceiver<SchedulerMsg>,
|
||||
pub sender: UnboundedSender<SchedulerMsg>,
|
||||
|
@ -92,7 +92,7 @@ pub struct VirtualDom {
|
|||
|
||||
pub dirty_scopes: IndexSet<ScopeId>,
|
||||
|
||||
pub saved_state: Option<SavedDiffWork<'static>>,
|
||||
pub(crate) saved_state: Option<SavedDiffWork<'static>>,
|
||||
|
||||
pub in_progress: bool,
|
||||
}
|
||||
|
@ -250,7 +250,8 @@ impl VirtualDom {
|
|||
where
|
||||
P: 'static,
|
||||
{
|
||||
let root_scope = self.pool.get_scope_mut(&self.base_scope).unwrap();
|
||||
let base = self.base_scope;
|
||||
let root_scope = self.get_scope_mut(&base).unwrap();
|
||||
|
||||
// Pre-emptively drop any downstream references of the old props
|
||||
root_scope.ensure_drop_safety();
|
||||
|
@ -532,7 +533,7 @@ For the rest, we defer to the rIC period and work down each queue from high to l
|
|||
impl VirtualDom {
|
||||
// returns true if the event is discrete
|
||||
pub fn handle_ui_event(&mut self, event: UserEvent) -> bool {
|
||||
let (discrete, priority) = event_meta(&event);
|
||||
// let (discrete, priority) = event_meta(&event);
|
||||
|
||||
if let Some(scope) = self.get_scope_mut(&event.scope) {
|
||||
if let Some(element) = event.mounted_dom_id {
|
||||
|
@ -555,7 +556,8 @@ impl VirtualDom {
|
|||
// Low => todo!(),
|
||||
// }
|
||||
|
||||
discrete
|
||||
todo!()
|
||||
// discrete
|
||||
}
|
||||
|
||||
fn prepare_work(&mut self) {
|
||||
|
@ -588,7 +590,7 @@ impl VirtualDom {
|
|||
SchedulerMsg::UiEvent(event) => {
|
||||
//
|
||||
|
||||
let (discrete, priority) = event_meta(&event);
|
||||
// let (discrete, priority) = event_meta(&event);
|
||||
|
||||
if let Some(scope) = self.get_scope_mut(&event.scope) {
|
||||
if let Some(element) = event.mounted_dom_id {
|
||||
|
@ -602,7 +604,7 @@ impl VirtualDom {
|
|||
}
|
||||
}
|
||||
|
||||
discrete;
|
||||
// discrete;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -625,12 +627,13 @@ impl VirtualDom {
|
|||
let mut ran_scopes = FxHashSet::default();
|
||||
|
||||
if machine.stack.is_empty() {
|
||||
self.dirty_scopes.retain(|id| self.get_scope(id).is_some());
|
||||
self.dirty_scopes.sort_by(|a, b| {
|
||||
let h1 = self.get_scope(a).unwrap().height;
|
||||
let h2 = self.get_scope(b).unwrap().height;
|
||||
h1.cmp(&h2).reverse()
|
||||
});
|
||||
todo!("order scopes");
|
||||
// self.dirty_scopes.retain(|id| self.get_scope(id).is_some());
|
||||
// self.dirty_scopes.sort_by(|a, b| {
|
||||
// let h1 = self.get_scope(a).unwrap().height;
|
||||
// let h2 = self.get_scope(b).unwrap().height;
|
||||
// h1.cmp(&h2).reverse()
|
||||
// });
|
||||
|
||||
if let Some(scopeid) = self.dirty_scopes.pop() {
|
||||
log::info!("handling dirty scope {:?}", scopeid);
|
||||
|
@ -640,21 +643,23 @@ impl VirtualDom {
|
|||
|
||||
// if let Some(component) = self.get_scope_mut(&scopeid) {
|
||||
if self.run_scope(&scopeid) {
|
||||
let (old, new) = (component.frames.wip_head(), component.frames.fin_head());
|
||||
todo!("diff the scope")
|
||||
// let (old, new) = (component.frames.wip_head(), component.frames.fin_head());
|
||||
machine.stack.scope_stack.push(scopeid);
|
||||
machine.stack.push(DiffInstruction::Diff { new, old });
|
||||
// // let (old, new) = (component.frames.wip_head(), component.frames.fin_head());
|
||||
// machine.stack.scope_stack.push(scopeid);
|
||||
// machine.stack.push(DiffInstruction::Diff { new, old });
|
||||
}
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let work_completed = machine.work(deadline_reached);
|
||||
let work_completed: bool = todo!();
|
||||
// let work_completed = machine.work(deadline_reached);
|
||||
|
||||
// log::debug!("raw edits {:?}", machine.mutations.edits);
|
||||
|
||||
let mut machine: DiffMachine<'static> = unsafe { std::mem::transmute(machine) };
|
||||
let mut machine: DiffState<'static> = unsafe { std::mem::transmute(machine) };
|
||||
// let mut saved = machine.save();
|
||||
|
||||
if work_completed {
|
||||
|
@ -681,8 +686,9 @@ impl VirtualDom {
|
|||
|
||||
// log::debug!("saved edits {:?}", mutations);
|
||||
|
||||
let mut saved = machine.save();
|
||||
self.save_work(saved);
|
||||
todo!();
|
||||
// let mut saved = machine.save();
|
||||
// self.save_work(saved);
|
||||
true
|
||||
|
||||
// self.save_work(saved);
|
||||
|
@ -801,24 +807,26 @@ impl VirtualDom {
|
|||
///
|
||||
/// Typically used to kickstart the VirtualDOM after initialization.
|
||||
pub fn rebuild_inner(&mut self, base_scope: ScopeId) -> Mutations {
|
||||
let mut diff_machine = DiffMachine::new(Mutations::new());
|
||||
|
||||
// TODO: drain any in-flight work
|
||||
let cur_component = self
|
||||
.get_scope_mut(&base_scope)
|
||||
.expect("The base scope should never be moved");
|
||||
|
||||
log::debug!("rebuild {:?}", base_scope);
|
||||
|
||||
// We run the component. If it succeeds, then we can diff it and add the changes to the dom.
|
||||
if self.run_scope(&base_scope) {
|
||||
let cur_component = self
|
||||
.get_scope_mut(&base_scope)
|
||||
.expect("The base scope should never be moved");
|
||||
|
||||
log::debug!("rebuild {:?}", base_scope);
|
||||
|
||||
let mut diff_machine = DiffState::new(Mutations::new());
|
||||
diff_machine
|
||||
.stack
|
||||
.create_node(cur_component.frames.fin_head(), MountType::Append);
|
||||
|
||||
diff_machine.stack.scope_stack.push(base_scope);
|
||||
|
||||
diff_machine.work(|| false);
|
||||
todo!()
|
||||
// self.work(&mut diff_machine, || false);
|
||||
// diff_machine.work(|| false);
|
||||
} else {
|
||||
// todo: should this be a hard error?
|
||||
log::warn!(
|
||||
|
@ -827,7 +835,8 @@ impl VirtualDom {
|
|||
);
|
||||
}
|
||||
|
||||
unsafe { std::mem::transmute(diff_machine.mutations) }
|
||||
todo!()
|
||||
// unsafe { std::mem::transmute(diff_machine.mutations) }
|
||||
}
|
||||
|
||||
pub fn hard_diff(&mut self, base_scope: ScopeId) -> Mutations {
|
||||
|
@ -838,16 +847,17 @@ impl VirtualDom {
|
|||
log::debug!("hard diff {:?}", base_scope);
|
||||
|
||||
if self.run_scope(&base_scope) {
|
||||
let mut diff_machine = DiffMachine::new(Mutations::new());
|
||||
let mut diff_machine = DiffState::new(Mutations::new());
|
||||
diff_machine.cfg.force_diff = true;
|
||||
diff_machine.diff_scope(base_scope);
|
||||
self.diff_scope(&mut diff_machine, base_scope);
|
||||
// diff_machine.diff_scope(base_scope);
|
||||
diff_machine.mutations
|
||||
} else {
|
||||
Mutations::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_scope_mut(&mut self, id: &ScopeId) -> Option<&mut ScopeInner> {
|
||||
pub fn get_scope_mut<'a>(&'a self, id: &ScopeId) -> Option<&'a ScopeInner> {
|
||||
self.scopes.get_mut(id)
|
||||
}
|
||||
|
||||
|
@ -868,7 +878,8 @@ impl VirtualDom {
|
|||
|
||||
// Safety:
|
||||
// - We've dropped all references to the wip bump frame
|
||||
unsafe { scope.frames.reset_wip_frame() };
|
||||
todo!("reset wip frame");
|
||||
// unsafe { scope.frames.reset_wip_frame() };
|
||||
|
||||
let items = scope.items.get_mut();
|
||||
|
||||
|
@ -903,6 +914,19 @@ impl VirtualDom {
|
|||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reserve_node(&self, node: &VNode) -> ElementId {
|
||||
todo!()
|
||||
// self.node_reservations.insert(id);
|
||||
}
|
||||
|
||||
pub fn collect_garbage(&self, id: ElementId) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn try_remove(&self, id: &ScopeId) -> Option<ScopeInner> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
// impl<'a> Future for PollAllTasks<'a> {
|
||||
|
|
Loading…
Reference in a new issue