From 78aa01fa2095c67c59a938772ca9e167f77615e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20C=C3=A1ceres?= Date: Tue, 26 Feb 2019 16:38:01 +1100 Subject: [PATCH 1/3] Events from GlobalEventHandlers must dispatch on disabled form elements --- .../Event-dispatch-on-disabled-elements.html | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/dom/events/Event-dispatch-on-disabled-elements.html b/dom/events/Event-dispatch-on-disabled-elements.html index 688524bd23879f..777992cd8eefae 100644 --- a/dom/events/Event-dispatch-on-disabled-elements.html +++ b/dom/events/Event-dispatch-on-disabled-elements.html @@ -98,6 +98,123 @@ } }, "Calling click() on disabled elements must not dispatch events."); +promise_test(async () => { + // Based on GlobalEventHandlers and mixins + // https://html.spec.whatwg.org/multipage/webappapis.html#globaleventhandlers + // https://drafts.csswg.org/css-transitions/#interface-globaleventhandlers-idl + const globalEventHandlers = new Map([ + [ + DragEvent, + [ + "drag", + "dragend", + "dragenter", + "dragexit", + "dragleave", + "dragover", + "dragstart", + "drop", + ], + ], + [ + Event, + [ + "abort", + "cancel", + "canplay", + "canplaythrough", + "change", + "close", + "cuechange", + "durationchange", + "emptied", + "ended", + "input", + "invalid", + "loadeddata", + "loadedmetadata", + "loadend", + "pause", + "play", + "playing", + "progress", + "ratechange", + "reset", + "securitypolicyviolation", + "seeked", + "seeking", + "select", + "stalled", + "submit", + "suspend", + "timeupdate", + "toggle", + "volumechange", + "waiting", + ], + ], + [FormDataEvent, ["formdata"]], + [KeyboardEvent, ["keydown", "keypress", "keyup"]], + [ + MouseEvent, + [ + "auxclick", + "contextmenu", + "dblclick", + "mousedown", + "mouseenter", + "mouseleave", + "mousemove", + "mouseout", + "mouseover", + "mouseup", + ], + ], + [ProgressEvent, ["loadend", "loadstart"]], + [ + TransitionEvent, + ["transitionstart", "transitionend", "transitionrun", "transitioncancel"], + ], + [WheelEvent, ["wheel"]], + ]); + // Using the appropriate interface, dispatch an event of each type. + for (const localName of formElements) { + const elem = document.createElement(localName); + elem.disabled = true; + document.body.appendChild(elem); + // Each interface. + for (const interfaceToTest of globalEventHandlers.keys()) { + // Each event type. + for (const type of globalEventHandlers.get(interfaceToTest)) { + let listenerFired = false; + elem.addEventListener(type, function f() { + listenerFired = true; + elem.removeEventListener(type, f); + }); + let handlerFired = false; + const handlerAttrName = `on${type}`; + elem[handlerAttrName] = () => { + handlerFired = true; + elem[handlerAttrName] = undefined; + }; + elem.dispatchEvent(new interfaceToTest(type)); + + // Generate expectation message. + const { name: constructorName } = Object.getPrototypeOf( + elem + ).constructor; + const msg = `on disabled ${constructorName} to receive ${ + interfaceToTest.name + } of type "${type}".`; + //See how it went... + assert_true(listenerFired, `Expected listener ${msg}`); + assert_true(handlerFired, `Expected handler ${msg}`); + } + } + elem.remove(); + } +}, "Events from GlobalEventHandlers must dispatch on disabled form elements."); + promise_test(async () => { for (const localName of formElements) { const elem = document.createElement(localName); From 7f20369cf91fa537367b36642a5aebb93df6296b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20C=C3=A1ceres?= Date: Tue, 26 Feb 2019 23:52:26 +1100 Subject: [PATCH 2/3] Refactored, bug fixes --- .../Event-dispatch-on-disabled-elements.html | 411 +++++++++++++----- 1 file changed, 305 insertions(+), 106 deletions(-) diff --git a/dom/events/Event-dispatch-on-disabled-elements.html b/dom/events/Event-dispatch-on-disabled-elements.html index 777992cd8eefae..a40fb952fbc15e 100644 --- a/dom/events/Event-dispatch-on-disabled-elements.html +++ b/dom/events/Event-dispatch-on-disabled-elements.html @@ -101,119 +101,318 @@ promise_test(async () => { // Based on GlobalEventHandlers and mixins // https://html.spec.whatwg.org/multipage/webappapis.html#globaleventhandlers - // https://drafts.csswg.org/css-transitions/#interface-globaleventhandlers-idl - const globalEventHandlers = new Map([ - [ - DragEvent, - [ - "drag", - "dragend", - "dragenter", - "dragexit", - "dragleave", - "dragover", - "dragstart", - "drop", - ], - ], - [ - Event, - [ - "abort", - "cancel", - "canplay", - "canplaythrough", - "change", - "close", - "cuechange", - "durationchange", - "emptied", - "ended", - "input", - "invalid", - "loadeddata", - "loadedmetadata", - "loadend", - "pause", - "play", - "playing", - "progress", - "ratechange", - "reset", - "securitypolicyviolation", - "seeked", - "seeking", - "select", - "stalled", - "submit", - "suspend", - "timeupdate", - "toggle", - "volumechange", - "waiting", - ], - ], - [FormDataEvent, ["formdata"]], - [KeyboardEvent, ["keydown", "keypress", "keyup"]], - [ - MouseEvent, - [ - "auxclick", - "contextmenu", - "dblclick", - "mousedown", - "mouseenter", - "mouseleave", - "mousemove", - "mouseout", - "mouseover", - "mouseup", - ], - ], - [ProgressEvent, ["loadend", "loadstart"]], - [ - TransitionEvent, - ["transitionstart", "transitionend", "transitionrun", "transitioncancel"], - ], - [WheelEvent, ["wheel"]], - ]); - // Using the appropriate interface, dispatch an event of each type. + const eventTypes = [ + "drag", + "dragend", + "dragenter", + "dragexit", + "dragleave", + "dragover", + "dragstart", + "drop", + ] for (const localName of formElements) { const elem = document.createElement(localName); elem.disabled = true; document.body.appendChild(elem); - // Each interface. - for (const interfaceToTest of globalEventHandlers.keys()) { - // Each event type. - for (const type of globalEventHandlers.get(interfaceToTest)) { - let listenerFired = false; - elem.addEventListener(type, function f() { - listenerFired = true; - elem.removeEventListener(type, f); - }); - let handlerFired = false; - const handlerAttrName = `on${type}`; - elem[handlerAttrName] = () => { - handlerFired = true; - elem[handlerAttrName] = undefined; - }; - elem.dispatchEvent(new interfaceToTest(type)); - - // Generate expectation message. - const { name: constructorName } = Object.getPrototypeOf( - elem - ).constructor; - const msg = `on disabled ${constructorName} to receive ${ - interfaceToTest.name - } of type "${type}".`; - //See how it went... - assert_true(listenerFired, `Expected listener ${msg}`); - assert_true(handlerFired, `Expected handler ${msg}`); - } + // Each event type. + for (const type of eventTypes) { + let listenerFired = false; + elem.addEventListener(type, function f() { + listenerFired = true; + elem.removeEventListener(type, f); + }); + let handlerFired = false; + const handlerAttrName = `on${type}`; + elem[handlerAttrName] = () => { + handlerFired = true; + elem[handlerAttrName] = undefined; + }; + elem.dispatchEvent(new DragEvent(type)); + + // Generate expectation message. + const { name: constructorName } = Object.getPrototypeOf( + elem + ).constructor; + const msg = `on disabled ${constructorName} to receive ${ + DragEvent.name + } of type "${type}".`; + //See how it went... + assert_true(listenerFired, `Expected listener ${msg}`); + assert_true(handlerFired, `Expected handler ${msg}`); + } + elem.remove(); + } +}, "Events from DragEvent must dispatch on disabled form elements."); + +promise_test(async () => { + // Based on GlobalEventHandlers and mixins + // https://html.spec.whatwg.org/multipage/webappapis.html#globaleventhandlers + const eventTypes = [ + "abort", + "cancel", + "canplay", + "canplaythrough", + "change", + "close", + "cuechange", + "durationchange", + "emptied", + "ended", + "input", + "invalid", + "loadeddata", + "loadedmetadata", + "loadend", + "pause", + "play", + "playing", + "progress", + "ratechange", + "reset", + "securitypolicyviolation", + "seeked", + "seeking", + "select", + "stalled", + "submit", + "suspend", + "timeupdate", + "toggle", + "volumechange", + "waiting", + ] + for (const localName of formElements) { + const elem = document.createElement(localName); + elem.disabled = true; + document.body.appendChild(elem); + // Each event type. + for (const type of eventTypes) { + let listenerFired = false; + elem.addEventListener(type, function f() { + listenerFired = true; + elem.removeEventListener(type, f); + }); + let handlerFired = false; + const handlerAttrName = `on${type}`; + elem[handlerAttrName] = () => { + handlerFired = true; + elem[handlerAttrName] = undefined; + }; + elem.dispatchEvent(new CustomEvent(type)); + + // Generate expectation message. + const { name: constructorName } = Object.getPrototypeOf( + elem + ).constructor; + const msg = `on disabled ${constructorName} to receive Event of type "${type}".`; + //See how it went... + assert_true(listenerFired, `Expected listener ${msg}`); + assert_true(handlerFired, `Expected handler ${msg}`); + } + elem.remove(); + } +}, "Events from Event interface must dispatch on disabled form elements."); + +promise_test(async () => { + // Based on GlobalEventHandlers and mixins + // https://html.spec.whatwg.org/multipage/webappapis.html#globaleventhandlers + const eventTypes = [ + "formdata" + ] + for (const localName of formElements) { + const elem = document.createElement(localName); + elem.disabled = true; + document.body.appendChild(elem); + // Each event type. + for (const type of eventTypes) { + let listenerFired = false; + elem.addEventListener(type, function f() { + listenerFired = true; + elem.removeEventListener(type, f); + }); + let handlerFired = false; + const handlerAttrName = `on${type}`; + elem[handlerAttrName] = () => { + handlerFired = true; + elem[handlerAttrName] = undefined; + }; + elem.dispatchEvent(new FormDataEvent(type, {formData: new FormData()})); + + // Generate expectation message. + const { name: constructorName } = Object.getPrototypeOf( + elem + ).constructor; + const msg = `on disabled ${constructorName} to receive FormDataEvent of type "${type}".`; + //See how it went... + assert_true(listenerFired, `Expected listener ${msg}`); + assert_true(handlerFired, `Expected handler ${msg}`); + } + elem.remove(); + } +}, "Events from FormDataEvent must dispatch on disabled form elements."); + +promise_test(async () => { + // Based on GlobalEventHandlers and mixins + // https://html.spec.whatwg.org/multipage/webappapis.html#globaleventhandlers + const eventTypes = [ + "keydown", "keypress", "keyup" + ] + for (const localName of formElements) { + const elem = document.createElement(localName); + elem.disabled = true; + document.body.appendChild(elem); + // Each event type. + for (const type of eventTypes) { + let listenerFired = false; + elem.addEventListener(type, function f() { + listenerFired = true; + elem.removeEventListener(type, f); + }); + let handlerFired = false; + const handlerAttrName = `on${type}`; + elem[handlerAttrName] = () => { + handlerFired = true; + elem[handlerAttrName] = undefined; + }; + elem.dispatchEvent(new KeyboardEvent(type)); + + // Generate expectation message. + const { name: constructorName } = Object.getPrototypeOf( + elem + ).constructor; + const msg = `on disabled ${constructorName} to receive KeyboardEvent of type "${type}".`; + //See how it went... + assert_true(listenerFired, `Expected listener ${msg}`); + assert_true(handlerFired, `Expected handler ${msg}`); + } + elem.remove(); + } +}, "Events from KeyboardEvent must dispatch on disabled form elements."); + + +promise_test(async () => { + // Based on GlobalEventHandlers and mixins + // https://html.spec.whatwg.org/multipage/webappapis.html#globaleventhandlers + const eventTypes = [ + "loadend", "loadstart" + ] + for (const localName of formElements) { + const elem = document.createElement(localName); + elem.disabled = true; + document.body.appendChild(elem); + // Each event type. + for (const type of eventTypes) { + let listenerFired = false; + elem.addEventListener(type, function f() { + listenerFired = true; + elem.removeEventListener(type, f); + }); + let handlerFired = false; + const handlerAttrName = `on${type}`; + elem[handlerAttrName] = () => { + handlerFired = true; + elem[handlerAttrName] = undefined; + }; + elem.dispatchEvent(new ProgressEvent(type)); + + // Generate expectation message. + const { name: constructorName } = Object.getPrototypeOf( + elem + ).constructor; + const msg = `on disabled ${constructorName} to receive ProgressEvent of type "${type}".`; + //See how it went... + assert_true(listenerFired, `Expected listener ${msg}`); + assert_true(handlerFired, `Expected handler ${msg}`); + } + elem.remove(); + } +}, "Events from ProgressEvent must dispatch on disabled form elements."); + +promise_test(async () => { + // Based on GlobalEventHandlers and mixins + // https://html.spec.whatwg.org/multipage/webappapis.html#globaleventhandlers + const eventTypes = [ + "wheel", + ] + for (const localName of formElements) { + const elem = document.createElement(localName); + elem.disabled = true; + document.body.appendChild(elem); + // Each event type. + for (const type of eventTypes) { + let listenerFired = false; + elem.addEventListener(type, function f() { + listenerFired = true; + elem.removeEventListener(type, f); + }); + let handlerFired = false; + const handlerAttrName = `on${type}`; + elem[handlerAttrName] = () => { + handlerFired = true; + elem[handlerAttrName] = undefined; + }; + elem.dispatchEvent(new WheelEvent(type)); + + // Generate expectation message. + const { name: constructorName } = Object.getPrototypeOf( + elem + ).constructor; + const msg = `on disabled ${constructorName} to receive WheelEvent of type "${type}".`; + //See how it went... + assert_true(listenerFired, `Expected listener ${msg}`); + assert_true(handlerFired, `Expected handler ${msg}`); + } + elem.remove(); + } +}, "Events from WheelEvent must dispatch on disabled form elements."); + +promise_test(async () => { + // Based on GlobalEventHandlers and mixins + // https://html.spec.whatwg.org/multipage/webappapis.html#globaleventhandlers + const eventTypes = [ + "auxclick", + "contextmenu", + "dblclick", + "mousedown", + "mouseenter", + "mouseleave", + "mousemove", + "mouseout", + "mouseover", + "mouseup", + ] + for (const localName of formElements) { + const elem = document.createElement(localName); + elem.disabled = true; + document.body.appendChild(elem); + // Each event type. + for (const type of eventTypes) { + let listenerFired = false; + elem.addEventListener(type, function f() { + listenerFired = true; + elem.removeEventListener(type, f); + }); + let handlerFired = false; + const handlerAttrName = `on${type}`; + elem[handlerAttrName] = () => { + handlerFired = true; + elem[handlerAttrName] = undefined; + }; + elem.dispatchEvent(new MouseEvent(type)); + + // Generate expectation message. + const { name: constructorName } = Object.getPrototypeOf( + elem + ).constructor; + const msg = `on disabled ${constructorName} to receive MouseEvent of type "${type}".`; + //See how it went... + assert_true(listenerFired, `Expected listener ${msg}`); + assert_true(handlerFired, `Expected handler ${msg}`); } elem.remove(); } -}, "Events from GlobalEventHandlers must dispatch on disabled form elements."); +}, "Events from MouseEvent must dispatch on disabled form elements."); promise_test(async () => { for (const localName of formElements) { From 408ba3d3856c350da9f43b41fef6be944b7d080d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20C=C3=A1ceres?= Date: Tue, 26 Feb 2019 23:53:43 +1100 Subject: [PATCH 3/3] prettier --- .../Event-dispatch-on-disabled-elements.html | 117 +++++++----------- 1 file changed, 47 insertions(+), 70 deletions(-) diff --git a/dom/events/Event-dispatch-on-disabled-elements.html b/dom/events/Event-dispatch-on-disabled-elements.html index a40fb952fbc15e..dfa9a18ce7d9d5 100644 --- a/dom/events/Event-dispatch-on-disabled-elements.html +++ b/dom/events/Event-dispatch-on-disabled-elements.html @@ -110,7 +110,7 @@ "dragover", "dragstart", "drop", - ] + ]; for (const localName of formElements) { const elem = document.createElement(localName); elem.disabled = true; @@ -131,9 +131,7 @@ elem.dispatchEvent(new DragEvent(type)); // Generate expectation message. - const { name: constructorName } = Object.getPrototypeOf( - elem - ).constructor; + const { name: constructorName } = Object.getPrototypeOf(elem).constructor; const msg = `on disabled ${constructorName} to receive ${ DragEvent.name } of type "${type}".`; @@ -149,39 +147,39 @@ // Based on GlobalEventHandlers and mixins // https://html.spec.whatwg.org/multipage/webappapis.html#globaleventhandlers const eventTypes = [ - "abort", - "cancel", - "canplay", - "canplaythrough", - "change", - "close", - "cuechange", - "durationchange", - "emptied", - "ended", - "input", - "invalid", - "loadeddata", - "loadedmetadata", - "loadend", - "pause", - "play", - "playing", - "progress", - "ratechange", - "reset", - "securitypolicyviolation", - "seeked", - "seeking", - "select", - "stalled", - "submit", - "suspend", - "timeupdate", - "toggle", - "volumechange", - "waiting", - ] + "abort", + "cancel", + "canplay", + "canplaythrough", + "change", + "close", + "cuechange", + "durationchange", + "emptied", + "ended", + "input", + "invalid", + "loadeddata", + "loadedmetadata", + "loadend", + "pause", + "play", + "playing", + "progress", + "ratechange", + "reset", + "securitypolicyviolation", + "seeked", + "seeking", + "select", + "stalled", + "submit", + "suspend", + "timeupdate", + "toggle", + "volumechange", + "waiting", + ]; for (const localName of formElements) { const elem = document.createElement(localName); elem.disabled = true; @@ -202,9 +200,7 @@ elem.dispatchEvent(new CustomEvent(type)); // Generate expectation message. - const { name: constructorName } = Object.getPrototypeOf( - elem - ).constructor; + const { name: constructorName } = Object.getPrototypeOf(elem).constructor; const msg = `on disabled ${constructorName} to receive Event of type "${type}".`; //See how it went... assert_true(listenerFired, `Expected listener ${msg}`); @@ -217,9 +213,7 @@ promise_test(async () => { // Based on GlobalEventHandlers and mixins // https://html.spec.whatwg.org/multipage/webappapis.html#globaleventhandlers - const eventTypes = [ - "formdata" - ] + const eventTypes = ["formdata"]; for (const localName of formElements) { const elem = document.createElement(localName); elem.disabled = true; @@ -237,12 +231,10 @@ handlerFired = true; elem[handlerAttrName] = undefined; }; - elem.dispatchEvent(new FormDataEvent(type, {formData: new FormData()})); + elem.dispatchEvent(new FormDataEvent(type, { formData: new FormData() })); // Generate expectation message. - const { name: constructorName } = Object.getPrototypeOf( - elem - ).constructor; + const { name: constructorName } = Object.getPrototypeOf(elem).constructor; const msg = `on disabled ${constructorName} to receive FormDataEvent of type "${type}".`; //See how it went... assert_true(listenerFired, `Expected listener ${msg}`); @@ -255,9 +247,7 @@ promise_test(async () => { // Based on GlobalEventHandlers and mixins // https://html.spec.whatwg.org/multipage/webappapis.html#globaleventhandlers - const eventTypes = [ - "keydown", "keypress", "keyup" - ] + const eventTypes = ["keydown", "keypress", "keyup"]; for (const localName of formElements) { const elem = document.createElement(localName); elem.disabled = true; @@ -278,9 +268,7 @@ elem.dispatchEvent(new KeyboardEvent(type)); // Generate expectation message. - const { name: constructorName } = Object.getPrototypeOf( - elem - ).constructor; + const { name: constructorName } = Object.getPrototypeOf(elem).constructor; const msg = `on disabled ${constructorName} to receive KeyboardEvent of type "${type}".`; //See how it went... assert_true(listenerFired, `Expected listener ${msg}`); @@ -290,13 +278,10 @@ } }, "Events from KeyboardEvent must dispatch on disabled form elements."); - promise_test(async () => { // Based on GlobalEventHandlers and mixins // https://html.spec.whatwg.org/multipage/webappapis.html#globaleventhandlers - const eventTypes = [ - "loadend", "loadstart" - ] + const eventTypes = ["loadend", "loadstart"]; for (const localName of formElements) { const elem = document.createElement(localName); elem.disabled = true; @@ -317,9 +302,7 @@ elem.dispatchEvent(new ProgressEvent(type)); // Generate expectation message. - const { name: constructorName } = Object.getPrototypeOf( - elem - ).constructor; + const { name: constructorName } = Object.getPrototypeOf(elem).constructor; const msg = `on disabled ${constructorName} to receive ProgressEvent of type "${type}".`; //See how it went... assert_true(listenerFired, `Expected listener ${msg}`); @@ -332,9 +315,7 @@ promise_test(async () => { // Based on GlobalEventHandlers and mixins // https://html.spec.whatwg.org/multipage/webappapis.html#globaleventhandlers - const eventTypes = [ - "wheel", - ] + const eventTypes = ["wheel"]; for (const localName of formElements) { const elem = document.createElement(localName); elem.disabled = true; @@ -355,9 +336,7 @@ elem.dispatchEvent(new WheelEvent(type)); // Generate expectation message. - const { name: constructorName } = Object.getPrototypeOf( - elem - ).constructor; + const { name: constructorName } = Object.getPrototypeOf(elem).constructor; const msg = `on disabled ${constructorName} to receive WheelEvent of type "${type}".`; //See how it went... assert_true(listenerFired, `Expected listener ${msg}`); @@ -381,7 +360,7 @@ "mouseout", "mouseover", "mouseup", - ] + ]; for (const localName of formElements) { const elem = document.createElement(localName); elem.disabled = true; @@ -402,9 +381,7 @@ elem.dispatchEvent(new MouseEvent(type)); // Generate expectation message. - const { name: constructorName } = Object.getPrototypeOf( - elem - ).constructor; + const { name: constructorName } = Object.getPrototypeOf(elem).constructor; const msg = `on disabled ${constructorName} to receive MouseEvent of type "${type}".`; //See how it went... assert_true(listenerFired, `Expected listener ${msg}`);