mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-10 06:34:20 +00:00
Wip: pre-diffmachine merge fork
This commit is contained in:
parent
69f5cc3802
commit
424a18137f
8 changed files with 67 additions and 231 deletions
1
.vscode/spellright.dict
vendored
1
.vscode/spellright.dict
vendored
|
@ -45,3 +45,4 @@ namespacing
|
||||||
impl
|
impl
|
||||||
destructured
|
destructured
|
||||||
linting
|
linting
|
||||||
|
lodash
|
||||||
|
|
|
@ -85,6 +85,7 @@ TypeScript is a great addition to JavaScript, but comes with a lot of tweaking f
|
||||||
- inline built-in unit/integration testing
|
- inline built-in unit/integration testing
|
||||||
- best-in-class error handling
|
- best-in-class error handling
|
||||||
- simple and fast build system
|
- simple and fast build system
|
||||||
|
- powerful standard library (no need for lodash or underscore)
|
||||||
- include_str! for integrating html/css/svg templates directly
|
- include_str! for integrating html/css/svg templates directly
|
||||||
- various macros (`html!`, `rsx!`) for fast template iteration
|
- various macros (`html!`, `rsx!`) for fast template iteration
|
||||||
|
|
||||||
|
|
2
packages/core/.vscode/settings.json
vendored
2
packages/core/.vscode/settings.json
vendored
|
@ -1,3 +1,3 @@
|
||||||
{
|
{
|
||||||
"rust-analyzer.inlayHints.enable": true
|
"rust-analyzer.inlayHints.enable": false
|
||||||
}
|
}
|
|
@ -1,17 +1,18 @@
|
||||||
use dioxus_core::prelude::*;
|
use dioxus_core::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let g = rsx! {
|
|
||||||
Fragment {
|
// let g = rsx! {
|
||||||
// div {}
|
// Fragment {
|
||||||
// div {}
|
// // div {}
|
||||||
// div {}
|
// // div {}
|
||||||
// div {}
|
// // div {}
|
||||||
// div {}
|
// // div {}
|
||||||
// div {}
|
// // div {}
|
||||||
// div {}
|
// // div {}
|
||||||
// div {}
|
// // div {}
|
||||||
// div {}
|
// // div {}
|
||||||
}
|
// // div {}
|
||||||
};
|
// }
|
||||||
|
// };
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
use std::{
|
use std::{
|
||||||
cell::{RefCell, UnsafeCell},
|
cell::{RefCell, UnsafeCell},
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
sync::Arc,
|
rc::Rc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use generational_arena::Arena;
|
use generational_arena::Arena;
|
||||||
|
|
||||||
use crate::innerlude::*;
|
use crate::innerlude::*;
|
||||||
|
|
||||||
type Rc<T> = Arc<T>;
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ScopeArena(Rc<RefCell<ScopeArenaInner>>);
|
pub struct ScopeArena(Rc<RefCell<ScopeArenaInner>>);
|
||||||
|
|
||||||
|
|
|
@ -1007,138 +1007,3 @@ enum KeyedPrefixResult {
|
||||||
// the beginning of `new` and `old` we already processed.
|
// the beginning of `new` and `old` we already processed.
|
||||||
MoreWorkToDo(usize),
|
MoreWorkToDo(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
mod support {
|
|
||||||
|
|
||||||
// // Get or create the template.
|
|
||||||
// //
|
|
||||||
// // Upon entering this function the change list stack may be in any shape:
|
|
||||||
// //
|
|
||||||
// // [...]
|
|
||||||
// //
|
|
||||||
// // When this function returns, it leaves a freshly cloned copy of the template
|
|
||||||
// // on the top of the change list stack:
|
|
||||||
// //
|
|
||||||
// // [... template]
|
|
||||||
// #[inline]
|
|
||||||
// pub fn get_or_create_template<'a>(// cached_set: &'a CachedSet,
|
|
||||||
// // change_list: &mut ChangeListBuilder,
|
|
||||||
// // registry: &mut EventsRegistry,
|
|
||||||
// // cached_roots: &mut FxHashSet<CacheId>,
|
|
||||||
// // template_id: CacheId,
|
|
||||||
// ) -> (&'a Node<'a>, bool) {
|
|
||||||
// let (template, template_template) = cached_set.get(template_id);
|
|
||||||
// debug_assert!(
|
|
||||||
// template_template.is_none(),
|
|
||||||
// "templates should not be templated themselves"
|
|
||||||
// );
|
|
||||||
|
|
||||||
// // If we haven't already created and saved the physical DOM subtree for this
|
|
||||||
// // template, do that now.
|
|
||||||
// if change_list.has_template(template_id) {
|
|
||||||
// // Clone the template and push it onto the stack.
|
|
||||||
// //
|
|
||||||
// // [...]
|
|
||||||
// change_list.push_template(template_id);
|
|
||||||
// // [... template]
|
|
||||||
|
|
||||||
// (template, true)
|
|
||||||
// } else {
|
|
||||||
// // [...]
|
|
||||||
// create(cached_set, change_list, registry, template, cached_roots);
|
|
||||||
// // [... template]
|
|
||||||
// change_list.save_template(template_id);
|
|
||||||
// // [... template]
|
|
||||||
|
|
||||||
// (template, false)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn create_and_replace(
|
|
||||||
// cached_set: &CachedSet,
|
|
||||||
// change_list: &mut ChangeListBuilder,
|
|
||||||
// registry: &mut EventsRegistry,
|
|
||||||
// new_template: Option<CacheId>,
|
|
||||||
// old: &Node,
|
|
||||||
// new: &Node,
|
|
||||||
// cached_roots: &mut FxHashSet<CacheId>,
|
|
||||||
// ) {
|
|
||||||
// debug_assert!(change_list.traversal_is_committed());
|
|
||||||
|
|
||||||
// if let Some(template_id) = new_template {
|
|
||||||
// let (template, needs_listeners) = get_or_create_template(
|
|
||||||
// cached_set,
|
|
||||||
// change_list,
|
|
||||||
// registry,
|
|
||||||
// cached_roots,
|
|
||||||
// template_id,
|
|
||||||
// );
|
|
||||||
// change_list.replace_with();
|
|
||||||
|
|
||||||
// let mut old_forcing = None;
|
|
||||||
// if needs_listeners {
|
|
||||||
// old_forcing = Some(change_list.push_force_new_listeners());
|
|
||||||
// }
|
|
||||||
|
|
||||||
// diff(
|
|
||||||
// cached_set,
|
|
||||||
// change_list,
|
|
||||||
// registry,
|
|
||||||
// template,
|
|
||||||
// new,
|
|
||||||
// cached_roots,
|
|
||||||
// );
|
|
||||||
|
|
||||||
// if let Some(old) = old_forcing {
|
|
||||||
// change_list.pop_force_new_listeners(old);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// change_list.commit_traversal();
|
|
||||||
// } else {
|
|
||||||
// create(cached_set, change_list, registry, new, cached_roots);
|
|
||||||
// change_list.replace_with();
|
|
||||||
// }
|
|
||||||
// registry.remove_subtree(old);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn create_with_template(
|
|
||||||
// cached_set: &CachedSet,
|
|
||||||
// change_list: &mut ChangeListBuilder,
|
|
||||||
// registry: &mut EventsRegistry,
|
|
||||||
// template_id: CacheId,
|
|
||||||
// node: &Node,
|
|
||||||
// cached_roots: &mut FxHashSet<CacheId>,
|
|
||||||
// ) {
|
|
||||||
// debug_assert!(change_list.traversal_is_committed());
|
|
||||||
|
|
||||||
// // [...]
|
|
||||||
// let (template, needs_listeners) =
|
|
||||||
// get_or_create_template(cached_set, change_list, registry, cached_roots, template_id);
|
|
||||||
// // [... template]
|
|
||||||
|
|
||||||
// // Now diff the node with its template.
|
|
||||||
// //
|
|
||||||
// // We must force adding new listeners instead of updating existing ones,
|
|
||||||
// // since listeners don't get cloned in `cloneNode`.
|
|
||||||
// let mut old_forcing = None;
|
|
||||||
// if needs_listeners {
|
|
||||||
// old_forcing = Some(change_list.push_force_new_listeners());
|
|
||||||
// }
|
|
||||||
|
|
||||||
// diff(
|
|
||||||
// cached_set,
|
|
||||||
// change_list,
|
|
||||||
// registry,
|
|
||||||
// template,
|
|
||||||
// node,
|
|
||||||
// cached_roots,
|
|
||||||
// );
|
|
||||||
|
|
||||||
// if let Some(old) = old_forcing {
|
|
||||||
// change_list.pop_force_new_listeners(old);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Make sure that we come back up to the level we were at originally.
|
|
||||||
// change_list.commit_traversal();
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
events::VirtualEvent,
|
events::VirtualEvent,
|
||||||
innerlude::{Context, Properties, Scope, ScopeIdx, FC},
|
innerlude::{Context, Properties, Scope, ScopeIdx, FC},
|
||||||
|
nodebuilder::text3,
|
||||||
};
|
};
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -28,6 +29,8 @@ pub enum VNode<'src> {
|
||||||
/// A text node (node type `TEXT_NODE`).
|
/// A text node (node type `TEXT_NODE`).
|
||||||
Text(VText<'src>),
|
Text(VText<'src>),
|
||||||
|
|
||||||
|
/// A fragment is a "virtual position" in the DOM
|
||||||
|
/// Fragments may have children and keys
|
||||||
Fragment(&'src VFragment<'src>),
|
Fragment(&'src VFragment<'src>),
|
||||||
|
|
||||||
/// A "suspended component"
|
/// A "suspended component"
|
||||||
|
@ -86,8 +89,8 @@ impl<'a> VNode<'a> {
|
||||||
VNode::Text(VText { text })
|
VNode::Text(VText { text })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn text_args(b: &'a Bump, f: Arguments) -> VNode<'a> {
|
pub fn text_args(bump: &'a Bump, args: Arguments) -> VNode<'a> {
|
||||||
todo!()
|
text3(bump, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -95,11 +98,11 @@ impl<'a> VNode<'a> {
|
||||||
match &self {
|
match &self {
|
||||||
VNode::Text(_) => NodeKey::NONE,
|
VNode::Text(_) => NodeKey::NONE,
|
||||||
VNode::Element(e) => e.key,
|
VNode::Element(e) => e.key,
|
||||||
VNode::Suspended => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
VNode::Fragment(frag) => frag.key,
|
VNode::Fragment(frag) => frag.key,
|
||||||
VNode::Component(c) => c.key,
|
VNode::Component(c) => c.key,
|
||||||
|
|
||||||
|
// todo suspend should be allowed to have keys
|
||||||
|
VNode::Suspended => NodeKey::NONE,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -254,9 +257,6 @@ pub struct VComponent<'src> {
|
||||||
_p: PhantomData<&'src ()>,
|
_p: PhantomData<&'src ()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn transmogrify<'a>(p: impl Properties + 'a) -> impl Properties + 'static {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
impl<'a> VComponent<'a> {
|
impl<'a> VComponent<'a> {
|
||||||
// use the type parameter on props creation and move it into a portable context
|
// use the type parameter on props creation and move it into a portable context
|
||||||
// this lets us keep scope generic *and* downcast its props when we need to:
|
// this lets us keep scope generic *and* downcast its props when we need to:
|
||||||
|
|
|
@ -154,10 +154,11 @@ impl VirtualDom {
|
||||||
// Make the first scope
|
// Make the first scope
|
||||||
// We don't run the component though, so renderers will need to call "rebuild" when they initialize their DOM
|
// We don't run the component though, so renderers will need to call "rebuild" when they initialize their DOM
|
||||||
let link = components.clone();
|
let link = components.clone();
|
||||||
|
let event_channel = Rc::new(move || {});
|
||||||
let base_scope = components
|
let base_scope = components
|
||||||
.with(|arena| {
|
.with(|arena| {
|
||||||
arena.insert_with(move |myidx| {
|
arena.insert_with(move |myidx| {
|
||||||
Scope::new(caller_ref, myidx, None, 0, _event_queue, link)
|
Scope::new(caller_ref, myidx, None, 0, event_channel, link, &[])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -172,6 +173,7 @@ impl VirtualDom {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Performs a *full* rebuild of the virtual dom, returning every edit required to generate the actual dom rom scratch
|
/// Performs a *full* rebuild of the virtual dom, returning every edit required to generate the actual dom rom scratch
|
||||||
|
/// Currently this doesn't do what we want it to do
|
||||||
pub fn rebuild<'s>(&'s mut self) -> Result<EditList<'s>> {
|
pub fn rebuild<'s>(&'s mut self) -> Result<EditList<'s>> {
|
||||||
let mut diff_machine = DiffMachine::new();
|
let mut diff_machine = DiffMachine::new();
|
||||||
|
|
||||||
|
@ -180,8 +182,9 @@ impl VirtualDom {
|
||||||
// Instead, this is done on top-level component
|
// Instead, this is done on top-level component
|
||||||
|
|
||||||
let base = self.components.try_get(self.base_scope)?;
|
let base = self.components.try_get(self.base_scope)?;
|
||||||
let immediate_update = self.event_queue.schedule_update(base);
|
|
||||||
immediate_update();
|
let update = &base.event_channel;
|
||||||
|
update();
|
||||||
|
|
||||||
self.progress_completely(&mut diff_machine)?;
|
self.progress_completely(&mut diff_machine)?;
|
||||||
|
|
||||||
|
@ -319,21 +322,23 @@ impl VirtualDom {
|
||||||
|
|
||||||
// Insert a new scope into our component list
|
// Insert a new scope into our component list
|
||||||
let idx = self.components.with(|components| {
|
let idx = self.components.with(|components| {
|
||||||
components.insert_with(|f| {
|
components.insert_with(|new_idx| {
|
||||||
|
let height = cur_height + 1;
|
||||||
Scope::new(
|
Scope::new(
|
||||||
caller,
|
caller,
|
||||||
f,
|
new_idx,
|
||||||
Some(cur_component.arena_idx),
|
Some(cur_component.arena_idx),
|
||||||
cur_height + 1,
|
height,
|
||||||
self.event_queue.clone(),
|
self.event_queue.new_channel(height, new_idx),
|
||||||
self.components.clone(),
|
self.components.clone(),
|
||||||
|
&[],
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
{
|
{
|
||||||
let cur_component = self.components.try_get_mut(update.idx).unwrap();
|
let cur_component = self.components.try_get_mut(update.idx).unwrap();
|
||||||
let mut ch = cur_component.children.borrow_mut();
|
let mut ch = cur_component.descendents.borrow_mut();
|
||||||
ch.insert(idx);
|
ch.insert(idx);
|
||||||
std::mem::drop(ch);
|
std::mem::drop(ch);
|
||||||
}
|
}
|
||||||
|
@ -444,7 +449,7 @@ impl VirtualDom {
|
||||||
// Accumulate all the child components that need to be removed
|
// Accumulate all the child components that need to be removed
|
||||||
while let Some(child_id) = children_to_remove.pop_back() {
|
while let Some(child_id) = children_to_remove.pop_back() {
|
||||||
let comp = self.components.try_get(child_id).unwrap();
|
let comp = self.components.try_get(child_id).unwrap();
|
||||||
let children = comp.children.borrow();
|
let children = comp.descendents.borrow();
|
||||||
for child in children.iter() {
|
for child in children.iter() {
|
||||||
children_to_remove.push_front(*child);
|
children_to_remove.push_front(*child);
|
||||||
}
|
}
|
||||||
|
@ -471,7 +476,6 @@ impl VirtualDom {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO!
|
// TODO!
|
||||||
//
|
|
||||||
// These impls are actually wrong. The DOM needs to have a mutex implemented.
|
// These impls are actually wrong. The DOM needs to have a mutex implemented.
|
||||||
unsafe impl Sync for VirtualDom {}
|
unsafe impl Sync for VirtualDom {}
|
||||||
unsafe impl Send for VirtualDom {}
|
unsafe impl Send for VirtualDom {}
|
||||||
|
@ -488,7 +492,9 @@ pub struct Scope {
|
||||||
|
|
||||||
// IDs of children that this scope has created
|
// IDs of children that this scope has created
|
||||||
// This enables us to drop the children and their children when this scope is destroyed
|
// This enables us to drop the children and their children when this scope is destroyed
|
||||||
children: RefCell<HashSet<ScopeIdx>>,
|
descendents: RefCell<HashSet<ScopeIdx>>,
|
||||||
|
|
||||||
|
child_nodes: &'static [VNode<'static>],
|
||||||
|
|
||||||
// A reference to the list of components.
|
// A reference to the list of components.
|
||||||
// This lets us traverse the component list whenever we need to access our parent or children.
|
// This lets us traverse the component list whenever we need to access our parent or children.
|
||||||
|
@ -501,8 +507,9 @@ pub struct Scope {
|
||||||
|
|
||||||
pub height: u32,
|
pub height: u32,
|
||||||
|
|
||||||
pub event_queue: EventQueue,
|
pub event_channel: Rc<dyn Fn() + 'static>,
|
||||||
|
|
||||||
|
// pub event_queue: EventQueue,
|
||||||
pub caller: Weak<OpaqueComponent<'static>>,
|
pub caller: Weak<OpaqueComponent<'static>>,
|
||||||
|
|
||||||
pub hookidx: RefCell<usize>,
|
pub hookidx: RefCell<usize>,
|
||||||
|
@ -528,6 +535,7 @@ pub struct Scope {
|
||||||
|
|
||||||
// We need to pin the hook so it doesn't move as we initialize the list of hooks
|
// We need to pin the hook so it doesn't move as we initialize the list of hooks
|
||||||
type Hook = Pin<Box<dyn std::any::Any>>;
|
type Hook = Pin<Box<dyn std::any::Any>>;
|
||||||
|
type EventChannel = Rc<dyn Fn()>;
|
||||||
|
|
||||||
impl Scope {
|
impl Scope {
|
||||||
// we are being created in the scope of an existing component (where the creator_node lifetime comes into play)
|
// we are being created in the scope of an existing component (where the creator_node lifetime comes into play)
|
||||||
|
@ -542,8 +550,9 @@ impl Scope {
|
||||||
arena_idx: ScopeIdx,
|
arena_idx: ScopeIdx,
|
||||||
parent: Option<ScopeIdx>,
|
parent: Option<ScopeIdx>,
|
||||||
height: u32,
|
height: u32,
|
||||||
event_queue: EventQueue,
|
event_channel: EventChannel,
|
||||||
arena_link: ScopeArena,
|
arena_link: ScopeArena,
|
||||||
|
child_nodes: &'creator_node [VNode<'creator_node>],
|
||||||
) -> Self {
|
) -> Self {
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"New scope created, height is {}, idx is {:?}",
|
"New scope created, height is {}, idx is {:?}",
|
||||||
|
@ -569,18 +578,19 @@ impl Scope {
|
||||||
};
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
child_nodes: &[],
|
||||||
caller,
|
caller,
|
||||||
parent,
|
parent,
|
||||||
arena_idx,
|
arena_idx,
|
||||||
height,
|
height,
|
||||||
event_queue,
|
event_channel,
|
||||||
arena_link,
|
arena_link,
|
||||||
frames: ActiveFrame::new(),
|
frames: ActiveFrame::new(),
|
||||||
hooks: Default::default(),
|
hooks: Default::default(),
|
||||||
shared_contexts: Default::default(),
|
shared_contexts: Default::default(),
|
||||||
listeners: Default::default(),
|
listeners: Default::default(),
|
||||||
hookidx: Default::default(),
|
hookidx: Default::default(),
|
||||||
children: Default::default(),
|
descendents: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -732,14 +742,18 @@ pub trait Scoped<'src>: Sized {
|
||||||
|
|
||||||
/// Access the children elements passed into the component
|
/// Access the children elements passed into the component
|
||||||
fn children(&self) -> &'src [VNode<'src>] {
|
fn children(&self) -> &'src [VNode<'src>] {
|
||||||
todo!("Children API not yet implemented for component Context")
|
// We're re-casting the nodes back out
|
||||||
|
// They don't really have a static lifetime
|
||||||
|
unsafe {
|
||||||
|
let scope = self.get_scope();
|
||||||
|
let nodes = scope.child_nodes;
|
||||||
|
nodes
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a subscription that schedules a future render for the reference component
|
/// Create a subscription that schedules a future render for the reference component
|
||||||
fn schedule_update(&self) -> Rc<dyn Fn() + 'static> {
|
fn schedule_update(&self) -> Rc<dyn Fn() + 'static> {
|
||||||
todo!()
|
self.get_scope().event_channel.clone()
|
||||||
// pub fn schedule_update(self) -> impl Fn() + 'static {
|
|
||||||
// self.scope.event_queue.schedule_update(&self.scope)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Take a lazy VNode structure and actually build it with the context of the VDom's efficient VNode allocator.
|
/// Take a lazy VNode structure and actually build it with the context of the VDom's efficient VNode allocator.
|
||||||
|
@ -759,22 +773,12 @@ pub trait Scoped<'src>: Sized {
|
||||||
///```
|
///```
|
||||||
fn render<'a, F: for<'b> FnOnce(&'b NodeCtx<'src>) -> VNode<'src> + 'src + 'a>(
|
fn render<'a, F: for<'b> FnOnce(&'b NodeCtx<'src>) -> VNode<'src> + 'src + 'a>(
|
||||||
self,
|
self,
|
||||||
// &'a/ self,
|
|
||||||
lazy_nodes: LazyNodes<'src, F>,
|
lazy_nodes: LazyNodes<'src, F>,
|
||||||
// lazy_nodes: LazyNodes<'src, F>,
|
|
||||||
) -> VNode<'src> {
|
) -> VNode<'src> {
|
||||||
let scope_ref = self.get_scope();
|
lazy_nodes.into_vnode(&NodeCtx {
|
||||||
let ctx = NodeCtx {
|
scope_ref: self.get_scope(),
|
||||||
scope_ref,
|
|
||||||
listener_id: 0.into(),
|
listener_id: 0.into(),
|
||||||
};
|
})
|
||||||
|
|
||||||
todo!()
|
|
||||||
// VNode {
|
|
||||||
// root: unsafe {
|
|
||||||
// std::mem::transmute::<VNode<'scope>, VNode<'static>>(lazy_nodes.into_vnode(&ctx))
|
|
||||||
// },
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// impl<'scope> Context<'scope> {
|
// impl<'scope> Context<'scope> {
|
||||||
|
@ -957,17 +961,14 @@ Any function prefixed with "use" should not be called conditionally.
|
||||||
// We then expose a handle to use those props for render in the form of "OpaqueComponent"
|
// We then expose a handle to use those props for render in the form of "OpaqueComponent"
|
||||||
pub(crate) type OpaqueComponent<'e> = dyn for<'b> Fn(&'b Scope) -> VNode<'b> + 'e;
|
pub(crate) type OpaqueComponent<'e> = dyn for<'b> Fn(&'b Scope) -> VNode<'b> + 'e;
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(PartialEq, Debug, Clone, Default)]
|
||||||
pub struct EventQueue(pub(crate) Rc<RefCell<Vec<HeightMarker>>>);
|
pub(crate) struct EventQueue(pub Rc<RefCell<Vec<HeightMarker>>>);
|
||||||
|
|
||||||
impl EventQueue {
|
impl EventQueue {
|
||||||
pub fn schedule_update(&self, source: &Scope) -> impl Fn() {
|
pub fn new_channel(&self, height: u32, idx: ScopeIdx) -> Rc<dyn Fn()> {
|
||||||
let inner = self.clone();
|
let inner = self.clone();
|
||||||
let marker = HeightMarker {
|
let marker = HeightMarker { height, idx };
|
||||||
height: source.height,
|
Rc::new(move || inner.0.as_ref().borrow_mut().push(marker))
|
||||||
idx: source.arena_idx,
|
|
||||||
};
|
|
||||||
move || inner.0.as_ref().borrow_mut().push(marker)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1107,35 +1108,3 @@ impl ActiveFrame {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn simulate() {
|
|
||||||
let dom = VirtualDom::new(|ctx| {
|
|
||||||
//
|
|
||||||
ctx.render(rsx! {
|
|
||||||
div {
|
|
||||||
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
// let root = dom.components.get(dom.base_scope).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ensure the virtualdom is send + sync
|
|
||||||
// needed for use in async/await contexts
|
|
||||||
#[test]
|
|
||||||
fn is_send_sync() {
|
|
||||||
fn check_send<T: Send>(_a: T) -> T {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
fn check_sync<T: Sync>(_a: T) -> T {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
let _ = check_send(VirtualDom::new(|ctx| ctx.render(rsx! { div {}})));
|
|
||||||
let _ = check_sync(VirtualDom::new(|ctx| ctx.render(rsx! { div {}})));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue