Implement AddEventListenerOptions: once

Fixes #13242
This commit is contained in:
Bastien Orivel 2018-11-03 16:23:33 +01:00
parent f3ca48206e
commit 50c832762f
5 changed files with 27 additions and 15 deletions

View file

@ -244,11 +244,18 @@ impl CompiledEventListener {
}
}
#[derive(Clone, DenyPublicFields, JSTraceable, MallocSizeOf, PartialEq)]
#[derive(Clone, DenyPublicFields, JSTraceable, MallocSizeOf)]
/// A listener in a collection of event listeners.
struct EventListenerEntry {
phase: ListenerPhase,
listener: EventListenerType,
once: bool,
}
impl std::cmp::PartialEq for EventListenerEntry {
fn eq(&self, other: &Self) -> bool {
self.phase == other.phase && self.listener == other.listener
}
}
#[derive(JSTraceable, MallocSizeOf)]
@ -401,12 +408,22 @@ impl EventTarget {
entries.push(EventListenerEntry {
phase: ListenerPhase::Bubbling,
listener: EventListenerType::Inline(listener),
once: false,
});
}
},
}
}
pub fn remove_listener_if_once(&self, ty: &Atom, listener: &Rc<EventListener>) {
let mut handlers = self.handlers.borrow_mut();
let listener = EventListenerType::Additive(listener.clone());
for entries in handlers.get_mut(ty) {
entries.drain_filter(|e| e.listener == listener && e.once);
}
}
fn get_inline_event_listener(&self, ty: &Atom) -> Option<CommonEventHandler> {
let mut handlers = self.handlers.borrow_mut();
handlers
@ -662,6 +679,7 @@ impl EventTarget {
let new_entry = EventListenerEntry {
phase: phase,
listener: EventListenerType::Additive(listener),
once: options.once,
};
if !entry.contains(&new_entry) {
entry.push(new_entry);
@ -690,6 +708,7 @@ impl EventTarget {
let old_entry = EventListenerEntry {
phase: phase,
listener: EventListenerType::Additive(listener.clone()),
once: false,
};
if let Some(position) = entry.iter().position(|e| *e == old_entry) {
entry.remove(position);
@ -744,6 +763,7 @@ impl From<AddEventListenerOptionsOrBoolean> for AddEventListenerOptions {
AddEventListenerOptionsOrBoolean::AddEventListenerOptions(options) => options,
AddEventListenerOptionsOrBoolean::Boolean(capture) => Self {
parent: EventListenerOptions { capture },
once: false,
},
}
}