mirror of
https://github.com/DioxusLabs/dioxus
synced 2025-02-17 06:08:26 +00:00
wip: clean up the core crate after switching to recursive diff engine
This commit is contained in:
parent
3bb5c8142c
commit
1ea42799c0
8 changed files with 562 additions and 1968 deletions
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,8 +1,7 @@
|
|||
#![allow(non_snake_case)]
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
// pub(crate) mod diff;
|
||||
pub(crate) mod diff_async;
|
||||
pub(crate) mod diff;
|
||||
pub(crate) mod events;
|
||||
pub(crate) mod lazynodes;
|
||||
pub(crate) mod mutations;
|
||||
|
@ -13,8 +12,7 @@ pub(crate) mod util;
|
|||
pub(crate) mod virtual_dom;
|
||||
|
||||
pub(crate) mod innerlude {
|
||||
pub(crate) use crate::diff_async::*;
|
||||
// pub(crate) use crate::diff::*;
|
||||
pub(crate) use crate::diff::*;
|
||||
pub use crate::events::*;
|
||||
pub use crate::lazynodes::*;
|
||||
pub use crate::mutations::*;
|
||||
|
|
|
@ -255,7 +255,7 @@ impl ScopeArena {
|
|||
let scope = unsafe { &mut *self.get_scope_raw(id).expect("could not find scope") };
|
||||
|
||||
// if cfg!(debug_assertions) {
|
||||
log::debug!("running scope {:?} symbol: {:?}", id, scope.fnptr);
|
||||
// log::debug!("running scope {:?} symbol: {:?}", id, scope.fnptr);
|
||||
|
||||
// todo: resolve frames properly
|
||||
backtrace::resolve(scope.fnptr, |symbol| {
|
||||
|
@ -733,7 +733,6 @@ impl ScopeState {
|
|||
while let Some(parent_ptr) = search_parent {
|
||||
// safety: all parent pointers are valid thanks to the bump arena
|
||||
let parent = unsafe { &*parent_ptr };
|
||||
log::trace!("Searching parent scope {:?}", parent.scope_id());
|
||||
if let Some(shared) = parent.shared_contexts.borrow().get(&TypeId::of::<T>()) {
|
||||
return Some(shared.clone().downcast::<T>().unwrap());
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//!
|
||||
//! This module provides the primary mechanics to create a hook-based, concurrent VDOM for Rust.
|
||||
|
||||
use crate::diff_async::AsyncDiffState as DiffState;
|
||||
use crate::diff::AsyncDiffState as DiffState;
|
||||
use crate::innerlude::*;
|
||||
use futures_channel::mpsc::{UnboundedReceiver, UnboundedSender};
|
||||
use futures_util::{future::poll_fn, StreamExt};
|
||||
|
|
|
@ -42,14 +42,8 @@ fn test_early_abort() {
|
|||
assert_eq!(
|
||||
edits.edits,
|
||||
[
|
||||
CreateElement {
|
||||
tag: "div",
|
||||
root: 1,
|
||||
},
|
||||
CreateTextNode {
|
||||
text: "Hello, world!",
|
||||
root: 2,
|
||||
},
|
||||
CreateElement { tag: "div", root: 1 },
|
||||
CreateTextNode { text: "Hello, world!", root: 2 },
|
||||
AppendChildren { many: 1 },
|
||||
AppendChildren { many: 1 },
|
||||
]
|
||||
|
@ -65,14 +59,8 @@ fn test_early_abort() {
|
|||
assert_eq!(
|
||||
edits.edits,
|
||||
[
|
||||
CreateElement {
|
||||
tag: "div",
|
||||
root: 2,
|
||||
},
|
||||
CreateTextNode {
|
||||
text: "Hello, world!",
|
||||
root: 4,
|
||||
},
|
||||
CreateElement { tag: "div", root: 1 }, // keys get reused
|
||||
CreateTextNode { text: "Hello, world!", root: 2 }, // keys get reused
|
||||
AppendChildren { many: 1 },
|
||||
ReplaceWith { root: 3, m: 1 },
|
||||
]
|
||||
|
|
|
@ -27,12 +27,7 @@ fn manual_diffing() {
|
|||
};
|
||||
|
||||
let value = Arc::new(Mutex::new("Hello"));
|
||||
let mut dom = VirtualDom::new_with_props(
|
||||
App,
|
||||
AppProps {
|
||||
value: value.clone(),
|
||||
},
|
||||
);
|
||||
let mut dom = VirtualDom::new_with_props(App, AppProps { value: value.clone() });
|
||||
|
||||
let _ = dom.rebuild();
|
||||
|
||||
|
@ -45,7 +40,7 @@ fn manual_diffing() {
|
|||
|
||||
#[test]
|
||||
fn events_generate() {
|
||||
static App: Component = |cx| {
|
||||
fn app(cx: Scope) -> Element {
|
||||
let count = cx.use_hook(|_| 0);
|
||||
|
||||
let inner = match *count {
|
||||
|
@ -66,7 +61,7 @@ fn events_generate() {
|
|||
cx.render(inner)
|
||||
};
|
||||
|
||||
let mut dom = VirtualDom::new(App);
|
||||
let mut dom = VirtualDom::new(app);
|
||||
let mut channel = dom.get_scheduler_channel();
|
||||
assert!(dom.has_work());
|
||||
|
||||
|
@ -74,28 +69,12 @@ fn events_generate() {
|
|||
assert_eq!(
|
||||
edits.edits,
|
||||
[
|
||||
CreateElement {
|
||||
tag: "div",
|
||||
root: 1,
|
||||
},
|
||||
NewEventListener {
|
||||
event_name: "click",
|
||||
scope: ScopeId(0),
|
||||
root: 1,
|
||||
},
|
||||
CreateElement {
|
||||
tag: "div",
|
||||
root: 2,
|
||||
},
|
||||
CreateTextNode {
|
||||
text: "nested",
|
||||
root: 3,
|
||||
},
|
||||
CreateElement { tag: "div", root: 1 },
|
||||
NewEventListener { event_name: "click", scope: ScopeId(0), root: 1 },
|
||||
CreateElement { tag: "div", root: 2 },
|
||||
CreateTextNode { text: "nested", root: 3 },
|
||||
AppendChildren { many: 1 },
|
||||
CreateTextNode {
|
||||
text: "Click me!",
|
||||
root: 4,
|
||||
},
|
||||
CreateTextNode { text: "Click me!", root: 4 },
|
||||
AppendChildren { many: 2 },
|
||||
AppendChildren { many: 1 },
|
||||
]
|
||||
|
@ -104,7 +83,7 @@ fn events_generate() {
|
|||
|
||||
#[test]
|
||||
fn components_generate() {
|
||||
static App: Component = |cx| {
|
||||
fn app(cx: Scope) -> Element {
|
||||
let render_phase = cx.use_hook(|_| 0);
|
||||
*render_phase += 1;
|
||||
|
||||
|
@ -121,106 +100,84 @@ fn components_generate() {
|
|||
})
|
||||
};
|
||||
|
||||
static Child: Component = |cx| {
|
||||
fn Child(cx: Scope) -> Element {
|
||||
log::debug!("Running child");
|
||||
cx.render(rsx! {
|
||||
h1 {}
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
let mut dom = VirtualDom::new(App);
|
||||
let mut dom = VirtualDom::new(app);
|
||||
let edits = dom.rebuild();
|
||||
assert_eq!(
|
||||
edits.edits,
|
||||
[
|
||||
CreateTextNode {
|
||||
text: "Text0",
|
||||
root: 1,
|
||||
},
|
||||
CreateTextNode { text: "Text0", root: 1 },
|
||||
AppendChildren { many: 1 },
|
||||
]
|
||||
);
|
||||
|
||||
let edits = dom.hard_diff(ScopeId(0));
|
||||
assert_eq!(
|
||||
edits.edits,
|
||||
dom.hard_diff(ScopeId(0)).edits,
|
||||
[
|
||||
CreateElement {
|
||||
tag: "div",
|
||||
root: 2,
|
||||
},
|
||||
CreateElement { tag: "div", root: 2 },
|
||||
ReplaceWith { root: 1, m: 1 },
|
||||
]
|
||||
);
|
||||
|
||||
let edits = dom.hard_diff(ScopeId(0));
|
||||
assert_eq!(
|
||||
edits.edits,
|
||||
dom.hard_diff(ScopeId(0)).edits,
|
||||
[
|
||||
CreateTextNode {
|
||||
text: "Text2",
|
||||
root: 3,
|
||||
},
|
||||
CreateTextNode { text: "Text2", root: 1 },
|
||||
ReplaceWith { root: 2, m: 1 },
|
||||
]
|
||||
);
|
||||
|
||||
let edits = dom.hard_diff(ScopeId(0));
|
||||
// child {}
|
||||
assert_eq!(
|
||||
edits.edits,
|
||||
dom.hard_diff(ScopeId(0)).edits,
|
||||
[
|
||||
CreateElement { tag: "h1", root: 4 },
|
||||
ReplaceWith { root: 3, m: 1 },
|
||||
CreateElement { tag: "h1", root: 2 },
|
||||
ReplaceWith { root: 1, m: 1 },
|
||||
]
|
||||
);
|
||||
|
||||
let edits = dom.hard_diff(ScopeId(0));
|
||||
// placeholder
|
||||
assert_eq!(
|
||||
edits.edits,
|
||||
[CreatePlaceholder { root: 5 }, ReplaceWith { root: 4, m: 1 },]
|
||||
dom.hard_diff(ScopeId(0)).edits,
|
||||
[CreatePlaceholder { root: 1 }, ReplaceWith { root: 2, m: 1 },]
|
||||
);
|
||||
|
||||
let edits = dom.hard_diff(ScopeId(0));
|
||||
assert_eq!(
|
||||
edits.edits,
|
||||
dom.hard_diff(ScopeId(0)).edits,
|
||||
[
|
||||
CreateTextNode {
|
||||
text: "text 3",
|
||||
root: 6,
|
||||
},
|
||||
ReplaceWith { root: 5, m: 1 },
|
||||
CreateTextNode { text: "text 3", root: 2 },
|
||||
ReplaceWith { root: 1, m: 1 },
|
||||
]
|
||||
);
|
||||
|
||||
let edits = dom.hard_diff(ScopeId(0));
|
||||
assert_eq!(
|
||||
edits.edits,
|
||||
dom.hard_diff(ScopeId(0)).edits,
|
||||
[
|
||||
CreateTextNode {
|
||||
text: "text 0",
|
||||
root: 7,
|
||||
},
|
||||
CreateTextNode {
|
||||
text: "text 1",
|
||||
root: 8,
|
||||
},
|
||||
ReplaceWith { root: 6, m: 2 },
|
||||
CreateTextNode { text: "text 0", root: 1 },
|
||||
CreateTextNode { text: "text 1", root: 3 },
|
||||
ReplaceWith { root: 2, m: 2 },
|
||||
]
|
||||
);
|
||||
|
||||
let edits = dom.hard_diff(ScopeId(0));
|
||||
assert_eq!(
|
||||
edits.edits,
|
||||
dom.hard_diff(ScopeId(0)).edits,
|
||||
[
|
||||
CreateElement { tag: "h1", root: 9 },
|
||||
ReplaceWith { root: 7, m: 1 },
|
||||
Remove { root: 8 },
|
||||
CreateElement { tag: "h1", root: 2 },
|
||||
ReplaceWith { root: 1, m: 1 },
|
||||
Remove { root: 3 },
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn component_swap() {
|
||||
static App: Component = |cx| {
|
||||
fn app(cx: Scope) -> Element {
|
||||
let render_phase = cx.use_hook(|_| 0);
|
||||
*render_phase += 1;
|
||||
|
||||
|
@ -296,7 +253,7 @@ fn component_swap() {
|
|||
})
|
||||
};
|
||||
|
||||
let mut dom = VirtualDom::new(App);
|
||||
let mut dom = VirtualDom::new(app);
|
||||
let edits = dom.rebuild();
|
||||
dbg!(&edits);
|
||||
|
||||
|
|
108
packages/core/tests/passthru.rs
Normal file
108
packages/core/tests/passthru.rs
Normal file
|
@ -0,0 +1,108 @@
|
|||
#![allow(unused, non_upper_case_globals)]
|
||||
|
||||
//! Diffing Tests
|
||||
//!
|
||||
//! These tests only verify that the diffing algorithm works properly for single components.
|
||||
//!
|
||||
//! It does not validated that component lifecycles work properly. This is done in another test file.
|
||||
|
||||
use dioxus::{prelude::*, DomEdit, ScopeId};
|
||||
use dioxus_core as dioxus;
|
||||
use dioxus_core_macro::*;
|
||||
use dioxus_html as dioxus_elements;
|
||||
|
||||
mod test_logging;
|
||||
|
||||
fn new_dom() -> VirtualDom {
|
||||
const IS_LOGGING_ENABLED: bool = false;
|
||||
test_logging::set_up_logging(IS_LOGGING_ENABLED);
|
||||
VirtualDom::new(|cx| rsx!(cx, "hi"))
|
||||
}
|
||||
|
||||
use DomEdit::*;
|
||||
|
||||
/// Should push the text node onto the stack and modify it
|
||||
#[test]
|
||||
fn nested_passthru_creates() {
|
||||
fn app(cx: Scope) -> Element {
|
||||
cx.render(rsx! {
|
||||
Child {
|
||||
Child {
|
||||
Child {
|
||||
div {
|
||||
"hi"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
#[inline_props]
|
||||
fn Child<'a>(cx: Scope, children: Element<'a>) -> Element {
|
||||
cx.render(rsx! {
|
||||
children
|
||||
})
|
||||
};
|
||||
|
||||
let mut dom = VirtualDom::new(app);
|
||||
let mut channel = dom.get_scheduler_channel();
|
||||
assert!(dom.has_work());
|
||||
|
||||
let edits = dom.rebuild();
|
||||
assert_eq!(
|
||||
edits.edits,
|
||||
[
|
||||
CreateElement { tag: "div", root: 1 },
|
||||
CreateTextNode { text: "hi", root: 2 },
|
||||
AppendChildren { many: 1 },
|
||||
AppendChildren { many: 1 },
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
/// Should push the text node onto the stack and modify it
|
||||
#[test]
|
||||
fn nested_passthru_creates_add() {
|
||||
fn app(cx: Scope) -> Element {
|
||||
cx.render(rsx! {
|
||||
Child {
|
||||
"1"
|
||||
Child {
|
||||
"2"
|
||||
Child {
|
||||
"3"
|
||||
div {
|
||||
"hi"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
#[inline_props]
|
||||
fn Child<'a>(cx: Scope, children: Element<'a>) -> Element {
|
||||
cx.render(rsx! {
|
||||
children
|
||||
})
|
||||
};
|
||||
|
||||
let mut dom = VirtualDom::new(app);
|
||||
let mut channel = dom.get_scheduler_channel();
|
||||
assert!(dom.has_work());
|
||||
|
||||
let edits = dom.rebuild();
|
||||
assert_eq!(
|
||||
edits.edits,
|
||||
[
|
||||
CreateTextNode { text: "1", root: 1 },
|
||||
CreateTextNode { text: "2", root: 2 },
|
||||
CreateTextNode { text: "3", root: 3 },
|
||||
CreateElement { tag: "div", root: 4 },
|
||||
CreateTextNode { text: "hi", root: 5 },
|
||||
AppendChildren { many: 1 },
|
||||
AppendChildren { many: 4 },
|
||||
]
|
||||
)
|
||||
}
|
Loading…
Add table
Reference in a new issue