make signals non-breaking

This commit is contained in:
Evan Almloff committed 2023-08-07 14:50:36 -07:00
1 parent 84734c4146
commit ddbe913e79
5 files changed
+44 -22

No files matched your search

+7 -1
View File
@@ -19,6 +19,9 @@ pub(crate) struct ElementRef {
// The actual template
pub template: Option<NonNull<VNode<'static>>>,
// The scope the element belongs to
pub scope: ScopeId,
}
#[derive(Clone, Copy, Debug)]
@@ -32,6 +35,7 @@ impl ElementRef {
Self {
template: None,
path: ElementPath::Root(0),
scope: ScopeId(0),
}
}
}
@@ -56,11 +60,13 @@ impl VirtualDom {
fn next_reference(&mut self, template: &VNode, path: ElementPath) -> ElementId {
let entry = self.elements.vacant_entry();
let id = entry.key();
let scope = self.runtime.current_scope_id().unwrap_or(ScopeId(0));
entry.insert(ElementRef {
// We know this is non-null because it comes from a reference
template: Some(unsafe { NonNull::new_unchecked(template as *const _ as *mut _) }),
path,
scope,
});
ElementId(id)
}
@@ -163,7 +169,7 @@ impl VirtualDom {
let listener = unsafe { &*listener };
match &listener.value {
AttributeValue::Listener(l) => {
_ = l.callback.take();
_ = l.take();
}
AttributeValue::Any(a) => {
_ = a.take();
+8 -3
View File
@@ -1,9 +1,8 @@
use crate::{runtime::with_runtime, ScopeId};
use std::{
cell::{Cell, RefCell},
rc::Rc,
};
use crate::ScopeId;
/// A wrapper around some generic data that handles the event's state
///
@@ -136,7 +135,7 @@ impl<T: std::fmt::Debug> std::fmt::Debug for Event<T> {
/// }
///
/// ```
pub struct EventHandler<'bump, T:?Sized = ()> {
pub struct EventHandler<'bump, T: ?Sized = ()> {
pub(crate) origin: ScopeId,
pub(super) callback: RefCell<Option<ExternalListenerCallback<'bump, T>>>,
}
@@ -158,7 +157,13 @@ impl<T> EventHandler<'_, T> {
/// This borrows the event using a RefCell. Recursively calling a listener will cause a panic.
pub fn call(&self, event: T) {
if let Some(callback) = self.callback.borrow_mut().as_mut() {
with_runtime(|rt| {
rt.scope_stack.borrow_mut().push(self.origin);
});
callback(event);
with_runtime(|rt| {
rt.scope_stack.borrow_mut().pop();
});
}
}
+4 -2
View File
@@ -1,4 +1,4 @@
use crate::prelude::EventHandler;use crate::{
use crate::{
any_props::AnyProps, arena::ElementId, Element, Event, LazyNodes, ScopeId, ScopeState,
};
use bumpalo::boxed::Box as BumpBox;
@@ -476,7 +476,7 @@ pub enum AttributeValue<'a> {
Bool(bool),
/// A listener, like "onclick"
Listener(EventHandler<'a, Event<dyn Any>>),
Listener(RefCell<Option<ListenerCb<'a>>>),
/// An arbitrary value that implements PartialEq and is static
Any(RefCell<Option<BumpBox<'a, dyn AnyValue>>>),
@@ -485,6 +485,8 @@ pub enum AttributeValue<'a> {
None,
}
pub type ListenerCb<'a> = BumpBox<'a, dyn FnMut(Event<dyn Any>) + 'a>;
/// Any of the built-in values that the Dioxus VirtualDom supports as dynamic attributes on elements that are borrowed
///
/// These varients are used to communicate what the value of an attribute is that needs to be updated
+19 -10
View File
@@ -446,7 +446,10 @@ impl<'src> ScopeState {
let handler: &mut dyn FnMut(T) = self.bump().alloc(f);
let caller = unsafe { BumpBox::from_raw(handler as *mut dyn FnMut(T)) };
let callback = RefCell::new(Some(caller));
EventHandler { callback, origin: self.context().id }
EventHandler {
callback,
origin: self.context().id,
}
}
/// Create a new [`AttributeValue`] with the listener variant from a callback
@@ -456,16 +459,22 @@ impl<'src> ScopeState {
&'src self,
mut callback: impl FnMut(Event<T>) + 'src,
) -> AttributeValue<'src> {
// safety: there's no other way to create a dynamicly-dispatched bump box other than alloc + from-raw
// This is the suggested way to build a bumpbox
//
// In theory, we could just use regular boxes
let boxed: BumpBox<'src, dyn FnMut(_) + 'src> = unsafe {
BumpBox::from_raw(self.bump().alloc(move |event: Event<dyn Any>| {
if let Ok(data) = event.data.downcast::<T>() {
callback(Event {
propagates: event.propagates,
data,
});
}
}))
};
AttributeValue::Listener(self.event_handler(move |event: Event<dyn Any>| {
if let Ok(data) = event.data.downcast::<T>() {
callback(Event {
propagates: event.propagates,
data,
});
}
}))
AttributeValue::Listener(RefCell::new(Some(boxed)))
}
/// Create a new [`AttributeValue`] with a value that implements [`AnyValue`]
+6 -6
View File
@@ -391,12 +391,12 @@ impl VirtualDom {
// We check the bubble state between each call to see if the event has been stopped from bubbling
for listener in listeners.drain(..).rev() {
if let AttributeValue::Listener(listener) = listener {
let origin = listener.origin;
self.runtime.scope_stack.borrow_mut().push(origin);
if let Some(cb) = listener.callback.borrow_mut().as_deref_mut() {
let origin = el_ref.scope;
self.runtime.scope_stack.borrow_mut().push(origin);
if let Some(cb) = listener.borrow_mut().as_deref_mut() {
cb(uievent.clone());
}
self.runtime.scope_stack.borrow_mut().pop();
self.runtime.scope_stack.borrow_mut().pop();
if !uievent.propagates.get() {
return;
@@ -425,9 +425,9 @@ impl VirtualDom {
// Only call the listener if this is the exact target element.
if attr.name.trim_start_matches("on") == name && target_path == this_path {
if let AttributeValue::Listener(listener) = &attr.value {
let origin = listener.origin;
let origin = el_ref.scope;
self.runtime.scope_stack.borrow_mut().push(origin);
if let Some(cb) = listener.callback.borrow_mut().as_deref_mut() {
if let Some(cb) = listener.borrow_mut().as_deref_mut() {
cb(uievent.clone());
}
self.runtime.scope_stack.borrow_mut().pop();