Skip to content

Commit

Permalink
use return value of invoking event handlers to cancel the event
Browse files Browse the repository at this point in the history
  • Loading branch information
jxs committed Dec 17, 2015
1 parent c6ae32a commit f6dd45d
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 12 deletions.
47 changes: 36 additions & 11 deletions components/script/dom/eventtarget.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -122,17 +123,22 @@ impl EventListenerType {
EventListenerType::Inline(ref handler) => {
match *handler {
CommonEventHandler::ErrorEventHandler(ref handler) => {
if let Some(event) = event.downcast::<ErrorEvent>() {
if let Some(error_event) = event.downcast::<ErrorEvent>() {
let global = global_root_from_reflector(object);
let cx = global.r().get_cx();
let error = RootedValue::new(cx, event.Error(cx));
let _ = handler.Call_(object,
EventOrString::eString(event.Message()),
Some(event.Filename()),
Some(event.Lineno()),
Some(event.Colno()),
Some(error.handle()),
exception_handle);
let error = RootedValue::new(cx, error_event.Error(cx));
let return_value = RootedValue::new(cx, handler.Call_(object,
EventOrString::eString(error_event.Message()),
Some(error_event.Filename()),
Some(error_event.Lineno()),
Some(error_event.Colno()),
Some(error.handle()),
exception_handle));
if let value = Ok(return_value) {

}&& return_value.unwrap().to_boolean() == true {
event.PreventDefault();
}
return;
}

Expand All @@ -141,10 +147,29 @@ impl EventListenerType {
}

CommonEventHandler::EventHandler(ref handler) => {
let _ = handler.Call_(object, event, exception_handle);
let return_value = handler.Call_(object, event, exception_handle);

//Step 4
match event.type_() {
atom!("mouseover") => {
if return_value.is_ok() && return_value.unwrap().to_boolean() == true {
event.PreventDefault();
}
},
atom!("beforeunload") => {
if let value = Ok(return_value) && value.is_null() {
event.PreventDefault();
}
},
_ => {
if return_value.is_ok() && return_value.unwrap().to_boolean() == false {
event.PreventDefault();
}
}
}
}
}
},
}
}

// TODO(#8490): step 4 (cancel event based on return value)
Expand Down
11 changes: 10 additions & 1 deletion tests/wpt/metadata/MANIFEST.json
Expand Up @@ -30149,7 +30149,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": {
Expand Down
@@ -0,0 +1,43 @@
<!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>
test(function(){
document.getElementById("foo").onmouseover = function() { return true; };
document.getElementById("foo").addEventListener("mouseover", function(ev) { assert_equals(ev.defaultPrevented, true) }, false);
document.getElementById("foo").dispatchEvent(new Event('mouseover', {cancelable: true}));
}, "test Mouseover listener returning true cancels event");
test(function(){
document.getElementById("foo").onmouseover = function() { return true; };
document.getElementById("foo").addEventListener("mouseover", function(ev) { assert_equals(ev.defaultPrevented, false) }, false);
document.getElementById("foo").dispatchEvent(new Event('mouseover', {cancelable: true}));
}, "test Mouseover listener returning false doesn't cancel event");
test(function(){
window.onbeforeunload = function() {return null};
window.addEventListener("beforeunload", function(ev) { assert_equals(ev.defaultPrevented, true)});
window.dispatchEvent(new Event('beforeunload', {cancelable: true}));
}, "test beforeunload listener returning null cancels event");
test(function(){
window.onbeforeunload = function() {return true};
window.addEventListener("beforeunload", function(ev) { assert_equals(ev.defaultPrevented, false)});
window.dispatchEvent(new Event('beforeunload', {cancelable: true}));
}, "test beforeunload listener returning non null doesn't cancel event");
test(function(){
document.getElementById("foo").onclick = function() { return false; };
document.getElementById("foo").addEventListener("click", function(ev) { assert_equals(ev.defaultPrevented, true) }, false);
document.getElementById("foo").dispatchEvent(new Event("click", {cancelable: true}));
}, "click listener returning false cancels event");
test(function(){
document.getElementById("foo").onblur = function() { return false; };
document.getElementById("foo").addEventListener("blur", function(ev) { assert_equals(ev.defaultPrevented, true) }, false);
document.getElementById("foo").dispatchEvent(new Event("blur", {cancelable: true}));
}, "blur listener returning false cancels event");
test(function(){
document.getElementById("foo").ondblkclick = function() { return false; };
document.getElementById("foo").addEventListener("dblclick", function(ev) { assert_equals(ev.defaultPrevented, true) }, false);
document.getElementById("foo").dispatchEvent(new Event("dblclick", {cancelable: true}));
}, "dblclick listener returning false cancels event");
</script>

0 comments on commit f6dd45d

Please sign in to comment.