diff --git a/components/script/dom/event.rs b/components/script/dom/event.rs index 8041c09a695..f658f479912 100644 --- a/components/script/dom/event.rs +++ b/components/script/dom/event.rs @@ -271,6 +271,7 @@ impl Event { object, self, Some(ListenerPhase::Capturing), + can_gc, ); } @@ -290,6 +291,7 @@ impl Event { object, self, Some(ListenerPhase::Bubbling), + can_gc, ); } } @@ -639,6 +641,7 @@ fn invoke( object: &EventTarget, event: &Event, phase: Option, + can_gc: CanGc, // TODO legacy_output_did_listeners_throw for indexeddb ) { // Step 1: Until shadow DOM puts the event path in the @@ -657,7 +660,7 @@ fn invoke( event.current_target.set(Some(object)); // Step 6 - let listeners = object.get_listeners_for(&event.type_(), phase); + let listeners = object.get_listeners_for(&event.type_(), phase, can_gc); // Step 7. let found = inner_invoke(timeline_window, object, event, &listeners); diff --git a/components/script/dom/eventtarget.rs b/components/script/dom/eventtarget.rs index 2b1ba39c687..811938b5aa5 100644 --- a/components/script/dom/eventtarget.rs +++ b/components/script/dom/eventtarget.rs @@ -108,11 +108,12 @@ impl InlineEventListener { &mut self, owner: &EventTarget, ty: &Atom, + can_gc: CanGc, ) -> Option { match mem::replace(self, InlineEventListener::Null) { InlineEventListener::Null => None, InlineEventListener::Uncompiled(handler) => { - let result = owner.get_compiled_event_handler(handler, ty); + let result = owner.get_compiled_event_handler(handler, ty, can_gc); if let Some(ref compiled) = result { *self = InlineEventListener::Compiled(compiled.clone()); } @@ -137,10 +138,11 @@ impl EventListenerType { &mut self, owner: &EventTarget, ty: &Atom, + can_gc: CanGc, ) -> Option { match *self { EventListenerType::Inline(ref mut inline) => inline - .get_compiled_handler(owner, ty) + .get_compiled_handler(owner, ty, can_gc) .map(CompiledEventListener::Handler), EventListenerType::Additive(ref listener) => { Some(CompiledEventListener::Listener(listener.clone())) @@ -309,11 +311,12 @@ impl EventListeners { &mut self, owner: &EventTarget, ty: &Atom, + can_gc: CanGc, ) -> Option { for entry in &mut self.0 { if let EventListenerType::Inline(ref mut inline) = entry.listener { // Step 1.1-1.8 and Step 2 - return inline.get_compiled_handler(owner, ty); + return inline.get_compiled_handler(owner, ty, can_gc); } } @@ -327,13 +330,14 @@ impl EventListeners { phase: Option, owner: &EventTarget, ty: &Atom, + can_gc: CanGc, ) -> Vec { self.0 .iter_mut() .filter_map(|entry| { if phase.is_none() || Some(entry.phase) == phase { // Step 1.1-1.8, 2 - entry.listener.get_compiled_listener(owner, ty) + entry.listener.get_compiled_listener(owner, ty, can_gc) } else { None } @@ -388,12 +392,13 @@ impl EventTarget { &self, type_: &Atom, specific_phase: Option, + can_gc: CanGc, ) -> Vec { self.handlers .borrow_mut() .get_mut(type_) .map_or(vec![], |listeners| { - listeners.get_listeners(specific_phase, self, type_) + listeners.get_listeners(specific_phase, self, type_, can_gc) }) } @@ -449,11 +454,11 @@ impl EventTarget { } } - fn get_inline_event_listener(&self, ty: &Atom) -> Option { + fn get_inline_event_listener(&self, ty: &Atom, can_gc: CanGc) -> Option { let mut handlers = self.handlers.borrow_mut(); handlers .get_mut(ty) - .and_then(|entry| entry.get_inline_listener(self, ty)) + .and_then(|entry| entry.get_inline_listener(self, ty, can_gc)) } /// Store the raw uncompiled event handler for on-demand compilation later. @@ -474,11 +479,14 @@ impl EventTarget { // https://html.spec.whatwg.org/multipage/#getting-the-current-value-of-the-event-handler // step 3 + // While the CanGc argument appears unused, it reflects the fact that the CompileFunction + // API call can trigger a GC operation. #[allow(unsafe_code)] fn get_compiled_event_handler( &self, handler: InternalRawUncompiledHandler, ty: &Atom, + _can_gc: CanGc, ) -> Option { // Step 3.1 let element = self.downcast::(); @@ -633,9 +641,13 @@ impl EventTarget { } #[allow(unsafe_code)] - pub fn get_event_handler_common(&self, ty: &str) -> Option> { + pub fn get_event_handler_common( + &self, + ty: &str, + can_gc: CanGc, + ) -> Option> { let cx = GlobalScope::get_cx(); - let listener = self.get_inline_event_listener(&Atom::from(ty)); + let listener = self.get_inline_event_listener(&Atom::from(ty), can_gc); unsafe { listener.map(|listener| { CallbackContainer::new(cx, listener.parent().callback_holder().get()) diff --git a/components/script/dom/htmlelement.rs b/components/script/dom/htmlelement.rs index d6f63e3ef72..cbbbd86ce3c 100644 --- a/components/script/dom/htmlelement.rs +++ b/components/script/dom/htmlelement.rs @@ -189,7 +189,7 @@ impl HTMLElementMethods for HTMLElement { } } else { self.upcast::() - .get_event_handler_common("error") + .get_event_handler_common("error", CanGc::note()) } } @@ -218,7 +218,7 @@ impl HTMLElementMethods for HTMLElement { } } else { self.upcast::() - .get_event_handler_common("load") + .get_event_handler_common("load", CanGc::note()) } } @@ -246,7 +246,7 @@ impl HTMLElementMethods for HTMLElement { } } else { self.upcast::() - .get_event_handler_common("blur") + .get_event_handler_common("blur", CanGc::note()) } } @@ -274,7 +274,7 @@ impl HTMLElementMethods for HTMLElement { } } else { self.upcast::() - .get_event_handler_common("focus") + .get_event_handler_common("focus", CanGc::note()) } } @@ -302,7 +302,7 @@ impl HTMLElementMethods for HTMLElement { } } else { self.upcast::() - .get_event_handler_common("resize") + .get_event_handler_common("resize", CanGc::note()) } } @@ -330,7 +330,7 @@ impl HTMLElementMethods for HTMLElement { } } else { self.upcast::() - .get_event_handler_common("scroll") + .get_event_handler_common("scroll", CanGc::note()) } } diff --git a/components/script/dom/macros.rs b/components/script/dom/macros.rs index 6bece48b720..4f9cbeae141 100644 --- a/components/script/dom/macros.rs +++ b/components/script/dom/macros.rs @@ -318,8 +318,9 @@ macro_rules! define_event_handler( fn $getter(&self) -> Option<::std::rc::Rc<$handler>> { use crate::dom::bindings::inheritance::Castable; use crate::dom::eventtarget::EventTarget; + use crate::script_runtime::CanGc; let eventtarget = self.upcast::(); - eventtarget.get_event_handler_common(stringify!($event_type)) + eventtarget.get_event_handler_common(stringify!($event_type), CanGc::note()) } fn $setter(&self, listener: Option<::std::rc::Rc<$handler>>) { diff --git a/components/script/dom/messageport.rs b/components/script/dom/messageport.rs index f5117cf209f..9ef658f78b3 100644 --- a/components/script/dom/messageport.rs +++ b/components/script/dom/messageport.rs @@ -28,7 +28,7 @@ use crate::dom::bindings::trace::RootedTraceableBox; use crate::dom::bindings::transferable::Transferable; use crate::dom::eventtarget::EventTarget; use crate::dom::globalscope::GlobalScope; -use crate::script_runtime::JSContext as SafeJSContext; +use crate::script_runtime::{CanGc, JSContext as SafeJSContext}; #[dom_struct] /// The MessagePort used in the DOM. @@ -327,7 +327,7 @@ impl MessagePortMethods for MessagePort { return None; } let eventtarget = self.upcast::(); - eventtarget.get_event_handler_common("message") + eventtarget.get_event_handler_common("message", CanGc::note()) } ///