make signals non-breaking
This commit is contained in:
1 parent
84734c4146
commit
ddbe913e79
5 files changed
+44
-22
No files matched your search
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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`]
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in new issue
Block a user