chore: rename ctx to cx
This commit is contained in:
1 parent
23c14078bb
commit
81382e7044
99 files changed
+789
-664
No files matched your search
@@ -3,7 +3,7 @@
|
||||
//!
|
||||
//! Note - using the builder pattern does not required the Properties trait to be implemented - the only thing that matters is
|
||||
//! if the type suppports PartialEq. The Properties trait is used by the rsx! and html! macros to generate the type-safe builder
|
||||
//! that ensures compile-time required and optional fields on ctx.
|
||||
//! that ensures compile-time required and optional fields on cx.
|
||||
|
||||
use crate::innerlude::FC;
|
||||
|
||||
@@ -50,9 +50,9 @@ pub fn fc_to_builder<T: Properties>(_: FC<T>) -> T::Builder {
|
||||
/// Fragments are incredibly useful when necessary, but *do* add cost in the diffing phase.
|
||||
/// Try to avoid nesting fragments if you can. Infinitely nested Fragments *will* cause diffing to crash.
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const Fragment: FC<()> = |ctx| {
|
||||
pub const Fragment: FC<()> = |cx| {
|
||||
use crate::prelude::*;
|
||||
ctx.render(LazyNodes::new(move |c| {
|
||||
crate::nodebuilder::vfragment(c, None, ctx.children())
|
||||
cx.render(LazyNodes::new(move |c| {
|
||||
crate::nodebuilder::vfragment(c, None, cx.children())
|
||||
}))
|
||||
};
|
||||
@@ -86,7 +86,7 @@ impl DebugVNodeSource {
|
||||
}
|
||||
|
||||
fn render_nodes(&self) -> VNode {
|
||||
// let ctx = NodeCtx
|
||||
// let cx = NodeCtx
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
@@ -97,9 +97,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn ensure_creation() -> Result<(), ()> {
|
||||
// static Example: FC<()> = |ctx| {
|
||||
// static Example: FC<()> = |cx| {
|
||||
// //
|
||||
// ctx.render(html! { <div> "hello world" </div> })
|
||||
// cx.render(html! { <div> "hello world" </div> })
|
||||
// };
|
||||
|
||||
// let mut dom = VirtualDom::new(Example);
|
||||
|
||||
@@ -44,6 +44,9 @@ pub enum VirtualEvent {
|
||||
MouseEvent(Rc<dyn on::MouseEvent>),
|
||||
PointerEvent(Rc<dyn on::PointerEvent>),
|
||||
|
||||
// Whenever a task is ready (complete) Dioxus produces this "FiberEvent"
|
||||
FiberEvent { task_id: u16 },
|
||||
|
||||
// image event has conflicting method types
|
||||
// ImageEvent(event_data::ImageEvent),
|
||||
OtherEvent,
|
||||
|
||||
+20
-20
@@ -28,8 +28,8 @@ mod use_state_def {
|
||||
///
|
||||
/// Usage:
|
||||
/// ```ignore
|
||||
/// static Example: FC<()> = |ctx| {
|
||||
/// let (counter, set_counter) = use_state(&ctx, || 0);
|
||||
/// static Example: FC<()> = |cx| {
|
||||
/// let (counter, set_counter) = use_state(&cx, || 0);
|
||||
/// let increment = |_| set_couter(counter + 1);
|
||||
/// let decrement = |_| set_couter(counter + 1);
|
||||
///
|
||||
@@ -43,7 +43,7 @@ mod use_state_def {
|
||||
/// }
|
||||
/// ```
|
||||
pub fn use_state<'a, 'c, T: 'static, F: FnOnce() -> T>(
|
||||
ctx: &impl Scoped<'a>,
|
||||
cx: &impl Scoped<'a>,
|
||||
initial_state_fn: F,
|
||||
) -> (&'a T, &'a Rc<dyn Fn(T)>) {
|
||||
struct UseState<T: 'static> {
|
||||
@@ -52,7 +52,7 @@ mod use_state_def {
|
||||
caller: Rc<dyn Fn(T) + 'static>,
|
||||
}
|
||||
|
||||
ctx.use_hook(
|
||||
cx.use_hook(
|
||||
move || UseState {
|
||||
new_val: Rc::new(RefCell::new(None)),
|
||||
current_val: initial_state_fn(),
|
||||
@@ -61,7 +61,7 @@ mod use_state_def {
|
||||
move |hook| {
|
||||
log::debug!("Use_state set called");
|
||||
let inner = hook.new_val.clone();
|
||||
let scheduled_update = ctx.schedule_update();
|
||||
let scheduled_update = cx.schedule_update();
|
||||
|
||||
// get ownership of the new val and replace the current with the new
|
||||
// -> as_ref -> borrow_mut -> deref_mut -> take
|
||||
@@ -155,8 +155,8 @@ mod new_use_state_def {
|
||||
///
|
||||
/// Usage:
|
||||
/// ```ignore
|
||||
/// static Example: FC<()> = |ctx| {
|
||||
/// let (counter, set_counter) = use_state(&ctx, || 0);
|
||||
/// static Example: FC<()> = |cx| {
|
||||
/// let (counter, set_counter) = use_state(&cx, || 0);
|
||||
/// let increment = |_| set_couter(counter + 1);
|
||||
/// let decrement = |_| set_couter(counter + 1);
|
||||
///
|
||||
@@ -170,10 +170,10 @@ mod new_use_state_def {
|
||||
/// }
|
||||
/// ```
|
||||
pub fn use_state_new<'a, 'c, T: 'static, F: FnOnce() -> T>(
|
||||
ctx: &impl Scoped<'a>,
|
||||
cx: &impl Scoped<'a>,
|
||||
initial_state_fn: F,
|
||||
) -> &'a UseState<T> {
|
||||
ctx.use_hook(
|
||||
cx.use_hook(
|
||||
move || UseState {
|
||||
modifier: Rc::new(RefCell::new(None)),
|
||||
current_val: initial_state_fn(),
|
||||
@@ -182,7 +182,7 @@ mod new_use_state_def {
|
||||
},
|
||||
move |hook| {
|
||||
log::debug!("addr of hook: {:#?}", hook as *const _);
|
||||
let scheduled_update = ctx.schedule_update();
|
||||
let scheduled_update = cx.schedule_update();
|
||||
|
||||
// log::debug!("Checking if new value {:#?}", &hook.current_val);
|
||||
// get ownership of the new val and replace the current with the new
|
||||
@@ -247,10 +247,10 @@ mod use_ref_def {
|
||||
/// Modifications to this value do not cause updates to the component
|
||||
/// Attach to inner context reference, so context can be consumed
|
||||
pub fn use_ref<'a, T: 'static>(
|
||||
ctx: &impl Scoped<'a>,
|
||||
cx: &impl Scoped<'a>,
|
||||
initial_state_fn: impl FnOnce() -> T + 'static,
|
||||
) -> &'a RefCell<T> {
|
||||
ctx.use_hook(|| RefCell::new(initial_state_fn()), |state| &*state, |_| {})
|
||||
cx.use_hook(|| RefCell::new(initial_state_fn()), |state| &*state, |_| {})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,11 +271,11 @@ mod use_reducer_def {
|
||||
/// This is behaves almost exactly the same way as React's "use_state".
|
||||
///
|
||||
pub fn use_reducer<'a, 'c, State: 'static, Action: 'static>(
|
||||
ctx: &impl Scoped<'a>,
|
||||
cx: &impl Scoped<'a>,
|
||||
initial_state_fn: impl FnOnce() -> State,
|
||||
_reducer: impl Fn(&mut State, Action),
|
||||
) -> (&'a State, &'a Box<dyn Fn(Action)>) {
|
||||
ctx.use_hook(
|
||||
cx.use_hook(
|
||||
move || UseReducer {
|
||||
new_val: Rc::new(RefCell::new(None)),
|
||||
current_val: initial_state_fn(),
|
||||
@@ -283,7 +283,7 @@ mod use_reducer_def {
|
||||
},
|
||||
move |hook| {
|
||||
let _inner = hook.new_val.clone();
|
||||
let scheduled_update = ctx.schedule_update();
|
||||
let scheduled_update = cx.schedule_update();
|
||||
|
||||
// get ownership of the new val and replace the current with the new
|
||||
// -> as_ref -> borrow_mut -> deref_mut -> take
|
||||
@@ -320,9 +320,9 @@ mod use_reducer_def {
|
||||
}
|
||||
|
||||
// #[allow(unused)]
|
||||
// static Example: FC<()> = |ctx| {
|
||||
// static Example: FC<()> = |cx| {
|
||||
// let (count, reduce) = use_reducer(
|
||||
// &ctx,
|
||||
// &cx,
|
||||
// || 0,
|
||||
// |count, action| match action {
|
||||
// Actions::Incr => *count += 1,
|
||||
@@ -330,7 +330,7 @@ mod use_reducer_def {
|
||||
// },
|
||||
// );
|
||||
|
||||
// ctx.render(rsx! {
|
||||
// cx.render(rsx! {
|
||||
// div {
|
||||
// h1 {"Count: {count}"}
|
||||
// button {
|
||||
@@ -347,8 +347,8 @@ mod use_reducer_def {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn use_is_initialized<P>(ctx: Context<P>) -> bool {
|
||||
let val = use_ref(&ctx, || false);
|
||||
pub fn use_is_initialized<P>(cx: Context<P>) -> bool {
|
||||
let val = use_ref(&cx, || false);
|
||||
match *val.borrow() {
|
||||
true => true,
|
||||
false => {
|
||||
|
||||
@@ -29,13 +29,14 @@ where
|
||||
Attributes: 'a + AsRef<[Attribute<'a>]>,
|
||||
Children: 'a + AsRef<[VNode<'a>]>,
|
||||
{
|
||||
ctx: &'b NodeCtx<'a>,
|
||||
cx: &'b NodeCtx<'a>,
|
||||
key: NodeKey<'a>,
|
||||
tag_name: &'a str,
|
||||
tag_name: &'static str,
|
||||
// tag_name: &'a str,
|
||||
listeners: Listeners,
|
||||
attributes: Attributes,
|
||||
children: Children,
|
||||
namespace: Option<&'a str>,
|
||||
namespace: Option<&'static str>,
|
||||
}
|
||||
|
||||
impl<'a, 'b>
|
||||
@@ -70,10 +71,10 @@ impl<'a, 'b>
|
||||
/// let my_element_builder = ElementBuilder::new(&b, tag_name);
|
||||
/// # fn flip_coin() -> bool { true }
|
||||
/// ```
|
||||
pub fn new(ctx: &'b NodeCtx<'a>, tag_name: &'static str) -> Self {
|
||||
let bump = ctx.bump();
|
||||
pub fn new(cx: &'b NodeCtx<'a>, tag_name: &'static str) -> Self {
|
||||
let bump = cx.bump();
|
||||
ElementBuilder {
|
||||
ctx,
|
||||
cx,
|
||||
key: NodeKey::NONE,
|
||||
tag_name,
|
||||
listeners: bumpalo::collections::Vec::new_in(bump),
|
||||
@@ -124,7 +125,7 @@ where
|
||||
L: 'a + AsRef<[Listener<'a>]>,
|
||||
{
|
||||
ElementBuilder {
|
||||
ctx: self.ctx,
|
||||
cx: self.cx,
|
||||
key: self.key,
|
||||
tag_name: self.tag_name,
|
||||
listeners,
|
||||
@@ -163,7 +164,7 @@ where
|
||||
A: 'a + AsRef<[Attribute<'a>]>,
|
||||
{
|
||||
ElementBuilder {
|
||||
ctx: self.ctx,
|
||||
cx: self.cx,
|
||||
key: self.key,
|
||||
tag_name: self.tag_name,
|
||||
listeners: self.listeners,
|
||||
@@ -202,7 +203,7 @@ where
|
||||
C: 'a + AsRef<[VNode<'a>]>,
|
||||
{
|
||||
ElementBuilder {
|
||||
ctx: self.ctx,
|
||||
cx: self.cx,
|
||||
key: self.key,
|
||||
tag_name: self.tag_name,
|
||||
listeners: self.listeners,
|
||||
@@ -227,9 +228,9 @@ where
|
||||
/// .finish();
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn namespace(self, namespace: Option<&'a str>) -> Self {
|
||||
pub fn namespace(self, namespace: Option<&'static str>) -> Self {
|
||||
ElementBuilder {
|
||||
ctx: self.ctx,
|
||||
cx: self.cx,
|
||||
key: self.key,
|
||||
tag_name: self.tag_name,
|
||||
listeners: self.listeners,
|
||||
@@ -281,7 +282,7 @@ where
|
||||
Some(static_str) => static_str,
|
||||
None => {
|
||||
use bumpalo::core_alloc::fmt::Write;
|
||||
let mut s = bumpalo::collections::String::new_in(self.ctx.bump());
|
||||
let mut s = bumpalo::collections::String::new_in(self.cx.bump());
|
||||
s.write_fmt(args).unwrap();
|
||||
s.into_bump_str()
|
||||
}
|
||||
@@ -307,7 +308,7 @@ where
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn finish(self) -> VNode<'a> {
|
||||
let bump = self.ctx.bump();
|
||||
let bump = self.cx.bump();
|
||||
|
||||
let children: &'a Children = bump.alloc(self.children);
|
||||
let children: &'a [VNode<'a>] = children.as_ref();
|
||||
@@ -357,11 +358,11 @@ where
|
||||
/// .finish();
|
||||
/// ```
|
||||
pub fn on(self, event: &'static str, callback: impl Fn(VirtualEvent) + 'a) -> Self {
|
||||
let bump = &self.ctx.bump();
|
||||
let bump = &self.cx.bump();
|
||||
let listener = Listener {
|
||||
event,
|
||||
callback: bump.alloc(callback),
|
||||
scope: self.ctx.scope_ref.arena_idx,
|
||||
scope: self.cx.scope_ref.arena_idx,
|
||||
mounted_node: bump.alloc(Cell::new(RealDomNode::empty())),
|
||||
};
|
||||
self.add_listener(listener)
|
||||
@@ -371,15 +372,15 @@ where
|
||||
self.listeners.push(listener);
|
||||
|
||||
// bump the context id forward
|
||||
let id = self.ctx.listener_id.get();
|
||||
self.ctx.listener_id.set(id + 1);
|
||||
let id = self.cx.listener_id.get();
|
||||
self.cx.listener_id.set(id + 1);
|
||||
|
||||
// Add this listener to the context list
|
||||
// This casts the listener to a self-referential pointer
|
||||
// This is okay because the bump arena is stable
|
||||
self.listeners.last().map(|g| {
|
||||
let r = unsafe { std::mem::transmute::<&Listener<'a>, &Listener<'static>>(g) };
|
||||
self.ctx
|
||||
self.cx
|
||||
.scope_ref
|
||||
.listeners
|
||||
.borrow_mut()
|
||||
@@ -413,7 +414,7 @@ where
|
||||
Some(static_str) => static_str,
|
||||
None => {
|
||||
use bumpalo::core_alloc::fmt::Write;
|
||||
let mut s = bumpalo::collections::String::new_in(self.ctx.bump());
|
||||
let mut s = bumpalo::collections::String::new_in(self.cx.bump());
|
||||
s.write_fmt(args).unwrap();
|
||||
s.into_bump_str()
|
||||
}
|
||||
@@ -501,7 +502,7 @@ where
|
||||
pub fn iter_child(mut self, nodes: impl IntoIterator<Item = impl IntoVNode<'a>>) -> Self {
|
||||
let len_before = self.children.len();
|
||||
for item in nodes {
|
||||
let child = item.into_vnode(&self.ctx);
|
||||
let child = item.into_vnode(&self.cx);
|
||||
self.children.push(child);
|
||||
}
|
||||
if cfg!(debug_assertions) {
|
||||
@@ -531,20 +532,20 @@ impl<'a> IntoIterator for VNode<'a> {
|
||||
}
|
||||
}
|
||||
impl<'a> IntoVNode<'a> for VNode<'a> {
|
||||
fn into_vnode(self, ctx: &NodeCtx<'a>) -> VNode<'a> {
|
||||
fn into_vnode(self, cx: &NodeCtx<'a>) -> VNode<'a> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoVNode<'a> for &VNode<'a> {
|
||||
fn into_vnode(self, ctx: &NodeCtx<'a>) -> VNode<'a> {
|
||||
fn into_vnode(self, cx: &NodeCtx<'a>) -> VNode<'a> {
|
||||
// cloning is cheap since vnodes are just references into bump arenas
|
||||
self.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait IntoVNode<'a> {
|
||||
fn into_vnode(self, ctx: &NodeCtx<'a>) -> VNode<'a>;
|
||||
fn into_vnode(self, cx: &NodeCtx<'a>) -> VNode<'a>;
|
||||
}
|
||||
|
||||
pub trait VNodeBuilder<'a, G>: IntoIterator<Item = G>
|
||||
@@ -590,8 +591,8 @@ impl<'a, G> IntoVNode<'a> for LazyNodes<'a, G>
|
||||
where
|
||||
G: for<'b> FnOnce(&'b NodeCtx<'a>) -> VNode<'a> + 'a,
|
||||
{
|
||||
fn into_vnode(self, ctx: &NodeCtx<'a>) -> VNode<'a> {
|
||||
(self.inner)(ctx)
|
||||
fn into_vnode(self, cx: &NodeCtx<'a>) -> VNode<'a> {
|
||||
(self.inner)(cx)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -608,14 +609,14 @@ where
|
||||
}
|
||||
|
||||
impl<'a> IntoVNode<'a> for () {
|
||||
fn into_vnode(self, ctx: &NodeCtx<'a>) -> VNode<'a> {
|
||||
fn into_vnode(self, cx: &NodeCtx<'a>) -> VNode<'a> {
|
||||
todo!();
|
||||
VNode::Suspended
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoVNode<'a> for Option<()> {
|
||||
fn into_vnode(self, ctx: &NodeCtx<'a>) -> VNode<'a> {
|
||||
fn into_vnode(self, cx: &NodeCtx<'a>) -> VNode<'a> {
|
||||
todo!();
|
||||
VNode::Suspended
|
||||
}
|
||||
@@ -679,7 +680,7 @@ pub fn attr<'a>(name: &'static str, value: &'a str) -> Attribute<'a> {
|
||||
}
|
||||
|
||||
pub fn virtual_child<'a, T: Properties + 'a>(
|
||||
ctx: &NodeCtx<'a>,
|
||||
cx: &NodeCtx<'a>,
|
||||
f: FC<T>,
|
||||
props: T,
|
||||
key: Option<&'a str>, // key: NodeKey<'a>,
|
||||
@@ -689,37 +690,37 @@ pub fn virtual_child<'a, T: Properties + 'a>(
|
||||
// might override it with the props macro
|
||||
// todo!()
|
||||
VNode::Component(
|
||||
ctx.bump()
|
||||
.alloc(crate::nodes::VComponent::new(ctx, f, props, key, children)),
|
||||
// ctx.bump()
|
||||
cx.bump()
|
||||
.alloc(crate::nodes::VComponent::new(cx, f, props, key, children)),
|
||||
// cx.bump()
|
||||
// .alloc(crate::nodes::VComponent::new(f, props, key)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn vfragment<'a>(
|
||||
ctx: &NodeCtx<'a>,
|
||||
cx: &NodeCtx<'a>,
|
||||
key: Option<&'a str>, // key: NodeKey<'a>,
|
||||
children: &'a [VNode<'a>],
|
||||
) -> VNode<'a> {
|
||||
VNode::Fragment(ctx.bump().alloc(VFragment::new(key, children)))
|
||||
VNode::Fragment(cx.bump().alloc(VFragment::new(key, children)))
|
||||
}
|
||||
|
||||
pub struct ChildrenList<'a, 'b> {
|
||||
ctx: &'b NodeCtx<'a>,
|
||||
cx: &'b NodeCtx<'a>,
|
||||
children: bumpalo::collections::Vec<'a, VNode<'a>>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> ChildrenList<'a, 'b> {
|
||||
pub fn new(ctx: &'b NodeCtx<'a>) -> Self {
|
||||
pub fn new(cx: &'b NodeCtx<'a>) -> Self {
|
||||
Self {
|
||||
ctx,
|
||||
children: bumpalo::collections::Vec::new_in(ctx.bump()),
|
||||
cx,
|
||||
children: bumpalo::collections::Vec::new_in(cx.bump()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_child(mut self, nodes: impl IntoIterator<Item = impl IntoVNode<'a>>) -> Self {
|
||||
for item in nodes {
|
||||
let child = item.into_vnode(&self.ctx);
|
||||
let child = item.into_vnode(&self.cx);
|
||||
self.children.push(child);
|
||||
}
|
||||
self
|
||||
|
||||
+48
-11
@@ -11,10 +11,8 @@ use crate::{
|
||||
};
|
||||
use bumpalo::Bump;
|
||||
use std::{
|
||||
any::Any,
|
||||
cell::{Cell, RefCell},
|
||||
fmt::{Arguments, Debug, Formatter},
|
||||
marker::PhantomData,
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
@@ -56,6 +54,43 @@ impl<'a> Clone for VNode<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'old, 'new> VNode<'old> {
|
||||
// performs a somewhat costly clone of this vnode into another bump
|
||||
// this is used when you want to drag nodes from an old frame into a new frame
|
||||
// There is no way to safely drag listeners over (no way to clone a closure)
|
||||
//
|
||||
// This method will only be called if a component was once a real node and then becomes suspended
|
||||
fn deep_clone_to_new_bump(&self, new: &'new Bump) -> VNode<'new> {
|
||||
match self {
|
||||
VNode::Element(el) => {
|
||||
let new_el: VElement<'new> = VElement {
|
||||
key: NodeKey::NONE,
|
||||
// key: el.key.clone(),
|
||||
tag_name: el.tag_name,
|
||||
// wipe listeners on deep clone, there's no way to know what other bump material they might be referencing (nodes, etc)
|
||||
listeners: &[],
|
||||
attributes: {
|
||||
let attr_vec = bumpalo::collections::Vec::new_in(new);
|
||||
attr_vec.into_bump_slice()
|
||||
},
|
||||
children: {
|
||||
let attr_vec = bumpalo::collections::Vec::new_in(new);
|
||||
attr_vec.into_bump_slice()
|
||||
},
|
||||
namespace: el.namespace.clone(),
|
||||
dom_id: el.dom_id.clone(),
|
||||
};
|
||||
|
||||
VNode::Element(new.alloc_with(move || new_el))
|
||||
}
|
||||
VNode::Text(_) => todo!(),
|
||||
VNode::Fragment(_) => todo!(),
|
||||
VNode::Suspended => todo!(),
|
||||
VNode::Component(_) => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> VNode<'a> {
|
||||
/// Low-level constructor for making a new `Node` of type element with given
|
||||
/// parts.
|
||||
@@ -67,11 +102,11 @@ impl<'a> VNode<'a> {
|
||||
pub fn element(
|
||||
bump: &'a Bump,
|
||||
key: NodeKey<'a>,
|
||||
tag_name: &'a str,
|
||||
tag_name: &'static str,
|
||||
listeners: &'a [Listener<'a>],
|
||||
attributes: &'a [Attribute<'a>],
|
||||
children: &'a [VNode<'a>],
|
||||
namespace: Option<&'a str>,
|
||||
namespace: Option<&'static str>,
|
||||
) -> VNode<'a> {
|
||||
let element = bump.alloc_with(|| VElement {
|
||||
key,
|
||||
@@ -157,14 +192,16 @@ pub struct VText<'src> {
|
||||
// ========================================================
|
||||
// VElement (div, h1, etc), attrs, keys, listener handle
|
||||
// ========================================================
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct VElement<'a> {
|
||||
/// Elements have a tag name, zero or more attributes, and zero or more
|
||||
pub key: NodeKey<'a>,
|
||||
pub tag_name: &'a str,
|
||||
pub tag_name: &'static str,
|
||||
pub listeners: &'a [Listener<'a>],
|
||||
pub attributes: &'a [Attribute<'a>],
|
||||
pub children: &'a [VNode<'a>],
|
||||
pub namespace: Option<&'a str>,
|
||||
pub namespace: Option<&'static str>,
|
||||
pub dom_id: Cell<RealDomNode>,
|
||||
}
|
||||
|
||||
@@ -298,13 +335,13 @@ impl<'a> VComponent<'a> {
|
||||
///
|
||||
/// If the CanMemo is `false`, then the macro will call the backup method which always defaults to "false"
|
||||
pub fn new<P: Properties + 'a>(
|
||||
ctx: &NodeCtx<'a>,
|
||||
cx: &NodeCtx<'a>,
|
||||
component: FC<P>,
|
||||
props: P,
|
||||
key: Option<&'a str>,
|
||||
children: &'a [VNode<'a>],
|
||||
) -> Self {
|
||||
let bump = ctx.bump();
|
||||
let bump = cx.bump();
|
||||
let user_fc = component as *const ();
|
||||
|
||||
let props = bump.alloc(props);
|
||||
@@ -370,13 +407,13 @@ fn create_closure<'a, P: 'a>(
|
||||
let g: Captured = Rc::new(move |scp: &Scope| -> VNode {
|
||||
// cast back into the right lifetime
|
||||
let safe_props: &'_ P = unsafe { &*(raw_props as *const P) };
|
||||
// let ctx: Context<P2> = todo!();
|
||||
let ctx: Context<P> = Context {
|
||||
// let cx: Context<P2> = todo!();
|
||||
let cx: Context<P> = Context {
|
||||
props: safe_props,
|
||||
scope: scp,
|
||||
};
|
||||
|
||||
let g = component(ctx);
|
||||
let g = component(cx);
|
||||
let g2 = unsafe { std::mem::transmute(g) };
|
||||
g2
|
||||
});
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
use crate::{arena::ScopeArena, innerlude::*};
|
||||
use bumpalo::Bump;
|
||||
use futures::FutureExt;
|
||||
use generational_arena::Arena;
|
||||
use std::{
|
||||
any::{Any, TypeId},
|
||||
@@ -55,7 +56,7 @@ pub struct VirtualDom {
|
||||
#[doc(hidden)]
|
||||
_root_caller: Rc<OpaqueComponent>,
|
||||
// _root_caller: Rc<OpaqueComponent<'static>>,
|
||||
/// Type of the original ctx. This is stored as TypeId so VirtualDom does not need to be generic.
|
||||
/// Type of the original cx. This is stored as TypeId so VirtualDom does not need to be generic.
|
||||
///
|
||||
/// Whenver props need to be updated, an Error will be thrown if the new props do not
|
||||
/// match the props used to create the VirtualDom.
|
||||
@@ -90,12 +91,12 @@ impl VirtualDom {
|
||||
/// ```ignore
|
||||
/// // Directly from a closure
|
||||
///
|
||||
/// let dom = VirtualDom::new(|ctx| ctx.render(rsx!{ div {"hello world"} }));
|
||||
/// let dom = VirtualDom::new(|cx| cx.render(rsx!{ div {"hello world"} }));
|
||||
///
|
||||
/// // or pass in...
|
||||
///
|
||||
/// let root = |ctx| {
|
||||
/// ctx.render(rsx!{
|
||||
/// let root = |cx| {
|
||||
/// cx.render(rsx!{
|
||||
/// div {"hello world"}
|
||||
/// })
|
||||
/// }
|
||||
@@ -103,8 +104,8 @@ impl VirtualDom {
|
||||
///
|
||||
/// // or directly from a fn
|
||||
///
|
||||
/// fn Example(ctx: Context<()>) -> VNode {
|
||||
/// ctx.render(rsx!{ div{"hello world"} })
|
||||
/// fn Example(cx: Context<()>) -> VNode {
|
||||
/// cx.render(rsx!{ div{"hello world"} })
|
||||
/// }
|
||||
///
|
||||
/// let dom = VirtualDom::new(Example);
|
||||
@@ -113,7 +114,7 @@ impl VirtualDom {
|
||||
Self::new_with_props(root, ())
|
||||
}
|
||||
|
||||
/// Start a new VirtualDom instance with a dependent ctx.
|
||||
/// Start a new VirtualDom instance with a dependent cx.
|
||||
/// Later, the props can be updated by calling "update" with a new set of props, causing a set of re-renders.
|
||||
///
|
||||
/// This is useful when a component tree can be driven by external state (IE SSR) but it would be too expensive
|
||||
@@ -122,12 +123,12 @@ impl VirtualDom {
|
||||
/// ```ignore
|
||||
/// // Directly from a closure
|
||||
///
|
||||
/// let dom = VirtualDom::new(|ctx| ctx.render(rsx!{ div {"hello world"} }));
|
||||
/// let dom = VirtualDom::new(|cx| cx.render(rsx!{ div {"hello world"} }));
|
||||
///
|
||||
/// // or pass in...
|
||||
///
|
||||
/// let root = |ctx| {
|
||||
/// ctx.render(rsx!{
|
||||
/// let root = |cx| {
|
||||
/// cx.render(rsx!{
|
||||
/// div {"hello world"}
|
||||
/// })
|
||||
/// }
|
||||
@@ -135,8 +136,8 @@ impl VirtualDom {
|
||||
///
|
||||
/// // or directly from a fn
|
||||
///
|
||||
/// fn Example(ctx: Context, props: &SomeProps) -> VNode {
|
||||
/// ctx.render(rsx!{ div{"hello world"} })
|
||||
/// fn Example(cx: Context, props: &SomeProps) -> VNode {
|
||||
/// cx.render(rsx!{ div{"hello world"} })
|
||||
/// }
|
||||
///
|
||||
/// let dom = VirtualDom::new(Example);
|
||||
@@ -395,11 +396,13 @@ pub struct Scope {
|
||||
// Stores references into the listeners attached to the vnodes
|
||||
// NEEDS TO BE PRIVATE
|
||||
pub(crate) listeners: RefCell<Vec<(*const Cell<RealDomNode>, *const dyn Fn(VirtualEvent))>>,
|
||||
|
||||
pub(crate) suspended_tasks: Vec<Box<dyn Future<Output = VNode<'static>>>>,
|
||||
// pub(crate) listeners: RefCell<nohash_hasher::IntMap<u32, *const dyn Fn(VirtualEvent)>>,
|
||||
// pub(crate) listeners: RefCell<Vec<*const dyn Fn(VirtualEvent)>>,
|
||||
// pub(crate) listeners: RefCell<Vec<*const dyn Fn(VirtualEvent)>>,
|
||||
// NoHashMap<RealDomNode, <*const dyn Fn(VirtualEvent)>
|
||||
// pub(crate) listeners: RefCell<Vec<*const dyn Fn(VirtualEvent)>>,
|
||||
// pub(crate) listeners: RefCell<Vec<*const dyn Fn(VirtualEvent)>>
|
||||
}
|
||||
|
||||
// We need to pin the hook so it doesn't move as we initialize the list of hooks
|
||||
@@ -465,6 +468,7 @@ impl Scope {
|
||||
listeners: Default::default(),
|
||||
hookidx: Default::default(),
|
||||
descendents: Default::default(),
|
||||
suspended_tasks: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -588,9 +592,9 @@ impl Scope {
|
||||
///
|
||||
/// }
|
||||
///
|
||||
/// fn example(ctx: Context, props: &Props -> VNode {
|
||||
/// fn example(cx: Context, props: &Props -> VNode {
|
||||
/// html! {
|
||||
/// <div> "Hello, {ctx.ctx.name}" </div>
|
||||
/// <div> "Hello, {cx.cx.name}" </div>
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
@@ -645,6 +649,14 @@ pub trait Scoped<'src>: Sized {
|
||||
self.get_scope().event_channel.clone()
|
||||
}
|
||||
|
||||
fn schedule_effect(&self) -> Rc<dyn Fn() + 'static> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn schedule_layout_effect(&self) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Take a lazy VNode structure and actually build it with the context of the VDom's efficient VNode allocator.
|
||||
///
|
||||
/// This function consumes the context and absorb the lifetime, so these VNodes *must* be returned.
|
||||
@@ -652,12 +664,12 @@ pub trait Scoped<'src>: Sized {
|
||||
/// ## Example
|
||||
///
|
||||
/// ```ignore
|
||||
/// fn Component(ctx: Context<()>) -> VNode {
|
||||
/// fn Component(cx: Context<()>) -> VNode {
|
||||
/// // Lazy assemble the VNode tree
|
||||
/// let lazy_tree = html! {<div> "Hello World" </div>};
|
||||
///
|
||||
/// // Actually build the tree and allocate it
|
||||
/// ctx.render(lazy_tree)
|
||||
/// cx.render(lazy_tree)
|
||||
/// }
|
||||
///```
|
||||
fn render<'a, F: for<'b> FnOnce(&'b NodeCtx<'src>) -> VNode<'src> + 'src + 'a>(
|
||||
@@ -750,7 +762,7 @@ Any function prefixed with "use" should not be called conditionally.
|
||||
///
|
||||
fn use_create_context<T: 'static>(&self, init: impl Fn() -> T) {
|
||||
let scope = self.get_scope();
|
||||
let mut ctxs = scope.shared_contexts.borrow_mut();
|
||||
let mut cxs = scope.shared_contexts.borrow_mut();
|
||||
let ty = TypeId::of::<T>();
|
||||
|
||||
let is_initialized = self.use_hook(
|
||||
@@ -763,14 +775,14 @@ Any function prefixed with "use" should not be called conditionally.
|
||||
|_| {},
|
||||
);
|
||||
|
||||
match (is_initialized, ctxs.contains_key(&ty)) {
|
||||
match (is_initialized, cxs.contains_key(&ty)) {
|
||||
// Do nothing, already initialized and already exists
|
||||
(true, true) => {}
|
||||
|
||||
// Needs to be initialized
|
||||
(false, false) => {
|
||||
log::debug!("Initializing context...");
|
||||
ctxs.insert(ty, Rc::new(init()));
|
||||
cxs.insert(ty, Rc::new(init()));
|
||||
}
|
||||
|
||||
_ => debug_assert!(false, "Cannot initialize two contexts of the same type"),
|
||||
@@ -810,9 +822,9 @@ Any function prefixed with "use" should not be called conditionally.
|
||||
log::debug!("Searching {:#?} for valid shared_context", inner.arena_idx);
|
||||
let shared_contexts = inner.shared_contexts.borrow();
|
||||
|
||||
if let Some(shared_ctx) = shared_contexts.get(&ty) {
|
||||
log::debug!("found matching ctx");
|
||||
let rc = shared_ctx
|
||||
if let Some(shared_cx) = shared_contexts.get(&ty) {
|
||||
log::debug!("found matching cx");
|
||||
let rc = shared_cx
|
||||
.clone()
|
||||
.downcast::<T>()
|
||||
.expect("Should not fail, already validated the type from the hashmap");
|
||||
@@ -841,10 +853,32 @@ Any function prefixed with "use" should not be called conditionally.
|
||||
)
|
||||
}
|
||||
|
||||
fn suspend<O>(
|
||||
fn suspend<O: 'src>(
|
||||
&self,
|
||||
f: impl Future<Output = O>,
|
||||
g: impl FnOnce(O) -> VNode<'src> + 'src,
|
||||
f: &'src mut Pin<Box<dyn Future<Output = O> + Send + 'static>>,
|
||||
g: impl FnOnce(SuspendedContext, O) -> VNode<'src> + 'src,
|
||||
) -> VNode<'src> {
|
||||
match f.now_or_never() {
|
||||
Some(o) => {
|
||||
let suspended_cx = SuspendedContext {};
|
||||
let nodes = g(suspended_cx, o);
|
||||
return nodes;
|
||||
}
|
||||
None => {
|
||||
// we need to register this task
|
||||
VNode::Suspended
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SuspendedContext {}
|
||||
|
||||
impl SuspendedContext {
|
||||
pub fn render<'a, 'src, F: for<'b> FnOnce(&'b NodeCtx<'src>) -> VNode<'src> + 'src + 'a>(
|
||||
self,
|
||||
lazy_nodes: LazyNodes<'src, F>,
|
||||
) -> VNode<'src> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user