Prevent ArenaRef
from being cloned (#3738)
This could cause multiple mutable references to be acquired for the same arena element, which is unsafe. I didn't see it cause problems in practice, but I realized this could have been a problem and fixed it before it bit us. Release Notes: - N/A
This commit is contained in:
commit
90db278724
3 changed files with 46 additions and 25 deletions
|
@ -98,15 +98,6 @@ pub struct ArenaRef<T: ?Sized> {
|
||||||
valid: Rc<Cell<bool>>,
|
valid: Rc<Cell<bool>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ?Sized> Clone for ArenaRef<T> {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
Self {
|
|
||||||
ptr: self.ptr,
|
|
||||||
valid: self.valid.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ?Sized> ArenaRef<T> {
|
impl<T: ?Sized> ArenaRef<T> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn map<U: ?Sized>(mut self, f: impl FnOnce(&mut T) -> &mut U) -> ArenaRef<U> {
|
pub fn map<U: ?Sized>(mut self, f: impl FnOnce(&mut T) -> &mut U) -> ArenaRef<U> {
|
||||||
|
|
|
@ -35,7 +35,6 @@ pub(crate) struct DispatchNode {
|
||||||
|
|
||||||
type KeyListener = ArenaRef<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext)>;
|
type KeyListener = ArenaRef<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext)>;
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub(crate) struct DispatchActionListener {
|
pub(crate) struct DispatchActionListener {
|
||||||
pub(crate) action_type: TypeId,
|
pub(crate) action_type: TypeId,
|
||||||
pub(crate) listener: ArenaRef<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext)>,
|
pub(crate) listener: ArenaRef<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext)>,
|
||||||
|
@ -267,6 +266,10 @@ impl DispatchTree {
|
||||||
&self.nodes[node_id.0]
|
&self.nodes[node_id.0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn node_mut(&mut self, node_id: DispatchNodeId) -> &mut DispatchNode {
|
||||||
|
&mut self.nodes[node_id.0]
|
||||||
|
}
|
||||||
|
|
||||||
fn active_node(&mut self) -> &mut DispatchNode {
|
fn active_node(&mut self) -> &mut DispatchNode {
|
||||||
let active_node_id = self.active_node_id();
|
let active_node_id = self.active_node_id();
|
||||||
&mut self.nodes[active_node_id.0]
|
&mut self.nodes[active_node_id.0]
|
||||||
|
|
|
@ -1572,30 +1572,43 @@ impl<'a> WindowContext<'a> {
|
||||||
self.propagate_event = true;
|
self.propagate_event = true;
|
||||||
|
|
||||||
for node_id in &dispatch_path {
|
for node_id in &dispatch_path {
|
||||||
let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
|
let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id);
|
||||||
|
|
||||||
if let Some(context) = node.context.clone() {
|
if let Some(context) = node.context.clone() {
|
||||||
context_stack.push(context);
|
context_stack.push(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
for key_listener in node.key_listeners.clone() {
|
let key_listeners = mem::take(&mut node.key_listeners);
|
||||||
|
for key_listener in &key_listeners {
|
||||||
key_listener(event, DispatchPhase::Capture, self);
|
key_listener(event, DispatchPhase::Capture, self);
|
||||||
if !self.propagate_event {
|
if !self.propagate_event {
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id);
|
||||||
|
node.key_listeners = key_listeners;
|
||||||
|
|
||||||
|
if !self.propagate_event {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bubble phase
|
// Bubble phase
|
||||||
for node_id in dispatch_path.iter().rev() {
|
for node_id in dispatch_path.iter().rev() {
|
||||||
// Handle low level key events
|
// Handle low level key events
|
||||||
let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
|
let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id);
|
||||||
for key_listener in node.key_listeners.clone() {
|
let key_listeners = mem::take(&mut node.key_listeners);
|
||||||
|
for key_listener in &key_listeners {
|
||||||
key_listener(event, DispatchPhase::Bubble, self);
|
key_listener(event, DispatchPhase::Bubble, self);
|
||||||
if !self.propagate_event {
|
if !self.propagate_event {
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id);
|
||||||
|
node.key_listeners = key_listeners;
|
||||||
|
|
||||||
|
if !self.propagate_event {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Match keystrokes
|
// Match keystrokes
|
||||||
let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
|
let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
|
||||||
|
@ -1639,38 +1652,52 @@ impl<'a> WindowContext<'a> {
|
||||||
|
|
||||||
// Capture phase
|
// Capture phase
|
||||||
for node_id in &dispatch_path {
|
for node_id in &dispatch_path {
|
||||||
let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
|
let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id);
|
||||||
|
let action_listeners = mem::take(&mut node.action_listeners);
|
||||||
for DispatchActionListener {
|
for DispatchActionListener {
|
||||||
action_type,
|
action_type,
|
||||||
listener,
|
listener,
|
||||||
} in node.action_listeners.clone()
|
} in &action_listeners
|
||||||
{
|
{
|
||||||
let any_action = action.as_any();
|
let any_action = action.as_any();
|
||||||
if action_type == any_action.type_id() {
|
if *action_type == any_action.type_id() {
|
||||||
listener(any_action, DispatchPhase::Capture, self);
|
listener(any_action, DispatchPhase::Capture, self);
|
||||||
if !self.propagate_event {
|
if !self.propagate_event {
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id);
|
||||||
|
node.action_listeners = action_listeners;
|
||||||
|
|
||||||
|
if !self.propagate_event {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Bubble phase
|
// Bubble phase
|
||||||
for node_id in dispatch_path.iter().rev() {
|
for node_id in dispatch_path.iter().rev() {
|
||||||
let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
|
let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id);
|
||||||
|
let action_listeners = mem::take(&mut node.action_listeners);
|
||||||
for DispatchActionListener {
|
for DispatchActionListener {
|
||||||
action_type,
|
action_type,
|
||||||
listener,
|
listener,
|
||||||
} in node.action_listeners.clone()
|
} in &action_listeners
|
||||||
{
|
{
|
||||||
let any_action = action.as_any();
|
let any_action = action.as_any();
|
||||||
if action_type == any_action.type_id() {
|
if *action_type == any_action.type_id() {
|
||||||
self.propagate_event = false; // Actions stop propagation by default during the bubble phase
|
self.propagate_event = false; // Actions stop propagation by default during the bubble phase
|
||||||
listener(any_action, DispatchPhase::Bubble, self);
|
listener(any_action, DispatchPhase::Bubble, self);
|
||||||
if !self.propagate_event {
|
if !self.propagate_event {
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id);
|
||||||
|
node.action_listeners = action_listeners;
|
||||||
|
if !self.propagate_event {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue