Mark CompileFunction as a potential GC operation. (#33937)

Signed-off-by: Josh Matthews <josh@joshmatthews.net>
This commit is contained in:
Josh Matthews 2024-10-21 08:29:50 -04:00 committed by GitHub
parent 9acb25521e
commit dc03d1f3e2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 35 additions and 19 deletions

View file

@ -271,6 +271,7 @@ impl Event {
object, object,
self, self,
Some(ListenerPhase::Capturing), Some(ListenerPhase::Capturing),
can_gc,
); );
} }
@ -290,6 +291,7 @@ impl Event {
object, object,
self, self,
Some(ListenerPhase::Bubbling), Some(ListenerPhase::Bubbling),
can_gc,
); );
} }
} }
@ -639,6 +641,7 @@ fn invoke(
object: &EventTarget, object: &EventTarget,
event: &Event, event: &Event,
phase: Option<ListenerPhase>, phase: Option<ListenerPhase>,
can_gc: CanGc,
// TODO legacy_output_did_listeners_throw for indexeddb // TODO legacy_output_did_listeners_throw for indexeddb
) { ) {
// Step 1: Until shadow DOM puts the event path in the // Step 1: Until shadow DOM puts the event path in the
@ -657,7 +660,7 @@ fn invoke(
event.current_target.set(Some(object)); event.current_target.set(Some(object));
// Step 6 // Step 6
let listeners = object.get_listeners_for(&event.type_(), phase); let listeners = object.get_listeners_for(&event.type_(), phase, can_gc);
// Step 7. // Step 7.
let found = inner_invoke(timeline_window, object, event, &listeners); let found = inner_invoke(timeline_window, object, event, &listeners);

View file

@ -108,11 +108,12 @@ impl InlineEventListener {
&mut self, &mut self,
owner: &EventTarget, owner: &EventTarget,
ty: &Atom, ty: &Atom,
can_gc: CanGc,
) -> Option<CommonEventHandler> { ) -> Option<CommonEventHandler> {
match mem::replace(self, InlineEventListener::Null) { match mem::replace(self, InlineEventListener::Null) {
InlineEventListener::Null => None, InlineEventListener::Null => None,
InlineEventListener::Uncompiled(handler) => { 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 { if let Some(ref compiled) = result {
*self = InlineEventListener::Compiled(compiled.clone()); *self = InlineEventListener::Compiled(compiled.clone());
} }
@ -137,10 +138,11 @@ impl EventListenerType {
&mut self, &mut self,
owner: &EventTarget, owner: &EventTarget,
ty: &Atom, ty: &Atom,
can_gc: CanGc,
) -> Option<CompiledEventListener> { ) -> Option<CompiledEventListener> {
match *self { match *self {
EventListenerType::Inline(ref mut inline) => inline EventListenerType::Inline(ref mut inline) => inline
.get_compiled_handler(owner, ty) .get_compiled_handler(owner, ty, can_gc)
.map(CompiledEventListener::Handler), .map(CompiledEventListener::Handler),
EventListenerType::Additive(ref listener) => { EventListenerType::Additive(ref listener) => {
Some(CompiledEventListener::Listener(listener.clone())) Some(CompiledEventListener::Listener(listener.clone()))
@ -309,11 +311,12 @@ impl EventListeners {
&mut self, &mut self,
owner: &EventTarget, owner: &EventTarget,
ty: &Atom, ty: &Atom,
can_gc: CanGc,
) -> Option<CommonEventHandler> { ) -> Option<CommonEventHandler> {
for entry in &mut self.0 { for entry in &mut self.0 {
if let EventListenerType::Inline(ref mut inline) = entry.listener { if let EventListenerType::Inline(ref mut inline) = entry.listener {
// Step 1.1-1.8 and Step 2 // 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<ListenerPhase>, phase: Option<ListenerPhase>,
owner: &EventTarget, owner: &EventTarget,
ty: &Atom, ty: &Atom,
can_gc: CanGc,
) -> Vec<CompiledEventListener> { ) -> Vec<CompiledEventListener> {
self.0 self.0
.iter_mut() .iter_mut()
.filter_map(|entry| { .filter_map(|entry| {
if phase.is_none() || Some(entry.phase) == phase { if phase.is_none() || Some(entry.phase) == phase {
// Step 1.1-1.8, 2 // Step 1.1-1.8, 2
entry.listener.get_compiled_listener(owner, ty) entry.listener.get_compiled_listener(owner, ty, can_gc)
} else { } else {
None None
} }
@ -388,12 +392,13 @@ impl EventTarget {
&self, &self,
type_: &Atom, type_: &Atom,
specific_phase: Option<ListenerPhase>, specific_phase: Option<ListenerPhase>,
can_gc: CanGc,
) -> Vec<CompiledEventListener> { ) -> Vec<CompiledEventListener> {
self.handlers self.handlers
.borrow_mut() .borrow_mut()
.get_mut(type_) .get_mut(type_)
.map_or(vec![], |listeners| { .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<CommonEventHandler> { fn get_inline_event_listener(&self, ty: &Atom, can_gc: CanGc) -> Option<CommonEventHandler> {
let mut handlers = self.handlers.borrow_mut(); let mut handlers = self.handlers.borrow_mut();
handlers handlers
.get_mut(ty) .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. /// 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 // https://html.spec.whatwg.org/multipage/#getting-the-current-value-of-the-event-handler
// step 3 // 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)] #[allow(unsafe_code)]
fn get_compiled_event_handler( fn get_compiled_event_handler(
&self, &self,
handler: InternalRawUncompiledHandler, handler: InternalRawUncompiledHandler,
ty: &Atom, ty: &Atom,
_can_gc: CanGc,
) -> Option<CommonEventHandler> { ) -> Option<CommonEventHandler> {
// Step 3.1 // Step 3.1
let element = self.downcast::<Element>(); let element = self.downcast::<Element>();
@ -633,9 +641,13 @@ impl EventTarget {
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
pub fn get_event_handler_common<T: CallbackContainer>(&self, ty: &str) -> Option<Rc<T>> { pub fn get_event_handler_common<T: CallbackContainer>(
&self,
ty: &str,
can_gc: CanGc,
) -> Option<Rc<T>> {
let cx = GlobalScope::get_cx(); 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 { unsafe {
listener.map(|listener| { listener.map(|listener| {
CallbackContainer::new(cx, listener.parent().callback_holder().get()) CallbackContainer::new(cx, listener.parent().callback_holder().get())

View file

@ -189,7 +189,7 @@ impl HTMLElementMethods for HTMLElement {
} }
} else { } else {
self.upcast::<EventTarget>() self.upcast::<EventTarget>()
.get_event_handler_common("error") .get_event_handler_common("error", CanGc::note())
} }
} }
@ -218,7 +218,7 @@ impl HTMLElementMethods for HTMLElement {
} }
} else { } else {
self.upcast::<EventTarget>() self.upcast::<EventTarget>()
.get_event_handler_common("load") .get_event_handler_common("load", CanGc::note())
} }
} }
@ -246,7 +246,7 @@ impl HTMLElementMethods for HTMLElement {
} }
} else { } else {
self.upcast::<EventTarget>() self.upcast::<EventTarget>()
.get_event_handler_common("blur") .get_event_handler_common("blur", CanGc::note())
} }
} }
@ -274,7 +274,7 @@ impl HTMLElementMethods for HTMLElement {
} }
} else { } else {
self.upcast::<EventTarget>() self.upcast::<EventTarget>()
.get_event_handler_common("focus") .get_event_handler_common("focus", CanGc::note())
} }
} }
@ -302,7 +302,7 @@ impl HTMLElementMethods for HTMLElement {
} }
} else { } else {
self.upcast::<EventTarget>() self.upcast::<EventTarget>()
.get_event_handler_common("resize") .get_event_handler_common("resize", CanGc::note())
} }
} }
@ -330,7 +330,7 @@ impl HTMLElementMethods for HTMLElement {
} }
} else { } else {
self.upcast::<EventTarget>() self.upcast::<EventTarget>()
.get_event_handler_common("scroll") .get_event_handler_common("scroll", CanGc::note())
} }
} }

View file

@ -318,8 +318,9 @@ macro_rules! define_event_handler(
fn $getter(&self) -> Option<::std::rc::Rc<$handler>> { fn $getter(&self) -> Option<::std::rc::Rc<$handler>> {
use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::inheritance::Castable;
use crate::dom::eventtarget::EventTarget; use crate::dom::eventtarget::EventTarget;
use crate::script_runtime::CanGc;
let eventtarget = self.upcast::<EventTarget>(); let eventtarget = self.upcast::<EventTarget>();
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>>) { fn $setter(&self, listener: Option<::std::rc::Rc<$handler>>) {

View file

@ -28,7 +28,7 @@ use crate::dom::bindings::trace::RootedTraceableBox;
use crate::dom::bindings::transferable::Transferable; use crate::dom::bindings::transferable::Transferable;
use crate::dom::eventtarget::EventTarget; use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::script_runtime::JSContext as SafeJSContext; use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
#[dom_struct] #[dom_struct]
/// The MessagePort used in the DOM. /// The MessagePort used in the DOM.
@ -327,7 +327,7 @@ impl MessagePortMethods for MessagePort {
return None; return None;
} }
let eventtarget = self.upcast::<EventTarget>(); let eventtarget = self.upcast::<EventTarget>();
eventtarget.get_event_handler_common("message") eventtarget.get_event_handler_common("message", CanGc::note())
} }
/// <https://html.spec.whatwg.org/multipage/#handler-messageport-onmessage> /// <https://html.spec.whatwg.org/multipage/#handler-messageport-onmessage>