Add a permanent root to WebIDL callbacks, ensuring they are always safe to store.

This commit is contained in:
Josh Matthews 2017-01-12 18:05:54 -05:00
parent 550df86ac8
commit 3f35c3eee2
4 changed files with 75 additions and 28 deletions

View file

@ -441,13 +441,13 @@ impl EventTarget {
assert!(!funobj.is_null());
// Step 1.14
if is_error {
Some(CommonEventHandler::ErrorEventHandler(OnErrorEventHandlerNonNull::new(funobj)))
Some(CommonEventHandler::ErrorEventHandler(OnErrorEventHandlerNonNull::new(cx, funobj)))
} else {
if ty == &atom!("beforeunload") {
Some(CommonEventHandler::BeforeUnloadEventHandler(
OnBeforeUnloadEventHandlerNonNull::new(funobj)))
OnBeforeUnloadEventHandlerNonNull::new(cx, funobj)))
} else {
Some(CommonEventHandler::EventHandler(EventHandlerNonNull::new(funobj)))
Some(CommonEventHandler::EventHandler(EventHandlerNonNull::new(cx, funobj)))
}
}
}
@ -455,36 +455,47 @@ impl EventTarget {
pub fn set_event_handler_common<T: CallbackContainer>(
&self, ty: &str, listener: Option<Rc<T>>)
{
let cx = self.global().get_cx();
let event_listener = listener.map(|listener|
InlineEventListener::Compiled(
CommonEventHandler::EventHandler(
EventHandlerNonNull::new(listener.callback()))));
EventHandlerNonNull::new(cx, listener.callback()))));
self.set_inline_event_listener(Atom::from(ty), event_listener);
}
pub fn set_error_event_handler<T: CallbackContainer>(
&self, ty: &str, listener: Option<Rc<T>>)
{
let cx = self.global().get_cx();
let event_listener = listener.map(|listener|
InlineEventListener::Compiled(
CommonEventHandler::ErrorEventHandler(
OnErrorEventHandlerNonNull::new(listener.callback()))));
OnErrorEventHandlerNonNull::new(cx, listener.callback()))));
self.set_inline_event_listener(Atom::from(ty), event_listener);
}
pub fn set_beforeunload_event_handler<T: CallbackContainer>(&self, ty: &str,
listener: Option<Rc<T>>) {
listener: Option<Rc<T>>) {
let cx = self.global().get_cx();
let event_listener = listener.map(|listener|
InlineEventListener::Compiled(
CommonEventHandler::BeforeUnloadEventHandler(
OnBeforeUnloadEventHandlerNonNull::new(listener.callback())))
OnBeforeUnloadEventHandlerNonNull::new(cx, listener.callback())))
);
self.set_inline_event_listener(Atom::from(ty), event_listener);
}
#[allow(unsafe_code)]
pub fn get_event_handler_common<T: CallbackContainer>(&self, ty: &str) -> Option<Rc<T>> {
let cx = self.global().get_cx();
let listener = self.get_inline_event_listener(&Atom::from(ty));
listener.map(|listener| CallbackContainer::new(listener.parent().callback_holder().get()))
unsafe {
listener.map(|listener|
CallbackContainer::new(cx, listener.parent().callback_holder().get()))
}
}
pub fn has_handlers(&self) -> bool {