aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoão Oliveira <hello@jxs.pt>2015-12-17 16:33:46 +0000
committerJosh Matthews <josh@joshmatthews.net>2016-02-26 10:17:57 -0500
commitb60d6689088ffca2a79467bbc0191961d6549cb7 (patch)
tree04a7904680475052848f6568171d5a6ea533471f
parentaaad24c5312367921c0d2eab117c3fa587018114 (diff)
downloadservo-b60d6689088ffca2a79467bbc0191961d6549cb7.tar.gz
servo-b60d6689088ffca2a79467bbc0191961d6549cb7.zip
use return value of invoking event handlers to cancel the event
-rw-r--r--components/script/dom/eventtarget.rs47
-rw-r--r--components/script/dom/htmlelement.rs18
-rw-r--r--components/script/dom/macros.rs7
-rw-r--r--components/script/dom/webidls/EventHandler.webidl10
-rw-r--r--tests/wpt/metadata/MANIFEST.json11
-rw-r--r--tests/wpt/metadata/html/dom/interfaces.html.ini36
-rw-r--r--tests/wpt/metadata/html/webappapis/scripting/events/event-handler-attributes-body-window.html.ini3
-rw-r--r--tests/wpt/metadata/html/webappapis/scripting/events/event-handler-processing-algorithm.html.ini4
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/events/event-handler-processing-algorithm.html63
9 files changed, 141 insertions, 58 deletions
diff --git a/components/script/dom/eventtarget.rs b/components/script/dom/eventtarget.rs
index 36aae8800da..aa49d9a110f 100644
--- a/components/script/dom/eventtarget.rs
+++ b/components/script/dom/eventtarget.rs
@@ -5,6 +5,7 @@
use dom::bindings::callback::{CallbackContainer, ExceptionHandling, CallbackFunction};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::ErrorEventBinding::ErrorEventMethods;
+use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::Bindings::EventHandlerBinding::OnErrorEventHandlerNonNull;
use dom::bindings::codegen::Bindings::EventListenerBinding::EventListener;
@@ -188,13 +189,20 @@ impl CompiledEventListener {
let global = object.global();
let cx = global.r().get_cx();
let error = RootedValue::new(cx, event.Error(cx));
- let _ = handler.Call_(object,
- EventOrString::String(event.Message()),
- Some(event.Filename()),
- Some(event.Lineno()),
- Some(event.Colno()),
- Some(error.handle()),
- exception_handle);
+ let return_value = handler.Call_(object,
+ EventOrString::String(event.Message()),
+ Some(event.Filename()),
+ Some(event.Lineno()),
+ Some(event.Colno()),
+ Some(error.handle()),
+ exception_handle);
+ // Step 4
+ if let Ok(return_value) = return_value {
+ let return_value = RootedValue::new(cx, return_value);
+ if return_value.handle().is_boolean() && return_value.handle().to_boolean() == true {
+ event.upcast::<Event>().PreventDefault();
+ }
+ }
return;
}
@@ -203,13 +211,26 @@ impl CompiledEventListener {
}
CommonEventHandler::EventHandler(ref handler) => {
- let _ = handler.Call_(object, event, exception_handle);
+ if let Ok(value) = handler.Call_(object, event, exception_handle) {
+ let global = object.global();
+ let cx = global.r().get_cx();
+ let value = RootedValue::new(cx, value);
+ let value = value.handle();
+
+ //Step 4
+ let should_cancel = match event.type_() {
+ atom!("mouseover") => value.is_boolean() && value.to_boolean() == true,
+ atom!("beforeunload") => value.is_null(),
+ _ => value.is_boolean() && value.to_boolean() == false
+ };
+ if should_cancel {
+ event.PreventDefault();
+ }
+ }
}
}
- },
+ }
}
-
- // TODO(#8490): step 4 (cancel event based on return value)
}
}
@@ -294,8 +315,8 @@ impl EventTarget {
}
pub fn dispatch_event_with_target(&self,
- target: &EventTarget,
- event: &Event) -> bool {
+ target: &EventTarget,
+ event: &Event) -> bool {
dispatch_event(self, Some(target), event)
}
diff --git a/components/script/dom/htmlelement.rs b/components/script/dom/htmlelement.rs
index 70e370a8c8a..7c37c3ca9e2 100644
--- a/components/script/dom/htmlelement.rs
+++ b/components/script/dom/htmlelement.rs
@@ -180,6 +180,24 @@ impl HTMLElementMethods for HTMLElement {
}
}
+ // https://html.spec.whatwg.org/multipage/#handler-onblur
+ fn GetOnblur(&self) -> Option<Rc<EventHandlerNonNull>> {
+ if self.is_body_or_frameset() {
+ window_from_node(self).GetOnblur()
+ } else {
+ self.upcast::<EventTarget>().get_event_handler_common("blur")
+ }
+ }
+
+ // https://html.spec.whatwg.org/multipage/#handler-onblur
+ fn SetOnblur(&self, listener: Option<Rc<EventHandlerNonNull>>) {
+ if self.is_body_or_frameset() {
+ window_from_node(self).SetOnblur(listener)
+ } else {
+ self.upcast::<EventTarget>().set_event_handler_common("blur", listener)
+ }
+ }
+
// https://html.spec.whatwg.org/multipage/#dom-click
fn Click(&self) {
if let Some(i) = self.downcast::<HTMLInputElement>() {
diff --git a/components/script/dom/macros.rs b/components/script/dom/macros.rs
index fb548266263..57966e37ae6 100644
--- a/components/script/dom/macros.rs
+++ b/components/script/dom/macros.rs
@@ -332,19 +332,22 @@ macro_rules! error_event_handler(
// As more methods get added, just update them here.
macro_rules! global_event_handlers(
() => (
+ event_handler!(blur, GetOnblur, SetOnblur);
event_handler!(load, GetOnload, SetOnload);
event_handler!(resize, GetOnresize, SetOnresize);
global_event_handlers!(NoOnload);
);
(NoOnload) => (
+ event_handler!(change, GetOnchange, SetOnchange);
event_handler!(click, GetOnclick, SetOnclick);
+ event_handler!(dblclick, GetOndblclick, SetOndblclick);
error_event_handler!(error, GetOnerror, SetOnerror);
+ event_handler!(input, GetOninput, SetOninput);
event_handler!(keydown, GetOnkeydown, SetOnkeydown);
event_handler!(keypress, GetOnkeypress, SetOnkeypress);
event_handler!(keyup, GetOnkeyup, SetOnkeyup);
- event_handler!(input, GetOninput, SetOninput);
- event_handler!(change, GetOnchange, SetOnchange);
+ event_handler!(mouseover, GetOnmouseover, SetOnmouseover);
event_handler!(reset, GetOnreset, SetOnreset);
event_handler!(submit, GetOnsubmit, SetOnsubmit);
event_handler!(toggle, GetOntoggle, SetOntoggle);
diff --git a/components/script/dom/webidls/EventHandler.webidl b/components/script/dom/webidls/EventHandler.webidl
index 9c822ae9522..318b81403c4 100644
--- a/components/script/dom/webidls/EventHandler.webidl
+++ b/components/script/dom/webidls/EventHandler.webidl
@@ -23,18 +23,22 @@ typedef OnErrorEventHandlerNonNull? OnErrorEventHandler;
[NoInterfaceObject]
interface GlobalEventHandlers {
+ attribute EventHandler onblur;
+ attribute EventHandler onchange;
attribute EventHandler onclick;
+ attribute EventHandler ondblclick;
attribute OnErrorEventHandler onerror;
- attribute EventHandler onload;
attribute EventHandler oninput;
attribute EventHandler onkeydown;
attribute EventHandler onkeypress;
attribute EventHandler onkeyup;
- attribute EventHandler onchange;
+ attribute EventHandler onload;
+ attribute EventHandler onmouseover;
attribute EventHandler onreset;
+ attribute EventHandler onresize;
attribute EventHandler onsubmit;
attribute EventHandler ontoggle;
- attribute EventHandler onresize;
+
};
[NoInterfaceObject]
diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json
index ec2048c4bfd..1085d8668a7 100644
--- a/tests/wpt/metadata/MANIFEST.json
+++ b/tests/wpt/metadata/MANIFEST.json
@@ -34512,7 +34512,16 @@
},
"local_changes": {
"deleted": [],
- "items": {},
+ "items": {
+ "testharness": {
+ "html/webappapis/scripting/events/event-handler-processing-algorithm.html": [
+ {
+ "path": "html/webappapis/scripting/events/event-handler-processing-algorithm.html",
+ "url": "/html/webappapis/scripting/events/event-handler-processing-algorithm.html"
+ }
+ ]
+ }
+ },
"reftest_nodes": {}
},
"reftest_nodes": {
diff --git a/tests/wpt/metadata/html/dom/interfaces.html.ini b/tests/wpt/metadata/html/dom/interfaces.html.ini
index 784d086c1a2..8aae22f264f 100644
--- a/tests/wpt/metadata/html/dom/interfaces.html.ini
+++ b/tests/wpt/metadata/html/dom/interfaces.html.ini
@@ -75,9 +75,6 @@
[Document interface: attribute onautocompleteerror]
expected: FAIL
- [Document interface: attribute onblur]
- expected: FAIL
-
[Document interface: attribute oncancel]
expected: FAIL
@@ -96,9 +93,6 @@
[Document interface: attribute oncuechange]
expected: FAIL
- [Document interface: attribute ondblclick]
- expected: FAIL
-
[Document interface: attribute ondrag]
expected: FAIL
@@ -162,9 +156,6 @@
[Document interface: attribute onmouseout]
expected: FAIL
- [Document interface: attribute onmouseover]
- expected: FAIL
-
[Document interface: attribute onmouseup]
expected: FAIL
@@ -1611,9 +1602,6 @@
[HTMLElement interface: attribute onautocompleteerror]
expected: FAIL
- [HTMLElement interface: attribute onblur]
- expected: FAIL
-
[HTMLElement interface: attribute oncancel]
expected: FAIL
@@ -1632,9 +1620,6 @@
[HTMLElement interface: attribute oncuechange]
expected: FAIL
- [HTMLElement interface: attribute ondblclick]
- expected: FAIL
-
[HTMLElement interface: attribute ondrag]
expected: FAIL
@@ -1698,9 +1683,6 @@
[HTMLElement interface: attribute onmouseout]
expected: FAIL
- [HTMLElement interface: attribute onmouseover]
- expected: FAIL
-
[HTMLElement interface: attribute onmouseup]
expected: FAIL
@@ -1839,9 +1821,6 @@
[HTMLElement interface: document.createElement("noscript") must inherit property "onautocompleteerror" with the proper type (34)]
expected: FAIL
- [HTMLElement interface: document.createElement("noscript") must inherit property "onblur" with the proper type (35)]
- expected: FAIL
-
[HTMLElement interface: document.createElement("noscript") must inherit property "oncancel" with the proper type (36)]
expected: FAIL
@@ -1860,9 +1839,6 @@
[HTMLElement interface: document.createElement("noscript") must inherit property "oncuechange" with the proper type (43)]
expected: FAIL
- [HTMLElement interface: document.createElement("noscript") must inherit property "ondblclick" with the proper type (44)]
- expected: FAIL
-
[HTMLElement interface: document.createElement("noscript") must inherit property "ondrag" with the proper type (45)]
expected: FAIL
@@ -1926,9 +1902,6 @@
[HTMLElement interface: document.createElement("noscript") must inherit property "onmouseout" with the proper type (71)]
expected: FAIL
- [HTMLElement interface: document.createElement("noscript") must inherit property "onmouseover" with the proper type (72)]
- expected: FAIL
-
[HTMLElement interface: document.createElement("noscript") must inherit property "onmouseup" with the proper type (73)]
expected: FAIL
@@ -8610,9 +8583,6 @@
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "onautocompleteerror" with the proper type (96)]
expected: FAIL
- [Document interface: document.implementation.createDocument(null, "", null) must inherit property "onblur" with the proper type (97)]
- expected: FAIL
-
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "oncancel" with the proper type (98)]
expected: FAIL
@@ -8631,9 +8601,6 @@
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "oncuechange" with the proper type (105)]
expected: FAIL
- [Document interface: document.implementation.createDocument(null, "", null) must inherit property "ondblclick" with the proper type (106)]
- expected: FAIL
-
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "ondrag" with the proper type (107)]
expected: FAIL
@@ -8697,9 +8664,6 @@
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "onmouseout" with the proper type (133)]
expected: FAIL
- [Document interface: document.implementation.createDocument(null, "", null) must inherit property "onmouseover" with the proper type (134)]
- expected: FAIL
-
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "onmouseup" with the proper type (135)]
expected: FAIL
diff --git a/tests/wpt/metadata/html/webappapis/scripting/events/event-handler-attributes-body-window.html.ini b/tests/wpt/metadata/html/webappapis/scripting/events/event-handler-attributes-body-window.html.ini
index a48897fc852..d297e0c7497 100644
--- a/tests/wpt/metadata/html/webappapis/scripting/events/event-handler-attributes-body-window.html.ini
+++ b/tests/wpt/metadata/html/webappapis/scripting/events/event-handler-attributes-body-window.html.ini
@@ -1,8 +1,5 @@
[event-handler-attributes-body-window.html]
type: testharness
- [blur]
- expected: FAIL
-
[error]
expected: FAIL
diff --git a/tests/wpt/metadata/html/webappapis/scripting/events/event-handler-processing-algorithm.html.ini b/tests/wpt/metadata/html/webappapis/scripting/events/event-handler-processing-algorithm.html.ini
new file mode 100644
index 00000000000..5a1fe9cac37
--- /dev/null
+++ b/tests/wpt/metadata/html/webappapis/scripting/events/event-handler-processing-algorithm.html.ini
@@ -0,0 +1,4 @@
+[event-handler-processing-algorithm.html]
+ type: testharness
+ [beforeunload listener returning null cancels event]
+ expected: FAIL
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/events/event-handler-processing-algorithm.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/events/event-handler-processing-algorithm.html
new file mode 100644
index 00000000000..f8c6e5ef03b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/events/event-handler-processing-algorithm.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<title>Event handlers processing algorithm</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script
+ <body>
+ <div id="foo" style="width: 100px; height: 100px; background-color: black"></div>
+ <script>
+ async_test(function(t) {
+ var ev = new Event('mouseover', {cancelable: true});
+ document.getElementById("foo").onmouseover = t.step_func(function() { return true });
+ document.getElementById("foo").dispatchEvent(ev);
+ assert_equals(ev.defaultPrevented, true)
+ t.done();
+ }, "mouseover listener returning true cancels event");
+
+ async_test(function(t) {
+ var ev = new Event('mouseover', {cancelable: true});
+ document.getElementById("foo").onmouseover = t.step_func(function() { return false; });
+ document.getElementById("foo").dispatchEvent(ev);
+ assert_equals(ev.defaultPrevented, false);
+ t.done();
+ }, "mouseover listener returning false doesn't cancel event");
+
+ async_test(function(t) {
+ var ev = new Event('beforeunload', {cancelable: true});
+ window.onbeforeunload = t.step_func(function() {return null});
+ window.dispatchEvent(ev);
+ assert_equals(ev.defaultPrevented, true);
+ t.done();
+ }, "beforeunload listener returning null cancels event");
+
+ async_test(function(t) {
+ var ev = new Event('beforeunload', {cancelable: true});
+ window.onbeforeunload = t.step_func(function() {return true});
+ window.dispatchEvent(ev);
+ assert_equals(ev.defaultPrevented, false);
+ t.done();
+ }, "beforeunload listener returning non-null doesn't cancel event");
+
+ async_test(function(t) {
+ var ev = new Event("click", {cancelable: true});
+ document.getElementById("foo").onclick = t.step_func(function() { return false; });
+ document.getElementById("foo").dispatchEvent(ev);
+ assert_equals(ev.defaultPrevented, true);
+ t.done();
+ }, "click listener returning false cancels event");
+
+ async_test(function(t) {
+ var ev = new Event("blur", {cancelable: true});
+ document.getElementById("foo").onblur = t.step_func(function() { return false; });
+ document.getElementById("foo").dispatchEvent(ev);
+ assert_equals(ev.defaultPrevented, true);
+ t.done();
+ }, "blur listener returning false cancels event");
+
+ async_test(function(t) {
+ var ev = new Event("dblclick", {cancelable: true});
+ document.getElementById("foo").ondblclick = t.step_func(function() { return false; });
+ document.getElementById("foo").dispatchEvent(ev);
+ assert_equals(ev.defaultPrevented, true);
+ t.done();
+ }, "dblclick listener returning false cancels event");
+</script>