Feat: some docs
This commit is contained in:
1 parent
508c560320
commit
1919f88f03
10 files changed
+179
-182
No files matched your search
Vendored
+2
@@ -43,3 +43,5 @@ virtualdom
|
|||||||
namespaced
|
namespaced
|
||||||
namespacing
|
namespacing
|
||||||
impl
|
impl
|
||||||
|
destructured
|
||||||
|
linting
|
||||||
@@ -9,8 +9,8 @@ struct MyProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn Example(ctx: Context<MyProps>) -> VNode {
|
fn Example(ctx: Context<MyProps>) -> VNode {
|
||||||
ctx.render(html! {
|
ctx.render(html! {
|
||||||
<div> "Hello {ctx.props().name}!" </div>
|
<div> "Hello {ctx.name}!" </div>
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ struct ExampleProps {
|
|||||||
fn Example(ctx: &mut Context<ExampleProps>) -> VNode {
|
fn Example(ctx: &mut Context<ExampleProps>) -> VNode {
|
||||||
let ExampleProps {
|
let ExampleProps {
|
||||||
name, pending, count
|
name, pending, count
|
||||||
} = ctx.props();
|
} = ctx.props;
|
||||||
|
|
||||||
rsx! {
|
rsx! {
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -4,10 +4,12 @@ Dioxus comes preloaded with two macros for creating VNodes.
|
|||||||
|
|
||||||
## html! macro
|
## html! macro
|
||||||
|
|
||||||
The html! macro supports the html standard. This macro will happily accept a copy-paste from something like tailwind builder. Writing this one by hand is a bit tedious and doesn't come with much help from Rust IDE tools.
|
The html! macro supports a limited subset of the html standard. This macro will happily accept a copy-paste from something like tailwind builder. However, writing HTML by hand is a bit tedious - IDE tools for Rust don't support linting/autocomplete/syntax highlighting. RSX is much more natural for Rust programs and _does_ integrate well with Rust IDE tools.
|
||||||
|
|
||||||
There is also limited support for dynamic handlers, but it will function similarly to JSX.
|
There is also limited support for dynamic handlers, but it will function similarly to JSX.
|
||||||
|
|
||||||
|
You'll want to write RSX where you can, and in a future release we'll have a tool that automatically converts HTML to RSX.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
#[fc]
|
#[fc]
|
||||||
fn Example(ctx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
|
fn Example(ctx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
|
||||||
@@ -23,9 +25,9 @@ fn Example(ctx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
|
|||||||
|
|
||||||
## rsx! macro
|
## rsx! macro
|
||||||
|
|
||||||
The rsx! macro is a VNode builder macro designed especially for Rust. Writing these should feel very natural, much like assembling a struct. VSCode also supports these with code folding, bracket-tabbing, bracket highlighting, and section selecting.
|
The rsx! macro is a VNode builder macro designed especially for Rust programs. Writing these should feel very natural, much like assembling a struct. VSCode also supports these with code folding, bracket-tabbing, bracket highlighting, and section selecting.
|
||||||
|
|
||||||
The Dioxus VSCode extension provides a function to convert a selection of html! template and turn it into rsx!, so you'll never need to transcribe templates by hand.
|
The Dioxus VSCode extension will eventually provide a macro to convert a selection of html! template and turn it into rsx!, so you'll never need to transcribe templates by hand.
|
||||||
|
|
||||||
It's also a bit easier on the eyes 🙂.
|
It's also a bit easier on the eyes 🙂.
|
||||||
|
|
||||||
@@ -51,30 +53,55 @@ Each element takes a comma-separated list of expressions to build the node. Roug
|
|||||||
- `CustomTag {}` adds a new child component
|
- `CustomTag {}` adds a new child component
|
||||||
- `{expr}` pastes the `expr` tokens literally. They must be IntoCtx<Vnode> to work properly
|
- `{expr}` pastes the `expr` tokens literally. They must be IntoCtx<Vnode> to work properly
|
||||||
|
|
||||||
Lists must include commas, much like how struct definitions work.
|
Commas are entirely optional, but might be useful to delineate between elements and attributes.
|
||||||
|
|
||||||
|
The `render` function provides an **extremely efficient** allocator for VNodes and text, so try not to use the `format!` macro in your components. Rust's default `ToString` methods pass through the global allocator, but all text in components is allocated inside a manually-managed Bump arena.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
static Example: FC<()> = |ctx| {
|
static Example: FC<()> = |ctx| {
|
||||||
|
|
||||||
|
let text = "example";
|
||||||
|
|
||||||
ctx.render(rsx!{
|
ctx.render(rsx!{
|
||||||
div {
|
div {
|
||||||
h1 { "Example" },
|
h1 { "Example" },
|
||||||
|
|
||||||
|
// fstring interpolation
|
||||||
|
"{text}"
|
||||||
|
|
||||||
p {
|
p {
|
||||||
// Props
|
// Attributes
|
||||||
tag: "type",
|
tag: "type",
|
||||||
|
|
||||||
|
// Anything that implements display can be an attribute
|
||||||
abc: 123,
|
abc: 123,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
class: "big small wide short",
|
|
||||||
|
// attributes also supports interpolation
|
||||||
|
// `class` is not a restricted keyword unlike JS and ClassName
|
||||||
|
class: "big small wide short {text}",
|
||||||
|
|
||||||
|
// bool-based classnames
|
||||||
|
classes: [("big", true), ("small", false)]
|
||||||
|
|
||||||
|
// Bool-based props
|
||||||
|
// *must* be in the tuple form, cannot enter as a variable
|
||||||
|
tag: ("type", false)
|
||||||
|
|
||||||
|
tag: {"these tokens are placed directly"}
|
||||||
|
|
||||||
// Children
|
// Children
|
||||||
a { "abcder" },
|
a { "abcder" },
|
||||||
|
|
||||||
// Children with props
|
// Children with attributes
|
||||||
h2 { "whatsup", class: "abc-123" },
|
h2 { "hello", class: "abc-123" },
|
||||||
|
|
||||||
// Child components
|
// Child components
|
||||||
CustomComponent { a: 123, b: 456, key: "1" },
|
CustomComponent { a: 123, b: 456, key: "1" },
|
||||||
|
|
||||||
|
// Child components with paths
|
||||||
|
crate::components::CustomComponent { a: 123, b: 456, key: "1" },
|
||||||
|
|
||||||
// Iterators
|
// Iterators
|
||||||
{ 0..3.map(|i| rsx!{ h1 {"{:i}"} }) },
|
{ 0..3.map(|i| rsx!{ h1 {"{:i}"} }) },
|
||||||
|
|
||||||
@@ -82,7 +109,34 @@ static Example: FC<()> = |ctx| {
|
|||||||
{ rsx! { div { } } },
|
{ rsx! { div { } } },
|
||||||
{ html! { <div> </div> } },
|
{ html! { <div> </div> } },
|
||||||
|
|
||||||
// Any expression that is Into<VNode>
|
// Matching
|
||||||
|
// Requires rendering the nodes first.
|
||||||
|
// rsx! is lazy, and the underlying closures cannot have the same type
|
||||||
|
// Rendering produces the VNode type
|
||||||
|
{match rand::gen_range::<i32>(1..3) {
|
||||||
|
1 => rsx!(in ctx, h1 { "big" })
|
||||||
|
2 => rsx!(in ctx, h2 { "medium" })
|
||||||
|
_ => rsx!(in ctx, h3 { "small" })
|
||||||
|
}}
|
||||||
|
|
||||||
|
// Optionals
|
||||||
|
{true.and_then(|f| rsx!{ h1 {"Conditional Rendering"} })}
|
||||||
|
|
||||||
|
// Bool options
|
||||||
|
{(rsx!{ h1 {"Conditional Rendering"}, true)}
|
||||||
|
|
||||||
|
// Child nodes
|
||||||
|
// Returns &[VNode]
|
||||||
|
{ctx.children()}
|
||||||
|
|
||||||
|
// Duplicating nodes
|
||||||
|
// Clones the nodes by reference, so they are literally identical
|
||||||
|
{{
|
||||||
|
let node = rsx!(in ctx, h1{ "TopNode" });
|
||||||
|
(0..10).map(|_| node.clone())
|
||||||
|
}}
|
||||||
|
|
||||||
|
// Any expression that is `IntoVNode`
|
||||||
{expr}
|
{expr}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
# A Simple Component
|
||||||
|
|
||||||
|
```rust
|
||||||
|
#[derive(PartialEq, Properties)]
|
||||||
|
struct Props { name: &'static str }
|
||||||
|
|
||||||
|
static HelloMessage: FC<Props> = |ctx| {
|
||||||
|
ctx.render(rsx!{
|
||||||
|
div { "Hello {ctx.props.name}" }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Any syntax you like
|
||||||
|
|
||||||
|
Choose from a close-to-html syntax or the standard rsx! syntax
|
||||||
|
|
||||||
|
```rust
|
||||||
|
static HelloMessage: FC<()> = |ctx| {
|
||||||
|
ctx.render(html!{
|
||||||
|
<div> Hello World! </div>
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# A Stateful Component
|
||||||
|
|
||||||
|
Store state with hooks!
|
||||||
|
|
||||||
|
```rust
|
||||||
|
enum LightState {
|
||||||
|
Green
|
||||||
|
Yellow,
|
||||||
|
Red,
|
||||||
|
}
|
||||||
|
static HelloMessage: FC<()> = |ctx| {
|
||||||
|
let (color, set_color) = use_state(ctx, || LightState::Green);
|
||||||
|
|
||||||
|
let title = match color {
|
||||||
|
Green => "Green means go",
|
||||||
|
Yellow => "Yellow means slow down",
|
||||||
|
Red => "Red means stop",
|
||||||
|
};
|
||||||
|
|
||||||
|
ctx.render(rsx!{
|
||||||
|
h1 {"{title}"}
|
||||||
|
button { "tick"
|
||||||
|
onclick: move |_| set_color(match color {
|
||||||
|
Green => Yellow,
|
||||||
|
Yellow => Red,
|
||||||
|
Red => Green,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -22,6 +22,7 @@ static Example: FC<()> = |ctx| {
|
|||||||
//
|
//
|
||||||
rsx! { in ctx,
|
rsx! { in ctx,
|
||||||
div {
|
div {
|
||||||
|
h1 {"these are children nodes: "}
|
||||||
{nodes}
|
{nodes}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,11 @@ static Header: FC<()> = |ctx| {
|
|||||||
|
|
||||||
ctx.render(dioxus::prelude::LazyNodes::new(|nodectx| {
|
ctx.render(dioxus::prelude::LazyNodes::new(|nodectx| {
|
||||||
builder::ElementBuilder::new(nodectx, "div")
|
builder::ElementBuilder::new(nodectx, "div")
|
||||||
.child(VNode::Component(VComponent::new(Bottom, (), None)))
|
.child(VNode::Component(nodectx.bump().alloc(VComponent::new(
|
||||||
|
Bottom,
|
||||||
|
(),
|
||||||
|
None,
|
||||||
|
))))
|
||||||
.finish()
|
.finish()
|
||||||
}))
|
}))
|
||||||
};
|
};
|
||||||
@@ -36,128 +40,3 @@ fn Top(ctx: Context<()>) -> VNode {
|
|||||||
</div>
|
</div>
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Callback<T>(Box<T>);
|
|
||||||
|
|
||||||
// impl<O, T: Fn() -> O> From<T> for Callback<T> {
|
|
||||||
// fn from(_: T) -> Self {
|
|
||||||
// todo!()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
impl<O, A> From<&dyn Fn(A) -> O> for Callback<&dyn Fn(A) -> O> {
|
|
||||||
fn from(_: &dyn Fn(A) -> O) -> Self {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<O, A, B> From<&dyn Fn(A, B) -> O> for Callback<&dyn Fn(A, B) -> O> {
|
|
||||||
fn from(_: &dyn Fn(A, B) -> O) -> Self {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// compile time reordering of arguments
|
|
||||||
// Allows for transparently calling
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct Args<A, B, C> {
|
|
||||||
pub a: CuOpt<A>,
|
|
||||||
pub b: CuOpt<B>,
|
|
||||||
pub c: CuOpt<C>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum CuOpt<T> {
|
|
||||||
Some(T),
|
|
||||||
None,
|
|
||||||
}
|
|
||||||
impl<T> Default for CuOpt<T> {
|
|
||||||
fn default() -> Self {
|
|
||||||
CuOpt::None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> CuOpt<T> {
|
|
||||||
fn unwrap(self) -> T {
|
|
||||||
match self {
|
|
||||||
CuOpt::Some(t) => t,
|
|
||||||
CuOpt::None => panic!(""),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trait IsMemo {
|
|
||||||
fn memo(&self, other: &Self) -> bool {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: PartialEq> IsMemo for CuOpt<T> {
|
|
||||||
fn memo(&self, other: &Self) -> bool {
|
|
||||||
self == other
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: PartialEq> PartialEq for CuOpt<T> {
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
match (self, other) {
|
|
||||||
(CuOpt::Some(a), CuOpt::Some(b)) => a == b,
|
|
||||||
(CuOpt::Some(_), CuOpt::None) => false,
|
|
||||||
(CuOpt::None, CuOpt::Some(_)) => false,
|
|
||||||
(CuOpt::None, CuOpt::None) => true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> IsMemo for &CuOpt<T> {
|
|
||||||
fn memo(&self, other: &Self) -> bool {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// #[test]
|
|
||||||
#[test]
|
|
||||||
fn try_test() {
|
|
||||||
// test_poc()
|
|
||||||
}
|
|
||||||
|
|
||||||
// fn test_poc(ctx: Context) {
|
|
||||||
// let b = Bump::new();
|
|
||||||
|
|
||||||
// let h = Args {
|
|
||||||
// a: CuOpt::Some("ASD"),
|
|
||||||
// b: CuOpt::Some(123),
|
|
||||||
// c: CuOpt::Some(|| {}),
|
|
||||||
// // c: CuOpt::Some(b.alloc(|| {})),
|
|
||||||
// // c: CuOpt::Some(Box::new(|| {}) as Box<dyn Fn()>),
|
|
||||||
// };
|
|
||||||
|
|
||||||
// let h2 = Args {
|
|
||||||
// a: CuOpt::Some("ASD"),
|
|
||||||
// b: CuOpt::Some(123),
|
|
||||||
// c: CuOpt::Some(|| {}),
|
|
||||||
// // c: CuOpt::Some(b.alloc(|| {})),
|
|
||||||
// // c: CuOpt::Some(Box::new(|| {}) as Box<dyn Fn()>),
|
|
||||||
// // c: CuOpt::Some(Box::new(|| {}) as Box<dyn Fn()>),
|
|
||||||
// // c: CuOpt::Some(Box::new(|| {}) as Box<dyn Fn()>),
|
|
||||||
// };
|
|
||||||
|
|
||||||
// // dbg!((&h.a).memo((&&h2.a)));
|
|
||||||
// // dbg!((&h.b).memo((&&h2.b)));
|
|
||||||
// // dbg!((&h.c).memo((&&h2.c)));
|
|
||||||
// //
|
|
||||||
// // ctx: Context
|
|
||||||
// Top(ctx, &h.a.unwrap(), &h.b.unwrap(), &h.c.unwrap());
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn test_realzies() {
|
|
||||||
// let h = Args {
|
|
||||||
// a: CuOpt::Some("ASD"),
|
|
||||||
// b: CuOpt::Some(123),
|
|
||||||
// c: CuOpt::Some(|| {}),
|
|
||||||
// };
|
|
||||||
|
|
||||||
// let g = |ctx: Context| {
|
|
||||||
// //
|
|
||||||
// Top(ctx, &h.a.unwrap(), &h.b.unwrap(), &h.c.unwrap())
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
@@ -486,14 +486,6 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// impl IntoIterator for VNode {
|
|
||||||
// type Item = VNode;
|
|
||||||
// type IntoIter = std::iter::Once<Self::Item>;
|
|
||||||
// fn into_iter(self) -> Self::IntoIter {
|
|
||||||
// std::iter::once(self)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
impl<'a> IntoIterator for VNode<'a> {
|
impl<'a> IntoIterator for VNode<'a> {
|
||||||
type Item = VNode<'a>;
|
type Item = VNode<'a>;
|
||||||
type IntoIter = std::iter::Once<Self::Item>;
|
type IntoIter = std::iter::Once<Self::Item>;
|
||||||
@@ -665,8 +657,9 @@ pub fn virtual_child<'a, T: Properties>(
|
|||||||
) -> VNode<'a> {
|
) -> VNode<'a> {
|
||||||
// currently concerned about if props have a custom drop implementation
|
// currently concerned about if props have a custom drop implementation
|
||||||
// might override it with the props macro
|
// might override it with the props macro
|
||||||
VNode::Component(
|
todo!()
|
||||||
ctx.bump()
|
// VNode::Component(
|
||||||
.alloc(crate::nodes::VComponent::new(f, props, key)),
|
// ctx.bump()
|
||||||
)
|
// .alloc(crate::nodes::VComponent::new(f, props, key)),
|
||||||
|
// )
|
||||||
}
|
}
|
||||||
+27
-19
@@ -235,7 +235,7 @@ pub struct VComponent<'src> {
|
|||||||
pub children: &'src [VNode<'src>],
|
pub children: &'src [VNode<'src>],
|
||||||
|
|
||||||
// a pointer into the bump arena (given by the 'src lifetime)
|
// a pointer into the bump arena (given by the 'src lifetime)
|
||||||
raw_props: Box<dyn Any>,
|
// raw_props: Box<dyn Any>,
|
||||||
// raw_props: *const (),
|
// raw_props: *const (),
|
||||||
|
|
||||||
// a pointer to the raw fn typ
|
// a pointer to the raw fn typ
|
||||||
@@ -243,13 +243,24 @@ 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:
|
||||||
// - perform comparisons when diffing (memoization)
|
// - perform comparisons when diffing (memoization)
|
||||||
// TODO: lift the requirement that props need to be static
|
// TODO: lift the requirement that props need to be static
|
||||||
// we want them to borrow references... maybe force implementing a "to_static_unsafe" trait
|
// we want them to borrow references... maybe force implementing a "to_static_unsafe" trait
|
||||||
pub fn new<P: Properties>(component: FC<P>, props: P, key: Option<&'a str>) -> Self {
|
|
||||||
|
pub fn new<P: Properties>(
|
||||||
|
component: FC<P>,
|
||||||
|
// props: bumpalo::boxed::Box<'a, P>,
|
||||||
|
props: P,
|
||||||
|
key: Option<&'a str>,
|
||||||
|
) -> Self {
|
||||||
|
// pub fn new<P: Properties + 'a>(component: FC<P>, props: P, key: Option<&'a str>) -> Self {
|
||||||
|
// let bad_props = unsafe { transmogrify(props) };
|
||||||
let caller_ref = component as *const ();
|
let caller_ref = component as *const ();
|
||||||
|
|
||||||
// let raw_props = props as *const P as *const ();
|
// let raw_props = props as *const P as *const ();
|
||||||
@@ -271,7 +282,19 @@ impl<'a> VComponent<'a> {
|
|||||||
// }
|
// }
|
||||||
// };
|
// };
|
||||||
|
|
||||||
let caller: Rc<dyn Fn(&Scope) -> VNode + 'a> = Rc::new(move |scp| todo!());
|
// let prref: &'a P = props.as_ref();
|
||||||
|
|
||||||
|
let caller: Rc<dyn Fn(&Scope) -> VNode> = Rc::new(move |scope| {
|
||||||
|
//
|
||||||
|
// let props2 = bad_props;
|
||||||
|
// props.as_ref()
|
||||||
|
// let ctx = Context {
|
||||||
|
// props: prref,
|
||||||
|
// scope,
|
||||||
|
// };
|
||||||
|
todo!()
|
||||||
|
// component(ctx)
|
||||||
|
});
|
||||||
// let caller = Rc::new(create_closure(component, raw_props));
|
// let caller = Rc::new(create_closure(component, raw_props));
|
||||||
|
|
||||||
let key = match key {
|
let key = match key {
|
||||||
@@ -283,7 +306,7 @@ impl<'a> VComponent<'a> {
|
|||||||
key,
|
key,
|
||||||
ass_scope: Rc::new(RefCell::new(None)),
|
ass_scope: Rc::new(RefCell::new(None)),
|
||||||
user_fc: caller_ref,
|
user_fc: caller_ref,
|
||||||
raw_props: Box::new(props),
|
// raw_props: Box::new(props),
|
||||||
_p: PhantomData,
|
_p: PhantomData,
|
||||||
children: &[],
|
children: &[],
|
||||||
caller,
|
caller,
|
||||||
@@ -292,18 +315,3 @@ impl<'a> VComponent<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn create_closure<P: Properties>(
|
|
||||||
// component: FC<P>,
|
|
||||||
// raw_props: *const (),
|
|
||||||
// ) -> impl for<'r> Fn(&'r Scope) -> VNode<'r> {
|
|
||||||
// move |ctx| -> VNode {
|
|
||||||
// // cast back into the right lifetime
|
|
||||||
// let safe_props: &P = unsafe { &*(raw_props as *const P) };
|
|
||||||
// component(Context {
|
|
||||||
// props: safe_props,
|
|
||||||
// scope: ctx,
|
|
||||||
// })
|
|
||||||
// // component(ctx, safe_props)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
@@ -137,12 +137,11 @@ impl VirtualDom {
|
|||||||
|
|
||||||
// Normally, a component would be passed as a child in the RSX macro which automatically produces OpaqueComponents
|
// Normally, a component would be passed as a child in the RSX macro which automatically produces OpaqueComponents
|
||||||
// Here, we need to make it manually, using an RC to force the Weak reference to stick around for the main scope.
|
// Here, we need to make it manually, using an RC to force the Weak reference to stick around for the main scope.
|
||||||
let _root_caller: Rc<OpaqueComponent> = Rc::new(move |ctx| {
|
let _root_caller: Rc<OpaqueComponent<'static>> = Rc::new(move |scope| {
|
||||||
todo!()
|
// the lifetime of this closure is just as long as the lifetime on the scope reference
|
||||||
// root(Context {
|
// this closure moves root props (which is static) into this closure
|
||||||
// props: &root_props,
|
let props = unsafe { &*(&root_props as *const _) };
|
||||||
// scope: ctx,
|
root(Context { props, scope })
|
||||||
// })
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create a weak reference to the OpaqueComponent for the root scope to use as its render function
|
// Create a weak reference to the OpaqueComponent for the root scope to use as its render function
|
||||||
@@ -618,18 +617,23 @@ impl Scope {
|
|||||||
.ok_or(Error::FatalInternal("Failed to get caller"))?;
|
.ok_or(Error::FatalInternal("Failed to get caller"))?;
|
||||||
|
|
||||||
// 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 new_head = unsafe {
|
let c2: &OpaqueComponent<'static> = caller.as_ref();
|
||||||
std::mem::transmute::<&OpaqueComponent<'static>, &OpaqueComponent<'sel>>(
|
let c3: &OpaqueComponent<'sel> = unsafe { std::mem::transmute(c2) };
|
||||||
caller.as_ref(),
|
|
||||||
)
|
|
||||||
}(&self);
|
|
||||||
|
|
||||||
todo!();
|
let unsafe_head = unsafe { self.own_vnodes(c3) };
|
||||||
// self.frames.cur_frame_mut().head_node = new_head;
|
|
||||||
|
self.frames.cur_frame_mut().head_node = unsafe_head;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this is its own function so we can preciesly control how lifetimes flow
|
||||||
|
unsafe fn own_vnodes<'a>(&'a self, f: &OpaqueComponent<'a>) -> VNode<'static> {
|
||||||
|
let new_head: VNode<'a> = f(self);
|
||||||
|
let out: VNode<'static> = std::mem::transmute(new_head);
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
// A safe wrapper around calling listeners
|
// A safe wrapper around calling listeners
|
||||||
// calling listeners will invalidate the list of listeners
|
// calling listeners will invalidate the list of listeners
|
||||||
// The listener list will be completely drained because the next frame will write over previous listeners
|
// The listener list will be completely drained because the next frame will write over previous listeners
|
||||||
|
|||||||
Reference in new issue
Block a user