Feat: capture pointer type
This commit is contained in:
1 parent
2c2882c9a2
commit
e939373616
4 files changed
+101
-16
No files matched your search
Vendored
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"rust-analyzer.inlayHints.enable": true
|
"rust-analyzer.inlayHints.enable": false
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
|
use dioxus_core as dioxus;
|
||||||
use dioxus_core::{
|
use dioxus_core::{
|
||||||
prelude::{Context, VElement, VNode, FC},
|
prelude::{html, Context, VElement, VNode, FC},
|
||||||
virtual_dom::{Properties, Scope},
|
virtual_dom::{Properties, Scope},
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
@@ -135,26 +136,50 @@ fn test_use_state(ctx: Context<()>) -> VNode {
|
|||||||
// whenever a listener wakes up, we take the reference directly from the bump arena and, with a small bit
|
// whenever a listener wakes up, we take the reference directly from the bump arena and, with a small bit
|
||||||
// of unsafe code, execute the associated closure / listener function
|
// of unsafe code, execute the associated closure / listener function
|
||||||
// Those vnodes are then tossed out and new ones are installed, meaning and old references (potentially bad)
|
// Those vnodes are then tossed out and new ones are installed, meaning and old references (potentially bad)
|
||||||
// are removed and UB is prevented from affecting the program
|
// are removed and UB is prevented from /affecting/ the program
|
||||||
{
|
{
|
||||||
VNode::Element(VElement::new("button"))
|
VNode::Element(VElement::new("button"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_use_state_2(ctx: Context<()>) -> VNode {
|
#[allow(unused, non_upper_case_globals)]
|
||||||
|
static UseStateBorrowedFc: FC<()> = |ctx| {
|
||||||
let (val, set_val) = use_state(&ctx, || 0);
|
let (val, set_val) = use_state(&ctx, || 0);
|
||||||
|
|
||||||
let incr = || set_val(val + 1);
|
let incr = || set_val(val + 1);
|
||||||
let decr = || set_val(val - 1);
|
let decr = || set_val(val - 1);
|
||||||
|
|
||||||
todo!()
|
ctx.view(html! {
|
||||||
// html! {
|
<div>
|
||||||
// <div>
|
<nav class="menu">
|
||||||
// <nav class="menu">
|
<button> "Increment" </button>
|
||||||
// <button onclick=incr> { "Increment" } </button>
|
<button> "Decrement" </button>
|
||||||
// <button onclick=decr> { "Decrement" } </button>
|
</nav>
|
||||||
// </nav>
|
<p> "Current value: {val}" </p>
|
||||||
// <p> <b>{ "Current value: {val}" }</b> </p>
|
</div>
|
||||||
// </div>
|
})
|
||||||
// }
|
};
|
||||||
|
|
||||||
|
/// A useful component
|
||||||
|
/// With some great documentation
|
||||||
|
/// it practically speaks for itself.
|
||||||
|
/// It's also only a server component :o
|
||||||
|
fn use_state_borrowed(ctx: Context<()>) -> VNode {
|
||||||
|
let (val, set_val) = use_state(&ctx, || 0);
|
||||||
|
|
||||||
|
let incr = || set_val(val + 1);
|
||||||
|
let decr = || set_val(val - 1);
|
||||||
|
|
||||||
|
ctx.view(html! {
|
||||||
|
<div>
|
||||||
|
<nav class="menu">
|
||||||
|
<button> "Increment" </button>
|
||||||
|
<button> "Decrement" </button>
|
||||||
|
</nav>
|
||||||
|
<p> "Current value: {val}" </p>
|
||||||
|
</div>
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// <button onclick=incr> { "Increment" } </button>
|
||||||
|
// <button onclick=decr> { "Decrement" } </button>
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
//! An example that shows how to:
|
||||||
|
//! create a scope,
|
||||||
|
//! render a component,
|
||||||
|
//! change some data
|
||||||
|
//! render it again
|
||||||
|
//! consume the diffs and write that to a renderer
|
||||||
|
|
||||||
|
use dioxus_core::{
|
||||||
|
prelude::*,
|
||||||
|
virtual_dom::{Properties, Scope},
|
||||||
|
};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut scope = Scope::new(Example);
|
||||||
|
let ctx = scope.create_context::<Props>();
|
||||||
|
let p1 = Props { name: "bob".into() };
|
||||||
|
|
||||||
|
let p2 = Props { name: "bob".into() };
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Props {
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
impl Properties for Props {
|
||||||
|
fn new() -> Self {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Example: FC<Props> = |ctx| {
|
||||||
|
ctx.view(html! {
|
||||||
|
<div>
|
||||||
|
<h1> </h1>
|
||||||
|
</div>
|
||||||
|
})
|
||||||
|
};
|
||||||
@@ -49,10 +49,11 @@ A Context
|
|||||||
*/
|
*/
|
||||||
use crate::nodes::VNode;
|
use crate::nodes::VNode;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use any::Any;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use generational_arena::{Arena, Index};
|
use generational_arena::{Arena, Index};
|
||||||
use std::{
|
use std::{
|
||||||
any::TypeId,
|
any::{self, TypeId},
|
||||||
cell::{RefCell, UnsafeCell},
|
cell::{RefCell, UnsafeCell},
|
||||||
future::Future,
|
future::Future,
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
@@ -279,6 +280,7 @@ pub struct Scope {
|
|||||||
arena: typed_arena::Arena<Hook>,
|
arena: typed_arena::Arena<Hook>,
|
||||||
hooks: RefCell<Vec<*mut Hook>>,
|
hooks: RefCell<Vec<*mut Hook>>,
|
||||||
props_type: TypeId,
|
props_type: TypeId,
|
||||||
|
caller: *const (),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Scope {
|
impl Scope {
|
||||||
@@ -289,10 +291,13 @@ impl Scope {
|
|||||||
let arena = typed_arena::Arena::new();
|
let arena = typed_arena::Arena::new();
|
||||||
let hooks = RefCell::new(Vec::new());
|
let hooks = RefCell::new(Vec::new());
|
||||||
|
|
||||||
|
let caller = f as *const ();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
arena,
|
arena,
|
||||||
hooks,
|
hooks,
|
||||||
props_type,
|
props_type,
|
||||||
|
caller,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,7 +313,26 @@ impl Scope {
|
|||||||
|
|
||||||
/// Create a new context and run the component with references from the Virtual Dom
|
/// Create a new context and run the component with references from the Virtual Dom
|
||||||
/// This function downcasts the function pointer based on the stored props_type
|
/// This function downcasts the function pointer based on the stored props_type
|
||||||
fn run() {}
|
fn run<T: 'static>(&self, f: FC<T>) {}
|
||||||
|
|
||||||
|
fn call<T: Properties + 'static>(&mut self, val: T) {
|
||||||
|
if self.props_type == TypeId::of::<T>() {
|
||||||
|
/*
|
||||||
|
SAFETY ALERT
|
||||||
|
|
||||||
|
This particular usage of transmute is outlined in its docs https://doc.rust-lang.org/std/mem/fn.transmute.html
|
||||||
|
We hide the generic bound on the function item by casting it to raw pointer. When the function is actually called,
|
||||||
|
we transmute the function back using the props as reference.
|
||||||
|
|
||||||
|
This is safe because we check that the generic type matches before casting.
|
||||||
|
*/
|
||||||
|
let caller = unsafe { std::mem::transmute::<*const (), FC<T>>(self.caller) };
|
||||||
|
let ctx = self.create_context::<T>();
|
||||||
|
let nodes = caller(ctx);
|
||||||
|
} else {
|
||||||
|
panic!("Do not try to use `call` on Scopes with the wrong props type")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Components in Dioxus use the "Context" object to interact with their lifecycle.
|
/// Components in Dioxus use the "Context" object to interact with their lifecycle.
|
||||||
|
|||||||
Reference in new issue
Block a user