wip: recoil

This commit is contained in:
Jonathan Kelley committed 2021-05-26 01:40:30 -04:00
1 parent 3cfa1fe125
commit ee67654f58
31 files changed
+1369 -235

No files matched your search

+106
View File
@@ -32,3 +32,109 @@ impl Properties for () {
pub fn fc_to_builder<T: Properties>(_f: FC<T>) -> T::Builder {
T::builder()
}
mod testing {
use std::any::Any;
// trait PossibleProps {
// type POut: PartialEq;
// fn as_partial_eq(&self) -> Option<&Self::POut> {
// None
// }
// }
// impl<T: PartialEq> PossibleProps for T {
// type POut = Self;
// }
// struct SomeProps2<'a> {
// inner: &'a str,
// }
// Fallback trait for to all types to default to `false`.
trait NotEq {
const IS_EQ: bool = false;
}
impl<T> NotEq for T {}
// Concrete wrapper type where `IS_COPY` becomes `true` if `T: Copy`.
struct IsEq<G, T>(std::marker::PhantomData<(G, T)>);
impl<G: PartialEq, T: PartialEq<G>> IsEq<G, T> {
// Because this is implemented directly on `IsCopy`, it has priority over
// the `NotCopy` trait impl.
//
// Note: this is a *totally different* associated constant from that in
// `NotCopy`. This does not specialize the `NotCopy` trait impl on `IsCopy`.
const IS_EQ: bool = true;
}
#[derive(PartialEq)]
struct SomeProps {
inner: &'static str,
}
struct SomeProps2 {
inner: &'static str,
}
#[test]
fn test() {
let g = IsEq::<SomeProps, SomeProps>::IS_EQ;
// let g = IsEq::<Vec<u32>>::IS_COPY;
// let g = IsEq::<u32>::IS_COPY;
// dbg!(g);
// let props = SomeProps { inner: "asd" };
// let intermediate: Box<dyn PartialEq<SomeProps>> = Box::new(props);
// let as_any: Box<dyn Any> = Box::new(intermediate);
// let as_partialeq = as_any
// .downcast_ref::<Box<dyn PartialEq<SomeProps>>>()
// .unwrap();
}
// struct blah {}
// #[reorder_args]
pub fn blah(a: i32, b: &str, c: &str) {}
// pub mod blah {
// pub const a: u8 = 0;
// pub const b: u8 = 1;
// }
trait Eat {}
impl Eat for fn() {}
impl<T> Eat for fn(T) {}
impl<T, K> Eat for fn(T, K) {}
mod other {
use super::blah;
fn test2() {
// rsx!{
// div {
// Ele {
// a: 10,
// b: "asd"
// c: impl Fn() -> ()
// }
// }
// }
// becomes
// const reorder: fn(_, _) = |a, b| {};
// blah::META;
// let a = 10;
// let b = "asd";
// let g = [10, 10.0];
// let c = g.a;
// blah(10, "asd");
}
}
}
mod style {}
+40 -21
View File
@@ -10,6 +10,8 @@ pub use use_reducer_def::use_reducer;
pub use use_ref_def::use_ref;
pub use use_state_def::use_state;
use crate::innerlude::Context;
mod use_state_def {
use crate::innerlude::*;
use std::{
@@ -213,26 +215,31 @@ mod use_ref_def {
use crate::innerlude::*;
use std::{cell::RefCell, ops::DerefMut};
pub struct UseRef<T: 'static> {
_current: RefCell<T>,
}
impl<T: 'static> UseRef<T> {
fn new(val: T) -> Self {
Self {
_current: RefCell::new(val),
}
}
// pub struct UseRef<T: 'static> {
// _current: RefCell<T>,
// }
// impl<T: 'static> UseRef<T> {
// fn new(val: T) -> Self {
// Self {
// _current: RefCell::new(val),
// }
// }
pub fn modify(&self, modifier: impl FnOnce(&mut T)) {
let mut val = self._current.borrow_mut();
let val_as_ref = val.deref_mut();
modifier(val_as_ref);
}
// pub fn set(&self, new: T) {
// let mut val = self._current.borrow_mut();
// *val = new;
// }
pub fn current(&self) -> std::cell::Ref<'_, T> {
self._current.borrow()
}
}
// pub fn modify(&self, modifier: impl FnOnce(&mut T)) {
// let mut val = self._current.borrow_mut();
// let val_as_ref = val.deref_mut();
// modifier(val_as_ref);
// }
// pub fn current(&self) -> std::cell::Ref<'_, T> {
// self._current.borrow()
// }
// }
/// Store a mutable value between renders!
/// To read the value, borrow the ref.
@@ -240,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: &'_ Context<'a>,
ctx: Context<'a>,
initial_state_fn: impl FnOnce() -> T + 'static,
) -> &'a UseRef<T> {
ctx.use_hook(|| UseRef::new(initial_state_fn()), |state| &*state, |_| {})
) -> &'a RefCell<T> {
ctx.use_hook(|| RefCell::new(initial_state_fn()), |state| &*state, |_| {})
}
}
@@ -339,3 +346,15 @@ mod use_reducer_def {
// };
}
}
pub fn use_is_initialized(ctx: Context) -> bool {
let val = use_ref(ctx, || false);
match *val.borrow() {
true => true,
false => {
//
*val.borrow_mut() = true;
false
}
}
}
+10
View File
@@ -142,5 +142,15 @@ pub mod prelude {
pub use crate::diff::DiffMachine;
pub use crate::debug_renderer::DebugRenderer;
pub use crate::dioxus_main;
pub use crate::hooks::*;
}
#[macro_export]
macro_rules! dioxus_main {
($i:ident) => {
fn main() {
todo!("this macro is a placeholder for launching a dioxus app on different platforms. \nYou probably don't want to use this, but it's okay for small apps.")
}
};
}
+83
View File
@@ -0,0 +1,83 @@
//! Dedicated styling system for Components
//! ---------------------------------------
//!
//!
//!
//!
//!
//!
//!
enum Styles {
background,
backgroundAttachment,
backgroundColor,
backgroundImage,
backgroundPosition,
backgroundRepeat,
border,
borderBottom,
borderBottomColor,
borderBottomStyle,
borderBottomWidth,
borderColor,
borderLeft,
borderLeftColor,
borderLeftStyle,
borderLeftWidth,
borderRight,
borderRightColor,
borderRightStyle,
borderRightWidth,
borderStyle,
borderTop,
borderTopColor,
borderTopStyle,
borderTopWidth,
borderWidth,
clear,
clip,
color,
cursor,
display,
filter,
cssFloat,
font,
fontFamily,
fontSize,
fontVariant,
fontWeight,
height,
left,
letterSpacing,
lineHeight,
listStyle,
listStyleImage,
listStylePosition,
listStyleType,
margin,
marginBottom,
marginLeft,
marginRight,
marginTop,
overflow,
padding,
paddingBottom,
paddingLeft,
paddingRight,
paddingTop,
pageBreakAfter,
pageBreakBefore,
position,
strokeDasharray,
strokeDashoffset,
textAlign,
textDecoration,
textIndent,
textTransform,
top,
verticalAlign,
visibility,
width,
zIndex,
}
+65 -28
View File
@@ -24,7 +24,6 @@ use bumpalo::Bump;
use generational_arena::Arena;
use std::{
any::{Any, TypeId},
borrow::{Borrow, BorrowMut},
cell::RefCell,
collections::{HashMap, HashSet, VecDeque},
fmt::Debug,
@@ -130,7 +129,7 @@ impl VirtualDom {
/// let dom = VirtualDom::new(Example);
/// ```
pub fn new_with_props<P: Properties + 'static>(root: FC<P>, root_props: P) -> Self {
let mut components = ScopeArena::new(Arena::new());
let components = ScopeArena::new(Arena::new());
// 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.
@@ -522,7 +521,7 @@ impl Scope {
// Therefore, their lifetimes are connected exclusively to the virtual dom
fn new<'creator_node>(
caller: Weak<OpaqueComponent<'creator_node>>,
myidx: ScopeIdx,
arena_idx: ScopeIdx,
parent: Option<ScopeIdx>,
height: u32,
event_queue: EventQueue,
@@ -531,7 +530,7 @@ impl Scope {
log::debug!(
"New scope created, height is {}, idx is {:?}",
height,
myidx
arena_idx
);
// The function to run this scope is actually located in the parent's bump arena.
@@ -544,7 +543,7 @@ impl Scope {
// this is a bit of a hack, but will remain this way until we've figured out a cleaner solution.
//
// Not the best solution, so TODO on removing this in favor of a dedicated resource abstraction.
let broken_caller = unsafe {
let caller = unsafe {
std::mem::transmute::<
Weak<OpaqueComponent<'creator_node>>,
Weak<OpaqueComponent<'static>>,
@@ -552,18 +551,18 @@ impl Scope {
};
Self {
shared_contexts: Default::default(),
caller: broken_caller,
hooks: RefCell::new(Vec::new()),
frames: ActiveFrame::new(),
listeners: Default::default(),
hookidx: Default::default(),
children: Default::default(),
caller,
parent,
arena_idx: myidx,
arena_idx,
height,
event_queue,
arena_link,
frames: ActiveFrame::new(),
hooks: Default::default(),
shared_contexts: Default::default(),
listeners: Default::default(),
hookidx: Default::default(),
children: Default::default(),
}
}
@@ -594,8 +593,8 @@ impl Scope {
.upgrade()
.ok_or(Error::FatalInternal("Failed to get caller"))?;
// Cast the caller ptr from static to one with our own reference
let new_head = unsafe {
// Cast the caller ptr from static to one with our own reference
std::mem::transmute::<&OpaqueComponent<'static>, &OpaqueComponent<'sel>>(
caller.as_ref(),
)
@@ -621,7 +620,7 @@ impl Scope {
.listeners
.try_borrow()
.ok()
.ok_or(Error::FatalInternal("Borrowing listener failed "))?
.ok_or(Error::FatalInternal("Borrowing listener failed"))?
.get(listener_id as usize)
.ok_or(Error::FatalInternal("Event should exist if triggered"))?
.as_ref()
@@ -797,10 +796,11 @@ impl Scope {
let internal_state = pinned_state.downcast_mut::<InternalHookState>().expect(
r###"
Unable to retrive the hook that was initialized in this index.
Consult the `rules of hooks` to understand how to use hooks properly.
Unable to retrive the hook that was initialized in this index.
Consult the `rules of hooks` to understand how to use hooks properly.
You likely used the hook in a conditional. Hooks rely on consistent ordering between renders.
You likely used the hook in a conditional. Hooks rely on consistent ordering between renders.
Any function prefixed with "use" should not be called conditionally.
"###,
);
@@ -813,7 +813,19 @@ impl Scope {
// Context API Implementation for Components
// ================================================
impl Scope {
pub fn create_context<T: 'static>(&self, init: impl Fn() -> T) {
/// This hook enables the ability to expose state to children further down the VirtualDOM Tree.
///
/// This is a hook, so it may not be called conditionally!
///
/// The init method is ran *only* on first use, otherwise it is ignored. However, it uses hooks (ie `use`)
/// so don't put it in a conditional.
///
/// When the component is dropped, so is the context. Be aware of this behavior when consuming
/// the context via Rc/Weak.
///
///
///
pub fn use_create_context<T: 'static>(&self, init: impl Fn() -> T) {
let mut ctxs = self.shared_contexts.borrow_mut();
let ty = TypeId::of::<T>();
@@ -837,27 +849,56 @@ impl Scope {
ctxs.insert(ty, Rc::new(init()));
}
(false, true) => panic!("Cannot initialize two contexts of the same type"),
(true, false) => panic!("Implementation failure resulted in missing context"),
_ => debug_assert!(false, "Cannot initialize two contexts of the same type"),
}
}
/// There are hooks going on here!
pub fn use_context<T: 'static>(&self) -> Rc<T> {
self.try_use_context().unwrap()
}
///
pub fn try_use_context<T: 'static>(&self) -> Result<Rc<T>> {
let ty = TypeId::of::<T>();
let mut scope = Some(self);
let cached_root = use_ref(self, || None as Option<Weak<T>>);
// Try to provide the cached version without having to re-climb the tree
if let Some(ptr) = cached_root.borrow().as_ref() {
if let Some(pt) = ptr.clone().upgrade() {
return Ok(pt);
} else {
/*
failed to upgrade the weak is strange
this means the root dropped the context (the scope was killed)
The main idea here is to prevent memory leaks where parents should be cleaning up their own memory.
However, this behavior allows receivers/providers to move around in the hierarchy.
This works because we climb the tree if upgrading the Rc failed.
*/
}
}
while let Some(inner) = scope {
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) {
return Ok(shared_ctx.clone().downcast().unwrap());
let rc = shared_ctx
.clone()
.downcast()
.expect("Should not fail, already validated the type from the hashmap");
*cached_root.borrow_mut() = Some(Rc::downgrade(&rc));
return Ok(rc);
} else {
match inner.parent {
Some(parid) => {
Some(parent_id) => {
let parent = inner
.arena_link
.try_get(parid)
.try_get(parent_id)
.map_err(|_| Error::FatalInternal("Failed to find parent"))?;
scope = Some(parent);
@@ -869,10 +910,6 @@ impl Scope {
Err(Error::MissingSharedContext)
}
pub fn use_context<T: 'static>(&self) -> Rc<T> {
self.try_use_context().unwrap()
}
}
// ==================================================================================