aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/eventtarget.rs
diff options
context:
space:
mode:
authorJosh Matthews <josh@joshmatthews.net>2024-10-28 12:27:42 -0400
committerGitHub <noreply@github.com>2024-10-28 16:27:42 +0000
commit1d6ede7b4868c5bd3ea821e0afd5df0bb99911cd (patch)
tree0173d51b4b6a7e094bfee4ec5886acbdcdc94396 /components/script/dom/eventtarget.rs
parenta01d66df5388d11aeb6dbd8ac9ccc84302d394bb (diff)
downloadservo-1d6ede7b4868c5bd3ea821e0afd5df0bb99911cd.tar.gz
servo-1d6ede7b4868c5bd3ea821e0afd5df0bb99911cd.zip
Remove GC hazard when compiling inline event listeners. (#33965)
Signed-off-by: Josh Matthews <josh@joshmatthews.net>
Diffstat (limited to 'components/script/dom/eventtarget.rs')
-rw-r--r--components/script/dom/eventtarget.rs84
1 files changed, 42 insertions, 42 deletions
diff --git a/components/script/dom/eventtarget.rs b/components/script/dom/eventtarget.rs
index b32472d12e1..98d1b912416 100644
--- a/components/script/dom/eventtarget.rs
+++ b/components/script/dom/eventtarget.rs
@@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+use std::cell::RefCell;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::default::Default;
use std::ffi::CString;
@@ -100,50 +101,49 @@ enum InlineEventListener {
Null,
}
-impl InlineEventListener {
- /// Get a compiled representation of this event handler, compiling it from its
- /// raw source if necessary.
- /// <https://html.spec.whatwg.org/multipage/#getting-the-current-value-of-the-event-handler>
- fn get_compiled_handler(
- &mut self,
- owner: &EventTarget,
- ty: &Atom,
- can_gc: CanGc,
- ) -> Option<CommonEventHandler> {
- match mem::replace(self, InlineEventListener::Null) {
- InlineEventListener::Null => None,
- InlineEventListener::Uncompiled(handler) => {
- let result = owner.get_compiled_event_handler(handler, ty, can_gc);
- if let Some(ref compiled) = result {
- *self = InlineEventListener::Compiled(compiled.clone());
- }
- result
- },
- InlineEventListener::Compiled(handler) => {
- *self = InlineEventListener::Compiled(handler.clone());
- Some(handler)
- },
- }
- }
+/// Get a compiled representation of this event handler, compiling it from its
+/// raw source if necessary.
+/// <https://html.spec.whatwg.org/multipage/#getting-the-current-value-of-the-event-handler>
+fn get_compiled_handler(
+ inline_listener: &RefCell<InlineEventListener>,
+ owner: &EventTarget,
+ ty: &Atom,
+ can_gc: CanGc,
+) -> Option<CommonEventHandler> {
+ let listener = mem::replace(
+ &mut *inline_listener.borrow_mut(),
+ InlineEventListener::Null,
+ );
+ let compiled = match listener {
+ InlineEventListener::Null => None,
+ InlineEventListener::Uncompiled(handler) => {
+ owner.get_compiled_event_handler(handler, ty, can_gc)
+ },
+ InlineEventListener::Compiled(handler) => Some(handler),
+ };
+ if let Some(ref compiled) = compiled {
+ *inline_listener.borrow_mut() = InlineEventListener::Compiled(compiled.clone());
+ }
+ compiled
}
#[derive(Clone, JSTraceable, MallocSizeOf, PartialEq)]
enum EventListenerType {
Additive(#[ignore_malloc_size_of = "Rc"] Rc<EventListener>),
- Inline(InlineEventListener),
+ Inline(RefCell<InlineEventListener>),
}
impl EventListenerType {
fn get_compiled_listener(
- &mut self,
+ &self,
owner: &EventTarget,
ty: &Atom,
can_gc: CanGc,
) -> Option<CompiledEventListener> {
match *self {
- EventListenerType::Inline(ref mut inline) => inline
- .get_compiled_handler(owner, ty, can_gc)
- .map(CompiledEventListener::Handler),
+ EventListenerType::Inline(ref inline) => {
+ get_compiled_handler(inline, owner, ty, can_gc).map(CompiledEventListener::Handler)
+ },
EventListenerType::Additive(ref listener) => {
Some(CompiledEventListener::Listener(listener.clone()))
},
@@ -308,15 +308,15 @@ impl DerefMut for EventListeners {
impl EventListeners {
// https://html.spec.whatwg.org/multipage/#getting-the-current-value-of-the-event-handler
fn get_inline_listener(
- &mut self,
+ &self,
owner: &EventTarget,
ty: &Atom,
can_gc: CanGc,
) -> Option<CommonEventHandler> {
- for entry in &mut self.0 {
- if let EventListenerType::Inline(ref mut inline) = entry.listener {
+ for entry in &self.0 {
+ if let EventListenerType::Inline(ref inline) = entry.listener {
// Step 1.1-1.8 and Step 2
- return inline.get_compiled_handler(owner, ty, can_gc);
+ return get_compiled_handler(inline, owner, ty, can_gc);
}
}
@@ -326,14 +326,14 @@ impl EventListeners {
// https://html.spec.whatwg.org/multipage/#getting-the-current-value-of-the-event-handler
fn get_listeners(
- &mut self,
+ &self,
phase: Option<ListenerPhase>,
owner: &EventTarget,
ty: &Atom,
can_gc: CanGc,
) -> Vec<CompiledEventListener> {
self.0
- .iter_mut()
+ .iter()
.filter_map(|entry| {
if phase.is_none() || Some(entry.phase) == phase {
// Step 1.1-1.8, 2
@@ -395,8 +395,8 @@ impl EventTarget {
can_gc: CanGc,
) -> Vec<CompiledEventListener> {
self.handlers
- .borrow_mut()
- .get_mut(type_)
+ .borrow()
+ .get(type_)
.map_or(vec![], |listeners| {
listeners.get_listeners(specific_phase, self, type_, can_gc)
})
@@ -427,7 +427,7 @@ impl EventTarget {
// Replace if there's something to replace with,
// but remove entirely if there isn't.
Some(listener) => {
- entries[idx].listener = EventListenerType::Inline(listener);
+ entries[idx].listener = EventListenerType::Inline(listener.into());
},
None => {
entries.remove(idx);
@@ -437,7 +437,7 @@ impl EventTarget {
if let Some(listener) = listener {
entries.push(EventListenerEntry {
phase: ListenerPhase::Bubbling,
- listener: EventListenerType::Inline(listener),
+ listener: EventListenerType::Inline(listener.into()),
once: false,
});
}
@@ -455,9 +455,9 @@ impl EventTarget {
}
fn get_inline_event_listener(&self, ty: &Atom, can_gc: CanGc) -> Option<CommonEventHandler> {
- let mut handlers = self.handlers.borrow_mut();
+ let handlers = self.handlers.borrow();
handlers
- .get_mut(ty)
+ .get(ty)
.and_then(|entry| entry.get_inline_listener(self, ty, can_gc))
}