feat: omg what a dumb mistake
This commit is contained in:
1 parent
4a0068f099
commit
f782e14211
15 files changed
+262
-131
No files matched your search
+1
-1
@@ -19,7 +19,7 @@ dioxus-mobile = { path = "./packages/mobile", optional = true }
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
# core
|
# core
|
||||||
default = ["core", "ssr"]
|
default = ["core", "ssr", "desktop"]
|
||||||
core = ["macro", "hooks", "html"]
|
core = ["macro", "hooks", "html"]
|
||||||
macro = ["dioxus-core-macro"]
|
macro = ["dioxus-core-macro"]
|
||||||
hooks = ["dioxus-hooks"]
|
hooks = ["dioxus-hooks"]
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
//! Example: Coroutines!
|
||||||
|
//! --------------------
|
||||||
|
//!
|
||||||
|
//! Coroutines are an awesome way to write concurrent code. Dioxus heavily leverages coroutines to make sense of complex
|
||||||
|
//! ongoing asynchronous tasks. The async scheduler of Dioxus supports both single-threaded and multi-threaded coroutines,
|
||||||
|
//! so you can drop in code to run across multiple threads without blocking the main thread.
|
||||||
|
//!
|
||||||
|
//! Dioxus cannot simply abstract away the threading model for the web, unfortunately. If you want to use "web threads"
|
||||||
|
//! you either need to limit support for Chrome, or you need to use a Web Workers and message passing. This is easy enough
|
||||||
|
//! to do in your own code, and doesn't require 1st-party support from Dioxus itself.
|
||||||
|
//!
|
||||||
|
//! UseState and friends work fine with coroutines, but coroutines might be easier to use with the Dirac global state
|
||||||
|
//! management API. This lets you easily drive global state from a coroutine without having to subscribe to the state.
|
||||||
|
//!
|
||||||
|
//! For now, this example shows how to use coroutines used with use_state.
|
||||||
|
//!
|
||||||
|
//!
|
||||||
|
//! ## What is a Couroutine?
|
||||||
|
//!
|
||||||
|
//! A coroutine is a function that can be paused and resumed. It can be paused internally through "await" or externally
|
||||||
|
//! using the `TaskHandle` API. Within a coroutine, you may execute asynchonous code, that modifies values captured when
|
||||||
|
//! the coroutine was initiated. `use_state` always returns the same setter, so you don't need to worry about
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
dioxus::desktop::launch(App, |c| c);
|
||||||
|
}
|
||||||
|
|
||||||
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
|
static App: FC<()> = |cx| {
|
||||||
|
let p1 = use_state(cx, || 0);
|
||||||
|
let p2 = use_state(cx, || 0);
|
||||||
|
|
||||||
|
let (mut p1_async, mut p2_async) = (p1.for_async(), p2.for_async());
|
||||||
|
let (p1_handle, _) = cx.use_task(|| async move {
|
||||||
|
loop {
|
||||||
|
*p1_async.get_mut() += 1;
|
||||||
|
async_std::task::sleep(std::time::Duration::from_millis(75)).await;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let (p2_handle, _) = cx.use_task(|| async move {
|
||||||
|
loop {
|
||||||
|
*p2_async.get_mut() += 1;
|
||||||
|
async_std::task::sleep(std::time::Duration::from_millis(100)).await;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
cx.render(rsx! {
|
||||||
|
div { style: { width: "400px", height: "400px", position: "relative", background: "yellow" }
|
||||||
|
button { "reset", onclick: move |_| {} }
|
||||||
|
Horsey { pos: *p1, "horsey 1" }
|
||||||
|
Horsey { pos: *p2, "horsey 2" }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(PartialEq, Props)]
|
||||||
|
struct HorseyProps {
|
||||||
|
pos: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
static Horsey: FC<HorseyProps> = |cx| {
|
||||||
|
cx.render(rsx! {
|
||||||
|
div {
|
||||||
|
button { "pause" }
|
||||||
|
div {
|
||||||
|
{cx.children()}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
//! Example: File Explorer
|
||||||
|
//! -------------------------
|
||||||
|
//!
|
||||||
|
//! This is a fun little desktop application that lets you explore the file system.
|
||||||
|
//!
|
||||||
|
//! This example is interesting because it's mixing filesystem operations and GUI, which is typically hard for UI to do.
|
||||||
|
|
||||||
|
use dioxus::desktop::wry::application::dpi::LogicalSize;
|
||||||
|
use dioxus::prelude::*;
|
||||||
|
use std::fs::{self, DirEntry};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
env_logger::init();
|
||||||
|
dioxus::desktop::launch(App, |c| {
|
||||||
|
c.with_resizable(false)
|
||||||
|
.with_inner_size(LogicalSize::new(800.0, 400.0))
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
static App: FC<()> = |cx| {
|
||||||
|
let files = use_state(cx, || Files::new());
|
||||||
|
|
||||||
|
let file_list = files.path_names.iter().enumerate().map(|(dir_id, path)| {
|
||||||
|
rsx! (
|
||||||
|
li { a {"{path}", onclick: move |_| files.get_mut().enter_dir(dir_id), href: "#"} }
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
let err_disp = files.err.as_ref().map(|err| {
|
||||||
|
rsx! {
|
||||||
|
div {
|
||||||
|
code {"{err}"}
|
||||||
|
button {"x", onclick: move |_| files.get_mut().clear_err() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let cur = files.current();
|
||||||
|
cx.render(rsx! {
|
||||||
|
div {
|
||||||
|
h1 {"Files: "}
|
||||||
|
h3 {"Cur dir: {cur}"}
|
||||||
|
button { "go up", onclick: move |_| files.get_mut().go_up() }
|
||||||
|
ol { {file_list} }
|
||||||
|
{err_disp}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
// right now, this gets cloned every time. It might be a bit better to use im_rc's collections instead
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct Files {
|
||||||
|
path_stack: Vec<String>,
|
||||||
|
path_names: Vec<String>,
|
||||||
|
err: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Files {
|
||||||
|
fn new() -> Self {
|
||||||
|
let mut files = Self {
|
||||||
|
path_stack: vec!["./".to_string()],
|
||||||
|
path_names: vec![],
|
||||||
|
err: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
files.reload_path_list();
|
||||||
|
|
||||||
|
files
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reload_path_list(&mut self) {
|
||||||
|
let cur_path = self.path_stack.last().unwrap();
|
||||||
|
let paths = match fs::read_dir(cur_path) {
|
||||||
|
Ok(e) => e,
|
||||||
|
Err(err) => {
|
||||||
|
let err = format!("An error occured: {:?}", err);
|
||||||
|
self.err = Some(err);
|
||||||
|
self.path_stack.pop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// clear the current state
|
||||||
|
self.clear_err();
|
||||||
|
self.path_names.clear();
|
||||||
|
|
||||||
|
for path in paths {
|
||||||
|
self.path_names
|
||||||
|
.push(path.unwrap().path().display().to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn go_up(&mut self) {
|
||||||
|
if self.path_stack.len() > 1 {
|
||||||
|
self.path_stack.pop();
|
||||||
|
}
|
||||||
|
self.reload_path_list();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn enter_dir(&mut self, dir_id: usize) {
|
||||||
|
let path = &self.path_names[dir_id];
|
||||||
|
self.path_stack.push(path.clone());
|
||||||
|
self.reload_path_list();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn current(&self) -> &str {
|
||||||
|
self.path_stack.last().unwrap()
|
||||||
|
}
|
||||||
|
fn clear_err(&mut self) {
|
||||||
|
self.err = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
-2
@@ -17,12 +17,17 @@
|
|||||||
|
|
||||||
use dioxus::events::on::*;
|
use dioxus::events::on::*;
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
use dioxus_desktop::wry::application::dpi::LogicalSize;
|
||||||
|
|
||||||
const STYLE: &str = include_str!("./assets/calculator.css");
|
const STYLE: &str = include_str!("./assets/calculator.css");
|
||||||
fn main() {
|
fn main() {
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
dioxus::desktop::launch(App, |cfg| cfg.with_title("Calculator Demo"))
|
dioxus::desktop::launch(App, |cfg| {
|
||||||
.expect("failed to launch dioxus app");
|
cfg.with_title("Calculator Demo")
|
||||||
|
.with_resizable(false)
|
||||||
|
.with_inner_size(LogicalSize::new(320.0, 530.0))
|
||||||
|
})
|
||||||
|
.expect("failed to launch dioxus app");
|
||||||
}
|
}
|
||||||
|
|
||||||
static App: FC<()> = |cx| {
|
static App: FC<()> = |cx| {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ pub struct ActiveFrame {
|
|||||||
|
|
||||||
pub struct BumpFrame {
|
pub struct BumpFrame {
|
||||||
pub bump: Bump,
|
pub bump: Bump,
|
||||||
pub head_node: VNode<'static>,
|
pub(crate) head_node: VNode<'static>,
|
||||||
|
|
||||||
// used internally for debugging
|
// used internally for debugging
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
@@ -36,6 +36,14 @@ impl ActiveFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub unsafe fn reset_wip_frame(&mut self) {
|
||||||
|
self.wip_frame_mut().bump.reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_head_node<'a>(&mut self, node: VNode<'a>) {
|
||||||
|
self.wip_frame_mut().head_node = unsafe { std::mem::transmute(node) };
|
||||||
|
}
|
||||||
|
|
||||||
/// The "work in progress frame" represents the frame that is currently being worked on.
|
/// The "work in progress frame" represents the frame that is currently being worked on.
|
||||||
pub fn wip_frame(&self) -> &BumpFrame {
|
pub fn wip_frame(&self) -> &BumpFrame {
|
||||||
match self.generation.get() & 1 == 0 {
|
match self.generation.get() & 1 == 0 {
|
||||||
|
|||||||
@@ -148,10 +148,10 @@ impl<'src, P> Context<'src, P> {
|
|||||||
lazy_nodes: LazyNodes<'src, F>,
|
lazy_nodes: LazyNodes<'src, F>,
|
||||||
) -> DomTree<'src> {
|
) -> DomTree<'src> {
|
||||||
let scope_ref = self.scope;
|
let scope_ref = self.scope;
|
||||||
let listener_id = &scope_ref.listener_idx;
|
// let listener_id = &scope_ref.listener_idx;
|
||||||
Some(lazy_nodes.into_vnode(NodeFactory {
|
Some(lazy_nodes.into_vnode(NodeFactory {
|
||||||
scope: scope_ref,
|
scope: scope_ref,
|
||||||
listener_id,
|
// listener_id,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -505,10 +505,7 @@ impl<'src> SuspendedContext<'src> {
|
|||||||
lazy_nodes: LazyNodes<'src, F>,
|
lazy_nodes: LazyNodes<'src, F>,
|
||||||
) -> DomTree<'src> {
|
) -> DomTree<'src> {
|
||||||
let scope_ref = self.inner.scope;
|
let scope_ref = self.inner.scope;
|
||||||
let listener_id = &scope_ref.listener_idx;
|
|
||||||
Some(lazy_nodes.into_vnode(NodeFactory {
|
Some(lazy_nodes.into_vnode(NodeFactory { scope: scope_ref }))
|
||||||
scope: scope_ref,
|
|
||||||
listener_id,
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+30
-63
@@ -55,7 +55,7 @@ use crate::{arena::SharedResources, innerlude::*};
|
|||||||
use fxhash::{FxHashMap, FxHashSet};
|
use fxhash::{FxHashMap, FxHashSet};
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
|
||||||
use std::{any::Any, borrow::Borrow};
|
use std::{any::Any, borrow::Borrow, cmp::Ordering};
|
||||||
|
|
||||||
/// Instead of having handles directly over nodes, Dioxus uses simple u32 as node IDs.
|
/// Instead of having handles directly over nodes, Dioxus uses simple u32 as node IDs.
|
||||||
/// The expectation is that the underlying renderer will mainain their Nodes in vec where the ids are the index. This allows
|
/// The expectation is that the underlying renderer will mainain their Nodes in vec where the ids are the index. This allows
|
||||||
@@ -206,13 +206,12 @@ impl<'real, 'bump> DiffMachine<'real, 'bump> {
|
|||||||
scope.update_children(ScopeChildren(new.children));
|
scope.update_children(ScopeChildren(new.children));
|
||||||
|
|
||||||
// React doesn't automatically memoize, but we do.
|
// React doesn't automatically memoize, but we do.
|
||||||
let should_render = true;
|
let are_the_same = match old.comparator {
|
||||||
// let should_render = match old.comparator {
|
Some(comparator) => comparator(new),
|
||||||
// Some(comparator) => comparator(new),
|
None => false,
|
||||||
// None => true,
|
};
|
||||||
// };
|
|
||||||
|
|
||||||
if should_render {
|
if !are_the_same {
|
||||||
scope.run_scope().unwrap();
|
scope.run_scope().unwrap();
|
||||||
self.diff_node(scope.frames.wip_head(), scope.frames.fin_head());
|
self.diff_node(scope.frames.wip_head(), scope.frames.fin_head());
|
||||||
} else {
|
} else {
|
||||||
@@ -915,7 +914,7 @@ impl<'a, 'bump> DiffMachine<'a, 'bump> {
|
|||||||
// [... parent]
|
// [... parent]
|
||||||
//
|
//
|
||||||
// When this function returns, the change list stack is in the same state.
|
// When this function returns, the change list stack is in the same state.
|
||||||
pub fn remove_all_children(&mut self, old: &'bump [VNode<'bump>]) {
|
fn remove_all_children(&mut self, old: &'bump [VNode<'bump>]) {
|
||||||
// debug_assert!(self.edits.traversal_is_committed());
|
// debug_assert!(self.edits.traversal_is_committed());
|
||||||
log::debug!("REMOVING CHILDREN");
|
log::debug!("REMOVING CHILDREN");
|
||||||
for _child in old {
|
for _child in old {
|
||||||
@@ -1208,67 +1207,35 @@ impl<'a, 'bump> DiffMachine<'a, 'bump> {
|
|||||||
// the change list stack is in the same state when this function returns.
|
// the change list stack is in the same state when this function returns.
|
||||||
fn diff_non_keyed_children(&mut self, old: &'bump [VNode<'bump>], new: &'bump [VNode<'bump>]) {
|
fn diff_non_keyed_children(&mut self, old: &'bump [VNode<'bump>], new: &'bump [VNode<'bump>]) {
|
||||||
// Handled these cases in `diff_children` before calling this function.
|
// Handled these cases in `diff_children` before calling this function.
|
||||||
|
//
|
||||||
// debug_assert!(!new.is_empty());
|
// debug_assert!(!new.is_empty());
|
||||||
// debug_assert!(!old.is_empty());
|
// debug_assert!(!old.is_empty());
|
||||||
|
|
||||||
// [... parent]
|
|
||||||
// self.edits.go_down();
|
|
||||||
// self.edits.push_root()
|
|
||||||
// [... parent child]
|
|
||||||
|
|
||||||
// todo!()
|
|
||||||
for (_i, (new_child, old_child)) in new.iter().zip(old.iter()).enumerate() {
|
for (_i, (new_child, old_child)) in new.iter().zip(old.iter()).enumerate() {
|
||||||
// [... parent prev_child]
|
|
||||||
// self.edits.go_to_sibling(i);
|
|
||||||
// [... parent this_child]
|
|
||||||
|
|
||||||
// let did = old_child.get_mounted_id(self.components).unwrap();
|
|
||||||
// if did.0 == 0 {
|
|
||||||
// log::debug!("Root is bad: {:#?}", old_child);
|
|
||||||
// }
|
|
||||||
// self.edits.push_root(did);
|
|
||||||
// dbg!("dffing child", new_child, old_child);
|
|
||||||
self.diff_node(old_child, new_child);
|
self.diff_node(old_child, new_child);
|
||||||
|
|
||||||
// let old_id = old_child.get_mounted_id(self.components).unwrap();
|
|
||||||
// let new_id = new_child.get_mounted_id(self.components).unwrap();
|
|
||||||
|
|
||||||
// log::debug!(
|
|
||||||
// "pushed root. {:?}, {:?}",
|
|
||||||
// old_child.get_mounted_id(self.components).unwrap(),
|
|
||||||
// new_child.get_mounted_id(self.components).unwrap()
|
|
||||||
// );
|
|
||||||
// if old_id != new_id {
|
|
||||||
// log::debug!("Mismatch: {:?}", new_child);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// match old.len().cmp(&new.len()) {
|
match old.len().cmp(&new.len()) {
|
||||||
// // old.len > new.len -> removing some nodes
|
// old.len > new.len -> removing some nodes
|
||||||
// Ordering::Greater => {
|
Ordering::Greater => {
|
||||||
// // [... parent prev_child]
|
for item in &old[new.len()..] {
|
||||||
// self.edits.go_to_sibling(new.len());
|
for i in RealChildIterator::new(item, self.vdom) {
|
||||||
// // [... parent first_child_to_remove]
|
self.edits.push_root(i.element_id().unwrap());
|
||||||
// // self.edits.commit_traversal();
|
self.edits.remove();
|
||||||
// // support::remove_self_and_next_siblings(state, &old[new.len()..]);
|
}
|
||||||
// self.remove_self_and_next_siblings(&old[new.len()..]);
|
}
|
||||||
// // [... parent]
|
}
|
||||||
// }
|
// old.len < new.len -> adding some nodes
|
||||||
// // old.len < new.len -> adding some nodes
|
Ordering::Less => {
|
||||||
// Ordering::Less => {
|
// [... parent last_child]
|
||||||
// // [... parent last_child]
|
// self.edits.go_up();
|
||||||
// self.edits.go_up();
|
// [... parent]
|
||||||
// // [... parent]
|
// self.edits.commit_traversal();
|
||||||
// // self.edits.commit_traversal();
|
self.create_and_append_children(&new[old.len()..]);
|
||||||
// self.create_and_append_children(&new[old.len()..]);
|
}
|
||||||
// }
|
// old.len == new.len -> no nodes added/removed, but πerhaps changed
|
||||||
// // old.len == new.len -> no nodes added/removed, but πerhaps changed
|
Ordering::Equal => {}
|
||||||
// Ordering::Equal => {
|
}
|
||||||
// // [... parent child]
|
|
||||||
// self.edits.go_up();
|
|
||||||
// // [... parent]
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ======================
|
// ======================
|
||||||
@@ -1284,7 +1251,7 @@ impl<'a, 'bump> DiffMachine<'a, 'bump> {
|
|||||||
// After the function returns, the child is no longer on the change list stack:
|
// After the function returns, the child is no longer on the change list stack:
|
||||||
//
|
//
|
||||||
// [... parent]
|
// [... parent]
|
||||||
pub fn remove_self_and_next_siblings(&self, old: &[VNode<'bump>]) {
|
fn remove_self_and_next_siblings(&self, old: &[VNode<'bump>]) {
|
||||||
// debug_assert!(self.edits.traversal_is_committed());
|
// debug_assert!(self.edits.traversal_is_committed());
|
||||||
for child in old {
|
for child in old {
|
||||||
if let VNodeKind::Component(_vcomp) = child.kind {
|
if let VNodeKind::Component(_vcomp) = child.kind {
|
||||||
|
|||||||
@@ -144,14 +144,12 @@ pub struct VComponent<'src> {
|
|||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct NodeFactory<'a> {
|
pub struct NodeFactory<'a> {
|
||||||
pub scope: &'a Scope,
|
pub scope: &'a Scope,
|
||||||
pub listener_id: &'a Cell<usize>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> NodeFactory<'a> {
|
impl<'a> NodeFactory<'a> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn bump(&self) -> &'a bumpalo::Bump {
|
pub fn bump(&self) -> &'a bumpalo::Bump {
|
||||||
&self.scope.frames.wip_frame().bump
|
&self.scope.frames.wip_frame().bump
|
||||||
// &self.scope.cur_frame().bump
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unstable_place_holder() -> VNode<'static> {
|
pub fn unstable_place_holder() -> VNode<'static> {
|
||||||
@@ -346,6 +344,9 @@ impl<'a> NodeFactory<'a> {
|
|||||||
if user_fc == other.user_fc {
|
if user_fc == other.user_fc {
|
||||||
let real_other = unsafe { &*(other.raw_props as *const _ as *const P) };
|
let real_other = unsafe { &*(other.raw_props as *const _ as *const P) };
|
||||||
let props_memoized = unsafe { props.memoize(&real_other) };
|
let props_memoized = unsafe { props.memoize(&real_other) };
|
||||||
|
|
||||||
|
// It's only okay to memoize if there are no children and the props can be memoized
|
||||||
|
// Implementing memoize is unsafe and done automatically with the props trait
|
||||||
match (props_memoized, children.len() == 0) {
|
match (props_memoized, children.len() == 0) {
|
||||||
(true, true) => true,
|
(true, true) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
@@ -395,7 +396,7 @@ impl<'a> NodeFactory<'a> {
|
|||||||
unsafe { std::mem::transmute::<_, Captured<'static>>(caller) }
|
unsafe { std::mem::transmute::<_, Captured<'static>>(caller) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fragment_from_iter(self, node_iter: impl IntoVNodeList<'a> + 'a) -> VNode<'a> {
|
pub fn fragment_from_iter(self, node_iter: impl IntoVNodeList<'a>) -> VNode<'a> {
|
||||||
let children = node_iter.into_vnode_list(self);
|
let children = node_iter.into_vnode_list(self);
|
||||||
|
|
||||||
VNode {
|
VNode {
|
||||||
@@ -501,37 +502,6 @@ impl<'a> IntoVNode<'a> for VNode<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For the case where a rendered VNode is by reference passed into the rsx! macro through curly braces
|
|
||||||
// This behavior is designed for the cx.children method where child nodes are passed by reference.
|
|
||||||
//
|
|
||||||
// Designed to support indexing
|
|
||||||
impl<'a> IntoVNode<'a> for &VNode<'a> {
|
|
||||||
fn into_vnode(self, _: NodeFactory<'a>) -> VNode<'a> {
|
|
||||||
todo!()
|
|
||||||
// let kind = match &self.kind {
|
|
||||||
// VNodeKind::Element(element) => VNodeKind::Element(element),
|
|
||||||
// VNodeKind::Text(old) => VNodeKind::Text(VText {
|
|
||||||
// text: old.text,
|
|
||||||
// is_static: old.is_static,
|
|
||||||
// }),
|
|
||||||
// VNodeKind::Fragment(fragment) => VNodeKind::Fragment(VFragment {
|
|
||||||
// children: fragment.children,
|
|
||||||
// is_static: fragment.is_static,
|
|
||||||
// }),
|
|
||||||
// VNodeKind::Component(component) => VNodeKind::Component(component),
|
|
||||||
|
|
||||||
// // todo: it doesn't make much sense to pass in suspended nodes
|
|
||||||
// // I think this is right but I'm not too sure.
|
|
||||||
// VNodeKind::Suspended { node } => VNodeKind::Suspended { node: node.clone() },
|
|
||||||
// };
|
|
||||||
// VNode {
|
|
||||||
// kind,
|
|
||||||
// dom_id: self.dom_id.clone(),
|
|
||||||
// key: self.key.clone(),
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A concrete type provider for closures that build VNode structures.
|
/// A concrete type provider for closures that build VNode structures.
|
||||||
///
|
///
|
||||||
/// This struct wraps lazy structs that build VNode trees Normally, we cannot perform a blanket implementation over
|
/// This struct wraps lazy structs that build VNode trees Normally, we cannot perform a blanket implementation over
|
||||||
|
|||||||
+17
-18
@@ -34,7 +34,6 @@ pub struct Scope {
|
|||||||
|
|
||||||
// Listeners
|
// Listeners
|
||||||
pub(crate) listeners: RefCell<Vec<*const Listener<'static>>>,
|
pub(crate) listeners: RefCell<Vec<*const Listener<'static>>>,
|
||||||
pub(crate) listener_idx: Cell<usize>,
|
|
||||||
|
|
||||||
// State
|
// State
|
||||||
pub(crate) hooks: HookList,
|
pub(crate) hooks: HookList,
|
||||||
@@ -72,9 +71,7 @@ impl Scope {
|
|||||||
vdom: SharedResources,
|
vdom: SharedResources,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let child_nodes = unsafe { child_nodes.extend_lifetime() };
|
let child_nodes = unsafe { child_nodes.extend_lifetime() };
|
||||||
// let child_nodes = unsafe { std::mem::transmute(child_nodes) };
|
|
||||||
|
|
||||||
// dbg!(child_nodes);
|
|
||||||
Self {
|
Self {
|
||||||
child_nodes,
|
child_nodes,
|
||||||
caller,
|
caller,
|
||||||
@@ -82,7 +79,6 @@ impl Scope {
|
|||||||
our_arena_idx: arena_idx,
|
our_arena_idx: arena_idx,
|
||||||
height,
|
height,
|
||||||
vdom,
|
vdom,
|
||||||
listener_idx: Default::default(),
|
|
||||||
frames: ActiveFrame::new(),
|
frames: ActiveFrame::new(),
|
||||||
hooks: Default::default(),
|
hooks: Default::default(),
|
||||||
shared_contexts: Default::default(),
|
shared_contexts: Default::default(),
|
||||||
@@ -114,24 +110,27 @@ impl Scope {
|
|||||||
|
|
||||||
// make sure we call the drop implementation on all the listeners
|
// make sure we call the drop implementation on all the listeners
|
||||||
// this is important to not leak memory
|
// this is important to not leak memory
|
||||||
for li in self.listeners.borrow_mut().drain(..) {
|
for listener in self
|
||||||
log::debug!("dropping listener");
|
.listeners
|
||||||
let d = unsafe { &*li };
|
.borrow_mut()
|
||||||
let mut r = d.callback.borrow_mut();
|
.drain(..)
|
||||||
let p = r.take().unwrap();
|
.map(|li| unsafe { &*li })
|
||||||
std::mem::drop(p);
|
{
|
||||||
// d.callback.borrow_mut();
|
let mut cb = listener.callback.borrow_mut();
|
||||||
|
match cb.take() {
|
||||||
|
Some(val) => std::mem::drop(val),
|
||||||
|
None => log::info!("no callback to drop. component must be broken"),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// self.listeners.borrow_mut().clear();
|
// Safety:
|
||||||
|
// - We dropped the listeners, so no more &mut T can be used while these are held
|
||||||
|
// - All children nodes that rely on &mut T are replaced with a new reference
|
||||||
unsafe { self.hooks.reset() };
|
unsafe { self.hooks.reset() };
|
||||||
|
|
||||||
self.listener_idx.set(0);
|
// Safety:
|
||||||
|
// - We've dropped all references to the wip bump frame
|
||||||
// This is a very dangerous operation
|
unsafe { self.frames.reset_wip_frame() };
|
||||||
let next_frame = self.frames.wip_frame_mut();
|
|
||||||
next_frame.bump.reset();
|
|
||||||
|
|
||||||
// Cast the caller ptr from static to one with our own reference
|
// Cast the caller ptr from static to one with our own reference
|
||||||
let c3: &WrappedCaller = self.caller.as_ref();
|
let c3: &WrappedCaller = self.caller.as_ref();
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ license = "MIT/Apache-2.0"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
# web-view = { git = "https://github.com/Boscop/web-view" }
|
# web-view = { git = "https://github.com/Boscop/web-view" }
|
||||||
dioxus-core = { path = "../core", version = "0.1.2", features = ["serialize"] }
|
dioxus-core = { path = "../core", version = "0.1.2", features = ["serialize"] }
|
||||||
anyhow = "1.0.38"
|
anyhow = "1.0"
|
||||||
argh = "0.1.4"
|
argh = "0.1.4"
|
||||||
serde = "1.0.120"
|
serde = "1.0.120"
|
||||||
serde_json = "1.0.61"
|
serde_json = "1.0.61"
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ use std::{
|
|||||||
pub fn use_state<'a, 'c, T: 'static, F: FnOnce() -> T, P>(
|
pub fn use_state<'a, 'c, T: 'static, F: FnOnce() -> T, P>(
|
||||||
cx: Context<'a, P>,
|
cx: Context<'a, P>,
|
||||||
initial_state_fn: F,
|
initial_state_fn: F,
|
||||||
) -> UseState<T> {
|
) -> UseState<'a, T> {
|
||||||
cx.use_hook(
|
cx.use_hook(
|
||||||
move |_| UseStateInner {
|
move |_| UseStateInner {
|
||||||
current_val: initial_state_fn(),
|
current_val: initial_state_fn(),
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ edition = "2018"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.42"
|
anyhow = "1.0"
|
||||||
# cacao = { git = "https://github.com/ryanmcgrath/cacao" }
|
# cacao = { git = "https://github.com/ryanmcgrath/cacao" }
|
||||||
dioxus-core = { path = "../core", version = "0.1.2" }
|
dioxus-core = { path = "../core", version = "0.1.2" }
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
|
|||||||
@@ -185,6 +185,7 @@ impl<T: Properties + 'static> WebviewRenderer<T> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// brad johnson go chat
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
init_logging();
|
init_logging();
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ tide-websockets = "*"
|
|||||||
thiserror = "1.0.23"
|
thiserror = "1.0.23"
|
||||||
log = "0.4.13"
|
log = "0.4.13"
|
||||||
fern = { version = "0.6.0", features = ["colored"] }
|
fern = { version = "0.6.0", features = ["colored"] }
|
||||||
anyhow = "1.0.38"
|
anyhow = "1.0"
|
||||||
argh = "0.1.4"
|
argh = "0.1.4"
|
||||||
serde = "1.0.120"
|
serde = "1.0.120"
|
||||||
serde_json = "1.0.61"
|
serde_json = "1.0.61"
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ generational-arena = "0.2.8"
|
|||||||
wasm-bindgen-test = "0.3.21"
|
wasm-bindgen-test = "0.3.21"
|
||||||
once_cell = "1.8"
|
once_cell = "1.8"
|
||||||
async-channel = "1.6.1"
|
async-channel = "1.6.1"
|
||||||
anyhow = "1.0.41"
|
anyhow = "1.0"
|
||||||
|
|
||||||
futures-util = "0.3.15"
|
futures-util = "0.3.15"
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user