mirror of
https://github.com/servo/servo.git
synced 2025-07-03 13:33:39 +01:00
use return value of invoking event handlers to cancel the event
This commit is contained in:
parent
aaad24c531
commit
b60d668908
9 changed files with 141 additions and 58 deletions
|
@ -5,6 +5,7 @@
|
||||||
use dom::bindings::callback::{CallbackContainer, ExceptionHandling, CallbackFunction};
|
use dom::bindings::callback::{CallbackContainer, ExceptionHandling, CallbackFunction};
|
||||||
use dom::bindings::cell::DOMRefCell;
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::ErrorEventBinding::ErrorEventMethods;
|
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::EventHandlerNonNull;
|
||||||
use dom::bindings::codegen::Bindings::EventHandlerBinding::OnErrorEventHandlerNonNull;
|
use dom::bindings::codegen::Bindings::EventHandlerBinding::OnErrorEventHandlerNonNull;
|
||||||
use dom::bindings::codegen::Bindings::EventListenerBinding::EventListener;
|
use dom::bindings::codegen::Bindings::EventListenerBinding::EventListener;
|
||||||
|
@ -188,13 +189,20 @@ impl CompiledEventListener {
|
||||||
let global = object.global();
|
let global = object.global();
|
||||||
let cx = global.r().get_cx();
|
let cx = global.r().get_cx();
|
||||||
let error = RootedValue::new(cx, event.Error(cx));
|
let error = RootedValue::new(cx, event.Error(cx));
|
||||||
let _ = handler.Call_(object,
|
let return_value = handler.Call_(object,
|
||||||
EventOrString::String(event.Message()),
|
EventOrString::String(event.Message()),
|
||||||
Some(event.Filename()),
|
Some(event.Filename()),
|
||||||
Some(event.Lineno()),
|
Some(event.Lineno()),
|
||||||
Some(event.Colno()),
|
Some(event.Colno()),
|
||||||
Some(error.handle()),
|
Some(error.handle()),
|
||||||
exception_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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,13 +211,26 @@ impl CompiledEventListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
CommonEventHandler::EventHandler(ref handler) => {
|
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,
|
pub fn dispatch_event_with_target(&self,
|
||||||
target: &EventTarget,
|
target: &EventTarget,
|
||||||
event: &Event) -> bool {
|
event: &Event) -> bool {
|
||||||
dispatch_event(self, Some(target), event)
|
dispatch_event(self, Some(target), event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
// https://html.spec.whatwg.org/multipage/#dom-click
|
||||||
fn Click(&self) {
|
fn Click(&self) {
|
||||||
if let Some(i) = self.downcast::<HTMLInputElement>() {
|
if let Some(i) = self.downcast::<HTMLInputElement>() {
|
||||||
|
|
|
@ -332,19 +332,22 @@ macro_rules! error_event_handler(
|
||||||
// As more methods get added, just update them here.
|
// As more methods get added, just update them here.
|
||||||
macro_rules! global_event_handlers(
|
macro_rules! global_event_handlers(
|
||||||
() => (
|
() => (
|
||||||
|
event_handler!(blur, GetOnblur, SetOnblur);
|
||||||
event_handler!(load, GetOnload, SetOnload);
|
event_handler!(load, GetOnload, SetOnload);
|
||||||
event_handler!(resize, GetOnresize, SetOnresize);
|
event_handler!(resize, GetOnresize, SetOnresize);
|
||||||
global_event_handlers!(NoOnload);
|
global_event_handlers!(NoOnload);
|
||||||
|
|
||||||
);
|
);
|
||||||
(NoOnload) => (
|
(NoOnload) => (
|
||||||
|
event_handler!(change, GetOnchange, SetOnchange);
|
||||||
event_handler!(click, GetOnclick, SetOnclick);
|
event_handler!(click, GetOnclick, SetOnclick);
|
||||||
|
event_handler!(dblclick, GetOndblclick, SetOndblclick);
|
||||||
error_event_handler!(error, GetOnerror, SetOnerror);
|
error_event_handler!(error, GetOnerror, SetOnerror);
|
||||||
|
event_handler!(input, GetOninput, SetOninput);
|
||||||
event_handler!(keydown, GetOnkeydown, SetOnkeydown);
|
event_handler!(keydown, GetOnkeydown, SetOnkeydown);
|
||||||
event_handler!(keypress, GetOnkeypress, SetOnkeypress);
|
event_handler!(keypress, GetOnkeypress, SetOnkeypress);
|
||||||
event_handler!(keyup, GetOnkeyup, SetOnkeyup);
|
event_handler!(keyup, GetOnkeyup, SetOnkeyup);
|
||||||
event_handler!(input, GetOninput, SetOninput);
|
event_handler!(mouseover, GetOnmouseover, SetOnmouseover);
|
||||||
event_handler!(change, GetOnchange, SetOnchange);
|
|
||||||
event_handler!(reset, GetOnreset, SetOnreset);
|
event_handler!(reset, GetOnreset, SetOnreset);
|
||||||
event_handler!(submit, GetOnsubmit, SetOnsubmit);
|
event_handler!(submit, GetOnsubmit, SetOnsubmit);
|
||||||
event_handler!(toggle, GetOntoggle, SetOntoggle);
|
event_handler!(toggle, GetOntoggle, SetOntoggle);
|
||||||
|
|
|
@ -23,18 +23,22 @@ typedef OnErrorEventHandlerNonNull? OnErrorEventHandler;
|
||||||
|
|
||||||
[NoInterfaceObject]
|
[NoInterfaceObject]
|
||||||
interface GlobalEventHandlers {
|
interface GlobalEventHandlers {
|
||||||
|
attribute EventHandler onblur;
|
||||||
|
attribute EventHandler onchange;
|
||||||
attribute EventHandler onclick;
|
attribute EventHandler onclick;
|
||||||
|
attribute EventHandler ondblclick;
|
||||||
attribute OnErrorEventHandler onerror;
|
attribute OnErrorEventHandler onerror;
|
||||||
attribute EventHandler onload;
|
|
||||||
attribute EventHandler oninput;
|
attribute EventHandler oninput;
|
||||||
attribute EventHandler onkeydown;
|
attribute EventHandler onkeydown;
|
||||||
attribute EventHandler onkeypress;
|
attribute EventHandler onkeypress;
|
||||||
attribute EventHandler onkeyup;
|
attribute EventHandler onkeyup;
|
||||||
attribute EventHandler onchange;
|
attribute EventHandler onload;
|
||||||
|
attribute EventHandler onmouseover;
|
||||||
attribute EventHandler onreset;
|
attribute EventHandler onreset;
|
||||||
|
attribute EventHandler onresize;
|
||||||
attribute EventHandler onsubmit;
|
attribute EventHandler onsubmit;
|
||||||
attribute EventHandler ontoggle;
|
attribute EventHandler ontoggle;
|
||||||
attribute EventHandler onresize;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
[NoInterfaceObject]
|
[NoInterfaceObject]
|
||||||
|
|
|
@ -34512,7 +34512,16 @@
|
||||||
},
|
},
|
||||||
"local_changes": {
|
"local_changes": {
|
||||||
"deleted": [],
|
"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": {}
|
||||||
},
|
},
|
||||||
"reftest_nodes": {
|
"reftest_nodes": {
|
||||||
|
|
|
@ -75,9 +75,6 @@
|
||||||
[Document interface: attribute onautocompleteerror]
|
[Document interface: attribute onautocompleteerror]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Document interface: attribute onblur]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Document interface: attribute oncancel]
|
[Document interface: attribute oncancel]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -96,9 +93,6 @@
|
||||||
[Document interface: attribute oncuechange]
|
[Document interface: attribute oncuechange]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Document interface: attribute ondblclick]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Document interface: attribute ondrag]
|
[Document interface: attribute ondrag]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -162,9 +156,6 @@
|
||||||
[Document interface: attribute onmouseout]
|
[Document interface: attribute onmouseout]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Document interface: attribute onmouseover]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Document interface: attribute onmouseup]
|
[Document interface: attribute onmouseup]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -1611,9 +1602,6 @@
|
||||||
[HTMLElement interface: attribute onautocompleteerror]
|
[HTMLElement interface: attribute onautocompleteerror]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[HTMLElement interface: attribute onblur]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLElement interface: attribute oncancel]
|
[HTMLElement interface: attribute oncancel]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -1632,9 +1620,6 @@
|
||||||
[HTMLElement interface: attribute oncuechange]
|
[HTMLElement interface: attribute oncuechange]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[HTMLElement interface: attribute ondblclick]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLElement interface: attribute ondrag]
|
[HTMLElement interface: attribute ondrag]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -1698,9 +1683,6 @@
|
||||||
[HTMLElement interface: attribute onmouseout]
|
[HTMLElement interface: attribute onmouseout]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[HTMLElement interface: attribute onmouseover]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLElement interface: attribute onmouseup]
|
[HTMLElement interface: attribute onmouseup]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -1839,9 +1821,6 @@
|
||||||
[HTMLElement interface: document.createElement("noscript") must inherit property "onautocompleteerror" with the proper type (34)]
|
[HTMLElement interface: document.createElement("noscript") must inherit property "onautocompleteerror" with the proper type (34)]
|
||||||
expected: FAIL
|
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)]
|
[HTMLElement interface: document.createElement("noscript") must inherit property "oncancel" with the proper type (36)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -1860,9 +1839,6 @@
|
||||||
[HTMLElement interface: document.createElement("noscript") must inherit property "oncuechange" with the proper type (43)]
|
[HTMLElement interface: document.createElement("noscript") must inherit property "oncuechange" with the proper type (43)]
|
||||||
expected: FAIL
|
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)]
|
[HTMLElement interface: document.createElement("noscript") must inherit property "ondrag" with the proper type (45)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -1926,9 +1902,6 @@
|
||||||
[HTMLElement interface: document.createElement("noscript") must inherit property "onmouseout" with the proper type (71)]
|
[HTMLElement interface: document.createElement("noscript") must inherit property "onmouseout" with the proper type (71)]
|
||||||
expected: FAIL
|
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)]
|
[HTMLElement interface: document.createElement("noscript") must inherit property "onmouseup" with the proper type (73)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -8610,9 +8583,6 @@
|
||||||
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "onautocompleteerror" with the proper type (96)]
|
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "onautocompleteerror" with the proper type (96)]
|
||||||
expected: FAIL
|
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)]
|
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "oncancel" with the proper type (98)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -8631,9 +8601,6 @@
|
||||||
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "oncuechange" with the proper type (105)]
|
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "oncuechange" with the proper type (105)]
|
||||||
expected: FAIL
|
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)]
|
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "ondrag" with the proper type (107)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -8697,9 +8664,6 @@
|
||||||
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "onmouseout" with the proper type (133)]
|
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "onmouseout" with the proper type (133)]
|
||||||
expected: FAIL
|
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)]
|
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "onmouseup" with the proper type (135)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
[event-handler-attributes-body-window.html]
|
[event-handler-attributes-body-window.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
[blur]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[error]
|
[error]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[event-handler-processing-algorithm.html]
|
||||||
|
type: testharness
|
||||||
|
[beforeunload listener returning null cancels event]
|
||||||
|
expected: FAIL
|
|
@ -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>
|
Loading…
Add table
Add a link
Reference in a new issue