diff options
author | João Oliveira <hello@jxs.pt> | 2015-12-17 16:33:46 +0000 |
---|---|---|
committer | Josh Matthews <josh@joshmatthews.net> | 2016-02-26 10:17:57 -0500 |
commit | b60d6689088ffca2a79467bbc0191961d6549cb7 (patch) | |
tree | 04a7904680475052848f6568171d5a6ea533471f | |
parent | aaad24c5312367921c0d2eab117c3fa587018114 (diff) | |
download | servo-b60d6689088ffca2a79467bbc0191961d6549cb7.tar.gz servo-b60d6689088ffca2a79467bbc0191961d6549cb7.zip |
use return value of invoking event handlers to cancel the event
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> |