docs: update local examples and docs to support new syntaxes

This commit is contained in:
Jonathan Kelley committed 2021-12-15 15:56:53 -05:00
1 parent e495b09bf1
commit 4de16c4779
118 files changed
+520 -1154

No files matched your search

+1 -1
View File
@@ -58,7 +58,7 @@ impl<'a, const A: bool> FragmentBuilder<'a, A> {
/// cx.render(rsx!{
/// div {
/// h1 {"Title card"}
/// {props.children}
/// {cx.props.children}
/// }
/// })
/// }
+6 -7
View File
@@ -440,7 +440,7 @@ impl<'bump> DiffState<'bump> {
let height = parent_scope.height + 1;
let subtree = parent_scope.subtree.get();
let parent_scope = unsafe { self.scopes.get_scope_raw(parent_idx) };
let parent_scope = self.scopes.get_scope_raw(parent_idx);
let caller = unsafe { std::mem::transmute(vcomponent.caller as *const _) };
let fc_ptr = vcomponent.user_fc;
@@ -716,13 +716,12 @@ impl<'bump> DiffState<'bump> {
new.associated_scope.set(Some(scope_addr));
// make sure the component's caller function is up to date
let scope = unsafe {
self.scopes
.get_scope_mut(scope_addr)
.unwrap_or_else(|| panic!("could not find {:?}", scope_addr))
};
let scope = self
.scopes
.get_scope(scope_addr)
.unwrap_or_else(|| panic!("could not find {:?}", scope_addr));
scope.caller = unsafe { std::mem::transmute(new.caller) };
scope.caller.set(unsafe { std::mem::transmute(new.caller) });
// React doesn't automatically memoize, but we do.
let props_are_the_same = old.comparator.unwrap();
+2 -2
View File
@@ -520,8 +520,8 @@ impl<'a> NodeFactory<'a> {
move |other: &VComponent| {
if user_fc == other.user_fc {
// Safety
// - We guarantee that FC<P> is the same by function pointer
// - Because FC<P> is the same, then P must be the same (even with generics)
// - We guarantee that Component<P> is the same by function pointer
// - Because Component<P> is the same, then P must be the same (even with generics)
// - Non-static P are autoderived to memoize as false
// - This comparator is only called on a corresponding set of bumpframes
//
+5 -5
View File
@@ -28,7 +28,7 @@ use bumpalo::{boxed::Box as BumpBox, Bump};
/// }
///
/// fn Example(cx: Context, props: &ExampleProps) -> Element {
/// cx.render(rsx!{ div {"Hello, {props.name}"} })
/// cx.render(rsx!{ div {"Hello, {cx.props.name}"} })
/// }
/// ```
pub struct Scope<'a, P> {
@@ -88,7 +88,7 @@ pub struct ScopeState {
pub(crate) frames: [BumpFrame; 2],
pub(crate) caller: *const dyn Fn(&ScopeState) -> Element,
pub(crate) caller: Cell<*const dyn Fn(&ScopeState) -> Element>,
pub(crate) items: RefCell<SelfReferentialItems<'static>>,
@@ -269,12 +269,12 @@ impl ScopeState {
/// ```rust, ignore
/// struct SharedState(&'static str);
///
/// static App: FC<()> = |cx, props|{
/// static App: Component<()> = |cx, props|{
/// cx.use_hook(|_| cx.provide_state(SharedState("world")), |_| {}, |_| {});
/// rsx!(cx, Child {})
/// }
///
/// static Child: FC<()> = |cx, props| {
/// static Child: Component<()> = |cx| {
/// let state = cx.consume_state::<SharedState>();
/// rsx!(cx, div { "hello {state.0}" })
/// }
@@ -344,7 +344,7 @@ impl ScopeState {
/// ## Example
///
/// ```ignore
/// fn Component(cx: Scope, props: &Props) -> Element {
/// fn Component(cx: Scope<Props>) -> Element {
/// // Lazy assemble the VNode tree
/// let lazy_nodes = rsx!("hello world");
///
+15 -38
View File
@@ -72,14 +72,10 @@ impl ScopeArena {
unsafe { self.scopes.borrow().get(&id).map(|f| &**f) }
}
pub(crate) unsafe fn get_scope_raw(&self, id: ScopeId) -> Option<*mut ScopeState> {
pub(crate) fn get_scope_raw(&self, id: ScopeId) -> Option<*mut ScopeState> {
self.scopes.borrow().get(&id).copied()
}
pub(crate) unsafe fn get_scope_mut(&self, id: ScopeId) -> Option<&mut ScopeState> {
self.scopes.borrow().get(&id).map(|s| &mut **s)
}
pub(crate) fn new_with_key(
&self,
fc_ptr: *const (),
@@ -95,35 +91,13 @@ impl ScopeArena {
if let Some(old_scope) = self.free_scopes.borrow_mut().pop() {
let scope = unsafe { &mut *old_scope };
scope.caller = caller;
scope.caller.set(caller);
scope.parent_scope = parent_scope;
scope.height = height;
scope.subtree = Cell::new(subtree);
scope.our_arena_idx = new_scope_id;
scope.container = container;
// scope.frames[0].nodes.get_mut().push({
// let vnode = scope.frames[0]
// .bump
// .alloc(VNode::Text(scope.frames[0].bump.alloc(VText {
// dom_id: Default::default(),
// is_static: false,
// text: "",
// })));
// unsafe { std::mem::transmute(vnode as *mut VNode) }
// });
// scope.frames[1].nodes.get_mut().push({
// let vnode = scope.frames[1]
// .bump
// .alloc(VNode::Text(scope.frames[1].bump.alloc(VText {
// dom_id: Default::default(),
// is_static: false,
// text: "",
// })));
// unsafe { std::mem::transmute(vnode as *mut VNode) }
// });
let any_item = self.scopes.borrow_mut().insert(new_scope_id, scope);
debug_assert!(any_item.is_none());
} else {
@@ -148,7 +122,7 @@ impl ScopeArena {
subtree: Cell::new(subtree),
is_subtree_root: Cell::new(false),
caller,
caller: Cell::new(caller),
generation: 0.into(),
shared_contexts: Default::default(),
@@ -277,18 +251,20 @@ impl ScopeArena {
// Remove all the outdated listeners
self.ensure_drop_safety(id);
let scope = unsafe { &mut *self.get_scope_mut(id).expect("could not find scope") };
// todo: we *know* that this is aliased by the contents of the scope itself
let scope = unsafe { &mut *self.get_scope_raw(id).expect("could not find scope") };
// 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
scope.hook_idx.set(0);
// Safety:
// - We've dropped all references to the wip bump frame with "ensure_drop_safety"
unsafe { scope.reset_wip_frame() };
// book keeping to ensure safety around the borrowed data
{
// Safety:
// - We've dropped all references to the wip bump frame with "ensure_drop_safety"
unsafe { scope.reset_wip_frame() };
let mut items = scope.items.borrow_mut();
// just forget about our suspended nodes while we're at it
@@ -298,12 +274,9 @@ impl ScopeArena {
debug_assert!(items.listeners.is_empty());
debug_assert!(items.borrowed_props.is_empty());
debug_assert!(items.tasks.is_empty());
// Todo: see if we can add stronger guarantees around internal bookkeeping and failed component renders.
// scope.wip_frame().nodes
}
let render: &dyn Fn(&ScopeState) -> Element = unsafe { &*scope.caller };
let render: &dyn Fn(&ScopeState) -> Element = unsafe { &*scope.caller.get() };
if let Some(node) = render(scope) {
if !scope.items.borrow().tasks.is_empty() {
@@ -319,6 +292,10 @@ impl ScopeArena {
scope.cycle_frame();
true
} else {
// the component bailed out early
// this leaves the wip frame and all descendents in a state where
// their WIP frames are invalid
// todo: descendents should not cause the app to crash
false
}
}
+4 -4
View File
@@ -25,7 +25,7 @@ use std::{any::Any, collections::VecDeque, pin::Pin, sync::Arc, task::Poll};
///
/// fn App(cx: Context, props: &AppProps) -> Element {
/// cx.render(rsx!(
/// div {"hello, {props.title}"}
/// div {"hello, {cx.props.title}"}
/// ))
/// }
/// ```
@@ -36,7 +36,7 @@ use std::{any::Any, collections::VecDeque, pin::Pin, sync::Arc, task::Poll};
/// fn App(cx: Context, props: &AppProps) -> Element {
/// cx.render(rsx!(
/// NavBar { routes: ROUTES }
/// Title { "{props.title}" }
/// Title { "{cx.props.title}" }
/// Footer {}
/// ))
/// }
@@ -459,7 +459,7 @@ impl VirtualDom {
///
/// # Example
/// ```rust, ignore
/// static App: FC<()> = |cx, props| cx.render(rsx!{ "hello world" });
/// static App: Component<()> = |cx, props| cx.render(rsx!{ "hello world" });
/// let mut dom = VirtualDom::new();
/// let edits = dom.rebuild();
///
@@ -497,7 +497,7 @@ impl VirtualDom {
/// value: Shared<&'static str>,
/// }
///
/// static App: FC<AppProps> = |cx, props|{
/// static App: Component<AppProps> = |cx, props|{
/// let val = cx.value.borrow();
/// cx.render(rsx! { div { "{val}" } })
/// };