Auto merge of #15359 - freeatnet:15332-macroed-event-handlers-check-for-window, r=KiChjang

Event handlers forwarded to a window check for window presence

<!-- Please describe your changes on the following line: -->
This change adds a check for the presence of a window in event handlers of `body` and `frameset` that are forwarded to the window.

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes fix #15332

<!-- Either: -->
- [x] There are tests for these changes OR
- [ ] These changes do not require tests because _____

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

I'm new to both Servo and Rust — so any suggestions for improvement are very welcome.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/15359)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-02-03 13:10:50 -08:00 committed by GitHub
commit 8926db302a
6 changed files with 119 additions and 13 deletions

View file

@ -367,6 +367,9 @@ impl Document {
self.loader.borrow_mut() self.loader.borrow_mut()
} }
#[inline]
pub fn has_browsing_context(&self) -> bool { self.has_browsing_context }
/// https://html.spec.whatwg.org/multipage/#concept-document-bc /// https://html.spec.whatwg.org/multipage/#concept-document-bc
#[inline] #[inline]
pub fn browsing_context(&self) -> Option<Root<BrowsingContext>> { pub fn browsing_context(&self) -> Option<Root<BrowsingContext>> {

View file

@ -151,7 +151,12 @@ impl HTMLElementMethods for HTMLElement {
// https://html.spec.whatwg.org/multipage/#handler-onload // https://html.spec.whatwg.org/multipage/#handler-onload
fn GetOnload(&self) -> Option<Rc<EventHandlerNonNull>> { fn GetOnload(&self) -> Option<Rc<EventHandlerNonNull>> {
if self.is_body_or_frameset() { if self.is_body_or_frameset() {
window_from_node(self).GetOnload() let document = document_from_node(self);
if document.has_browsing_context() {
document.window().GetOnload()
} else {
None
}
} else { } else {
self.upcast::<EventTarget>().get_event_handler_common("load") self.upcast::<EventTarget>().get_event_handler_common("load")
} }
@ -160,7 +165,10 @@ impl HTMLElementMethods for HTMLElement {
// https://html.spec.whatwg.org/multipage/#handler-onload // https://html.spec.whatwg.org/multipage/#handler-onload
fn SetOnload(&self, listener: Option<Rc<EventHandlerNonNull>>) { fn SetOnload(&self, listener: Option<Rc<EventHandlerNonNull>>) {
if self.is_body_or_frameset() { if self.is_body_or_frameset() {
window_from_node(self).SetOnload(listener) let document = document_from_node(self);
if document.has_browsing_context() {
document.window().SetOnload(listener)
}
} else { } else {
self.upcast::<EventTarget>().set_event_handler_common("load", listener) self.upcast::<EventTarget>().set_event_handler_common("load", listener)
} }
@ -169,7 +177,12 @@ impl HTMLElementMethods for HTMLElement {
// https://html.spec.whatwg.org/multipage/#handler-onresize // https://html.spec.whatwg.org/multipage/#handler-onresize
fn GetOnresize(&self) -> Option<Rc<EventHandlerNonNull>> { fn GetOnresize(&self) -> Option<Rc<EventHandlerNonNull>> {
if self.is_body_or_frameset() { if self.is_body_or_frameset() {
window_from_node(self).GetOnload() let document = document_from_node(self);
if document.has_browsing_context() {
document.window().GetOnload()
} else {
None
}
} else { } else {
self.upcast::<EventTarget>().get_event_handler_common("resize") self.upcast::<EventTarget>().get_event_handler_common("resize")
} }
@ -178,7 +191,10 @@ impl HTMLElementMethods for HTMLElement {
// https://html.spec.whatwg.org/multipage/#handler-onresize // https://html.spec.whatwg.org/multipage/#handler-onresize
fn SetOnresize(&self, listener: Option<Rc<EventHandlerNonNull>>) { fn SetOnresize(&self, listener: Option<Rc<EventHandlerNonNull>>) {
if self.is_body_or_frameset() { if self.is_body_or_frameset() {
window_from_node(self).SetOnresize(listener); let document = document_from_node(self);
if document.has_browsing_context() {
document.window().SetOnresize(listener);
}
} else { } else {
self.upcast::<EventTarget>().set_event_handler_common("resize", listener) self.upcast::<EventTarget>().set_event_handler_common("resize", listener)
} }
@ -187,7 +203,12 @@ impl HTMLElementMethods for HTMLElement {
// https://html.spec.whatwg.org/multipage/#handler-onblur // https://html.spec.whatwg.org/multipage/#handler-onblur
fn GetOnblur(&self) -> Option<Rc<EventHandlerNonNull>> { fn GetOnblur(&self) -> Option<Rc<EventHandlerNonNull>> {
if self.is_body_or_frameset() { if self.is_body_or_frameset() {
window_from_node(self).GetOnblur() let document = document_from_node(self);
if document.has_browsing_context() {
document.window().GetOnblur()
} else {
None
}
} else { } else {
self.upcast::<EventTarget>().get_event_handler_common("blur") self.upcast::<EventTarget>().get_event_handler_common("blur")
} }
@ -196,7 +217,10 @@ impl HTMLElementMethods for HTMLElement {
// https://html.spec.whatwg.org/multipage/#handler-onblur // https://html.spec.whatwg.org/multipage/#handler-onblur
fn SetOnblur(&self, listener: Option<Rc<EventHandlerNonNull>>) { fn SetOnblur(&self, listener: Option<Rc<EventHandlerNonNull>>) {
if self.is_body_or_frameset() { if self.is_body_or_frameset() {
window_from_node(self).SetOnblur(listener) let document = document_from_node(self);
if document.has_browsing_context() {
document.window().SetOnblur(listener)
}
} else { } else {
self.upcast::<EventTarget>().set_event_handler_common("blur", listener) self.upcast::<EventTarget>().set_event_handler_common("blur", listener)
} }
@ -205,7 +229,12 @@ impl HTMLElementMethods for HTMLElement {
// https://html.spec.whatwg.org/multipage/#handler-onfocus // https://html.spec.whatwg.org/multipage/#handler-onfocus
fn GetOnfocus(&self) -> Option<Rc<EventHandlerNonNull>> { fn GetOnfocus(&self) -> Option<Rc<EventHandlerNonNull>> {
if self.is_body_or_frameset() { if self.is_body_or_frameset() {
window_from_node(self).GetOnfocus() let document = document_from_node(self);
if document.has_browsing_context() {
document.window().GetOnfocus()
} else {
None
}
} else { } else {
self.upcast::<EventTarget>().get_event_handler_common("focus") self.upcast::<EventTarget>().get_event_handler_common("focus")
} }
@ -214,7 +243,10 @@ impl HTMLElementMethods for HTMLElement {
// https://html.spec.whatwg.org/multipage/#handler-onfocus // https://html.spec.whatwg.org/multipage/#handler-onfocus
fn SetOnfocus(&self, listener: Option<Rc<EventHandlerNonNull>>) { fn SetOnfocus(&self, listener: Option<Rc<EventHandlerNonNull>>) {
if self.is_body_or_frameset() { if self.is_body_or_frameset() {
window_from_node(self).SetOnfocus(listener) let document = document_from_node(self);
if document.has_browsing_context() {
document.window().SetOnfocus(listener)
}
} else { } else {
self.upcast::<EventTarget>().set_event_handler_common("focus", listener) self.upcast::<EventTarget>().set_event_handler_common("focus", listener)
} }
@ -223,7 +255,12 @@ impl HTMLElementMethods for HTMLElement {
// https://html.spec.whatwg.org/multipage/#handler-onscroll // https://html.spec.whatwg.org/multipage/#handler-onscroll
fn GetOnscroll(&self) -> Option<Rc<EventHandlerNonNull>> { fn GetOnscroll(&self) -> Option<Rc<EventHandlerNonNull>> {
if self.is_body_or_frameset() { if self.is_body_or_frameset() {
window_from_node(self).GetOnscroll() let document = document_from_node(self);
if document.has_browsing_context() {
document.window().GetOnscroll()
} else {
None
}
} else { } else {
self.upcast::<EventTarget>().get_event_handler_common("scroll") self.upcast::<EventTarget>().get_event_handler_common("scroll")
} }
@ -232,7 +269,10 @@ impl HTMLElementMethods for HTMLElement {
// https://html.spec.whatwg.org/multipage/#handler-onscroll // https://html.spec.whatwg.org/multipage/#handler-onscroll
fn SetOnscroll(&self, listener: Option<Rc<EventHandlerNonNull>>) { fn SetOnscroll(&self, listener: Option<Rc<EventHandlerNonNull>>) {
if self.is_body_or_frameset() { if self.is_body_or_frameset() {
window_from_node(self).SetOnscroll(listener) let document = document_from_node(self);
if document.has_browsing_context() {
document.window().SetOnscroll(listener)
}
} else { } else {
self.upcast::<EventTarget>().set_event_handler_common("scroll", listener) self.upcast::<EventTarget>().set_event_handler_common("scroll", listener)
} }

View file

@ -10,7 +10,7 @@ use dom::bindings::js::Root;
use dom::bindings::str::DOMString; use dom::bindings::str::DOMString;
use dom::document::Document; use dom::document::Document;
use dom::htmlelement::HTMLElement; use dom::htmlelement::HTMLElement;
use dom::node::{Node, window_from_node}; use dom::node::{Node, document_from_node};
use html5ever_atoms::LocalName; use html5ever_atoms::LocalName;
#[dom_struct] #[dom_struct]

View file

@ -354,11 +354,19 @@ macro_rules! define_event_handler(
macro_rules! define_window_owned_event_handler( macro_rules! define_window_owned_event_handler(
($handler: ident, $event_type: ident, $getter: ident, $setter: ident) => ( ($handler: ident, $event_type: ident, $getter: ident, $setter: ident) => (
fn $getter(&self) -> Option<::std::rc::Rc<$handler>> { fn $getter(&self) -> Option<::std::rc::Rc<$handler>> {
window_from_node(self).$getter() let document = document_from_node(self);
if document.has_browsing_context() {
document.window().$getter()
} else {
None
}
} }
fn $setter(&self, listener: Option<::std::rc::Rc<$handler>>) { fn $setter(&self, listener: Option<::std::rc::Rc<$handler>>) {
window_from_node(self).$setter(listener) let document = document_from_node(self);
if document.has_browsing_context() {
document.window().$setter(listener)
}
} }
) )
); );

View file

@ -45890,6 +45890,12 @@
"path": "html/semantics/embedded-content/the-img-element/not-rendered-dimension-getter.html", "path": "html/semantics/embedded-content/the-img-element/not-rendered-dimension-getter.html",
"url": "/html/semantics/embedded-content/the-img-element/not-rendered-dimension-getter.html" "url": "/html/semantics/embedded-content/the-img-element/not-rendered-dimension-getter.html"
} }
],
"html/webappapis/scripting/events/body-exposed-window-event-handlers.html": [
{
"path": "html/webappapis/scripting/events/body-exposed-window-event-handlers.html",
"url": "/html/webappapis/scripting/events/body-exposed-window-event-handlers.html"
}
] ]
} }
}, },

View file

@ -0,0 +1,49 @@
<!doctype html>
<meta charset="utf-8">
<title></title>
<body></body>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
var elements = ['body', 'frameset'];
var handlers = [
'load', 'resize', 'blur', 'focus', 'scroll',
'afterprint', 'beforeprint', 'beforeunload', 'hashchange',
'languagechange', 'message', 'offline', 'online', 'pagehide',
'pageshow', 'popstate', 'rejectionhandled', 'storage',
'unhandledrejection', 'unload'];
elements.forEach(function (elementName) {
handlers.forEach(function (eventName) {
var handlerName = "on" + eventName;
test(function() {
var windowHandler = function () { return "Handler attached to the window"; };
window[handlerName] = windowHandler;
var d = (new DOMParser).parseFromString('', 'text/html');
var b = d.createElement(elementName);
assert_equals(b[handlerName], null);
window[handlerName] = null;
}, "Return null when getting the " + eventName + " event handler of a windowless " + elementName);
test(function() {
var windowHandler = function () { return "Handler attached to the window"; };
window[handlerName] = windowHandler;
var d = (new DOMParser).parseFromString('', 'text/html');
var b = d.createElement(elementName);
b[handlerName] = function() { return "Handler attached to windowless element"; };
assert_equals(window[handlerName], windowHandler);
assert_equals(b[handlerName], null);
// Clean up window event handler
window[handlerName] = null;
}, "Ignore setting of " + eventName + " window event handlers on windowless " + elementName);
});
});
</script>