Переглянути джерело

Tests: Import a bunch of WPT tests from /dom/events

Andreas Kling 8 місяців тому
батько
коміт
aa9ed71ff3
100 змінених файлів з 4626 додано та 0 видалено
  1. 58 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Body-FrameSet-Event-Handlers.txt
  2. 13 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/CustomEvent.txt
  3. 18 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-cancelBubble.txt
  4. 10 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-constants.txt
  5. 12 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-defaultPrevented-after-dispatch.txt
  6. 18 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-defaultPrevented.txt
  7. 11 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-bubble-canceled.txt
  8. 16 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-bubbles-false.txt
  9. 16 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-bubbles-true.txt
  10. 17 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-click.tentative.txt
  11. 44 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-click.txt
  12. 12 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-detached-click.txt
  13. 22 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-detached-input-and-change.txt
  14. 11 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-handlers-changed.txt
  15. 11 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-multiple-cancelBubble.txt
  16. 11 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-multiple-stopPropagation.txt
  17. 11 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-omitted-capture.txt
  18. 11 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-order-at-target.txt
  19. 11 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-order.txt
  20. 11 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-other-document.txt
  21. 11 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-propagation-stopped.txt
  22. 11 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-reenter.txt
  23. 143 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-single-activation-behavior.txt
  24. 11 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-target-moved.txt
  25. 11 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-target-removed.txt
  26. 12 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-throwing-multiple-globals.txt
  27. 12 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-throwing.txt
  28. 16 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-init-while-dispatching.txt
  29. 22 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-initEvent.txt
  30. 17 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-propagation.txt
  31. 17 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-returnValue.txt
  32. 11 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-stopImmediatePropagation.txt
  33. 11 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-stopPropagation-cancel-bubbling.txt
  34. 60 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-subclasses-constructors.txt
  35. 11 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-timestamp-cross-realm-getter.txt
  36. 11 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-timestamp-high-resolution.https.txt
  37. 14 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-timestamp-high-resolution.txt
  38. 11 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-timestamp-safe-resolution.txt
  39. 12 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-type-empty.txt
  40. 13 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-type.txt
  41. 16 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/EventListener-handleEvent.txt
  42. 14 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/EventListenerOptions-capture.txt
  43. 11 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/EventTarget-add-listener-platform-object.txt
  44. 12 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/EventTarget-dispatchEvent-returnvalue.txt
  45. 35 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/EventTarget-dispatchEvent.txt
  46. 16 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/EventTarget-this-of-listener.txt
  47. 13 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/KeyEvent-initKeyEvent.txt
  48. 11 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/event-disabled-dynamic.txt
  49. 19 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/event-global.txt
  50. 11 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/mouse-event-retarget.txt
  51. 111 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/passive-by-default.txt
  52. 11 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/preventDefault-during-activation-behavior.txt
  53. 13 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/remove-all-listeners.txt
  54. 12 0
      Tests/LibWeb/Text/expected/wpt-import/dom/events/shadow-relatedTarget.txt
  55. 96 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/AddEventListenerOptions-once.any.js
  56. 134 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/AddEventListenerOptions-passive.any.js
  57. 143 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/AddEventListenerOptions-signal.any.js
  58. 123 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Body-FrameSet-Event-Handlers.html
  59. 35 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/CustomEvent.html
  60. 132 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-cancelBubble.html
  61. 23 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-constants.html
  62. 120 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-constructors.any.js
  63. 44 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-defaultPrevented-after-dispatch.html
  64. 55 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-defaultPrevented.html
  65. 59 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-bubble-canceled.html
  66. 98 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-bubbles-false.html
  67. 108 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-bubbles-true.html
  68. 425 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-click.html
  69. 78 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-click.tentative.html
  70. 20 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-detached-click.html
  71. 190 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-detached-input-and-change.html
  72. 91 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-handlers-changed.html
  73. 20 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-listener-order.window.js
  74. 51 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-multiple-cancelBubble.html
  75. 51 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-multiple-stopPropagation.html
  76. 70 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-omitted-capture.html
  77. 31 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-order-at-target.html
  78. 26 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-order.html
  79. 23 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-other-document.html
  80. 59 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-propagation-stopped.html
  81. 66 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-reenter.html
  82. 164 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-single-activation-behavior.html
  83. 73 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-target-moved.html
  84. 72 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-target-removed.html
  85. 69 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-throwing-multiple-globals.html
  86. 51 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-throwing.html
  87. 83 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-init-while-dispatching.html
  88. 136 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-initEvent.html
  89. 11 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-isTrusted.any.js
  90. 48 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-propagation.html
  91. 64 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-returnValue.html
  92. 34 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-stopImmediatePropagation.html
  93. 20 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-stopPropagation-cancel-bubbling.html
  94. 179 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-subclasses-constructors.html
  95. 27 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-timestamp-cross-realm-getter.html
  96. 16 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-timestamp-high-resolution.html
  97. 16 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-timestamp-high-resolution.https.html
  98. 49 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-timestamp-safe-resolution.html
  99. 35 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-type-empty.html
  100. 22 0
      Tests/LibWeb/Text/input/wpt-import/dom/events/Event-type.html

+ 58 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Body-FrameSet-Event-Handlers.txt

@@ -0,0 +1,58 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 48 tests
+
+48 Pass
+Details
+Result	Test Name	MessagePass	Set HTMLBodyElement.onblur	
+Pass	Enumerate HTMLBodyElement.onblur	
+Pass	Reflect HTMLBodyElement.onblur	
+Pass	Forward HTMLBodyElement.onblur to Window	
+Pass	Set HTMLFrameSetElement.onblur	
+Pass	Enumerate HTMLFrameSetElement.onblur	
+Pass	Reflect HTMLFrameSetElement.onblur	
+Pass	Forward HTMLFrameSetElement.onblur to Window	
+Pass	Set HTMLBodyElement.onerror	
+Pass	Enumerate HTMLBodyElement.onerror	
+Pass	Reflect HTMLBodyElement.onerror	
+Pass	Forward HTMLBodyElement.onerror to Window	
+Pass	Set HTMLFrameSetElement.onerror	
+Pass	Enumerate HTMLFrameSetElement.onerror	
+Pass	Reflect HTMLFrameSetElement.onerror	
+Pass	Forward HTMLFrameSetElement.onerror to Window	
+Pass	Set HTMLBodyElement.onfocus	
+Pass	Enumerate HTMLBodyElement.onfocus	
+Pass	Reflect HTMLBodyElement.onfocus	
+Pass	Forward HTMLBodyElement.onfocus to Window	
+Pass	Set HTMLFrameSetElement.onfocus	
+Pass	Enumerate HTMLFrameSetElement.onfocus	
+Pass	Reflect HTMLFrameSetElement.onfocus	
+Pass	Forward HTMLFrameSetElement.onfocus to Window	
+Pass	Set HTMLBodyElement.onload	
+Pass	Enumerate HTMLBodyElement.onload	
+Pass	Reflect HTMLBodyElement.onload	
+Pass	Forward HTMLBodyElement.onload to Window	
+Pass	Set HTMLFrameSetElement.onload	
+Pass	Enumerate HTMLFrameSetElement.onload	
+Pass	Reflect HTMLFrameSetElement.onload	
+Pass	Forward HTMLFrameSetElement.onload to Window	
+Pass	Set HTMLBodyElement.onscroll	
+Pass	Enumerate HTMLBodyElement.onscroll	
+Pass	Reflect HTMLBodyElement.onscroll	
+Pass	Forward HTMLBodyElement.onscroll to Window	
+Pass	Set HTMLFrameSetElement.onscroll	
+Pass	Enumerate HTMLFrameSetElement.onscroll	
+Pass	Reflect HTMLFrameSetElement.onscroll	
+Pass	Forward HTMLFrameSetElement.onscroll to Window	
+Pass	Set HTMLBodyElement.onresize	
+Pass	Enumerate HTMLBodyElement.onresize	
+Pass	Reflect HTMLBodyElement.onresize	
+Pass	Forward HTMLBodyElement.onresize to Window	
+Pass	Set HTMLFrameSetElement.onresize	
+Pass	Enumerate HTMLFrameSetElement.onresize	
+Pass	Reflect HTMLFrameSetElement.onresize	
+Pass	Forward HTMLFrameSetElement.onresize to Window	

+ 13 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/CustomEvent.txt

@@ -0,0 +1,13 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 3 tests
+
+3 Pass
+Details
+Result	Test Name	MessagePass	CustomEvent dispatching.	
+Pass	First parameter to initCustomEvent should be mandatory.	
+Pass	initCustomEvent's default parameter values.	

+ 18 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-cancelBubble.txt

@@ -0,0 +1,18 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 8 tests
+
+8 Pass
+Details
+Result	Test Name	MessagePass	cancelBubble must be false when an event is initially created.	
+Pass	Initializing an event must set cancelBubble to false.	
+Pass	stopPropagation() must set cancelBubble to true.	
+Pass	stopImmediatePropagation() must set cancelBubble to true.	
+Pass	Event.cancelBubble=false must have no effect.	
+Pass	Event.cancelBubble=false must have no effect during event propagation.	
+Pass	cancelBubble must be false after an event has been dispatched.	
+Pass	Event.cancelBubble=true must set the stop propagation flag.	

+ 10 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-constants.txt

@@ -0,0 +1,10 @@
+Summary
+
+Harness status: Error
+
+Rerun
+
+Found  tests
+
+Details
+Result	Test Name	Message

+ 12 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-defaultPrevented-after-dispatch.txt

@@ -0,0 +1,12 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 2 tests
+
+2 Pass
+Details
+Result	Test Name	MessagePass	Default prevention via preventDefault	
+Pass	Default prevention via returnValue	

+ 18 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-defaultPrevented.txt

@@ -0,0 +1,18 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 8 tests
+
+8 Pass
+Details
+Result	Test Name	MessagePass	When an event is created, defaultPrevented should be initialized to false.	
+Pass	initEvent should work correctly (not cancelable).	
+Pass	preventDefault() should not change defaultPrevented if cancelable is false.	
+Pass	returnValue should not change defaultPrevented if cancelable is false.	
+Pass	initEvent should work correctly (cancelable).	
+Pass	preventDefault() should change defaultPrevented if cancelable is true.	
+Pass	returnValue should change defaultPrevented if cancelable is true.	
+Pass	initEvent should unset defaultPrevented.	

+ 11 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-bubble-canceled.txt

@@ -0,0 +1,11 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 1 tests
+
+1 Pass
+Details
+Result	Test Name	MessagePass	Setting cancelBubble=true prior to dispatchEvent()	

+ 16 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-bubbles-false.txt

@@ -0,0 +1,16 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 5 tests
+
+4 Pass
+1 Fail
+Details
+Result	Test Name	MessageFail	In window.document with click event	
+Pass	In window.document with load event	
+Pass	In window.document.cloneNode(true)	
+Pass	In new Document()	
+Pass	In DOMImplementation.createHTMLDocument()	

+ 16 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-bubbles-true.txt

@@ -0,0 +1,16 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 5 tests
+
+4 Pass
+1 Fail
+Details
+Result	Test Name	MessageFail	In window.document with click event	
+Pass	In window.document with load event	
+Pass	In window.document.cloneNode(true)	
+Pass	In new Document()	
+Pass	In DOMImplementation.createHTMLDocument()	

+ 17 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-click.tentative.txt

@@ -0,0 +1,17 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 6 tests
+
+4 Pass
+2 Fail
+Details
+Result	Test Name	MessagePass	disabled checkbox should not be checked from label click	
+Pass	disabled radio should not be checked from label click	
+Pass	disabled checkbox should not be checked from label click by dispatchEvent	
+Pass	disabled radio should not be checked from label click by dispatchEvent	
+Fail	checkbox morphed into another type should not mutate checked state	
+Fail	radio morphed into another type should not steal the existing checked state	

+ 44 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-click.txt

@@ -0,0 +1,44 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 33 tests
+
+30 Pass
+3 Fail
+Details
+Result	Test Name	MessagePass	basic with click()	
+Pass	basic with dispatchEvent()	
+Pass	basic with wrong event class	
+Pass	look at parents only when event bubbles	
+Pass	look at parents when event bubbles	
+Pass	pick the first with activation behavior <input type=checkbox>	
+Pass	pick the first with activation behavior <a href>	
+Pass	pick the first with activation behavior <input type=radio>	
+Pass	event state during post-click handling	
+Pass	redispatch during post-click handling	
+Pass	disabled checkbox still has activation behavior	
+Pass	disabled checkbox still has activation behavior, part 2	
+Pass	disabled radio still has activation behavior	
+Pass	disconnected checkbox should be checked	
+Pass	disconnected radio should be checked	
+Pass	disconnected checkbox should be checked from dispatchEvent(new MouseEvent('click'))	
+Pass	disconnected radio should be checked from dispatchEvent(new MouseEvent('click'))	
+Pass	disabled checkbox should be checked from dispatchEvent(new MouseEvent("click"))	
+Pass	disabled radio should be checked from dispatchEvent(new MouseEvent("click"))	
+Pass	disabled checkbox should fire onclick	
+Pass	disabled radio should fire onclick	
+Pass	disabled checkbox should get legacy-canceled-activation behavior	
+Pass	disabled radio should get legacy-canceled-activation behavior	
+Pass	disabled checkbox should get legacy-canceled-activation behavior 2	
+Pass	disabled radio should get legacy-canceled-activation behavior 2	
+Pass	disabling checkbox in onclick listener shouldn't suppress oninput	
+Pass	disabling checkbox in onclick listener shouldn't suppress onchange	
+Pass	disabling radio in onclick listener shouldn't suppress oninput	
+Pass	disabling radio in onclick listener shouldn't suppress onchange	
+Pass	disconnected form should not submit	
+Fail	disabled submit button should not activate	
+Fail	submit button should not activate if the event listener disables it	
+Fail	submit button that morphed from checkbox should not activate	

+ 12 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-detached-click.txt

@@ -0,0 +1,12 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 2 tests
+
+2 Pass
+Details
+Result	Test Name	MessagePass	Click event on an element not in the document	
+Pass	Click event can be dispatched to an element that is not in the document.	

+ 22 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-detached-input-and-change.txt

@@ -0,0 +1,22 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 12 tests
+
+12 Pass
+Details
+Result	Test Name	MessagePass	detached checkbox should not emit input or change events on click().	
+Pass	detached radio should not emit input or change events on click().	
+Pass	detached checkbox should not emit input or change events on dispatchEvent(new MouseEvent('click')).	
+Pass	detached radio should not emit input or change events on dispatchEvent(new MouseEvent('click')).	
+Pass	attached checkbox should emit input and change events on click().	
+Pass	attached radio should emit input and change events on click().	
+Pass	attached checkbox should emit input and change events on dispatchEvent(new MouseEvent('click')).	
+Pass	attached radio should emit input and change events on dispatchEvent(new MouseEvent('click')).	
+Pass	attached to shadow dom checkbox should emit input and change events on click().	
+Pass	attached to shadow dom radio should emit input and change events on click().	
+Pass	attached to shadow dom checkbox should emit input and change events on dispatchEvent(new MouseEvent('click')).	
+Pass	attached to shadow dom radio should emit input and change events on dispatchEvent(new MouseEvent('click')).	

+ 11 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-handlers-changed.txt

@@ -0,0 +1,11 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 1 tests
+
+1 Fail
+Details
+Result	Test Name	MessageFail	 Dispatch additional events inside an event listener 	

+ 11 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-multiple-cancelBubble.txt

@@ -0,0 +1,11 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 1 tests
+
+1 Fail
+Details
+Result	Test Name	MessageFail	Multiple dispatchEvent() and cancelBubble	

+ 11 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-multiple-stopPropagation.txt

@@ -0,0 +1,11 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 1 tests
+
+1 Fail
+Details
+Result	Test Name	MessageFail	 Multiple dispatchEvent() and stopPropagation() 	

+ 11 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-omitted-capture.txt

@@ -0,0 +1,11 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 1 tests
+
+1 Fail
+Details
+Result	Test Name	MessageFail	EventTarget.addEventListener with the capture argument omitted	

+ 11 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-order-at-target.txt

@@ -0,0 +1,11 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 1 tests
+
+1 Pass
+Details
+Result	Test Name	MessagePass	Listeners are invoked in correct order (AT_TARGET phase)	

+ 11 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-order.txt

@@ -0,0 +1,11 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 1 tests
+
+1 Pass
+Details
+Result	Test Name	MessagePass	Event phases order	

+ 11 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-other-document.txt

@@ -0,0 +1,11 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 1 tests
+
+1 Pass
+Details
+Result	Test Name	MessagePass	Custom event on an element in another document	

+ 11 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-propagation-stopped.txt

@@ -0,0 +1,11 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 1 tests
+
+1 Pass
+Details
+Result	Test Name	MessagePass	 Calling stopPropagation() prior to dispatchEvent() 	

+ 11 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-reenter.txt

@@ -0,0 +1,11 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 1 tests
+
+1 Fail
+Details
+Result	Test Name	MessageFail	 Dispatch additional events inside an event listener 	

+ 143 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-single-activation-behavior.txt

@@ -0,0 +1,143 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 132 tests
+
+103 Pass
+29 Fail
+Details
+Result	Test Name	MessagePass	When clicking child <INPUT type=checkbox></INPUT> of parent <INPUT type=radio></INPUT>, only child should be activated.	
+Pass	When clicking child <INPUT type=checkbox></INPUT> of parent <FORM><INPUT type=submit></INPUT></FORM>, only child should be activated.	
+Pass	When clicking child <INPUT type=checkbox></INPUT> of parent <FORM><INPUT type=image></INPUT></FORM>, only child should be activated.	
+Pass	When clicking child <INPUT type=checkbox></INPUT> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.	
+Pass	When clicking child <INPUT type=checkbox></INPUT> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.	
+Pass	When clicking child <INPUT type=checkbox></INPUT> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.	
+Pass	When clicking child <INPUT type=checkbox></INPUT> of parent <A></A>, only child should be activated.	
+Pass	When clicking child <INPUT type=checkbox></INPUT> of parent <AREA></AREA>, only child should be activated.	
+Pass	When clicking child <INPUT type=checkbox></INPUT> of parent <DETAILS><SUMMARY></SUMMARY></DETAILS>, only child should be activated.	
+Pass	When clicking child <INPUT type=checkbox></INPUT> of parent <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL>, only child should be activated.	
+Pass	When clicking child <INPUT type=checkbox></INPUT> of parent <LABEL><BUTTON type=button></BUTTON></LABEL>, only child should be activated.	
+Pass	When clicking child <INPUT type=radio></INPUT> of parent <INPUT type=checkbox></INPUT>, only child should be activated.	
+Pass	When clicking child <INPUT type=radio></INPUT> of parent <FORM><INPUT type=submit></INPUT></FORM>, only child should be activated.	
+Pass	When clicking child <INPUT type=radio></INPUT> of parent <FORM><INPUT type=image></INPUT></FORM>, only child should be activated.	
+Pass	When clicking child <INPUT type=radio></INPUT> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.	
+Pass	When clicking child <INPUT type=radio></INPUT> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.	
+Pass	When clicking child <INPUT type=radio></INPUT> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.	
+Pass	When clicking child <INPUT type=radio></INPUT> of parent <A></A>, only child should be activated.	
+Pass	When clicking child <INPUT type=radio></INPUT> of parent <AREA></AREA>, only child should be activated.	
+Pass	When clicking child <INPUT type=radio></INPUT> of parent <DETAILS><SUMMARY></SUMMARY></DETAILS>, only child should be activated.	
+Pass	When clicking child <INPUT type=radio></INPUT> of parent <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL>, only child should be activated.	
+Pass	When clicking child <INPUT type=radio></INPUT> of parent <LABEL><BUTTON type=button></BUTTON></LABEL>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=submit></INPUT></FORM> of parent <INPUT type=checkbox></INPUT>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=submit></INPUT></FORM> of parent <INPUT type=radio></INPUT>, only child should be activated.	
+Fail	When clicking child <FORM><INPUT type=submit></INPUT></FORM> of parent <FORM><INPUT type=image></INPUT></FORM>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=submit></INPUT></FORM> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.	
+Fail	When clicking child <FORM><INPUT type=submit></INPUT></FORM> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=submit></INPUT></FORM> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=submit></INPUT></FORM> of parent <A></A>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=submit></INPUT></FORM> of parent <AREA></AREA>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=submit></INPUT></FORM> of parent <DETAILS><SUMMARY></SUMMARY></DETAILS>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=submit></INPUT></FORM> of parent <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=submit></INPUT></FORM> of parent <LABEL><BUTTON type=button></BUTTON></LABEL>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <INPUT type=checkbox></INPUT>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <INPUT type=radio></INPUT>, only child should be activated.	
+Fail	When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <FORM><INPUT type=submit></INPUT></FORM>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.	
+Fail	When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <A></A>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <AREA></AREA>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <DETAILS><SUMMARY></SUMMARY></DETAILS>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <LABEL><BUTTON type=button></BUTTON></LABEL>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=reset></INPUT></FORM> of parent <INPUT type=checkbox></INPUT>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=reset></INPUT></FORM> of parent <INPUT type=radio></INPUT>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=reset></INPUT></FORM> of parent <FORM><INPUT type=submit></INPUT></FORM>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=reset></INPUT></FORM> of parent <FORM><INPUT type=image></INPUT></FORM>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=reset></INPUT></FORM> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.	
+Fail	When clicking child <FORM><INPUT type=reset></INPUT></FORM> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=reset></INPUT></FORM> of parent <A></A>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=reset></INPUT></FORM> of parent <AREA></AREA>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=reset></INPUT></FORM> of parent <DETAILS><SUMMARY></SUMMARY></DETAILS>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=reset></INPUT></FORM> of parent <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL>, only child should be activated.	
+Pass	When clicking child <FORM><INPUT type=reset></INPUT></FORM> of parent <LABEL><BUTTON type=button></BUTTON></LABEL>, only child should be activated.	
+Pass	When clicking child <FORM><BUTTON type=submit></BUTTON></FORM> of parent <INPUT type=checkbox></INPUT>, only child should be activated.	
+Pass	When clicking child <FORM><BUTTON type=submit></BUTTON></FORM> of parent <INPUT type=radio></INPUT>, only child should be activated.	
+Fail	When clicking child <FORM><BUTTON type=submit></BUTTON></FORM> of parent <FORM><INPUT type=submit></INPUT></FORM>, only child should be activated.	
+Fail	When clicking child <FORM><BUTTON type=submit></BUTTON></FORM> of parent <FORM><INPUT type=image></INPUT></FORM>, only child should be activated.	
+Pass	When clicking child <FORM><BUTTON type=submit></BUTTON></FORM> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.	
+Pass	When clicking child <FORM><BUTTON type=submit></BUTTON></FORM> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.	
+Pass	When clicking child <FORM><BUTTON type=submit></BUTTON></FORM> of parent <A></A>, only child should be activated.	
+Pass	When clicking child <FORM><BUTTON type=submit></BUTTON></FORM> of parent <AREA></AREA>, only child should be activated.	
+Pass	When clicking child <FORM><BUTTON type=submit></BUTTON></FORM> of parent <DETAILS><SUMMARY></SUMMARY></DETAILS>, only child should be activated.	
+Pass	When clicking child <FORM><BUTTON type=submit></BUTTON></FORM> of parent <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL>, only child should be activated.	
+Pass	When clicking child <FORM><BUTTON type=submit></BUTTON></FORM> of parent <LABEL><BUTTON type=button></BUTTON></LABEL>, only child should be activated.	
+Pass	When clicking child <FORM><BUTTON type=reset></BUTTON></FORM> of parent <INPUT type=checkbox></INPUT>, only child should be activated.	
+Pass	When clicking child <FORM><BUTTON type=reset></BUTTON></FORM> of parent <INPUT type=radio></INPUT>, only child should be activated.	
+Pass	When clicking child <FORM><BUTTON type=reset></BUTTON></FORM> of parent <FORM><INPUT type=submit></INPUT></FORM>, only child should be activated.	
+Pass	When clicking child <FORM><BUTTON type=reset></BUTTON></FORM> of parent <FORM><INPUT type=image></INPUT></FORM>, only child should be activated.	
+Fail	When clicking child <FORM><BUTTON type=reset></BUTTON></FORM> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.	
+Pass	When clicking child <FORM><BUTTON type=reset></BUTTON></FORM> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.	
+Pass	When clicking child <FORM><BUTTON type=reset></BUTTON></FORM> of parent <A></A>, only child should be activated.	
+Pass	When clicking child <FORM><BUTTON type=reset></BUTTON></FORM> of parent <AREA></AREA>, only child should be activated.	
+Pass	When clicking child <FORM><BUTTON type=reset></BUTTON></FORM> of parent <DETAILS><SUMMARY></SUMMARY></DETAILS>, only child should be activated.	
+Pass	When clicking child <FORM><BUTTON type=reset></BUTTON></FORM> of parent <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL>, only child should be activated.	
+Pass	When clicking child <FORM><BUTTON type=reset></BUTTON></FORM> of parent <LABEL><BUTTON type=button></BUTTON></LABEL>, only child should be activated.	
+Pass	When clicking child <A></A> of parent <INPUT type=checkbox></INPUT>, only child should be activated.	
+Pass	When clicking child <A></A> of parent <INPUT type=radio></INPUT>, only child should be activated.	
+Pass	When clicking child <A></A> of parent <FORM><INPUT type=submit></INPUT></FORM>, only child should be activated.	
+Pass	When clicking child <A></A> of parent <FORM><INPUT type=image></INPUT></FORM>, only child should be activated.	
+Pass	When clicking child <A></A> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.	
+Pass	When clicking child <A></A> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.	
+Pass	When clicking child <A></A> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.	
+Pass	When clicking child <A></A> of parent <AREA></AREA>, only child should be activated.	
+Pass	When clicking child <A></A> of parent <DETAILS><SUMMARY></SUMMARY></DETAILS>, only child should be activated.	
+Pass	When clicking child <A></A> of parent <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL>, only child should be activated.	
+Pass	When clicking child <A></A> of parent <LABEL><BUTTON type=button></BUTTON></LABEL>, only child should be activated.	
+Fail	When clicking child <AREA></AREA> of parent <INPUT type=checkbox></INPUT>, only child should be activated.	
+Fail	When clicking child <AREA></AREA> of parent <INPUT type=radio></INPUT>, only child should be activated.	
+Fail	When clicking child <AREA></AREA> of parent <FORM><INPUT type=submit></INPUT></FORM>, only child should be activated.	
+Fail	When clicking child <AREA></AREA> of parent <FORM><INPUT type=image></INPUT></FORM>, only child should be activated.	
+Fail	When clicking child <AREA></AREA> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.	
+Fail	When clicking child <AREA></AREA> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.	
+Fail	When clicking child <AREA></AREA> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.	
+Pass	When clicking child <AREA></AREA> of parent <A></A>, only child should be activated.	
+Fail	When clicking child <AREA></AREA> of parent <DETAILS><SUMMARY></SUMMARY></DETAILS>, only child should be activated.	
+Fail	When clicking child <AREA></AREA> of parent <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL>, only child should be activated.	
+Fail	When clicking child <AREA></AREA> of parent <LABEL><BUTTON type=button></BUTTON></LABEL>, only child should be activated.	
+Pass	When clicking child <DETAILS><SUMMARY></SUMMARY></DETAILS> of parent <INPUT type=checkbox></INPUT>, only child should be activated.	
+Pass	When clicking child <DETAILS><SUMMARY></SUMMARY></DETAILS> of parent <INPUT type=radio></INPUT>, only child should be activated.	
+Pass	When clicking child <DETAILS><SUMMARY></SUMMARY></DETAILS> of parent <FORM><INPUT type=submit></INPUT></FORM>, only child should be activated.	
+Pass	When clicking child <DETAILS><SUMMARY></SUMMARY></DETAILS> of parent <FORM><INPUT type=image></INPUT></FORM>, only child should be activated.	
+Pass	When clicking child <DETAILS><SUMMARY></SUMMARY></DETAILS> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.	
+Pass	When clicking child <DETAILS><SUMMARY></SUMMARY></DETAILS> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.	
+Pass	When clicking child <DETAILS><SUMMARY></SUMMARY></DETAILS> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.	
+Pass	When clicking child <DETAILS><SUMMARY></SUMMARY></DETAILS> of parent <A></A>, only child should be activated.	
+Pass	When clicking child <DETAILS><SUMMARY></SUMMARY></DETAILS> of parent <AREA></AREA>, only child should be activated.	
+Pass	When clicking child <DETAILS><SUMMARY></SUMMARY></DETAILS> of parent <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL>, only child should be activated.	
+Pass	When clicking child <DETAILS><SUMMARY></SUMMARY></DETAILS> of parent <LABEL><BUTTON type=button></BUTTON></LABEL>, only child should be activated.	
+Fail	When clicking child <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL> of parent <INPUT type=checkbox></INPUT>, only child should be activated.	
+Fail	When clicking child <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL> of parent <INPUT type=radio></INPUT>, only child should be activated.	
+Fail	When clicking child <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL> of parent <FORM><INPUT type=submit></INPUT></FORM>, only child should be activated.	
+Fail	When clicking child <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL> of parent <FORM><INPUT type=image></INPUT></FORM>, only child should be activated.	
+Fail	When clicking child <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.	
+Fail	When clicking child <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.	
+Fail	When clicking child <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.	
+Fail	When clicking child <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL> of parent <A></A>, only child should be activated.	
+Fail	When clicking child <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL> of parent <AREA></AREA>, only child should be activated.	
+Fail	When clicking child <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL> of parent <DETAILS><SUMMARY></SUMMARY></DETAILS>, only child should be activated.	
+Fail	When clicking child <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL> of parent <LABEL><BUTTON type=button></BUTTON></LABEL>, only child should be activated.	
+Pass	When clicking child <LABEL><BUTTON type=button></BUTTON></LABEL> of parent <INPUT type=checkbox></INPUT>, only child should be activated.	
+Pass	When clicking child <LABEL><BUTTON type=button></BUTTON></LABEL> of parent <INPUT type=radio></INPUT>, only child should be activated.	
+Pass	When clicking child <LABEL><BUTTON type=button></BUTTON></LABEL> of parent <FORM><INPUT type=submit></INPUT></FORM>, only child should be activated.	
+Pass	When clicking child <LABEL><BUTTON type=button></BUTTON></LABEL> of parent <FORM><INPUT type=image></INPUT></FORM>, only child should be activated.	
+Pass	When clicking child <LABEL><BUTTON type=button></BUTTON></LABEL> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.	
+Pass	When clicking child <LABEL><BUTTON type=button></BUTTON></LABEL> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.	
+Pass	When clicking child <LABEL><BUTTON type=button></BUTTON></LABEL> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.	
+Pass	When clicking child <LABEL><BUTTON type=button></BUTTON></LABEL> of parent <A></A>, only child should be activated.	
+Pass	When clicking child <LABEL><BUTTON type=button></BUTTON></LABEL> of parent <AREA></AREA>, only child should be activated.	
+Pass	When clicking child <LABEL><BUTTON type=button></BUTTON></LABEL> of parent <DETAILS><SUMMARY></SUMMARY></DETAILS>, only child should be activated.	
+Pass	When clicking child <LABEL><BUTTON type=button></BUTTON></LABEL> of parent <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL>, only child should be activated.	

+ 11 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-target-moved.txt

@@ -0,0 +1,11 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 1 tests
+
+1 Fail
+Details
+Result	Test Name	MessageFail	Event propagation path when an element in it is moved within the DOM	

+ 11 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-target-removed.txt

@@ -0,0 +1,11 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 1 tests
+
+1 Fail
+Details
+Result	Test Name	MessageFail	Event propagation path when an element in it is removed from the DOM	

+ 12 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-throwing-multiple-globals.txt

@@ -0,0 +1,12 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 2 tests
+
+2 Fail
+Details
+Result	Test Name	MessageFail	exception thrown in event listener function should result in error event on listener's global	
+Fail	exception thrown in event listener interface object should result in error event on listener's global	

+ 12 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-dispatch-throwing.txt

@@ -0,0 +1,12 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 2 tests
+
+2 Pass
+Details
+Result	Test Name	MessagePass	Throwing in event listener with a single listeners	
+Pass	Throwing in event listener with multiple listeners	

+ 16 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-init-while-dispatching.txt

@@ -0,0 +1,16 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 5 tests
+
+4 Pass
+1 Fail
+Details
+Result	Test Name	MessagePass	Calling initKeyboardEvent while dispatching.	
+Pass	Calling initMouseEvent while dispatching.	
+Pass	Calling initCustomEvent while dispatching.	
+Fail	Calling initUIEvent while dispatching.	Not an object of type Window
+Pass	Calling initEvent while dispatching.	

+ 22 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-initEvent.txt

@@ -0,0 +1,22 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 12 tests
+
+12 Pass
+Details
+Result	Test Name	MessagePass	Properties of initEvent(type, true, true)	
+Pass	Properties of initEvent(type, true, false)	
+Pass	Properties of initEvent(type, false, true)	
+Pass	Properties of initEvent(type, false, false)	
+Pass	Calling initEvent multiple times (getting type).	
+Pass	Calling initEvent multiple times (not getting type).	
+Pass	Calling initEvent must not have an effect during dispatching.	
+Pass	Calling initEvent must unset the stop propagation flag.	
+Pass	Calling initEvent must unset the stop immediate propagation flag.	
+Pass	Calling initEvent during propagation.	
+Pass	First parameter to initEvent should be mandatory.	
+Pass	Tests initEvent's default parameter values.	

+ 17 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-propagation.txt

@@ -0,0 +1,17 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 7 tests
+
+7 Pass
+Details
+Result	Test Name	MessagePass	Newly-created Event	
+Pass	After stopPropagation()	
+Pass	Reinitialized after stopPropagation()	
+Pass	After stopImmediatePropagation()	
+Pass	Reinitialized after stopImmediatePropagation()	
+Pass	After cancelBubble=true	
+Pass	Reinitialized after cancelBubble=true	

+ 17 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-returnValue.txt

@@ -0,0 +1,17 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 7 tests
+
+7 Pass
+Details
+Result	Test Name	MessagePass	When an event is created, returnValue should be initialized to true.	
+Pass	preventDefault() should not change returnValue if cancelable is false.	
+Pass	returnValue=false should have no effect if cancelable is false.	
+Pass	preventDefault() should change returnValue if cancelable is true.	
+Pass	returnValue should change returnValue if cancelable is true.	
+Pass	initEvent should unset returnValue.	
+Pass	returnValue=true should have no effect once the canceled flag was set.	

+ 11 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-stopImmediatePropagation.txt

@@ -0,0 +1,11 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 1 tests
+
+1 Pass
+Details
+Result	Test Name	MessagePass	Event's stopImmediatePropagation	

+ 11 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-stopPropagation-cancel-bubbling.txt

@@ -0,0 +1,11 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 1 tests
+
+1 Pass
+Details
+Result	Test Name	MessagePass	Event-stopPropagation-cancel-bubbling	

+ 60 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-subclasses-constructors.txt

@@ -0,0 +1,60 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 49 tests
+
+43 Pass
+6 Fail
+Details
+Result	Test Name	MessagePass	Event constructor (no argument)	
+Pass	Event constructor (undefined argument)	
+Pass	Event constructor (null argument)	
+Pass	Event constructor (empty argument)	
+Pass	Event constructor (argument with default values)	
+Pass	Event constructor (argument with non-default values)	
+Pass	UIEvent constructor (no argument)	
+Pass	UIEvent constructor (undefined argument)	
+Pass	UIEvent constructor (null argument)	
+Pass	UIEvent constructor (empty argument)	
+Pass	UIEvent constructor (argument with default values)	
+Fail	UIEvent constructor (argument with non-default values)	Not an object of type Window
+Pass	FocusEvent constructor (no argument)	
+Pass	FocusEvent constructor (undefined argument)	
+Pass	FocusEvent constructor (null argument)	
+Pass	FocusEvent constructor (empty argument)	
+Pass	FocusEvent constructor (argument with default values)	
+Fail	FocusEvent constructor (argument with non-default values)	Not an object of type Window
+Pass	MouseEvent constructor (no argument)	
+Pass	MouseEvent constructor (undefined argument)	
+Pass	MouseEvent constructor (null argument)	
+Pass	MouseEvent constructor (empty argument)	
+Pass	MouseEvent constructor (argument with default values)	
+Fail	MouseEvent constructor (argument with non-default values)	Not an object of type Window
+Pass	WheelEvent constructor (no argument)	
+Pass	WheelEvent constructor (undefined argument)	
+Pass	WheelEvent constructor (null argument)	
+Pass	WheelEvent constructor (empty argument)	
+Pass	WheelEvent constructor (argument with default values)	
+Fail	WheelEvent constructor (argument with non-default values)	Not an object of type Window
+Pass	KeyboardEvent constructor (no argument)	
+Pass	KeyboardEvent constructor (undefined argument)	
+Pass	KeyboardEvent constructor (null argument)	
+Pass	KeyboardEvent constructor (empty argument)	
+Pass	KeyboardEvent constructor (argument with default values)	
+Fail	KeyboardEvent constructor (argument with non-default values)	Not an object of type Window
+Pass	CompositionEvent constructor (no argument)	
+Pass	CompositionEvent constructor (undefined argument)	
+Pass	CompositionEvent constructor (null argument)	
+Pass	CompositionEvent constructor (empty argument)	
+Pass	CompositionEvent constructor (argument with default values)	
+Fail	CompositionEvent constructor (argument with non-default values)	Not an object of type Window
+Pass	SubclassedEvent constructor (no argument)	
+Pass	SubclassedEvent constructor (undefined argument)	
+Pass	SubclassedEvent constructor (null argument)	
+Pass	SubclassedEvent constructor (empty argument)	
+Pass	SubclassedEvent constructor (argument with default values)	
+Pass	SubclassedEvent constructor (argument with non-default values)	
+Pass	UIEvent constructor (view argument with wrong type)	

+ 11 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-timestamp-cross-realm-getter.txt

@@ -0,0 +1,11 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 1 tests
+
+1 Pass
+Details
+Result	Test Name	MessagePass	event.timeStamp is initialized using event's relevant global object	

+ 11 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-timestamp-high-resolution.https.txt

@@ -0,0 +1,11 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 1 tests
+
+1 Fail
+Details
+Result	Test Name	MessageFail	Constructed GamepadEvent timestamp should be high resolution and have the same time origin as performance.now()	undefined is not a constructor (evaluated from 'window[<computed>]')

+ 14 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-timestamp-high-resolution.txt

@@ -0,0 +1,14 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 4 tests
+
+4 Pass
+Details
+Result	Test Name	MessagePass	Constructed MouseEvent timestamp should be high resolution and have the same time origin as performance.now()	
+Pass	Constructed KeyboardEvent timestamp should be high resolution and have the same time origin as performance.now()	
+Pass	Constructed WheelEvent timestamp should be high resolution and have the same time origin as performance.now()	
+Pass	Constructed FocusEvent timestamp should be high resolution and have the same time origin as performance.now()	

+ 11 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-timestamp-safe-resolution.txt

@@ -0,0 +1,11 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 1 tests
+
+1 Fail
+Details
+Result	Test Name	MessageFail	Event timestamp should not have a resolution better than 5 microseconds	

+ 12 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-type-empty.txt

@@ -0,0 +1,12 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 2 tests
+
+2 Pass
+Details
+Result	Test Name	MessagePass	initEvent	
+Pass	Constructor	

+ 13 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/Event-type.txt

@@ -0,0 +1,13 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 3 tests
+
+3 Pass
+Details
+Result	Test Name	MessagePass	Event.type should initially be the empty string	
+Pass	Event.type should be initialized by initEvent	
+Pass	Event.type should be initialized by the constructor	

+ 16 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/EventListener-handleEvent.txt

@@ -0,0 +1,16 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 6 tests
+
+6 Pass
+Details
+Result	Test Name	MessagePass	calls `handleEvent` method of `EventListener`	
+Pass	performs `Get` every time event is dispatched	
+Pass	doesn't call `handleEvent` method on callable `EventListener`	
+Pass	rethrows errors when getting `handleEvent`	
+Pass	throws if `handleEvent` is falsy and not callable	
+Pass	throws if `handleEvent` is thruthy and not callable	

+ 14 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/EventListenerOptions-capture.txt

@@ -0,0 +1,14 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 4 tests
+
+4 Pass
+Details
+Result	Test Name	MessagePass	Capture boolean should be honored correctly	
+Pass	Capture option should be honored correctly	
+Pass	Supports capture option	
+Pass	Equivalence of option values	

+ 11 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/EventTarget-add-listener-platform-object.txt

@@ -0,0 +1,11 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 1 tests
+
+1 Pass
+Details
+Result	Test Name	MessagePass	addEventListener with a platform object	

+ 12 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/EventTarget-dispatchEvent-returnvalue.txt

@@ -0,0 +1,12 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 2 tests
+
+2 Pass
+Details
+Result	Test Name	MessagePass	Return value of EventTarget.dispatchEvent() affected by preventDefault().	
+Pass	Return value of EventTarget.dispatchEvent() affected by returnValue.	

+ 35 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/EventTarget-dispatchEvent.txt

@@ -0,0 +1,35 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 25 tests
+
+25 Pass
+Details
+Result	Test Name	MessagePass	Calling dispatchEvent(null).	
+Pass	If the event's initialized flag is not set, an InvalidStateError must be thrown (BeforeUnloadEvent).	
+Pass	If the event's initialized flag is not set, an InvalidStateError must be thrown (CompositionEvent).	
+Pass	If the event's initialized flag is not set, an InvalidStateError must be thrown (CustomEvent).	
+Pass	If the event's initialized flag is not set, an InvalidStateError must be thrown (DeviceMotionEvent).	
+Pass	If the event's initialized flag is not set, an InvalidStateError must be thrown (DeviceOrientationEvent).	
+Pass	If the event's initialized flag is not set, an InvalidStateError must be thrown (DragEvent).	
+Pass	If the event's initialized flag is not set, an InvalidStateError must be thrown (Event).	
+Pass	If the event's initialized flag is not set, an InvalidStateError must be thrown (Events).	
+Pass	If the event's initialized flag is not set, an InvalidStateError must be thrown (FocusEvent).	
+Pass	If the event's initialized flag is not set, an InvalidStateError must be thrown (HashChangeEvent).	
+Pass	If the event's initialized flag is not set, an InvalidStateError must be thrown (HTMLEvents).	
+Pass	If the event's initialized flag is not set, an InvalidStateError must be thrown (KeyboardEvent).	
+Pass	If the event's initialized flag is not set, an InvalidStateError must be thrown (MessageEvent).	
+Pass	If the event's initialized flag is not set, an InvalidStateError must be thrown (MouseEvent).	
+Pass	If the event's initialized flag is not set, an InvalidStateError must be thrown (MouseEvents).	
+Pass	If the event's initialized flag is not set, an InvalidStateError must be thrown (StorageEvent).	
+Pass	If the event's initialized flag is not set, an InvalidStateError must be thrown (SVGEvents).	
+Pass	If the event's initialized flag is not set, an InvalidStateError must be thrown (TextEvent).	
+Pass	If the event's initialized flag is not set, an InvalidStateError must be thrown (UIEvent).	
+Pass	If the event's initialized flag is not set, an InvalidStateError must be thrown (UIEvents).	
+Pass	If the event's dispatch flag is set, an InvalidStateError must be thrown.	
+Pass	Exceptions from event listeners must not be propagated.	
+Pass	Event listeners added during dispatch should be called	
+Pass	Capturing event listeners should be called before non-capturing ones	

+ 16 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/EventTarget-this-of-listener.txt

@@ -0,0 +1,16 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 6 tests
+
+6 Pass
+Details
+Result	Test Name	MessagePass	the this value inside the event listener callback should be the node	
+Pass	the this value inside the event listener object handleEvent should be the object	
+Pass	dispatchEvent should invoke the current handleEvent method of the object	
+Pass	addEventListener should not require handleEvent to be defined on object listeners	
+Pass	handleEvent properties added to a function before addEventListener are not reached	
+Pass	handleEvent properties added to a function after addEventListener are not reached	

+ 13 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/KeyEvent-initKeyEvent.txt

@@ -0,0 +1,13 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 3 tests
+
+3 Pass
+Details
+Result	Test Name	MessagePass	KeyboardEvent.initKeyEvent shouldn't be defined (created by createEvent("KeyboardEvent")	
+Pass	KeyboardEvent.initKeyEvent shouldn't be defined (created by constructor)	
+Pass	KeyboardEvent.prototype.initKeyEvent shouldn't be defined	

+ 11 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/event-disabled-dynamic.txt

@@ -0,0 +1,11 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 1 tests
+
+1 Pass
+Details
+Result	Test Name	MessagePass	disabled is honored properly in presence of dynamic changes	

+ 19 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/event-global.txt

@@ -0,0 +1,19 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 8 tests
+
+7 Pass
+1 Fail
+Details
+Result	Test Name	MessagePass	event exists on window, which is initially set to undefined	
+Pass	window.event is only defined during dispatch	
+Pass	window.event is undefined if the target is in a shadow tree (event dispatched outside shadow tree)	
+Pass	window.event is undefined if the target is in a shadow tree (event dispatched inside shadow tree)	
+Fail	window.event is undefined inside window.onerror if the target is in a shadow tree (ErrorEvent dispatched inside shadow tree)	
+Pass	window.event is set to the current event during dispatch	
+Pass	window.event is set to the current event, which is the event passed to dispatch	
+Pass	window.event is set to the current event, which is the event passed to dispatch (2)	

+ 11 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/mouse-event-retarget.txt

@@ -0,0 +1,11 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 1 tests
+
+1 Fail
+Details
+Result	Test Name	MessageFail	offsetX is correctly adjusted	

+ 111 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/passive-by-default.txt

@@ -0,0 +1,111 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 100 tests
+
+68 Pass
+32 Fail
+Details
+Result	Test Name	MessageFail	touchstart listener is passive by default for Window	
+Fail	touchstart listener is passive with {passive:undefined} for Window	
+Pass	touchstart listener is non-passive with {passive:false} for Window	
+Pass	touchstart listener is passive with {passive:true} for Window	
+Fail	touchstart listener is passive by default for HTMLDocument	
+Fail	touchstart listener is passive with {passive:undefined} for HTMLDocument	
+Pass	touchstart listener is non-passive with {passive:false} for HTMLDocument	
+Pass	touchstart listener is passive with {passive:true} for HTMLDocument	
+Fail	touchstart listener is passive by default for HTMLHtmlElement	
+Fail	touchstart listener is passive with {passive:undefined} for HTMLHtmlElement	
+Pass	touchstart listener is non-passive with {passive:false} for HTMLHtmlElement	
+Pass	touchstart listener is passive with {passive:true} for HTMLHtmlElement	
+Fail	touchstart listener is passive by default for HTMLBodyElement	
+Fail	touchstart listener is passive with {passive:undefined} for HTMLBodyElement	
+Pass	touchstart listener is non-passive with {passive:false} for HTMLBodyElement	
+Pass	touchstart listener is passive with {passive:true} for HTMLBodyElement	
+Pass	touchstart listener is non-passive by default for HTMLDivElement	
+Pass	touchstart listener is non-passive with {passive:undefined} for HTMLDivElement	
+Pass	touchstart listener is non-passive with {passive:false} for HTMLDivElement	
+Pass	touchstart listener is passive with {passive:true} for HTMLDivElement	
+Fail	touchmove listener is passive by default for Window	
+Fail	touchmove listener is passive with {passive:undefined} for Window	
+Pass	touchmove listener is non-passive with {passive:false} for Window	
+Pass	touchmove listener is passive with {passive:true} for Window	
+Fail	touchmove listener is passive by default for HTMLDocument	
+Fail	touchmove listener is passive with {passive:undefined} for HTMLDocument	
+Pass	touchmove listener is non-passive with {passive:false} for HTMLDocument	
+Pass	touchmove listener is passive with {passive:true} for HTMLDocument	
+Fail	touchmove listener is passive by default for HTMLHtmlElement	
+Fail	touchmove listener is passive with {passive:undefined} for HTMLHtmlElement	
+Pass	touchmove listener is non-passive with {passive:false} for HTMLHtmlElement	
+Pass	touchmove listener is passive with {passive:true} for HTMLHtmlElement	
+Fail	touchmove listener is passive by default for HTMLBodyElement	
+Fail	touchmove listener is passive with {passive:undefined} for HTMLBodyElement	
+Pass	touchmove listener is non-passive with {passive:false} for HTMLBodyElement	
+Pass	touchmove listener is passive with {passive:true} for HTMLBodyElement	
+Pass	touchmove listener is non-passive by default for HTMLDivElement	
+Pass	touchmove listener is non-passive with {passive:undefined} for HTMLDivElement	
+Pass	touchmove listener is non-passive with {passive:false} for HTMLDivElement	
+Pass	touchmove listener is passive with {passive:true} for HTMLDivElement	
+Fail	wheel listener is passive by default for Window	
+Fail	wheel listener is passive with {passive:undefined} for Window	
+Pass	wheel listener is non-passive with {passive:false} for Window	
+Pass	wheel listener is passive with {passive:true} for Window	
+Fail	wheel listener is passive by default for HTMLDocument	
+Fail	wheel listener is passive with {passive:undefined} for HTMLDocument	
+Pass	wheel listener is non-passive with {passive:false} for HTMLDocument	
+Pass	wheel listener is passive with {passive:true} for HTMLDocument	
+Fail	wheel listener is passive by default for HTMLHtmlElement	
+Fail	wheel listener is passive with {passive:undefined} for HTMLHtmlElement	
+Pass	wheel listener is non-passive with {passive:false} for HTMLHtmlElement	
+Pass	wheel listener is passive with {passive:true} for HTMLHtmlElement	
+Fail	wheel listener is passive by default for HTMLBodyElement	
+Fail	wheel listener is passive with {passive:undefined} for HTMLBodyElement	
+Pass	wheel listener is non-passive with {passive:false} for HTMLBodyElement	
+Pass	wheel listener is passive with {passive:true} for HTMLBodyElement	
+Pass	wheel listener is non-passive by default for HTMLDivElement	
+Pass	wheel listener is non-passive with {passive:undefined} for HTMLDivElement	
+Pass	wheel listener is non-passive with {passive:false} for HTMLDivElement	
+Pass	wheel listener is passive with {passive:true} for HTMLDivElement	
+Fail	mousewheel listener is passive by default for Window	
+Fail	mousewheel listener is passive with {passive:undefined} for Window	
+Pass	mousewheel listener is non-passive with {passive:false} for Window	
+Pass	mousewheel listener is passive with {passive:true} for Window	
+Fail	mousewheel listener is passive by default for HTMLDocument	
+Fail	mousewheel listener is passive with {passive:undefined} for HTMLDocument	
+Pass	mousewheel listener is non-passive with {passive:false} for HTMLDocument	
+Pass	mousewheel listener is passive with {passive:true} for HTMLDocument	
+Fail	mousewheel listener is passive by default for HTMLHtmlElement	
+Fail	mousewheel listener is passive with {passive:undefined} for HTMLHtmlElement	
+Pass	mousewheel listener is non-passive with {passive:false} for HTMLHtmlElement	
+Pass	mousewheel listener is passive with {passive:true} for HTMLHtmlElement	
+Fail	mousewheel listener is passive by default for HTMLBodyElement	
+Fail	mousewheel listener is passive with {passive:undefined} for HTMLBodyElement	
+Pass	mousewheel listener is non-passive with {passive:false} for HTMLBodyElement	
+Pass	mousewheel listener is passive with {passive:true} for HTMLBodyElement	
+Pass	mousewheel listener is non-passive by default for HTMLDivElement	
+Pass	mousewheel listener is non-passive with {passive:undefined} for HTMLDivElement	
+Pass	mousewheel listener is non-passive with {passive:false} for HTMLDivElement	
+Pass	mousewheel listener is passive with {passive:true} for HTMLDivElement	
+Pass	touchend listener is non-passive by default for Window	
+Pass	touchend listener is non-passive with {passive:undefined} for Window	
+Pass	touchend listener is non-passive with {passive:false} for Window	
+Pass	touchend listener is passive with {passive:true} for Window	
+Pass	touchend listener is non-passive by default for HTMLDocument	
+Pass	touchend listener is non-passive with {passive:undefined} for HTMLDocument	
+Pass	touchend listener is non-passive with {passive:false} for HTMLDocument	
+Pass	touchend listener is passive with {passive:true} for HTMLDocument	
+Pass	touchend listener is non-passive by default for HTMLHtmlElement	
+Pass	touchend listener is non-passive with {passive:undefined} for HTMLHtmlElement	
+Pass	touchend listener is non-passive with {passive:false} for HTMLHtmlElement	
+Pass	touchend listener is passive with {passive:true} for HTMLHtmlElement	
+Pass	touchend listener is non-passive by default for HTMLBodyElement	
+Pass	touchend listener is non-passive with {passive:undefined} for HTMLBodyElement	
+Pass	touchend listener is non-passive with {passive:false} for HTMLBodyElement	
+Pass	touchend listener is passive with {passive:true} for HTMLBodyElement	
+Pass	touchend listener is non-passive by default for HTMLDivElement	
+Pass	touchend listener is non-passive with {passive:undefined} for HTMLDivElement	
+Pass	touchend listener is non-passive with {passive:false} for HTMLDivElement	
+Pass	touchend listener is passive with {passive:true} for HTMLDivElement	

+ 11 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/preventDefault-during-activation-behavior.txt

@@ -0,0 +1,11 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 1 tests
+
+1 Pass
+Details
+Result	Test Name	MessagePass	behavior of preventDefault during activation behavior	

+ 13 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/remove-all-listeners.txt

@@ -0,0 +1,13 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 2 tests
+
+1 Pass
+1 Fail
+Details
+Result	Test Name	MessagePass	Removing all listeners and then adding a new one should work.	
+Fail	Nested usage of once listeners should work.	

+ 12 - 0
Tests/LibWeb/Text/expected/wpt-import/dom/events/shadow-relatedTarget.txt

@@ -0,0 +1,12 @@
+Summary
+
+Harness status: OK
+
+Rerun
+
+Found 2 tests
+
+2 Fail
+Details
+Result	Test Name	MessageFail	relatedTarget should not leak at capturing phase, at window object.	
+Fail	relatedTarget should not leak at target.	

+ 96 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/AddEventListenerOptions-once.any.js

@@ -0,0 +1,96 @@
+// META: title=AddEventListenerOptions.once
+
+"use strict";
+
+test(function() {
+  var invoked_once = false;
+  var invoked_normal = false;
+  function handler_once() {
+    invoked_once = true;
+  }
+  function handler_normal() {
+    invoked_normal = true;
+  }
+
+  const et = new EventTarget();
+  et.addEventListener('test', handler_once, {once: true});
+  et.addEventListener('test', handler_normal);
+  et.dispatchEvent(new Event('test'));
+  assert_equals(invoked_once, true, "Once handler should be invoked");
+  assert_equals(invoked_normal, true, "Normal handler should be invoked");
+
+  invoked_once = false;
+  invoked_normal = false;
+  et.dispatchEvent(new Event('test'));
+  assert_equals(invoked_once, false, "Once handler shouldn't be invoked again");
+  assert_equals(invoked_normal, true, "Normal handler should be invoked again");
+  et.removeEventListener('test', handler_normal);
+}, "Once listener should be invoked only once");
+
+test(function() {
+  const et = new EventTarget();
+  var invoked_count = 0;
+  function handler() {
+    invoked_count++;
+    if (invoked_count == 1)
+    et.dispatchEvent(new Event('test'));
+  }
+  et.addEventListener('test', handler, {once: true});
+  et.dispatchEvent(new Event('test'));
+  assert_equals(invoked_count, 1, "Once handler should only be invoked once");
+
+  invoked_count = 0;
+  function handler2() {
+    invoked_count++;
+    if (invoked_count == 1)
+      et.addEventListener('test', handler2, {once: true});
+    if (invoked_count <= 2)
+      et.dispatchEvent(new Event('test'));
+  }
+  et.addEventListener('test', handler2, {once: true});
+  et.dispatchEvent(new Event('test'));
+  assert_equals(invoked_count, 2, "Once handler should only be invoked once after each adding");
+}, "Once listener should be invoked only once even if the event is nested");
+
+test(function() {
+  var invoked_count = 0;
+  function handler() {
+    invoked_count++;
+  }
+
+  const et = new EventTarget();
+
+  et.addEventListener('test', handler, {once: true});
+  et.addEventListener('test', handler);
+  et.dispatchEvent(new Event('test'));
+  assert_equals(invoked_count, 1, "The handler should only be added once");
+
+  invoked_count = 0;
+  et.dispatchEvent(new Event('test'));
+  assert_equals(invoked_count, 0, "The handler was added as a once listener");
+
+  invoked_count = 0;
+  et.addEventListener('test', handler, {once: true});
+  et.removeEventListener('test', handler);
+  et.dispatchEvent(new Event('test'));
+  assert_equals(invoked_count, 0, "The handler should have been removed");
+}, "Once listener should be added / removed like normal listeners");
+
+test(function() {
+  const et = new EventTarget();
+
+  var invoked_count = 0;
+
+  for (let n = 4; n > 0; n--) {
+    et.addEventListener('test', (e) => {
+      invoked_count++;
+      e.stopImmediatePropagation();
+    }, {once: true});
+  }
+
+  for (let n = 4; n > 0; n--) {
+    et.dispatchEvent(new Event('test'));
+  }
+
+  assert_equals(invoked_count, 4, "The listeners should be invoked");
+}, "Multiple once listeners should be invoked even if the stopImmediatePropagation is set");

+ 134 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/AddEventListenerOptions-passive.any.js

@@ -0,0 +1,134 @@
+// META: title=AddEventListenerOptions.passive
+
+test(function() {
+  var supportsPassive = false;
+  var query_options = {
+    get passive() {
+      supportsPassive = true;
+      return false;
+    },
+    get dummy() {
+      assert_unreached("dummy value getter invoked");
+      return false;
+    }
+  };
+
+  const et = new EventTarget();
+  et.addEventListener('test_event', null, query_options);
+  assert_true(supportsPassive, "addEventListener doesn't support the passive option");
+
+  supportsPassive = false;
+  et.removeEventListener('test_event', null, query_options);
+  assert_false(supportsPassive, "removeEventListener supports the passive option when it should not");
+}, "Supports passive option on addEventListener only");
+
+function testPassiveValue(optionsValue, expectedDefaultPrevented, existingEventTarget) {
+  var defaultPrevented = undefined;
+  var handler = function handler(e) {
+    assert_false(e.defaultPrevented, "Event prematurely marked defaultPrevented");
+    e.preventDefault();
+    defaultPrevented = e.defaultPrevented;
+  }
+  const et = existingEventTarget || new EventTarget();
+  et.addEventListener('test', handler, optionsValue);
+  var uncanceled = et.dispatchEvent(new Event('test', {bubbles: true, cancelable: true}));
+
+  assert_equals(defaultPrevented, expectedDefaultPrevented, "Incorrect defaultPrevented for options: " + JSON.stringify(optionsValue));
+  assert_equals(uncanceled, !expectedDefaultPrevented, "Incorrect return value from dispatchEvent");
+
+  et.removeEventListener('test', handler, optionsValue);
+}
+
+test(function() {
+  testPassiveValue(undefined, true);
+  testPassiveValue({}, true);
+  testPassiveValue({passive: false}, true);
+  testPassiveValue({passive: true}, false);
+  testPassiveValue({passive: 0}, true);
+  testPassiveValue({passive: 1}, false);
+}, "preventDefault should be ignored if-and-only-if the passive option is true");
+
+function testPassiveValueOnReturnValue(test, optionsValue, expectedDefaultPrevented) {
+  var defaultPrevented = undefined;
+  var handler = test.step_func(e => {
+    assert_false(e.defaultPrevented, "Event prematurely marked defaultPrevented");
+    e.returnValue = false;
+    defaultPrevented = e.defaultPrevented;
+  });
+  const et = new EventTarget();
+  et.addEventListener('test', handler, optionsValue);
+  var uncanceled = et.dispatchEvent(new Event('test', {bubbles: true, cancelable: true}));
+
+  assert_equals(defaultPrevented, expectedDefaultPrevented, "Incorrect defaultPrevented for options: " + JSON.stringify(optionsValue));
+  assert_equals(uncanceled, !expectedDefaultPrevented, "Incorrect return value from dispatchEvent");
+
+  et.removeEventListener('test', handler, optionsValue);
+}
+
+async_test(t => {
+  testPassiveValueOnReturnValue(t, undefined, true);
+  testPassiveValueOnReturnValue(t, {}, true);
+  testPassiveValueOnReturnValue(t, {passive: false}, true);
+  testPassiveValueOnReturnValue(t, {passive: true}, false);
+  testPassiveValueOnReturnValue(t, {passive: 0}, true);
+  testPassiveValueOnReturnValue(t, {passive: 1}, false);
+  t.done();
+}, "returnValue should be ignored if-and-only-if the passive option is true");
+
+function testPassiveWithOtherHandlers(optionsValue, expectedDefaultPrevented) {
+  var handlerInvoked1 = false;
+  var dummyHandler1 = function() {
+    handlerInvoked1 = true;
+  };
+  var handlerInvoked2 = false;
+  var dummyHandler2 = function() {
+    handlerInvoked2 = true;
+  };
+
+  const et = new EventTarget();
+  et.addEventListener('test', dummyHandler1, {passive:true});
+  et.addEventListener('test', dummyHandler2);
+
+  testPassiveValue(optionsValue, expectedDefaultPrevented, et);
+
+  assert_true(handlerInvoked1, "Extra passive handler not invoked");
+  assert_true(handlerInvoked2, "Extra non-passive handler not invoked");
+
+  et.removeEventListener('test', dummyHandler1);
+  et.removeEventListener('test', dummyHandler2);
+}
+
+test(function() {
+  testPassiveWithOtherHandlers({}, true);
+  testPassiveWithOtherHandlers({passive: false}, true);
+  testPassiveWithOtherHandlers({passive: true}, false);
+}, "passive behavior of one listener should be unaffected by the presence of other listeners");
+
+function testOptionEquivalence(optionValue1, optionValue2, expectedEquality) {
+  var invocationCount = 0;
+  var handler = function handler(e) {
+    invocationCount++;
+  }
+  const et = new EventTarget();
+  et.addEventListener('test', handler, optionValue1);
+  et.addEventListener('test', handler, optionValue2);
+  et.dispatchEvent(new Event('test', {bubbles: true}));
+  assert_equals(invocationCount, expectedEquality ? 1 : 2, "equivalence of options " +
+    JSON.stringify(optionValue1) + " and " + JSON.stringify(optionValue2));
+  et.removeEventListener('test', handler, optionValue1);
+  et.removeEventListener('test', handler, optionValue2);
+}
+
+test(function() {
+  // Sanity check options that should be treated as distinct handlers
+  testOptionEquivalence({capture:true}, {capture:false, passive:false}, false);
+  testOptionEquivalence({capture:true}, {passive:true}, false);
+
+  // Option values that should be treated as equivalent
+  testOptionEquivalence({}, {passive:false}, true);
+  testOptionEquivalence({passive:true}, {passive:false}, true);
+  testOptionEquivalence(undefined, {passive:true}, true);
+  testOptionEquivalence({capture: true, passive: false}, {capture: true, passive: true}, true);
+
+}, "Equivalence of option values");
+

+ 143 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/AddEventListenerOptions-signal.any.js

@@ -0,0 +1,143 @@
+'use strict';
+
+test(function() {
+  let count = 0;
+  function handler() {
+    count++;
+  }
+  const et = new EventTarget();
+  const controller = new AbortController();
+  et.addEventListener('test', handler, { signal: controller.signal });
+  et.dispatchEvent(new Event('test'));
+  assert_equals(count, 1, "Adding a signal still adds a listener");
+  et.dispatchEvent(new Event('test'));
+  assert_equals(count, 2, "The listener was not added with the once flag");
+  controller.abort();
+  et.dispatchEvent(new Event('test'));
+  assert_equals(count, 2, "Aborting on the controller removes the listener");
+  et.addEventListener('test', handler, { signal: controller.signal });
+  et.dispatchEvent(new Event('test'));
+  assert_equals(count, 2, "Passing an aborted signal never adds the handler");
+}, "Passing an AbortSignal to addEventListener options should allow removing a listener");
+
+test(function() {
+  let count = 0;
+  function handler() {
+    count++;
+  }
+  const et = new EventTarget();
+  const controller = new AbortController();
+  et.addEventListener('test', handler, { signal: controller.signal });
+  et.removeEventListener('test', handler);
+  et.dispatchEvent(new Event('test'));
+  assert_equals(count, 0, "The listener was still removed");
+}, "Passing an AbortSignal to addEventListener does not prevent removeEventListener");
+
+test(function() {
+  let count = 0;
+  function handler() {
+    count++;
+  }
+  const et = new EventTarget();
+  const controller = new AbortController();
+  et.addEventListener('test', handler, { signal: controller.signal, once: true });
+  controller.abort();
+  et.dispatchEvent(new Event('test'));
+  assert_equals(count, 0, "The listener was still removed");
+}, "Passing an AbortSignal to addEventListener works with the once flag");
+
+test(function() {
+  let count = 0;
+  function handler() {
+    count++;
+  }
+  const et = new EventTarget();
+  const controller = new AbortController();
+  et.addEventListener('test', handler, { signal: controller.signal, once: true });
+  et.removeEventListener('test', handler);
+  et.dispatchEvent(new Event('test'));
+  assert_equals(count, 0, "The listener was still removed");
+}, "Removing a once listener works with a passed signal");
+
+test(function() {
+  let count = 0;
+  function handler() {
+    count++;
+  }
+  const et = new EventTarget();
+  const controller = new AbortController();
+  et.addEventListener('first', handler, { signal: controller.signal, once: true });
+  et.addEventListener('second', handler, { signal: controller.signal, once: true });
+  controller.abort();
+  et.dispatchEvent(new Event('first'));
+  et.dispatchEvent(new Event('second'));
+  assert_equals(count, 0, "The listener was still removed");
+}, "Passing an AbortSignal to multiple listeners");
+
+test(function() {
+  let count = 0;
+  function handler() {
+    count++;
+  }
+  const et = new EventTarget();
+  const controller = new AbortController();
+  et.addEventListener('test', handler, { signal: controller.signal, capture: true });
+  controller.abort();
+  et.dispatchEvent(new Event('test'));
+  assert_equals(count, 0, "The listener was still removed");
+}, "Passing an AbortSignal to addEventListener works with the capture flag");
+
+test(function() {
+  let count = 0;
+  function handler() {
+    count++;
+  }
+  const et = new EventTarget();
+  const controller = new AbortController();
+  et.addEventListener('test', () => {
+    controller.abort();
+  }, { signal: controller.signal });
+  et.addEventListener('test', handler, { signal: controller.signal });
+  et.dispatchEvent(new Event('test'));
+  assert_equals(count, 0, "The listener was still removed");
+}, "Aborting from a listener does not call future listeners");
+
+test(function() {
+  let count = 0;
+  function handler() {
+    count++;
+  }
+  const et = new EventTarget();
+  const controller = new AbortController();
+  et.addEventListener('test', () => {
+    et.addEventListener('test', handler, { signal: controller.signal });
+    controller.abort();
+  }, { signal: controller.signal });
+  et.dispatchEvent(new Event('test'));
+  assert_equals(count, 0, "The listener was still removed");
+}, "Adding then aborting a listener in another listener does not call it");
+
+test(function() {
+  const et = new EventTarget();
+  const ac = new AbortController();
+  let count = 0;
+  et.addEventListener('foo', () => {
+    et.addEventListener('foo', () => {
+      count++;
+      if (count > 5) ac.abort();
+      et.dispatchEvent(new Event('foo'));
+    }, { signal: ac.signal });
+    et.dispatchEvent(new Event('foo'));
+  }, { once: true });
+  et.dispatchEvent(new Event('foo'));
+}, "Aborting from a nested listener should remove it");
+
+test(function() {
+  const et = new EventTarget();
+  assert_throws_js(TypeError, () => { et.addEventListener("foo", () => {}, { signal: null }); });
+}, "Passing null as the signal should throw");
+
+test(function() {
+  const et = new EventTarget();
+  assert_throws_js(TypeError, () => { et.addEventListener("foo", null, { signal: null }); });
+}, "Passing null as the signal should throw (listener is also null)");

+ 123 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Body-FrameSet-Event-Handlers.html

@@ -0,0 +1,123 @@
+<!DOCTYPE html>
+<html>
+<title>HTMLBodyElement and HTMLFrameSetElement Event Handler Tests</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+
+<script>
+function getObject(interface) {
+    switch(interface) {
+        case "Element":
+            var e = document.createElementNS("http://example.com/", "example");
+            assert_true(e instanceof Element);
+            assert_false(e instanceof HTMLElement);
+            assert_false(e instanceof SVGElement);
+            return e;
+        case "HTMLElement":
+            var e = document.createElement("html");
+            assert_true(e instanceof HTMLElement);
+            return e;
+        case "HTMLBodyElement":
+            var e = document.createElement("body");
+            assert_true(e instanceof HTMLBodyElement);
+            return e;
+        case "HTMLFormElement":
+            var e = document.createElement("form");
+            assert_true(e instanceof HTMLFormElement);
+            return e;
+        case "HTMLFrameSetElement":
+            var e = document.createElement("frameset");
+            assert_true(e instanceof HTMLFrameSetElement);
+            return e;
+        case "SVGElement":
+            var e = document.createElementNS("http://www.w3.org/2000/svg", "rect");
+            assert_true(e instanceof SVGElement);
+            return e;
+        case "Document":
+            assert_true(document instanceof Document);
+            return document;
+        case "Window":
+            assert_true(window instanceof Window);
+            return window;
+    }
+    assert_unreached();
+}
+
+function testSet(interface, attribute) {
+    test(function() {
+        var object = getObject(interface);
+        function nop() {}
+        assert_equals(object[attribute], null, "Initially null");
+        object[attribute] = nop;
+        assert_equals(object[attribute], nop, "Return same function");
+        object[attribute] = "";
+        assert_equals(object[attribute], null, "Return null after setting string");
+        object[attribute] = null;
+        assert_equals(object[attribute], null, "Finally null");
+    }, "Set " + interface + "." + attribute);
+}
+
+function testReflect(interface, attribute) {
+    test(function() {
+        var element = getObject(interface);
+        assert_false(element.hasAttribute(attribute), "Initially missing");
+        element.setAttribute(attribute, "return");
+        assert_equals(element.getAttribute(attribute), "return", "Return same string");
+        assert_equals(typeof element[attribute], "function", "Convert to function");
+        element.removeAttribute(attribute);
+    }, "Reflect " + interface + "." + attribute);
+}
+
+function testForwardToWindow(interface, attribute) {
+    test(function() {
+        var element = getObject(interface);
+        window[attribute] = null;
+        element.setAttribute(attribute, "return");
+        assert_equals(typeof window[attribute], "function", "Convert to function");
+        assert_equals(window[attribute], element[attribute], "Forward content attribute");
+        function nop() {}
+        element[attribute] = nop;
+        assert_equals(window[attribute], nop, "Forward IDL attribute");
+        window[attribute] = null;
+    }, "Forward " + interface + "." + attribute + " to Window");
+}
+
+// Object.propertyIsEnumerable cannot be used because it doesn't
+// work with properties inherited through the prototype chain.
+function getEnumerable(interface) {
+    var enumerable = {};
+    for (var attribute in getObject(interface)) {
+        enumerable[attribute] = true;
+    }
+    return enumerable;
+}
+
+var enumerableCache = {};
+function testEnumerate(interface, attribute) {
+    if (!(interface in enumerableCache)) {
+        enumerableCache[interface] = getEnumerable(interface);
+    }
+    test(function() {
+        assert_true(enumerableCache[interface][attribute]);
+    }, "Enumerate " + interface + "." + attribute);
+}
+
+[
+    "onblur",
+    "onerror",
+    "onfocus",
+    "onload",
+    "onscroll",
+    "onresize"
+].forEach(function(attribute) {
+    testSet("HTMLBodyElement", attribute);
+    testEnumerate("HTMLBodyElement", attribute);
+    testReflect("HTMLBodyElement", attribute);
+    testForwardToWindow("HTMLBodyElement", attribute);
+    testSet("HTMLFrameSetElement", attribute);
+    testEnumerate("HTMLFrameSetElement", attribute);
+    testReflect("HTMLFrameSetElement", attribute);
+    testForwardToWindow("HTMLFrameSetElement", attribute);
+});
+</script>
+</html>

+ 35 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/CustomEvent.html

@@ -0,0 +1,35 @@
+<!doctype html>
+<title>CustomEvent</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  var type = "foo";
+
+  var target = document.createElement("div");
+  target.addEventListener(type, this.step_func(function(evt) {
+    assert_equals(evt.type, type);
+  }), true);
+
+  var fooEvent = document.createEvent("CustomEvent");
+  fooEvent.initEvent(type, true, true);
+  target.dispatchEvent(fooEvent);
+}, "CustomEvent dispatching.");
+
+test(function() {
+    var e = document.createEvent("CustomEvent");
+    assert_throws_js(TypeError, function() {
+        e.initCustomEvent();
+    });
+}, "First parameter to initCustomEvent should be mandatory.");
+
+test(function() {
+    var e = document.createEvent("CustomEvent");
+    e.initCustomEvent("foo");
+    assert_equals(e.type, "foo", "type");
+    assert_false(e.bubbles, "bubbles");
+    assert_false(e.cancelable, "cancelable");
+    assert_equals(e.detail, null, "detail");
+}, "initCustomEvent's default parameter values.");
+</script>

+ 132 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-cancelBubble.html

@@ -0,0 +1,132 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Event.cancelBubble</title>
+  <link rel="author" title="Chris Rebert" href="http://chrisrebert.com">
+  <link rel="help" href="https://dom.spec.whatwg.org/#dom-event-cancelbubble">
+  <meta name="flags" content="dom">
+  <script src="../../resources/testharness.js"></script>
+  <script src="../../resources/testharnessreport.js"></script>
+</head>
+<body>
+  <div id="outer">
+    <div id="middle">
+      <div id="inner"></div>
+    </div>
+  </div>
+  <script>
+test(function () {
+  // See https://dom.spec.whatwg.org/#stop-propagation-flag
+  var e = document.createEvent('Event');
+  assert_false(e.cancelBubble, "cancelBubble must be false after event creation.");
+}, "cancelBubble must be false when an event is initially created.");
+
+test(function () {
+  // See https://dom.spec.whatwg.org/#concept-event-initialize
+
+  // Event which bubbles.
+  var one = document.createEvent('Event');
+  one.cancelBubble = true;
+  one.initEvent('foo', true/*bubbles*/, false/*cancelable*/);
+  assert_false(one.cancelBubble, "initEvent() must set cancelBubble to false. [bubbles=true]");
+  // Re-initialization.
+  one.cancelBubble = true;
+  one.initEvent('foo', true/*bubbles*/, false/*cancelable*/);
+  assert_false(one.cancelBubble, "2nd initEvent() call must set cancelBubble to false. [bubbles=true]");
+
+  // Event which doesn't bubble.
+  var two = document.createEvent('Event');
+  two.cancelBubble = true;
+  two.initEvent('foo', false/*bubbles*/, false/*cancelable*/);
+  assert_false(two.cancelBubble, "initEvent() must set cancelBubble to false. [bubbles=false]");
+  // Re-initialization.
+  two.cancelBubble = true;
+  two.initEvent('foo', false/*bubbles*/, false/*cancelable*/);
+  assert_false(two.cancelBubble, "2nd initEvent() call must set cancelBubble to false. [bubbles=false]");
+}, "Initializing an event must set cancelBubble to false.");
+
+test(function () {
+  // See https://dom.spec.whatwg.org/#dom-event-stoppropagation
+  var e = document.createEvent('Event');
+  e.stopPropagation();
+  assert_true(e.cancelBubble, "stopPropagation() must set cancelBubble to true.");
+}, "stopPropagation() must set cancelBubble to true.");
+
+test(function () {
+  // See https://dom.spec.whatwg.org/#dom-event-stopimmediatepropagation
+  var e = document.createEvent('Event');
+  e.stopImmediatePropagation();
+  assert_true(e.cancelBubble, "stopImmediatePropagation() must set cancelBubble to true.");
+}, "stopImmediatePropagation() must set cancelBubble to true.");
+
+test(function () {
+  var one = document.createEvent('Event');
+  one.stopPropagation();
+  one.cancelBubble = false;
+  assert_true(one.cancelBubble, "cancelBubble must still be true after attempting to set it to false.");
+}, "Event.cancelBubble=false must have no effect.");
+
+test(function (t) {
+  var outer = document.getElementById('outer');
+  var middle = document.getElementById('middle');
+  var inner = document.getElementById('inner');
+
+  outer.addEventListener('barbaz', t.step_func(function () {
+    assert_unreached("Setting Event.cancelBubble=false after setting Event.cancelBubble=true should have no effect.");
+  }), false/*useCapture*/);
+
+  middle.addEventListener('barbaz', function (e) {
+    e.cancelBubble = true;// Stop propagation.
+    e.cancelBubble = false;// Should be a no-op.
+  }, false/*useCapture*/);
+
+  var barbazEvent = document.createEvent('Event');
+  barbazEvent.initEvent('barbaz', true/*bubbles*/, false/*cancelable*/);
+  inner.dispatchEvent(barbazEvent);
+}, "Event.cancelBubble=false must have no effect during event propagation.");
+
+test(function () {
+  // See https://dom.spec.whatwg.org/#concept-event-dispatch
+  // "14. Unset event’s [...] stop propagation flag,"
+  var e = document.createEvent('Event');
+  e.initEvent('foobar', true/*bubbles*/, true/*cancelable*/);
+  document.body.addEventListener('foobar', function listener(e) {
+    e.stopPropagation();
+  });
+  document.body.dispatchEvent(e);
+  assert_false(e.cancelBubble, "cancelBubble must be false after an event has been dispatched.");
+}, "cancelBubble must be false after an event has been dispatched.");
+
+test(function (t) {
+  var outer = document.getElementById('outer');
+  var middle = document.getElementById('middle');
+  var inner = document.getElementById('inner');
+
+  var propagationStopper = function (e) {
+    e.cancelBubble = true;
+  };
+
+  // Bubble phase
+  middle.addEventListener('bar', propagationStopper, false/*useCapture*/);
+  outer.addEventListener('bar', t.step_func(function listenerOne() {
+    assert_unreached("Setting cancelBubble=true should stop the event from bubbling further.");
+  }), false/*useCapture*/);
+
+  var barEvent = document.createEvent('Event');
+  barEvent.initEvent('bar', true/*bubbles*/, false/*cancelable*/);
+  inner.dispatchEvent(barEvent);
+
+  // Capture phase
+  outer.addEventListener('qux', propagationStopper, true/*useCapture*/);
+  middle.addEventListener('qux', t.step_func(function listenerTwo() {
+    assert_unreached("Setting cancelBubble=true should stop the event from propagating further, including during the Capture Phase.");
+  }), true/*useCapture*/);
+
+  var quxEvent = document.createEvent('Event');
+  quxEvent.initEvent('qux', false/*bubbles*/, false/*cancelable*/);
+  inner.dispatchEvent(quxEvent);
+}, "Event.cancelBubble=true must set the stop propagation flag.");
+  </script>
+</body>
+</html>

+ 23 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-constants.html

@@ -0,0 +1,23 @@
+<!doctype html>
+<title>Event constants</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../constants.js"></script>
+<div id="log"></div>
+<script>
+var objects;
+setup(function() {
+  objects = [
+    [Event, "Event interface object"],
+    [Event.prototype, "Event prototype object"],
+    [document.createEvent("Event"), "Event object"],
+    [document.createEvent("CustomEvent"), "CustomEvent object"]
+  ]
+})
+testConstants(objects, [
+  ["NONE", 0],
+  ["CAPTURING_PHASE", 1],
+  ["AT_TARGET", 2],
+  ["BUBBLING_PHASE", 3]
+], "eventPhase")
+</script>

+ 120 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-constructors.any.js

@@ -0,0 +1,120 @@
+// META: title=Event constructors
+
+test(function() {
+  assert_throws_js(
+    TypeError,
+    () => Event(""),
+    "Calling Event constructor without 'new' must throw")
+})
+test(function() {
+  assert_throws_js(TypeError, function() {
+    new Event()
+  })
+})
+test(function() {
+  var test_error = { name: "test" }
+  assert_throws_exactly(test_error, function() {
+    new Event({ toString: function() { throw test_error; } })
+  })
+})
+test(function() {
+  var ev = new Event("")
+  assert_equals(ev.type, "")
+  assert_equals(ev.target, null)
+  assert_equals(ev.srcElement, null)
+  assert_equals(ev.currentTarget, null)
+  assert_equals(ev.eventPhase, Event.NONE)
+  assert_equals(ev.bubbles, false)
+  assert_equals(ev.cancelable, false)
+  assert_equals(ev.defaultPrevented, false)
+  assert_equals(ev.returnValue, true)
+  assert_equals(ev.isTrusted, false)
+  assert_true(ev.timeStamp > 0)
+  assert_true("initEvent" in ev)
+})
+test(function() {
+  var ev = new Event("test")
+  assert_equals(ev.type, "test")
+  assert_equals(ev.target, null)
+  assert_equals(ev.srcElement, null)
+  assert_equals(ev.currentTarget, null)
+  assert_equals(ev.eventPhase, Event.NONE)
+  assert_equals(ev.bubbles, false)
+  assert_equals(ev.cancelable, false)
+  assert_equals(ev.defaultPrevented, false)
+  assert_equals(ev.returnValue, true)
+  assert_equals(ev.isTrusted, false)
+  assert_true(ev.timeStamp > 0)
+  assert_true("initEvent" in ev)
+})
+test(function() {
+  assert_throws_js(TypeError, function() { Event("test") },
+                   'Calling Event constructor without "new" must throw');
+})
+test(function() {
+  var ev = new Event("I am an event", { bubbles: true, cancelable: false})
+  assert_equals(ev.type, "I am an event")
+  assert_equals(ev.bubbles, true)
+  assert_equals(ev.cancelable, false)
+})
+test(function() {
+  var ev = new Event("@", { bubblesIGNORED: true, cancelable: true})
+  assert_equals(ev.type, "@")
+  assert_equals(ev.bubbles, false)
+  assert_equals(ev.cancelable, true)
+})
+test(function() {
+  var ev = new Event("@", { "bubbles\0IGNORED": true, cancelable: true})
+  assert_equals(ev.type, "@")
+  assert_equals(ev.bubbles, false)
+  assert_equals(ev.cancelable, true)
+})
+test(function() {
+  var ev = new Event("Xx", { cancelable: true})
+  assert_equals(ev.type, "Xx")
+  assert_equals(ev.bubbles, false)
+  assert_equals(ev.cancelable, true)
+})
+test(function() {
+  var ev = new Event("Xx", {})
+  assert_equals(ev.type, "Xx")
+  assert_equals(ev.bubbles, false)
+  assert_equals(ev.cancelable, false)
+})
+test(function() {
+  var ev = new Event("Xx", {bubbles: true, cancelable: false, sweet: "x"})
+  assert_equals(ev.type, "Xx")
+  assert_equals(ev.bubbles, true)
+  assert_equals(ev.cancelable, false)
+  assert_equals(ev.sweet, undefined)
+})
+test(function() {
+  var called = []
+  var ev = new Event("Xx", {
+    get cancelable() {
+      called.push("cancelable")
+      return false
+    },
+    get bubbles() {
+      called.push("bubbles")
+      return true;
+    },
+    get sweet() {
+      called.push("sweet")
+      return "x"
+    }
+  })
+  assert_array_equals(called, ["bubbles", "cancelable"])
+  assert_equals(ev.type, "Xx")
+  assert_equals(ev.bubbles, true)
+  assert_equals(ev.cancelable, false)
+  assert_equals(ev.sweet, undefined)
+})
+test(function() {
+  var ev = new CustomEvent("$", {detail: 54, sweet: "x", sweet2: "x", cancelable:true})
+  assert_equals(ev.type, "$")
+  assert_equals(ev.bubbles, false)
+  assert_equals(ev.cancelable, true)
+  assert_equals(ev.sweet, undefined)
+  assert_equals(ev.detail, 54)
+})

+ 44 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-defaultPrevented-after-dispatch.html

@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Event.defaultPrevented is not reset after dispatchEvent()</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+<input id="target" type="hidden" value=""/>
+<script>
+test(function() {
+    var EVENT = "foo";
+    var TARGET = document.getElementById("target");
+    var evt = document.createEvent("Event");
+    evt.initEvent(EVENT, true, true);
+
+    TARGET.addEventListener(EVENT, this.step_func(function(e) {
+        e.preventDefault();
+        assert_true(e.defaultPrevented, "during dispatch");
+    }), true);
+    TARGET.dispatchEvent(evt);
+
+    assert_true(evt.defaultPrevented, "after dispatch");
+    assert_equals(evt.target, TARGET);
+    assert_equals(evt.srcElement, TARGET);
+}, "Default prevention via preventDefault");
+
+test(function() {
+    var EVENT = "foo";
+    var TARGET = document.getElementById("target");
+    var evt = document.createEvent("Event");
+    evt.initEvent(EVENT, true, true);
+
+    TARGET.addEventListener(EVENT, this.step_func(function(e) {
+        e.returnValue = false;
+        assert_true(e.defaultPrevented, "during dispatch");
+    }), true);
+    TARGET.dispatchEvent(evt);
+
+    assert_true(evt.defaultPrevented, "after dispatch");
+    assert_equals(evt.target, TARGET);
+    assert_equals(evt.srcElement, TARGET);
+}, "Default prevention via returnValue");
+</script>

+ 55 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-defaultPrevented.html

@@ -0,0 +1,55 @@
+<!doctype html>
+<title>Event.defaultPrevented</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var ev;
+test(function() {
+  ev = document.createEvent("Event");
+  assert_equals(ev.defaultPrevented, false, "defaultPrevented");
+}, "When an event is created, defaultPrevented should be initialized to false.");
+test(function() {
+  ev.initEvent("foo", true, false);
+  assert_equals(ev.bubbles, true, "bubbles");
+  assert_equals(ev.cancelable, false, "cancelable");
+  assert_equals(ev.defaultPrevented, false, "defaultPrevented");
+}, "initEvent should work correctly (not cancelable).");
+test(function() {
+  assert_equals(ev.cancelable, false, "cancelable (before)");
+  ev.preventDefault();
+  assert_equals(ev.cancelable, false, "cancelable (after)");
+  assert_equals(ev.defaultPrevented, false, "defaultPrevented");
+}, "preventDefault() should not change defaultPrevented if cancelable is false.");
+test(function() {
+  assert_equals(ev.cancelable, false, "cancelable (before)");
+  ev.returnValue = false;
+  assert_equals(ev.cancelable, false, "cancelable (after)");
+  assert_equals(ev.defaultPrevented, false, "defaultPrevented");
+}, "returnValue should not change defaultPrevented if cancelable is false.");
+test(function() {
+  ev.initEvent("foo", true, true);
+  assert_equals(ev.bubbles, true, "bubbles");
+  assert_equals(ev.cancelable, true, "cancelable");
+  assert_equals(ev.defaultPrevented, false, "defaultPrevented");
+}, "initEvent should work correctly (cancelable).");
+test(function() {
+  assert_equals(ev.cancelable, true, "cancelable (before)");
+  ev.preventDefault();
+  assert_equals(ev.cancelable, true, "cancelable (after)");
+  assert_equals(ev.defaultPrevented, true, "defaultPrevented");
+}, "preventDefault() should change defaultPrevented if cancelable is true.");
+test(function() {
+  ev.initEvent("foo", true, true);
+  assert_equals(ev.cancelable, true, "cancelable (before)");
+  ev.returnValue = false;
+  assert_equals(ev.cancelable, true, "cancelable (after)");
+  assert_equals(ev.defaultPrevented, true, "defaultPrevented");
+}, "returnValue should change defaultPrevented if cancelable is true.");
+test(function() {
+  ev.initEvent("foo", true, true);
+  assert_equals(ev.bubbles, true, "bubbles");
+  assert_equals(ev.cancelable, true, "cancelable");
+  assert_equals(ev.defaultPrevented, false, "defaultPrevented");
+}, "initEvent should unset defaultPrevented.");
+</script>

+ 59 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-bubble-canceled.html

@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Setting cancelBubble=true prior to dispatchEvent()</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+
+<table id="table" border="1" style="display: none">
+    <tbody id="table-body">
+    <tr id="table-row">
+        <td id="table-cell">Shady Grove</td>
+        <td>Aeolian</td>
+    </tr>
+    <tr id="parent">
+        <td id="target">Over the river, Charlie</td>
+        <td>Dorian</td>
+    </tr>
+    </tbody>
+</table>
+
+<script>
+test(function() {
+    var event = "foo";
+    var target = document.getElementById("target");
+    var parent = document.getElementById("parent");
+    var tbody = document.getElementById("table-body");
+    var table = document.getElementById("table");
+    var body = document.body;
+    var html = document.documentElement;
+    var current_targets = [window, document, html, body, table, tbody, parent, target];
+    var expected_targets = [];
+    var actual_targets = [];
+    var expected_phases = [];
+    var actual_phases = [];
+
+    var test_event = function(evt) {
+        actual_targets.push(evt.currentTarget);
+        actual_phases.push(evt.eventPhase);
+    };
+
+    for (var i = 0; i < current_targets.length; ++i) {
+        current_targets[i].addEventListener(event, test_event, true);
+        current_targets[i].addEventListener(event, test_event, false);
+    }
+
+    var evt = document.createEvent("Event");
+    evt.initEvent(event, true, true);
+    evt.cancelBubble = true;
+    target.dispatchEvent(evt);
+
+    assert_array_equals(actual_targets, expected_targets, "actual_targets");
+    assert_array_equals(actual_phases, expected_phases, "actual_phases");
+});
+</script>
+</body>
+</html>

+ 98 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-bubbles-false.html

@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title> Event.bubbles attribute is set to false </title>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-event-initevent">
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<table id="table" border="1" style="display: none">
+    <tbody id="table-body">
+    <tr id="table-row">
+        <td id="table-cell">Shady Grove</td>
+        <td>Aeolian</td>
+    </tr>
+    <tr id="parent">
+        <td id="target">Over the river, Charlie</td>
+        <td>Dorian</td>
+    </tr>
+    </tbody>
+</table>
+<script>
+function targetsForDocumentChain(document) {
+    return [
+        document,
+        document.documentElement,
+        document.getElementsByTagName("body")[0],
+        document.getElementById("table"),
+        document.getElementById("table-body"),
+        document.getElementById("parent")
+    ];
+}
+
+function testChain(document, targetParents, phases, event_type) {
+    var target = document.getElementById("target");
+    var targets = targetParents.concat(target);
+    var expected_targets = targets.concat(target);
+
+    var actual_targets = [], actual_phases = [];
+    var test_event = function(evt) {
+        actual_targets.push(evt.currentTarget);
+        actual_phases.push(evt.eventPhase);
+    }
+
+    for (var i = 0; i < targets.length; i++) {
+        targets[i].addEventListener(event_type, test_event, true);
+        targets[i].addEventListener(event_type, test_event, false);
+    }
+
+    var evt = document.createEvent("Event");
+    evt.initEvent(event_type, false, true);
+
+    target.dispatchEvent(evt);
+
+    assert_array_equals(actual_targets, expected_targets, "targets");
+    assert_array_equals(actual_phases, phases, "phases");
+}
+
+var phasesForDocumentChain = [
+    Event.CAPTURING_PHASE,
+    Event.CAPTURING_PHASE,
+    Event.CAPTURING_PHASE,
+    Event.CAPTURING_PHASE,
+    Event.CAPTURING_PHASE,
+    Event.CAPTURING_PHASE,
+    Event.AT_TARGET,
+    Event.AT_TARGET,
+];
+
+test(function () {
+    var chainWithWindow = [window].concat(targetsForDocumentChain(document));
+    testChain(
+        document, chainWithWindow, [Event.CAPTURING_PHASE].concat(phasesForDocumentChain), "click");
+}, "In window.document with click event");
+
+test(function () {
+    testChain(document, targetsForDocumentChain(document), phasesForDocumentChain, "load");
+}, "In window.document with load event")
+
+test(function () {
+    var documentClone = document.cloneNode(true);
+    testChain(
+        documentClone, targetsForDocumentChain(documentClone), phasesForDocumentChain, "click");
+}, "In window.document.cloneNode(true)");
+
+test(function () {
+    var newDocument = new Document();
+    newDocument.appendChild(document.documentElement.cloneNode(true));
+    testChain(
+        newDocument, targetsForDocumentChain(newDocument), phasesForDocumentChain, "click");
+}, "In new Document()");
+
+test(function () {
+    var HTMLDocument = document.implementation.createHTMLDocument();
+    HTMLDocument.body.appendChild(document.getElementById("table").cloneNode(true));
+    testChain(
+        HTMLDocument, targetsForDocumentChain(HTMLDocument), phasesForDocumentChain, "click");
+}, "In DOMImplementation.createHTMLDocument()");
+</script>

+ 108 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-bubbles-true.html

@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title> Event.bubbles attribute is set to false </title>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-event-initevent">
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<table id="table" border="1" style="display: none">
+    <tbody id="table-body">
+    <tr id="table-row">
+        <td id="table-cell">Shady Grove</td>
+        <td>Aeolian</td>
+    </tr>
+    <tr id="parent">
+        <td id="target">Over the river, Charlie</td>
+        <td>Dorian</td>
+    </tr>
+    </tbody>
+</table>
+<script>
+function concatReverse(a) {
+    return a.concat(a.map(function(x) { return x }).reverse());
+}
+
+function targetsForDocumentChain(document) {
+    return [
+        document,
+        document.documentElement,
+        document.getElementsByTagName("body")[0],
+        document.getElementById("table"),
+        document.getElementById("table-body"),
+        document.getElementById("parent")
+    ];
+}
+
+function testChain(document, targetParents, phases, event_type) {
+    var target = document.getElementById("target");
+    var targets = targetParents.concat(target);
+    var expected_targets = concatReverse(targets);
+
+    var actual_targets = [], actual_phases = [];
+    var test_event = function(evt) {
+        actual_targets.push(evt.currentTarget);
+        actual_phases.push(evt.eventPhase);
+    }
+
+    for (var i = 0; i < targets.length; i++) {
+        targets[i].addEventListener(event_type, test_event, true);
+        targets[i].addEventListener(event_type, test_event, false);
+    }
+
+    var evt = document.createEvent("Event");
+    evt.initEvent(event_type, true, true);
+
+    target.dispatchEvent(evt);
+
+    assert_array_equals(actual_targets, expected_targets, "targets");
+    assert_array_equals(actual_phases, phases, "phases");
+}
+
+var phasesForDocumentChain = [
+    Event.CAPTURING_PHASE,
+    Event.CAPTURING_PHASE,
+    Event.CAPTURING_PHASE,
+    Event.CAPTURING_PHASE,
+    Event.CAPTURING_PHASE,
+    Event.CAPTURING_PHASE,
+    Event.AT_TARGET,
+    Event.AT_TARGET,
+    Event.BUBBLING_PHASE,
+    Event.BUBBLING_PHASE,
+    Event.BUBBLING_PHASE,
+    Event.BUBBLING_PHASE,
+    Event.BUBBLING_PHASE,
+    Event.BUBBLING_PHASE,
+];
+
+test(function () {
+    var chainWithWindow = [window].concat(targetsForDocumentChain(document));
+    var phases = [Event.CAPTURING_PHASE].concat(phasesForDocumentChain, Event.BUBBLING_PHASE);
+    testChain(document, chainWithWindow, phases, "click");
+}, "In window.document with click event");
+
+test(function () {
+    testChain(document, targetsForDocumentChain(document), phasesForDocumentChain, "load");
+}, "In window.document with load event")
+
+test(function () {
+    var documentClone = document.cloneNode(true);
+    testChain(
+        documentClone, targetsForDocumentChain(documentClone), phasesForDocumentChain, "click");
+}, "In window.document.cloneNode(true)");
+
+test(function () {
+    var newDocument = new Document();
+    newDocument.appendChild(document.documentElement.cloneNode(true));
+    testChain(
+        newDocument, targetsForDocumentChain(newDocument), phasesForDocumentChain, "click");
+}, "In new Document()");
+
+test(function () {
+    var HTMLDocument = document.implementation.createHTMLDocument();
+    HTMLDocument.body.appendChild(document.getElementById("table").cloneNode(true));
+    testChain(
+        HTMLDocument, targetsForDocumentChain(HTMLDocument), phasesForDocumentChain, "click");
+}, "In DOMImplementation.createHTMLDocument()");
+</script>

+ 425 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-click.html

@@ -0,0 +1,425 @@
+<!doctype html>
+<title>Synthetic click event "magic"</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<div id=dump style=display:none></div>
+<script>
+var dump = document.getElementById("dump")
+
+async_test(function(t) {
+  var input = document.createElement("input")
+  input.type = "checkbox"
+  dump.appendChild(input)
+  input.onclick = t.step_func_done(function() {
+    assert_true(input.checked)
+  })
+  input.click()
+}, "basic with click()")
+
+async_test(function(t) {
+  var input = document.createElement("input")
+  input.type = "checkbox"
+  dump.appendChild(input)
+  input.onclick = t.step_func_done(function() {
+    assert_true(input.checked)
+  })
+  input.dispatchEvent(new MouseEvent("click", {bubbles:true})) // equivalent to the above
+}, "basic with dispatchEvent()")
+
+async_test(function(t) {
+  var input = document.createElement("input")
+  input.type = "checkbox"
+  dump.appendChild(input)
+  input.onclick = t.step_func_done(function() {
+    assert_false(input.checked)
+  })
+  input.dispatchEvent(new Event("click", {bubbles:true})) // no MouseEvent
+}, "basic with wrong event class")
+
+async_test(function(t) {
+  var input = document.createElement("input")
+  input.type = "checkbox"
+  dump.appendChild(input)
+  var child = input.appendChild(new Text("does not matter"))
+  child.dispatchEvent(new MouseEvent("click")) // does not bubble
+  assert_false(input.checked)
+  t.done()
+}, "look at parents only when event bubbles")
+
+async_test(function(t) {
+  var input = document.createElement("input")
+  input.type = "checkbox"
+  dump.appendChild(input)
+  input.onclick = t.step_func_done(function() {
+    assert_true(input.checked)
+  })
+  var child = input.appendChild(new Text("does not matter"))
+  child.dispatchEvent(new MouseEvent("click", {bubbles:true}))
+}, "look at parents when event bubbles")
+
+async_test(function(t) {
+  var input = document.createElement("input")
+  input.type = "checkbox"
+  dump.appendChild(input)
+  input.onclick = t.step_func(function() {
+    assert_false(input.checked, "input pre-click must not be triggered")
+  })
+  var child = input.appendChild(document.createElement("input"))
+  child.type = "checkbox"
+  child.onclick = t.step_func(function() {
+    assert_true(child.checked, "child pre-click must be triggered")
+  })
+  child.dispatchEvent(new MouseEvent("click", {bubbles:true}))
+  t.done()
+}, "pick the first with activation behavior <input type=checkbox>")
+
+async_test(function(t) { // as above with <a>
+  window.hrefComplete = t.step_func(function(a) {
+    assert_equals(a, 'child');
+    t.done();
+  });
+  var link = document.createElement("a")
+  link.href = "javascript:hrefComplete('link')" // must not be triggered
+  dump.appendChild(link)
+  var child = link.appendChild(document.createElement("a"))
+  child.href = "javascript:hrefComplete('child')"
+  child.dispatchEvent(new MouseEvent("click", {bubbles:true}))
+}, "pick the first with activation behavior <a href>")
+
+async_test(function(t) {
+  var input = document.createElement("input")
+  input.type = "radio"
+  dump.appendChild(input)
+  input.onclick = t.step_func(function() {
+    assert_false(input.checked, "input pre-click must not be triggered")
+  })
+  var child = input.appendChild(document.createElement("input"))
+  child.type = "radio"
+  child.onclick = t.step_func(function() {
+    assert_true(child.checked, "child pre-click must be triggered")
+  })
+  child.dispatchEvent(new MouseEvent("click", {bubbles:true}))
+  t.done()
+}, "pick the first with activation behavior <input type=radio>")
+
+async_test(function(t) {
+  var input = document.createElement("input")
+  input.type = "checkbox"
+  dump.appendChild(input)
+  var clickEvent = new MouseEvent("click")
+  input.onchange = t.step_func_done(function() {
+    assert_false(clickEvent.defaultPrevented)
+    assert_true(clickEvent.returnValue)
+    assert_equals(clickEvent.eventPhase, 0)
+    assert_equals(clickEvent.currentTarget, null)
+    assert_equals(clickEvent.target, input)
+    assert_equals(clickEvent.srcElement, input)
+    assert_equals(clickEvent.composedPath().length, 0)
+  })
+  input.dispatchEvent(clickEvent)
+}, "event state during post-click handling")
+
+async_test(function(t) {
+  var input = document.createElement("input")
+  input.type = "checkbox"
+  dump.appendChild(input)
+  var clickEvent = new MouseEvent("click")
+  var finalTarget = document.createElement("doesnotmatter")
+  finalTarget.onclick = t.step_func_done(function() {
+    assert_equals(clickEvent.target, finalTarget)
+    assert_equals(clickEvent.srcElement, finalTarget)
+  })
+  input.onchange = t.step_func(function() {
+    finalTarget.dispatchEvent(clickEvent)
+  })
+  input.dispatchEvent(clickEvent)
+}, "redispatch during post-click handling")
+
+async_test(function(t) {
+  var input = document.createElement("input")
+  input.type = "checkbox"
+  dump.appendChild(input)
+  var child = input.appendChild(document.createElement("input"))
+  child.type = "checkbox"
+  child.disabled = true
+  child.click()
+  assert_false(input.checked)
+  assert_false(child.checked)
+  t.done()
+}, "disabled checkbox still has activation behavior")
+
+async_test(function(t) {
+  var state = "start"
+
+  var form = document.createElement("form")
+  form.onsubmit = t.step_func(() => {
+    if(state == "start" || state == "checkbox") {
+      state = "failure"
+    } else if(state == "form") {
+      state = "done"
+    }
+    return false
+  })
+  dump.appendChild(form)
+  var button = form.appendChild(document.createElement("button"))
+  button.type = "submit"
+  var checkbox = button.appendChild(document.createElement("input"))
+  checkbox.type = "checkbox"
+  checkbox.onclick = t.step_func(() => {
+    if(state == "start") {
+      assert_unreached()
+    } else if(state == "checkbox") {
+      assert_true(checkbox.checked)
+    }
+  })
+  checkbox.disabled = true
+  checkbox.click()
+  assert_equals(state, "start")
+
+  state = "checkbox"
+  checkbox.disabled = false
+  checkbox.click()
+  assert_equals(state, "checkbox")
+
+  state = "form"
+  button.click()
+  assert_equals(state, "done")
+
+  t.done()
+}, "disabled checkbox still has activation behavior, part 2")
+
+async_test(function(t) {
+  var state = "start"
+
+  var form = document.createElement("form")
+  form.onsubmit = t.step_func(() => {
+    if(state == "start" || state == "radio") {
+      state = "failure"
+    } else if(state == "form") {
+      state = "done"
+    }
+    return false
+  })
+  dump.appendChild(form)
+  var button = form.appendChild(document.createElement("button"))
+  button.type = "submit"
+  var radio = button.appendChild(document.createElement("input"))
+  radio.type = "radio"
+  radio.onclick = t.step_func(() => {
+    if(state == "start") {
+      assert_unreached()
+    } else if(state == "radio") {
+      assert_true(radio.checked)
+    }
+  })
+  radio.disabled = true
+  radio.click()
+  assert_equals(state, "start")
+
+  state = "radio"
+  radio.disabled = false
+  radio.click()
+  assert_equals(state, "radio")
+
+  state = "form"
+  button.click()
+  assert_equals(state, "done")
+
+  t.done()
+}, "disabled radio still has activation behavior")
+
+async_test(function(t) {
+  var input = document.createElement("input")
+  input.type = "checkbox"
+  input.onclick = t.step_func_done(function() {
+    assert_true(input.checked)
+  })
+  input.click()
+}, "disconnected checkbox should be checked")
+
+async_test(function(t) {
+  var input = document.createElement("input")
+  input.type = "radio"
+  input.onclick = t.step_func_done(function() {
+    assert_true(input.checked)
+  })
+  input.click()
+}, "disconnected radio should be checked")
+
+async_test(t => {
+  const input = document.createElement('input');
+  input.type = 'checkbox';
+  input.onclick = t.step_func_done(() => {
+    assert_true(input.checked);
+  });
+  input.dispatchEvent(new MouseEvent('click'));
+}, `disconnected checkbox should be checked from dispatchEvent(new MouseEvent('click'))`);
+
+async_test(t => {
+  const input = document.createElement('input');
+  input.type = 'radio';
+  input.onclick = t.step_func_done(() => {
+    assert_true(input.checked);
+  });
+  input.dispatchEvent(new MouseEvent('click'));
+}, `disconnected radio should be checked from dispatchEvent(new MouseEvent('click'))`);
+
+test(() => {
+  const input = document.createElement("input");
+  input.type = "checkbox";
+  input.disabled = true;
+  input.dispatchEvent(new MouseEvent("click"));
+  assert_true(input.checked);
+}, `disabled checkbox should be checked from dispatchEvent(new MouseEvent("click"))`);
+
+test(() => {
+  const input = document.createElement("input");
+  input.type = "radio";
+  input.disabled = true;
+  input.dispatchEvent(new MouseEvent("click"));
+  assert_true(input.checked);
+}, `disabled radio should be checked from dispatchEvent(new MouseEvent("click"))`);
+
+async_test(t => {
+  const input = document.createElement("input");
+  input.type = "checkbox";
+  input.disabled = true;
+  input.onclick = t.step_func_done();
+  input.dispatchEvent(new MouseEvent("click"));
+}, `disabled checkbox should fire onclick`);
+
+async_test(t => {
+  const input = document.createElement("input");
+  input.type = "radio";
+  input.disabled = true;
+  input.onclick = t.step_func_done();
+  input.dispatchEvent(new MouseEvent("click"));
+}, `disabled radio should fire onclick`);
+
+async_test(t => {
+  const input = document.createElement("input");
+  input.type = "checkbox";
+  input.disabled = true;
+  input.onclick = t.step_func(ev => {
+    assert_true(input.checked);
+    ev.preventDefault();
+    queueMicrotask(t.step_func_done(() => {
+      assert_false(input.checked);
+    }));
+  });
+  input.dispatchEvent(new MouseEvent("click", { cancelable: true }));
+}, `disabled checkbox should get legacy-canceled-activation behavior`);
+
+async_test(t => {
+  const input = document.createElement("input");
+  input.type = "radio";
+  input.disabled = true;
+  input.onclick = t.step_func(ev => {
+    assert_true(input.checked);
+    ev.preventDefault();
+    queueMicrotask(t.step_func_done(() => {
+      assert_false(input.checked);
+    }));
+  });
+  input.dispatchEvent(new MouseEvent("click", { cancelable: true }));
+}, `disabled radio should get legacy-canceled-activation behavior`);
+
+test(t => {
+  const input = document.createElement("input");
+  input.type = "checkbox";
+  input.disabled = true;
+  const ev = new MouseEvent("click", { cancelable: true });
+  ev.preventDefault();
+  input.dispatchEvent(ev);
+  assert_false(input.checked);
+}, `disabled checkbox should get legacy-canceled-activation behavior 2`);
+
+test(t => {
+  const input = document.createElement("input");
+  input.type = "radio";
+  input.disabled = true;
+  const ev = new MouseEvent("click", { cancelable: true });
+  ev.preventDefault();
+  input.dispatchEvent(ev);
+  assert_false(input.checked);
+}, `disabled radio should get legacy-canceled-activation behavior 2`);
+
+for (const type of ["checkbox", "radio"]) {
+  for (const handler of ["oninput", "onchange"]) {
+    async_test(t => {
+      const input = document.createElement("input");
+      input.type = type;
+      input.onclick = t.step_func(ev => {
+        input.disabled = true;
+      });
+      input[handler] = t.step_func(ev => {
+        assert_equals(input.checked, true);
+        t.done();
+      });
+      dump.append(input);
+      input.click();
+    }, `disabling ${type} in onclick listener shouldn't suppress ${handler}`);
+  }
+}
+
+async_test(function(t) {
+  var form = document.createElement("form")
+  var didSubmit = false
+  form.onsubmit = t.step_func(() => {
+    didSubmit = true
+    return false
+  })
+  var input = form.appendChild(document.createElement("input"))
+  input.type = "submit"
+  input.click()
+  assert_false(didSubmit)
+  t.done()
+}, "disconnected form should not submit")
+
+async_test(t => {
+  const form = document.createElement("form");
+  form.onsubmit = t.step_func(ev => {
+    ev.preventDefault();
+    assert_unreached("The form is unexpectedly submitted.");
+  });
+  dump.append(form);
+  const input = form.appendChild(document.createElement("input"));
+  input.type = "submit"
+  input.disabled = true;
+  input.dispatchEvent(new MouseEvent("click", { cancelable: true }));
+  t.done();
+}, "disabled submit button should not activate");
+
+async_test(t => {
+  const form = document.createElement("form");
+  form.onsubmit = t.step_func(ev => {
+    ev.preventDefault();
+    assert_unreached("The form is unexpectedly submitted.");
+  });
+  dump.append(form);
+  const input = form.appendChild(document.createElement("input"));
+  input.onclick = t.step_func(() => {
+    input.disabled = true;
+  });
+  input.type = "submit"
+  input.dispatchEvent(new MouseEvent("click", { cancelable: true }));
+  t.done();
+}, "submit button should not activate if the event listener disables it");
+
+async_test(t => {
+  const form = document.createElement("form");
+  form.onsubmit = t.step_func(ev => {
+    ev.preventDefault();
+    assert_unreached("The form is unexpectedly submitted.");
+  });
+  dump.append(form);
+  const input = form.appendChild(document.createElement("input"));
+  input.onclick = t.step_func(() => {
+    input.type = "submit"
+    input.disabled = true;
+  });
+  input.click();
+  t.done();
+}, "submit button that morphed from checkbox should not activate");
+</script>

+ 78 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-click.tentative.html

@@ -0,0 +1,78 @@
+<!doctype html>
+<title>Clicks on input element</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<div id=dump style=display:none></div>
+<script>
+var dump = document.getElementById("dump")
+
+test(t => {
+  const input = document.createElement("input");
+  input.type = "checkbox";
+  input.disabled = true;
+  const label = document.createElement("label");
+  label.append(input);
+  dump.append(label);
+  label.click();
+  assert_false(input.checked);
+}, "disabled checkbox should not be checked from label click");
+
+test(t => {
+  const input = document.createElement("input");
+  input.type = "radio";
+  input.disabled = true;
+  const label = document.createElement("label");
+  label.append(input);
+  dump.append(label);
+  label.click();
+  assert_false(input.checked);
+}, "disabled radio should not be checked from label click");
+
+test(t => {
+  const input = document.createElement("input");
+  input.type = "checkbox";
+  input.disabled = true;
+  const label = document.createElement("label");
+  label.append(input);
+  dump.append(label);
+  label.dispatchEvent(new MouseEvent("click"));
+  assert_false(input.checked);
+}, "disabled checkbox should not be checked from label click by dispatchEvent");
+
+test(t => {
+  const input = document.createElement("input");
+  input.type = "radio";
+  input.disabled = true;
+  const label = document.createElement("label");
+  label.append(input);
+  dump.append(label);
+  label.dispatchEvent(new MouseEvent("click"));
+  assert_false(input.checked);
+}, "disabled radio should not be checked from label click by dispatchEvent");
+
+test(t => {
+  const checkbox = dump.appendChild(document.createElement("input"));
+  checkbox.type = "checkbox";
+  checkbox.onclick = ev => {
+    checkbox.type = "date";
+    ev.preventDefault();
+  };
+  checkbox.dispatchEvent(new MouseEvent("click", { cancelable: true }));
+  assert_false(checkbox.checked);
+}, "checkbox morphed into another type should not mutate checked state");
+
+test(t => {
+  const radio1 = dump.appendChild(document.createElement("input"));
+  const radio2 = dump.appendChild(radio1.cloneNode());
+  radio1.type = radio2.type = "radio";
+  radio1.name = radio2.name = "foo";
+  radio2.checked = true;
+  radio1.onclick = ev => {
+    radio1.type = "date";
+    ev.preventDefault();
+  };
+  radio1.dispatchEvent(new MouseEvent("click", { cancelable: true }));
+  assert_false(radio1.checked);
+  assert_true(radio2.checked);
+}, "radio morphed into another type should not steal the existing checked state");
+</script>

+ 20 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-detached-click.html

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title>Click event on an element not in the document</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+  var EVENT = "click";
+  var TARGET = document.createElement("somerandomelement");
+  var t = async_test("Click event can be dispatched to an element that is not in the document.")
+  TARGET.addEventListener(EVENT, t.step_func(function(evt) {
+    assert_equals(evt.target, TARGET);
+    assert_equals(evt.srcElement, TARGET);
+    t.done();
+  }), true);
+  var e = document.createEvent("Event");
+  e.initEvent(EVENT, true, true);
+  TARGET.dispatchEvent(e);
+});
+</script>

+ 190 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-detached-input-and-change.html

@@ -0,0 +1,190 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<link rel="author" title="Joey Arhar" href="mailto:jarhar@chromium.org">
+<title>input and change events for detached checkbox and radio elements</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+
+<body>
+<script>
+
+test(() => {
+  const input = document.createElement('input');
+  input.type = 'checkbox';
+
+  let inputEventFired = false;
+  input.addEventListener('input', () => inputEventFired = true);
+  let changeEventFired = false;
+  input.addEventListener('change', () => changeEventFired = true);
+  input.click();
+  assert_false(inputEventFired);
+  assert_false(changeEventFired);
+}, 'detached checkbox should not emit input or change events on click().');
+
+test(() => {
+  const input = document.createElement('input');
+  input.type = 'radio';
+
+  let inputEventFired = false;
+  input.addEventListener('input', () => inputEventFired = true);
+  let changeEventFired = false;
+  input.addEventListener('change', () => changeEventFired = true);
+  input.click();
+  assert_false(inputEventFired);
+  assert_false(changeEventFired);
+}, 'detached radio should not emit input or change events on click().');
+
+test(() => {
+  const input = document.createElement('input');
+  input.type = 'checkbox';
+
+  let inputEventFired = false;
+  input.addEventListener('input', () => inputEventFired = true);
+  let changeEventFired = false;
+  input.addEventListener('change', () => changeEventFired = true);
+  input.dispatchEvent(new MouseEvent('click'));
+  assert_false(inputEventFired);
+  assert_false(changeEventFired);
+}, `detached checkbox should not emit input or change events on dispatchEvent(new MouseEvent('click')).`);
+
+test(() => {
+  const input = document.createElement('input');
+  input.type = 'radio';
+
+  let inputEventFired = false;
+  input.addEventListener('input', () => inputEventFired = true);
+  let changeEventFired = false;
+  input.addEventListener('change', () => changeEventFired = true);
+  input.dispatchEvent(new MouseEvent('click'));
+  assert_false(inputEventFired);
+  assert_false(changeEventFired);
+}, `detached radio should not emit input or change events on dispatchEvent(new MouseEvent('click')).`);
+
+
+test(() => {
+  const input = document.createElement('input');
+  input.type = 'checkbox';
+  document.body.appendChild(input);
+
+  let inputEventFired = false;
+  input.addEventListener('input', () => inputEventFired = true);
+  let changeEventFired = false;
+  input.addEventListener('change', () => changeEventFired = true);
+  input.click();
+  assert_true(inputEventFired);
+  assert_true(changeEventFired);
+}, 'attached checkbox should emit input and change events on click().');
+
+test(() => {
+  const input = document.createElement('input');
+  input.type = 'radio';
+  document.body.appendChild(input);
+
+  let inputEventFired = false;
+  input.addEventListener('input', () => inputEventFired = true);
+  let changeEventFired = false;
+  input.addEventListener('change', () => changeEventFired = true);
+  input.click();
+  assert_true(inputEventFired);
+  assert_true(changeEventFired);
+}, 'attached radio should emit input and change events on click().');
+
+test(() => {
+  const input = document.createElement('input');
+  input.type = 'checkbox';
+  document.body.appendChild(input);
+
+  let inputEventFired = false;
+  input.addEventListener('input', () => inputEventFired = true);
+  let changeEventFired = false;
+  input.addEventListener('change', () => changeEventFired = true);
+  input.dispatchEvent(new MouseEvent('click'));
+  assert_true(inputEventFired);
+  assert_true(changeEventFired);
+}, `attached checkbox should emit input and change events on dispatchEvent(new MouseEvent('click')).`);
+
+test(() => {
+  const input = document.createElement('input');
+  input.type = 'radio';
+  document.body.appendChild(input);
+
+  let inputEventFired = false;
+  input.addEventListener('input', () => inputEventFired = true);
+  let changeEventFired = false;
+  input.addEventListener('change', () => changeEventFired = true);
+  input.dispatchEvent(new MouseEvent('click'));
+  assert_true(inputEventFired);
+  assert_true(changeEventFired);
+}, `attached radio should emit input and change events on dispatchEvent(new MouseEvent('click')).`);
+
+
+test(() => {
+  const input = document.createElement('input');
+  input.type = 'checkbox';
+  const shadowHost = document.createElement('div');
+  document.body.appendChild(shadowHost);
+  const shadowRoot = shadowHost.attachShadow({mode: 'open'});
+  shadowRoot.appendChild(input);
+
+  let inputEventFired = false;
+  input.addEventListener('input', () => inputEventFired = true);
+  let changeEventFired = false;
+  input.addEventListener('change', () => changeEventFired = true);
+  input.click();
+  assert_true(inputEventFired);
+  assert_true(changeEventFired);
+}, 'attached to shadow dom checkbox should emit input and change events on click().');
+
+test(() => {
+  const input = document.createElement('input');
+  input.type = 'radio';
+  const shadowHost = document.createElement('div');
+  document.body.appendChild(shadowHost);
+  const shadowRoot = shadowHost.attachShadow({mode: 'open'});
+  shadowRoot.appendChild(input);
+
+  let inputEventFired = false;
+  input.addEventListener('input', () => inputEventFired = true);
+  let changeEventFired = false;
+  input.addEventListener('change', () => changeEventFired = true);
+  input.click();
+  assert_true(inputEventFired);
+  assert_true(changeEventFired);
+}, 'attached to shadow dom radio should emit input and change events on click().');
+
+test(() => {
+  const input = document.createElement('input');
+  input.type = 'checkbox';
+  const shadowHost = document.createElement('div');
+  document.body.appendChild(shadowHost);
+  const shadowRoot = shadowHost.attachShadow({mode: 'open'});
+  shadowRoot.appendChild(input);
+
+  let inputEventFired = false;
+  input.addEventListener('input', () => inputEventFired = true);
+  let changeEventFired = false;
+  input.addEventListener('change', () => changeEventFired = true);
+  input.dispatchEvent(new MouseEvent('click'));
+  assert_true(inputEventFired);
+  assert_true(changeEventFired);
+}, `attached to shadow dom checkbox should emit input and change events on dispatchEvent(new MouseEvent('click')).`);
+
+test(() => {
+  const input = document.createElement('input');
+  input.type = 'radio';
+  const shadowHost = document.createElement('div');
+  document.body.appendChild(shadowHost);
+  const shadowRoot = shadowHost.attachShadow({mode: 'open'});
+  shadowRoot.appendChild(input);
+
+  let inputEventFired = false;
+  input.addEventListener('input', () => inputEventFired = true);
+  let changeEventFired = false;
+  input.addEventListener('change', () => changeEventFired = true);
+  input.dispatchEvent(new MouseEvent('click'));
+  assert_true(inputEventFired);
+  assert_true(changeEventFired);
+}, `attached to shadow dom radio should emit input and change events on dispatchEvent(new MouseEvent('click')).`);
+
+</script>
+</body>

+ 91 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-handlers-changed.html

@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title> Dispatch additional events inside an event listener </title>
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<div id=log></div>
+
+<table id="table" border="1" style="display: none">
+    <tbody id="table-body">
+    <tr id="table-row">
+        <td id="table-cell">Shady Grove</td>
+        <td>Aeolian</td>
+    </tr>
+    <tr id="parent">
+        <td id="target">Over the river, Charlie</td>
+        <td>Dorian</td>
+    </tr>
+    </tbody>
+</table>
+
+<script>
+test(function() {
+  var event_type = "bar";
+  var target = document.getElementById("target");
+  var parent = document.getElementById("parent");
+  var tbody = document.getElementById("table-body");
+  var table = document.getElementById("table");
+  var body = document.body;
+  var html = document.documentElement;
+  var targets = [window, document, html, body, table, tbody, parent, target];
+  var expected_targets = [
+    window,
+    document,
+    html,
+    body,
+    table,
+    tbody,
+    parent,
+    target,
+    target,
+    target, // The additional listener for target runs as we copy its listeners twice
+    parent,
+    tbody,
+    table,
+    body,
+    html,
+    document,
+    window
+  ];
+  var expected_listeners = [0,0,0,0,0,0,0,0,1,3,1,1,1,1,1,1,1];
+
+  var actual_targets = [], actual_listeners = [];
+  var test_event_function = function(i) {
+    return this.step_func(function(evt) {
+      actual_targets.push(evt.currentTarget);
+      actual_listeners.push(i);
+
+      if (evt.eventPhase != evt.BUBBLING_PHASE && evt.currentTarget.foo != 1) {
+        evt.currentTarget.removeEventListener(event_type, event_handlers[0], true);
+        evt.currentTarget.addEventListener(event_type, event_handlers[2], true);
+        evt.currentTarget.foo = 1;
+      }
+
+      if (evt.eventPhase != evt.CAPTURING_PHASE && evt.currentTarget.foo != 3) {
+        evt.currentTarget.removeEventListener(event_type, event_handlers[0], false);
+        evt.currentTarget.addEventListener(event_type, event_handlers[3], false);
+        evt.currentTarget.foo = 3;
+      }
+    });
+  }.bind(this);
+  var event_handlers = [
+    test_event_function(0),
+    test_event_function(1),
+    test_event_function(2),
+    test_event_function(3),
+  ];
+
+  for (var i = 0; i < targets.length; ++i) {
+    targets[i].addEventListener(event_type, event_handlers[0], true);
+    targets[i].addEventListener(event_type, event_handlers[1], false);
+  }
+
+  var evt = document.createEvent("Event");
+  evt.initEvent(event_type, true, true);
+  target.dispatchEvent(evt);
+
+  assert_array_equals(actual_targets, expected_targets, "actual_targets");
+  assert_array_equals(actual_listeners, expected_listeners, "actual_listeners");
+});
+</script>

+ 20 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-listener-order.window.js

@@ -0,0 +1,20 @@
+test(t => {
+  const hostParent = document.createElement("section"),
+        host = hostParent.appendChild(document.createElement("div")),
+        shadowRoot = host.attachShadow({ mode: "closed" }),
+        targetParent = shadowRoot.appendChild(document.createElement("p")),
+        target = targetParent.appendChild(document.createElement("span")),
+        path = [hostParent, host, shadowRoot, targetParent, target],
+        expected = [],
+        result = [];
+  path.forEach((node, index) => {
+    expected.splice(index, 0, "capturing " + node.nodeName);
+    expected.splice(index + 1, 0, "bubbling " + node.nodeName);
+  });
+  path.forEach(node => {
+    node.addEventListener("test", () => { result.push("bubbling " + node.nodeName) });
+    node.addEventListener("test", () => { result.push("capturing " + node.nodeName) }, true);
+  });
+  target.dispatchEvent(new CustomEvent('test', { detail: {}, bubbles: true, composed: true }));
+  assert_array_equals(result, expected);
+});

+ 51 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-multiple-cancelBubble.html

@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Multiple dispatchEvent() and cancelBubble</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div id="parent" style="display: none">
+    <input id="target" type="hidden" value=""/>
+</div>
+
+<script>
+test(function() {
+    var event_type = "foo";
+    var target = document.getElementById("target");
+    var parent = document.getElementById("parent");
+    var actual_result;
+    var test_event = function(evt) {
+        actual_result.push(evt.currentTarget);
+
+        if (parent == evt.currentTarget) {
+            evt.cancelBubble = true;
+        }
+    };
+
+    var evt = document.createEvent("Event");
+    evt.initEvent(event_type, true, true);
+
+    target.addEventListener(event_type, test_event, false);
+    parent.addEventListener(event_type, test_event, false);
+    document.addEventListener(event_type, test_event, false);
+    window.addEventListener(event_type, test_event, false);
+
+    actual_result = [];
+    target.dispatchEvent(evt);
+    assert_array_equals(actual_result, [target, parent]);
+
+    actual_result = [];
+    parent.dispatchEvent(evt);
+    assert_array_equals(actual_result, [parent]);
+
+    actual_result = [];
+    document.dispatchEvent(evt);
+    assert_array_equals(actual_result, [document, window]);
+});
+</script>
+</body>
+</html>

+ 51 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-multiple-stopPropagation.html

@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> Multiple dispatchEvent() and stopPropagation() </title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div id="parent" style="display: none">
+    <input id="target" type="hidden" value=""/>
+</div>
+
+<script>
+test(function() {
+    var event_type = "foo";
+    var target = document.getElementById("target");
+    var parent = document.getElementById("parent");
+    var actual_result;
+    var test_event = function(evt) {
+        actual_result.push(evt.currentTarget);
+
+        if (parent == evt.currentTarget) {
+            evt.stopPropagation();
+        }
+    };
+
+    var evt = document.createEvent("Event");
+    evt.initEvent(event_type, true, true);
+
+    target.addEventListener(event_type, test_event, false);
+    parent.addEventListener(event_type, test_event, false);
+    document.addEventListener(event_type, test_event, false);
+    window.addEventListener(event_type, test_event, false);
+
+    actual_result = [];
+    target.dispatchEvent(evt);
+    assert_array_equals(actual_result, [target, parent]);
+
+    actual_result = [];
+    parent.dispatchEvent(evt);
+    assert_array_equals(actual_result, [parent]);
+
+    actual_result = [];
+    document.dispatchEvent(evt);
+    assert_array_equals(actual_result, [document, window]);
+});
+</script>
+</body>
+</html>

+ 70 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-omitted-capture.html

@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>EventTarget.addEventListener: capture argument omitted</title>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener">
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<table id="table" border="1" style="display: none">
+    <tbody id="table-body">
+    <tr id="table-row">
+        <td id="table-cell">Shady Grove</td>
+        <td>Aeolian</td>
+    </tr>
+    <tr id="parent">
+        <td id="target">Over the river, Charlie</td>
+        <td>Dorian</td>
+    </tr>
+    </tbody>
+</table>
+<script>
+test(function() {
+    var event_type = "foo";
+    var target = document.getElementById("target");
+    var targets = [
+        target,
+        document.getElementById("parent"),
+        document.getElementById("table-body"),
+        document.getElementById("table"),
+        document.body,
+        document.documentElement,
+        document,
+        window
+    ];
+    var phases = [
+        Event.AT_TARGET,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE
+    ];
+
+    var actual_targets = [], actual_phases = [];
+    var test_event = function(evt) {
+        actual_targets.push(evt.currentTarget);
+        actual_phases.push(evt.eventPhase);
+    }
+
+    for (var i = 0; i < targets.length; i++) {
+        targets[i].addEventListener(event_type, test_event);
+    }
+
+    var evt = document.createEvent("Event");
+    evt.initEvent(event_type, true, true);
+
+    target.dispatchEvent(evt);
+
+    for (var i = 0; i < targets.length; i++) {
+        targets[i].removeEventListener(event_type, test_event);
+    }
+
+    target.dispatchEvent(evt);
+
+    assert_array_equals(actual_targets, targets, "targets");
+    assert_array_equals(actual_phases, phases, "phases");
+}, "EventTarget.addEventListener with the capture argument omitted");
+</script>

+ 31 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-order-at-target.html

@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Listeners are invoked in correct order (AT_TARGET phase)</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+"use strict";
+
+test(() => {
+    const el = document.createElement("div");
+    const expectedOrder = ["capturing", "bubbling"];
+
+    let actualOrder = [];
+    el.addEventListener("click", evt => {
+        assert_equals(evt.eventPhase, Event.AT_TARGET);
+        actualOrder.push("bubbling");
+    }, false);
+    el.addEventListener("click", evt => {
+        assert_equals(evt.eventPhase, Event.AT_TARGET);
+        actualOrder.push("capturing");
+    }, true);
+
+    el.dispatchEvent(new Event("click", {bubbles: true}));
+    assert_array_equals(actualOrder, expectedOrder, "bubbles: true");
+
+    actualOrder = [];
+    el.dispatchEvent(new Event("click", {bubbles: false}));
+    assert_array_equals(actualOrder, expectedOrder, "bubbles: false");
+}, "Listeners are invoked in correct order (AT_TARGET phase)");
+</script>

+ 26 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-order.html

@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Event phases order</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+    document.addEventListener('DOMContentLoaded', this.step_func_done(function() {
+        var parent = document.getElementById('parent');
+        var child = document.getElementById('child');
+
+        var order = [];
+
+        parent.addEventListener('click', this.step_func(function(){ order.push(1) }), true);
+        child.addEventListener('click', this.step_func(function(){ order.push(2) }), false);
+        parent.addEventListener('click', this.step_func(function(){ order.push(3) }), false);
+
+        child.dispatchEvent(new Event('click', {bubbles: true}));
+
+        assert_array_equals(order, [1, 2, 3]);
+    }));
+}, "Event phases order");
+</script>
+<div id="parent">
+    <div id="child"></div>
+</div>

+ 23 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-other-document.html

@@ -0,0 +1,23 @@
+<!doctype html>
+<title>Custom event on an element in another document</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+  var doc = document.implementation.createHTMLDocument("Demo");
+  var element = doc.createElement("div");
+  var called = false;
+  element.addEventListener("foo", this.step_func(function(ev) {
+    assert_false(called);
+    called = true;
+    assert_equals(ev.target, element);
+    assert_equals(ev.srcElement, element);
+  }));
+  doc.body.appendChild(element);
+
+  var event = new Event("foo");
+  element.dispatchEvent(event);
+  assert_true(called);
+});
+</script>

+ 59 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-propagation-stopped.html

@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> Calling stopPropagation() prior to dispatchEvent() </title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<table id="table" border="1" style="display: none">
+    <tbody id="table-body">
+    <tr id="table-row">
+        <td id="table-cell">Shady Grove</td>
+        <td>Aeolian</td>
+    </tr>
+    <tr id="parent">
+        <td id="target">Over the river, Charlie</td>
+        <td>Dorian</td>
+    </tr>
+    </tbody>
+</table>
+
+<script>
+test(function() {
+    var event = "foo";
+    var target = document.getElementById("target");
+    var parent = document.getElementById("parent");
+    var tbody = document.getElementById("table-body");
+    var table = document.getElementById("table");
+    var body = document.body;
+    var html = document.documentElement;
+    var current_targets = [window, document, html, body, table, tbody, parent, target];
+    var expected_targets = [];
+    var actual_targets = [];
+    var expected_phases = [];
+    var actual_phases = [];
+
+    var test_event = function(evt) {
+        actual_targets.push(evt.currentTarget);
+        actual_phases.push(evt.eventPhase);
+    };
+
+    for (var i = 0; i < current_targets.length; ++i) {
+        current_targets[i].addEventListener(event, test_event, true);
+        current_targets[i].addEventListener(event, test_event, false);
+    }
+
+    var evt = document.createEvent("Event");
+    evt.initEvent(event, true, true);
+    evt.stopPropagation();
+    target.dispatchEvent(evt);
+
+    assert_array_equals(actual_targets, expected_targets, "actual_targets");
+    assert_array_equals(actual_phases, expected_phases, "actual_phases");
+});
+</script>
+</body>
+</html>

+ 66 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-reenter.html

@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title> Dispatch additional events inside an event listener </title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<table id="table" border="1" style="display: none">
+    <tbody id="table-body">
+    <tr id="table-row">
+        <td id="table-cell">Shady Grove</td>
+        <td>Aeolian</td>
+    </tr>
+    <tr id="parent">
+        <td id="target">Over the river, Charlie</td>
+        <td>Dorian</td>
+    </tr>
+    </tbody>
+</table>
+<script>
+test(function() {
+    var event_type = "foo";
+    var target = document.getElementById("target");
+    var parent = document.getElementById("parent");
+    var tbody = document.getElementById("table-body");
+    var table = document.getElementById("table");
+    var body = document.body;
+    var html = document.documentElement;
+    var targets = [window, document, html, body, table, tbody, parent, target];
+    var expected_targets = [
+        window, document, html, body, table,
+        target, parent, tbody,
+        table, body, html, document, window,
+        tbody, parent, target];
+    var actual_targets = [];
+    var expected_types = [
+        "foo", "foo", "foo", "foo", "foo",
+        "bar", "bar", "bar",
+        "bar", "bar", "bar", "bar", "bar",
+        "foo", "foo", "foo"
+    ];
+
+    var actual_targets = [], actual_types = [];
+    var test_event = this.step_func(function(evt) {
+        actual_targets.push(evt.currentTarget);
+        actual_types.push(evt.type);
+
+        if (table == evt.currentTarget && event_type == evt.type) {
+            var e = document.createEvent("Event");
+            e.initEvent("bar", true, true);
+            target.dispatchEvent(e);
+        }
+    });
+
+    for (var i = 0; i < targets.length; ++i) {
+        targets[i].addEventListener(event_type, test_event, true);
+        targets[i].addEventListener("bar", test_event, false);
+    }
+
+    var evt = document.createEvent("Event");
+    evt.initEvent(event_type, false, true);
+    target.dispatchEvent(evt);
+
+    assert_array_equals(actual_targets, expected_targets, "actual_targets");
+    assert_array_equals(actual_types, expected_types, "actual_types");
+});
+</script>

+ 164 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-single-activation-behavior.html

@@ -0,0 +1,164 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title> Only one activation behavior is executed during dispatch</title>
+<link rel="author" title="Vincent Hilla" href="mailto:vhilla@mozilla.com">
+<link rel="help" href="https://dom.spec.whatwg.org/#eventtarget-activation-behavior">
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<div id=log></div>
+
+<div id=test_container></div>
+
+<!--
+    Three classes:
+    click
+        Element to be clicked to cause activation behavior
+    activates
+        Element that registers the activation behavior
+    container
+        Element in which other elements with activation behavior are placed.
+        We test that those won't be activated too.
+-->
+<template>
+    <!--input, change event bubble, so have to check if checked is true-->
+    <input class="click activates container" type="checkbox" oninput="this.checked ? activated(this) : null">
+    <input class="click activates container" type="radio" oninput="this.checked ? activated(this) : null">
+    <form onsubmit="activated(this); return false" class="activates">
+        <input class="click container" type="submit">
+    </form>
+    <form onsubmit="activated(this); return false" class="activates">
+        <input class="click container" type="image">
+    </form>
+    <form onreset="activated(this)" class="activates">
+        <input class="click container" type="reset">
+    </form>
+    <form onsubmit="activated(this); return false" class="activates">
+        <button class="click container" type="submit"></button>
+    </form>
+    <form onreset="activated(this)" class="activates">
+        <button class="click container" type="reset"></button>
+    </form>
+    <a href="#link" class="click container activates"></a>
+    <area href="#link" class="click container activates">
+    <details ontoggle="activated(this)" class="activates">
+        <summary class="click container"></summary>
+    </details>
+    <label>
+      <input type=checkbox onclick="this.checked ? activated(this) : null" class="activates">
+      <span class="click container">label</span>
+    </label>
+    <!--activation behavior of label for event targeted at interactive content descendant is to do nothing-->
+    <label class="container">
+        <button class="click" type="button"></button>
+    </label>
+</template>
+
+<script>
+let activations = [];
+function activated(e) {
+    activations.push(e);
+}
+
+function getActivations(testidx) {
+    return activations.filter(a =>
+        (a.endsWith && a.endsWith("test"+testidx+"_link"))
+        || (a.classList && a.classList.contains("test"+testidx))
+    );
+}
+
+// for a and area elements
+window.onhashchange = function(e) {
+    if (e.newURL.endsWith("link")) {
+        activated(e.newURL);
+    }
+    window.location.hash = "";
+};
+
+function getElementsByClassNameInclusive(e, clsname) {
+    let ls = Array.from(e.getElementsByClassName(clsname));
+    if (e.classList.contains(clsname)) ls.push(e);
+    return ls;
+}
+
+function getClickTarget(e) {
+    return getElementsByClassNameInclusive(e, "click")[0];
+}
+
+function getContainer(e) {
+    return getElementsByClassNameInclusive(e, "container")[0];
+}
+
+function getExpectedActivations(e) {
+    let ls = getElementsByClassNameInclusive(e, "activates");
+
+    // special case, for a and area the window registers the activation
+    // have to use string, as testrunner cannot stringify the window object
+    ls = ls.map(e => e.tagName === "A" || e.tagName === "AREA" ? e.href : e);
+
+    return ls;
+}
+
+function toString(e) {
+    const children = Array.from(e.children);
+    const childstr = (children.map(toString)).join("");
+    const tag = e.tagName;
+    const typestr = e.type ? " type="+e.type : "";
+    return `<${tag}${typestr}>${childstr}</${tag}>`;
+}
+
+// generate O(n^2) test combinations
+const template = document.querySelector("template");
+const elements = Array.from(template.content.children);
+const tests = []
+for (const target of elements) {
+    for (const parent of elements) {
+        if (target === parent) continue;
+        tests.push([target.cloneNode(true), parent.cloneNode(true)])
+    }
+}
+
+const test_container = document.getElementById("test_container");
+
+/**
+ * Test that if two elements in an event target chain have activation behavior,
+ * only one of them will be activated.
+ *
+ * Each child of <template> represents one case of activation behavior.
+ * The behavior should be triggered by clicking the element of class click
+ * and will manifest as a call to activated().
+ *
+ * For each [target, parent] in tests, we make target a descendant of parent
+ * and test that only target gets activated when dispatching a click.
+ */
+for (let i = 0; i < tests.length; i++) {
+    let [target, parent] = tests[i];
+    async_test(function(t) {
+        let test = document.createElement("div");
+        test_container.appendChild(test);
+        test.appendChild(parent);
+        getContainer(parent).appendChild(target);
+
+        // for later filtering out the activations belonging to this test
+        for (let e of test.getElementsByClassName("activates")) {
+            e.classList.add("test"+i);
+        }
+        for (let e of test.querySelectorAll("a, area")) {
+            e.href = "#test"+i+"_link";
+        }
+
+        getClickTarget(target).click();
+
+        // Need to spin event loop twice, as some clicks might dispatch another task
+        t.step_timeout(() => {
+            t.step_timeout(t.step_func_done(() => {
+                    assert_array_equals(getActivations(i), getExpectedActivations(target));
+            }), 0);
+        }, 0);
+
+        t.add_cleanup(function() {
+            test_container.removeChild(test);
+        });
+    }, `When clicking child ${toString(target)} of parent ${toString(parent)}, only child should be activated.`);
+}
+</script>

+ 73 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-target-moved.html

@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title> Determined event propagation path - target moved </title>
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<table id="table" border="1" style="display: none">
+    <tbody id="table-body">
+    <tr id="table-row">
+        <td id="table-cell">Shady Grove</td>
+        <td>Aeolian</td>
+    </tr>
+    <tr id="parent">
+        <td id="target">Over the river, Charlie</td>
+        <td>Dorian</td>
+    </tr>
+    </tbody>
+</table>
+<script>
+test(function() {
+    var event_type = "foo";
+    var target = document.getElementById("target");
+    var parent = document.getElementById("parent");
+    var tbody = document.getElementById("table-body");
+    var table = document.getElementById("table");
+    var body = document.body;
+    var html = document.documentElement;
+    var targets = [window, document, html, body, table, tbody, parent, target];
+    var expected_targets = targets.concat([target, parent, tbody, table, body, html, document, window]);
+    var phases = [
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.AT_TARGET,
+        Event.AT_TARGET,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+    ];
+
+    var actual_targets = [], actual_phases = [];
+    var test_event = this.step_func(function(evt) {
+        if (parent === target.parentNode) {
+            var table_row = document.getElementById("table-row");
+            table_row.appendChild(parent.removeChild(target));
+        }
+
+        actual_targets.push(evt.currentTarget);
+        actual_phases.push(evt.eventPhase);
+    });
+
+    for (var i = 0; i < targets.length; i++) {
+        targets[i].addEventListener(event_type, test_event, true);
+        targets[i].addEventListener(event_type, test_event, false);
+    }
+
+    var evt = document.createEvent("Event");
+    evt.initEvent(event_type, true, true);
+    target.dispatchEvent(evt);
+
+    assert_array_equals(actual_targets, expected_targets, "targets");
+    assert_array_equals(actual_phases, phases, "phases");
+}, "Event propagation path when an element in it is moved within the DOM");
+</script>

+ 72 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-target-removed.html

@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Determined event propagation path - target removed</title>
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<div id=log></div>
+<table id="table" border="1" style="display: none">
+    <tbody id="table-body">
+    <tr id="table-row">
+        <td id="table-cell">Shady Grove</td>
+        <td>Aeolian</td>
+    </tr>
+    <tr id="parent">
+        <td id="target">Over the river, Charlie</td>
+        <td>Dorian</td>
+    </tr>
+    </tbody>
+</table>
+<script>
+test(function() {
+    var event_type = "foo";
+    var target = document.getElementById("target");
+    var parent = document.getElementById("parent");
+    var tbody = document.getElementById("table-body");
+    var table = document.getElementById("table");
+    var body = document.body;
+    var html = document.documentElement;
+    var targets = [window, document, html, body, table, tbody, parent, target];
+    var expected_targets = targets.concat([target, parent, tbody, table, body, html, document, window]);
+    var phases = [
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.CAPTURING_PHASE,
+        Event.AT_TARGET,
+        Event.AT_TARGET,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+        Event.BUBBLING_PHASE,
+    ];
+
+    var actual_targets = [], actual_phases = [];
+    var test_event = this.step_func(function(evt) {
+        if (parent === target.parentNode) {
+            parent.removeChild(target);
+        }
+
+        actual_targets.push(evt.currentTarget);
+        actual_phases.push(evt.eventPhase);
+    });
+
+    for (var i = 0; i < targets.length; i++) {
+        targets[i].addEventListener(event_type, test_event, true);
+        targets[i].addEventListener(event_type, test_event, false);
+    }
+
+    var evt = document.createEvent("Event");
+    evt.initEvent(event_type, true, true);
+    target.dispatchEvent(evt);
+
+    assert_array_equals(actual_targets, expected_targets, "targets");
+    assert_array_equals(actual_phases, phases, "phases");
+}, "Event propagation path when an element in it is removed from the DOM");
+</script>

+ 69 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-throwing-multiple-globals.html

@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<body>
+<script>
+function createIframe(t, srcdoc = '') {
+  let iframe = document.createElement('iframe');
+  iframe.srcdoc = srcdoc;
+  t.add_cleanup(() => iframe.remove());
+  return new Promise((resolve, reject) => {
+    iframe.addEventListener('load', () => resolve(iframe.contentWindow));
+    document.body.appendChild(iframe);
+  });
+}
+
+// Returns a promise which will resolve with the next error event fired at any
+// of `windows`, after the invocation of this function. Once one does, this
+// function removes its listeners and produces that error event so that it can
+// be examined (most notably for which global proxy it was targeted at).
+async function nextErrorEvent(windows) {
+  let listener;
+  let p = new Promise((resolve, reject) => {
+    listener = (event) => { resolve(event); event.preventDefault(); };
+  });
+  for (let w of windows) {
+    w.addEventListener('error', listener);
+  }
+  try {
+    return await p;
+  } finally {
+    for (let w of windows) {
+      w.removeEventListener('error', listener);
+    }
+  }
+}
+
+promise_test(async t => {
+  let w = await createIframe(t, `<script>function listener() { throw new Error(); }<`+`/script>`);
+  let w2 = await createIframe(t);
+
+  let target = new w2.EventTarget();
+  target.addEventListener('party', w.listener);
+  let nextErrorPromise = nextErrorEvent([self, w, w2]);
+  target.dispatchEvent(new Event('party'));
+  let errorEvent = await nextErrorPromise;
+  if (errorEvent.error) {
+    assert_true(errorEvent.error instanceof w.Error, 'error should be an instance created inside the listener function');
+  }
+  assert_equals(errorEvent.target, w, `error event should target listener's global but instead targets ${event.currentTarget === w2 ? 'target\'s global' : 'test harness global'}`);
+}, 'exception thrown in event listener function should result in error event on listener\'s global');
+
+promise_test(async t => {
+  let w = await createIframe(t, `<script>listener = {};<`+`/script>`);
+  let w2 = await createIframe(t, `<script>handleEvent = () => { throw new Error; };<`+`/script>`);
+  let w3 = await createIframe(t);
+  w.listener.handleEvent = w2.handleEvent;
+
+  let target = new w3.EventTarget();
+  target.addEventListener('party', w.listener);
+  let nextErrorPromise = nextErrorEvent([self, w, w2, w3]);
+  target.dispatchEvent(new Event('party'));
+  let errorEvent = await nextErrorPromise;
+  if (errorEvent.error) {
+    assert_true(errorEvent.error instanceof w2.Error, 'error should be an instance created inside the listener function');
+  }
+  assert_equals(errorEvent.target, w, `error event should target listener's global but instead targets ${event.currentTarget === w2 ? 'target\'s global' : event.currentTarget === w3 ? 'function\'s global' : 'test harness global'}`);
+}, 'exception thrown in event listener interface object should result in error event on listener\'s global');
+</script>
+</body>

+ 51 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-dispatch-throwing.html

@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<title>Throwing in event listeners</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+setup({allow_uncaught_exception:true})
+
+test(function() {
+    var errorEvents = 0;
+    window.onerror = this.step_func(function(e) {
+        assert_equals(typeof e, 'string');
+        ++errorEvents;
+    });
+
+    var element = document.createElement('div');
+
+    element.addEventListener('click', function() {
+        throw new Error('Error from only listener');
+    });
+
+    element.dispatchEvent(new Event('click'));
+
+    assert_equals(errorEvents, 1);
+}, "Throwing in event listener with a single listeners");
+
+test(function() {
+    var errorEvents = 0;
+    window.onerror = this.step_func(function(e) {
+        assert_equals(typeof e, 'string');
+        ++errorEvents;
+    });
+
+    var element = document.createElement('div');
+
+    var secondCalled = false;
+
+    element.addEventListener('click', function() {
+        throw new Error('Error from first listener');
+    });
+    element.addEventListener('click', this.step_func(function() {
+        secondCalled = true;
+    }), false);
+
+    element.dispatchEvent(new Event('click'));
+
+    assert_equals(errorEvents, 1);
+    assert_true(secondCalled);
+}, "Throwing in event listener with multiple listeners");
+</script>

+ 83 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-init-while-dispatching.html

@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Re-initializing events while dispatching them</title>
+<link rel="author" title="Josh Matthews" href="mailto:josh@joshmatthews.net">
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var events = {
+  'KeyboardEvent': {
+    'constructor': function() { return new KeyboardEvent("type", {key: "A"}); },
+    'init': function(ev) { ev.initKeyboardEvent("type2", true, true, null, "a", 1, "", true, "") },
+    'check': function(ev) {
+       assert_equals(ev.key, "A", "initKeyboardEvent key setter should short-circuit");
+       assert_false(ev.repeat, "initKeyboardEvent repeat setter should short-circuit");
+       assert_equals(ev.location, 0, "initKeyboardEvent location setter should short-circuit");
+     }
+  },
+  'MouseEvent': {
+    'constructor': function() { return new MouseEvent("type"); },
+    'init': function(ev) { ev.initMouseEvent("type2", true, true, null, 0, 1, 1, 1, 1, true, true, true, true, 1, null) },
+    'check': function(ev) {
+      assert_equals(ev.screenX, 0, "initMouseEvent screenX setter should short-circuit");
+      assert_equals(ev.screenY, 0, "initMouseEvent screenY setter should short-circuit");
+      assert_equals(ev.clientX, 0, "initMouseEvent clientX setter should short-circuit");
+      assert_equals(ev.clientY, 0, "initMouseEvent clientY setter should short-circuit");
+      assert_false(ev.ctrlKey, "initMouseEvent ctrlKey setter should short-circuit");
+      assert_false(ev.altKey, "initMouseEvent altKey setter should short-circuit");
+      assert_false(ev.shiftKey, "initMouseEvent shiftKey setter should short-circuit");
+      assert_false(ev.metaKey, "initMouseEvent metaKey setter should short-circuit");
+      assert_equals(ev.button, 0, "initMouseEvent button setter should short-circuit");
+    }
+  },
+  'CustomEvent': {
+    'constructor': function() { return new CustomEvent("type") },
+    'init': function(ev) { ev.initCustomEvent("type2", true, true, 1) },
+    'check': function(ev) {
+      assert_equals(ev.detail, null, "initCustomEvent detail setter should short-circuit");
+    }
+  },
+  'UIEvent': {
+    'constructor': function() { return new UIEvent("type") },
+    'init': function(ev) { ev.initUIEvent("type2", true, true, window, 1) },
+    'check': function(ev) {
+      assert_equals(ev.view, null, "initUIEvent view setter should short-circuit");
+      assert_equals(ev.detail, 0, "initUIEvent detail setter should short-circuit");
+    }
+  },
+  'Event': {
+    'constructor': function() { return new Event("type") },
+    'init': function(ev) { ev.initEvent("type2", true, true) },
+    'check': function(ev) {
+      assert_equals(ev.bubbles, false, "initEvent bubbles setter should short-circuit");
+      assert_equals(ev.cancelable, false, "initEvent cancelable setter should short-circuit");
+      assert_equals(ev.type, "type", "initEvent type setter should short-circuit");
+    }
+  }
+};
+
+var names = Object.keys(events);
+for (var i = 0; i < names.length; i++) {
+  var t = async_test("Calling init" + names[i] + " while dispatching.");
+  t.step(function() {
+    var e = events[names[i]].constructor();
+
+    var target = document.createElement("div")
+    target.addEventListener("type", t.step_func(function() {
+      events[names[i]].init(e);
+
+      var o = e;
+      while ((o = Object.getPrototypeOf(o))) {
+        if (!(o.constructor.name in events)) {
+          break;
+        }
+        events[o.constructor.name].check(e);
+      }
+    }), false);
+
+    assert_equals(target.dispatchEvent(e), true, "dispatchEvent must return true")
+  });
+  t.done();
+}
+</script>

+ 136 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-initEvent.html

@@ -0,0 +1,136 @@
+<!DOCTYPE html>
+<title>Event.initEvent</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var booleans = [true, false];
+booleans.forEach(function(bubbles) {
+  booleans.forEach(function(cancelable) {
+    test(function() {
+      var e = document.createEvent("Event")
+      e.initEvent("type", bubbles, cancelable)
+
+      // Step 2.
+      // Stop (immediate) propagation flag is tested later
+      assert_equals(e.defaultPrevented, false, "defaultPrevented")
+      assert_equals(e.returnValue, true, "returnValue")
+      // Step 3.
+      assert_equals(e.isTrusted, false, "isTrusted")
+      // Step 4.
+      assert_equals(e.target, null, "target")
+      assert_equals(e.srcElement, null, "srcElement")
+      // Step 5.
+      assert_equals(e.type, "type", "type")
+      // Step 6.
+      assert_equals(e.bubbles, bubbles, "bubbles")
+      // Step 7.
+      assert_equals(e.cancelable, cancelable, "cancelable")
+    }, "Properties of initEvent(type, " + bubbles + ", " + cancelable + ")")
+  })
+})
+
+test(function() {
+  var e = document.createEvent("Event")
+  e.initEvent("type 1", true, false)
+  assert_equals(e.type, "type 1", "type (first init)")
+  assert_equals(e.bubbles, true, "bubbles (first init)")
+  assert_equals(e.cancelable, false, "cancelable (first init)")
+
+  e.initEvent("type 2", false, true)
+  assert_equals(e.type, "type 2", "type (second init)")
+  assert_equals(e.bubbles, false, "bubbles (second init)")
+  assert_equals(e.cancelable, true, "cancelable (second init)")
+}, "Calling initEvent multiple times (getting type).")
+
+test(function() {
+  // https://bugzilla.mozilla.org/show_bug.cgi?id=998809
+  var e = document.createEvent("Event")
+  e.initEvent("type 1", true, false)
+  assert_equals(e.bubbles, true, "bubbles (first init)")
+  assert_equals(e.cancelable, false, "cancelable (first init)")
+
+  e.initEvent("type 2", false, true)
+  assert_equals(e.type, "type 2", "type (second init)")
+  assert_equals(e.bubbles, false, "bubbles (second init)")
+  assert_equals(e.cancelable, true, "cancelable (second init)")
+}, "Calling initEvent multiple times (not getting type).")
+
+// Step 2.
+async_test(function() {
+  // https://www.w3.org/Bugs/Public/show_bug.cgi?id=17715
+
+  var e = document.createEvent("Event")
+  e.initEvent("type", false, false)
+  assert_equals(e.type, "type", "type (first init)")
+  assert_equals(e.bubbles, false, "bubbles (first init)")
+  assert_equals(e.cancelable, false, "cancelable (first init)")
+
+  var target = document.createElement("div")
+  target.addEventListener("type", this.step_func(function() {
+    e.initEvent("fail", true, true)
+    assert_equals(e.type, "type", "type (second init)")
+    assert_equals(e.bubbles, false, "bubbles (second init)")
+    assert_equals(e.cancelable, false, "cancelable (second init)")
+  }), false)
+
+  assert_equals(target.dispatchEvent(e), true, "dispatchEvent must return true")
+
+  this.done()
+}, "Calling initEvent must not have an effect during dispatching.")
+
+test(function() {
+  var e = document.createEvent("Event")
+  e.stopPropagation()
+  e.initEvent("type", false, false)
+  var target = document.createElement("div")
+  var called = false
+  target.addEventListener("type", function() { called = true }, false)
+  assert_false(e.cancelBubble, "cancelBubble must be false")
+  assert_true(target.dispatchEvent(e), "dispatchEvent must return true")
+  assert_true(called, "Listener must be called")
+}, "Calling initEvent must unset the stop propagation flag.")
+
+test(function() {
+  var e = document.createEvent("Event")
+  e.stopImmediatePropagation()
+  e.initEvent("type", false, false)
+  var target = document.createElement("div")
+  var called = false
+  target.addEventListener("type", function() { called = true }, false)
+  assert_true(target.dispatchEvent(e), "dispatchEvent must return true")
+  assert_true(called, "Listener must be called")
+}, "Calling initEvent must unset the stop immediate propagation flag.")
+
+async_test(function() {
+  var e = document.createEvent("Event")
+  e.initEvent("type", false, false)
+
+  var target = document.createElement("div")
+  target.addEventListener("type", this.step_func(function() {
+    e.initEvent("type2", true, true);
+    assert_equals(e.type, "type", "initEvent type setter should short-circuit");
+    assert_false(e.bubbles, "initEvent bubbles setter should short-circuit");
+    assert_false(e.cancelable, "initEvent cancelable setter should short-circuit");
+  }), false)
+  assert_equals(target.dispatchEvent(e), true, "dispatchEvent must return true")
+
+  this.done()
+}, "Calling initEvent during propagation.")
+
+test(function() {
+  var e = document.createEvent("Event")
+  assert_throws_js(TypeError, function() {
+    e.initEvent()
+  })
+}, "First parameter to initEvent should be mandatory.")
+
+test(function() {
+  var e = document.createEvent("Event")
+  e.initEvent("type")
+  assert_equals(e.type, "type", "type")
+  assert_false(e.bubbles, "bubbles")
+  assert_false(e.cancelable, "cancelable")
+}, "Tests initEvent's default parameter values.")
+</script>

+ 11 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-isTrusted.any.js

@@ -0,0 +1,11 @@
+test(function() {
+  var desc1 = Object.getOwnPropertyDescriptor(new Event("x"), "isTrusted");
+  assert_not_equals(desc1, undefined);
+  assert_equals(typeof desc1.get, "function");
+
+  var desc2 = Object.getOwnPropertyDescriptor(new Event("x"), "isTrusted");
+  assert_not_equals(desc2, undefined);
+  assert_equals(typeof desc2.get, "function");
+
+  assert_equals(desc1.get, desc2.get);
+});

+ 48 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-propagation.html

@@ -0,0 +1,48 @@
+<!doctype html>
+<title>Event propagation tests</title>
+<link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
+<div id=log></div>
+<script src=../../resources/testharness.js></script>
+<script src=../../resources/testharnessreport.js></script>
+<script>
+"use strict";
+
+function testPropagationFlag(ev, expected, desc) {
+  test(function() {
+    var called = false;
+    var callback = function() { called = true };
+    this.add_cleanup(function() {
+      document.head.removeEventListener("foo", callback)
+    });
+    document.head.addEventListener("foo", callback);
+    document.head.dispatchEvent(ev);
+    assert_equals(called, expected, "Propagation flag");
+    // dispatchEvent resets the propagation flags so it will happily dispatch
+    // the event the second time around.
+    document.head.dispatchEvent(ev);
+    assert_equals(called, true, "Propagation flag after first dispatch");
+  }, desc);
+}
+
+var ev = document.createEvent("Event");
+ev.initEvent("foo", true, false);
+testPropagationFlag(ev, true, "Newly-created Event");
+ev.stopPropagation();
+testPropagationFlag(ev, false, "After stopPropagation()");
+ev.initEvent("foo", true, false);
+testPropagationFlag(ev, true, "Reinitialized after stopPropagation()");
+
+var ev = document.createEvent("Event");
+ev.initEvent("foo", true, false);
+ev.stopImmediatePropagation();
+testPropagationFlag(ev, false, "After stopImmediatePropagation()");
+ev.initEvent("foo", true, false);
+testPropagationFlag(ev, true, "Reinitialized after stopImmediatePropagation()");
+
+var ev = document.createEvent("Event");
+ev.initEvent("foo", true, false);
+ev.cancelBubble = true;
+testPropagationFlag(ev, false, "After cancelBubble=true");
+ev.initEvent("foo", true, false);
+testPropagationFlag(ev, true, "Reinitialized after cancelBubble=true");
+</script>

+ 64 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-returnValue.html

@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Event.returnValue</title>
+  <link rel="author" title="Chris Rebert" href="http://chrisrebert.com">
+  <link rel="help" href="https://dom.spec.whatwg.org/#dom-event-returnvalue">
+  <meta name="flags" content="dom">
+  <script src="../../resources/testharness.js"></script>
+  <script src="../../resources/testharnessreport.js"></script>
+</head>
+<body>
+  <div id="log"></div>
+  <script>
+test(function() {
+  var ev = new Event("foo");
+  assert_true(ev.returnValue, "returnValue");
+}, "When an event is created, returnValue should be initialized to true.");
+test(function() {
+  var ev = new Event("foo", {"cancelable": false});
+  assert_false(ev.cancelable, "cancelable (before)");
+  ev.preventDefault();
+  assert_false(ev.cancelable, "cancelable (after)");
+  assert_true(ev.returnValue, "returnValue");
+}, "preventDefault() should not change returnValue if cancelable is false.");
+test(function() {
+  var ev = new Event("foo", {"cancelable": false});
+  assert_false(ev.cancelable, "cancelable (before)");
+  ev.returnValue = false;
+  assert_false(ev.cancelable, "cancelable (after)");
+  assert_true(ev.returnValue, "returnValue");
+}, "returnValue=false should have no effect if cancelable is false.");
+test(function() {
+  var ev = new Event("foo", {"cancelable": true});
+  assert_true(ev.cancelable, "cancelable (before)");
+  ev.preventDefault();
+  assert_true(ev.cancelable, "cancelable (after)");
+  assert_false(ev.returnValue, "returnValue");
+}, "preventDefault() should change returnValue if cancelable is true.");
+test(function() {
+  var ev = new Event("foo", {"cancelable": true});
+  assert_true(ev.cancelable, "cancelable (before)");
+  ev.returnValue = false;
+  assert_true(ev.cancelable, "cancelable (after)");
+  assert_false(ev.returnValue, "returnValue");
+}, "returnValue should change returnValue if cancelable is true.");
+test(function() {
+  var ev = document.createEvent("Event");
+  ev.returnValue = false;
+  ev.initEvent("foo", true, true);
+  assert_true(ev.bubbles, "bubbles");
+  assert_true(ev.cancelable, "cancelable");
+  assert_true(ev.returnValue, "returnValue");
+}, "initEvent should unset returnValue.");
+test(function() {
+  var ev = new Event("foo", {"cancelable": true});
+  ev.preventDefault();
+  ev.returnValue = true;// no-op
+  assert_true(ev.defaultPrevented);
+  assert_false(ev.returnValue);
+}, "returnValue=true should have no effect once the canceled flag was set.");
+  </script>
+</body>
+</html>

+ 34 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-stopImmediatePropagation.html

@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Event's stopImmediatePropagation</title>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-event-stopimmediatepropagation">
+<link rel="author" href="mailto:d@domenic.me" title="Domenic Denicola">
+
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+
+<div id="target"></div>
+
+<script>
+"use strict";
+
+setup({ single_test: true });
+
+const target = document.querySelector("#target");
+
+let timesCalled = 0;
+target.addEventListener("test", e => {
+  ++timesCalled;
+  e.stopImmediatePropagation();
+  assert_equals(e.cancelBubble, true, "The stop propagation flag must have been set");
+});
+target.addEventListener("test", () => {
+  ++timesCalled;
+});
+
+const e = new Event("test");
+target.dispatchEvent(e);
+assert_equals(timesCalled, 1, "The second listener must not have been called");
+
+done();
+</script>

+ 20 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-stopPropagation-cancel-bubbling.html

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<link rel="author" title="Joey Arhar" href="mailto:jarhar@chromium.org">
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<body>
+<script>
+test(t => {
+  const element = document.createElement('div');
+
+  element.addEventListener('click', () => {
+    event.stopPropagation();
+  }, { capture: true });
+
+  element.addEventListener('click',
+    t.unreached_func('stopPropagation in the capture handler should have canceled this bubble handler.'));
+
+  element.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true }));
+});
+</script>

+ 179 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-subclasses-constructors.html

@@ -0,0 +1,179 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Event constructors</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function assert_props(iface, event, defaults) {
+  assert_true(event instanceof self[iface]);
+  expected[iface].properties.forEach(function(p) {
+    var property = p[0], value = p[defaults ? 1 : 2];
+    assert_true(property in event,
+                "Event " + format_value(event) + " should have a " +
+                property + " property");
+    assert_equals(event[property], value,
+                  "The value of the " + property + " property should be " +
+                  format_value(value));
+  });
+  if ("parent" in expected[iface]) {
+    assert_props(expected[iface].parent, event, defaults);
+  }
+}
+
+// Class declarations don't go on the global by default, so put it there ourselves:
+
+self.SubclassedEvent = class SubclassedEvent extends Event {
+  constructor(name, props) {
+    super(name, props);
+    if (props && typeof(props) == "object" && "customProp" in props) {
+      this.customProp = props.customProp;
+    } else {
+      this.customProp = 5;
+    }
+  }
+
+  get fixedProp() {
+    return 17;
+  }
+}
+
+var EventModifierInit = [
+  ["ctrlKey", false, true],
+  ["shiftKey", false, true],
+  ["altKey", false, true],
+  ["metaKey", false, true],
+];
+var expected = {
+  "Event": {
+    "properties": [
+      ["bubbles", false, true],
+      ["cancelable", false, true],
+      ["isTrusted", false, false],
+    ],
+  },
+
+  "UIEvent": {
+    "parent": "Event",
+    "properties": [
+      ["view", null, window],
+      ["detail", 0, 7],
+    ],
+  },
+
+  "FocusEvent": {
+    "parent": "UIEvent",
+    "properties": [
+      ["relatedTarget", null, document],
+    ],
+  },
+
+  "MouseEvent": {
+    "parent": "UIEvent",
+    "properties": EventModifierInit.concat([
+      ["screenX", 0, 40],
+      ["screenY", 0, 40],
+      ["clientX", 0, 40],
+      ["clientY", 0, 40],
+      ["button", 0, 40],
+      ["buttons", 0, 40],
+      ["relatedTarget", null, document],
+    ]),
+  },
+
+  "WheelEvent": {
+    "parent": "MouseEvent",
+    "properties": [
+      ["deltaX", 0.0, 3.1],
+      ["deltaY", 0.0, 3.1],
+      ["deltaZ", 0.0, 3.1],
+      ["deltaMode", 0, 40],
+    ],
+  },
+
+  "KeyboardEvent": {
+    "parent": "UIEvent",
+    "properties": EventModifierInit.concat([
+      ["key", "", "string"],
+      ["code", "", "string"],
+      ["location", 0, 7],
+      ["repeat", false, true],
+      ["isComposing", false, true],
+      ["charCode", 0, 7],
+      ["keyCode", 0, 7],
+      ["which", 0, 7],
+    ]),
+  },
+
+  "CompositionEvent": {
+    "parent": "UIEvent",
+    "properties": [
+      ["data", "", "string"],
+    ],
+  },
+
+  "SubclassedEvent": {
+    "parent": "Event",
+    "properties": [
+      ["customProp", 5, 8],
+      ["fixedProp", 17, 17],
+    ],
+  },
+};
+
+Object.keys(expected).forEach(function(iface) {
+  test(function() {
+    var event = new self[iface]("type");
+    assert_props(iface, event, true);
+  }, iface + " constructor (no argument)");
+
+  test(function() {
+    var event = new self[iface]("type", undefined);
+    assert_props(iface, event, true);
+  }, iface + " constructor (undefined argument)");
+
+  test(function() {
+    var event = new self[iface]("type", null);
+    assert_props(iface, event, true);
+  }, iface + " constructor (null argument)");
+
+  test(function() {
+    var event = new self[iface]("type", {});
+    assert_props(iface, event, true);
+  }, iface + " constructor (empty argument)");
+
+  test(function() {
+    var dictionary = {};
+    expected[iface].properties.forEach(function(p) {
+      var property = p[0], value = p[1];
+      dictionary[property] = value;
+    });
+    var event = new self[iface]("type", dictionary);
+    assert_props(iface, event, true);
+  }, iface + " constructor (argument with default values)");
+
+  test(function() {
+    function fill_in(iface, dictionary) {
+      if ("parent" in expected[iface]) {
+        fill_in(expected[iface].parent, dictionary)
+      }
+      expected[iface].properties.forEach(function(p) {
+        var property = p[0], value = p[2];
+        dictionary[property] = value;
+      });
+    }
+
+    var dictionary = {};
+    fill_in(iface, dictionary);
+
+    var event = new self[iface]("type", dictionary);
+    assert_props(iface, event, false);
+  }, iface + " constructor (argument with non-default values)");
+});
+
+test(function () {
+  assert_throws_js(TypeError, function() {
+    new UIEvent("x", { view: 7 })
+  });
+}, "UIEvent constructor (view argument with wrong type)")
+</script>

+ 27 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-timestamp-cross-realm-getter.html

@@ -0,0 +1,27 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>event.timeStamp is initialized using event's relevant global object</title>
+<link rel="help" href="https://dom.spec.whatwg.org/#ref-for-dom-event-timestamp%E2%91%A1">
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+
+<body>
+<script>
+const t = async_test();
+t.step_timeout(() => {
+  const iframeDelayed = document.createElement("iframe");
+  iframeDelayed.onload = t.step_func_done(() => {
+    // Use eval() to eliminate false-positive test result for WebKit builds before r280256,
+    // which invoked WebIDL accessors in context of lexical (caller) global object.
+    const timeStampExpected = iframeDelayed.contentWindow.eval(`new Event("foo").timeStamp`);
+    const eventDelayed = new iframeDelayed.contentWindow.Event("foo");
+
+    const {get} = Object.getOwnPropertyDescriptor(Event.prototype, "timeStamp");
+    assert_approx_equals(get.call(eventDelayed), timeStampExpected, 5, "via Object.getOwnPropertyDescriptor");
+
+    Object.setPrototypeOf(eventDelayed, Event.prototype);
+    assert_approx_equals(eventDelayed.timeStamp, timeStampExpected, 5, "via Object.setPrototypeOf");
+  });
+  document.body.append(iframeDelayed);
+}, 1000);
+</script>

+ 16 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-timestamp-high-resolution.html

@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script type="text/javascript">
+'use strict';
+for (let eventType of ["MouseEvent", "KeyboardEvent", "WheelEvent", "FocusEvent"]) {
+    test(function() {
+        let before = performance.now();
+        let e = new window[eventType]('test');
+        let after = performance.now();
+        assert_greater_than_equal(e.timeStamp, before, "Event timestamp should be greater than performance.now() timestamp taken before its creation");
+        assert_less_than_equal(e.timeStamp, after, "Event timestamp should be less than performance.now() timestamp taken after its creation");
+    }, `Constructed ${eventType} timestamp should be high resolution and have the same time origin as performance.now()`);
+}
+</script>

+ 16 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-timestamp-high-resolution.https.html

@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script type="text/javascript">
+'use strict';
+for (let eventType of ["GamepadEvent"]) {
+    test(function() {
+        let before = performance.now();
+        let e = new window[eventType]('test');
+        let after = performance.now();
+        assert_greater_than_equal(e.timeStamp, before, "Event timestamp should be greater than performance.now() timestamp taken before its creation");
+        assert_less_than_equal(e.timeStamp, after, "Event timestamp should be less than performance.now() timestamp taken after its creation");
+    }, `Constructed ${eventType} timestamp should be high resolution and have the same time origin as performance.now()`);
+}
+</script>

+ 49 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-timestamp-safe-resolution.html

@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script type="text/javascript">
+'use strict';
+
+// Computes greatest common divisor of a and b using Euclid's algorithm
+function computeGCD(a, b) {
+  if (!Number.isInteger(a) || !Number.isInteger(b)) {
+    throw new Error('Parameters must be integer numbers');
+  }
+
+  var r;
+  while (b != 0) {
+    r = a % b;
+    a = b;
+    b = r;
+  }
+  return (a < 0) ? -a : a;
+}
+
+// Finds minimum resolution Δ given a set of samples which are known to be in the form of N*Δ.
+// We use GCD of all samples as a simple estimator.
+function estimateMinimumResolution(samples) {
+  var gcd;
+  for (const sample of samples) {
+    gcd = gcd ? computeGCD(gcd, sample) : sample;
+  }
+
+  return gcd;
+}
+
+test(function() {
+  const samples = [];
+  for (var i = 0; i < 1e3; i++) {
+    var deltaInMicroSeconds = 0;
+    const e1 = new MouseEvent('test1');
+    do {
+      const e2 = new MouseEvent('test2');
+      deltaInMicroSeconds = Math.round((e2.timeStamp - e1.timeStamp) * 1000);
+    } while (deltaInMicroSeconds == 0) // only collect non-zero samples
+
+    samples.push(deltaInMicroSeconds);
+  }
+
+  const minResolution = estimateMinimumResolution(samples);
+  assert_greater_than_equal(minResolution, 5);
+}, 'Event timestamp should not have a resolution better than 5 microseconds');
+</script>

+ 35 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-type-empty.html

@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<title>Event.type set to the empty string</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-event-type">
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function do_test(t, e) {
+  assert_equals(e.type, "", "type");
+  assert_equals(e.bubbles, false, "bubbles");
+  assert_equals(e.cancelable, false, "cancelable");
+
+  var target = document.createElement("div");
+  var handled = false;
+  target.addEventListener("", t.step_func(function(e) {
+    handled = true;
+  }));
+  assert_true(target.dispatchEvent(e));
+  assert_true(handled);
+}
+
+async_test(function() {
+  var e = document.createEvent("Event");
+  e.initEvent("", false, false);
+  do_test(this, e);
+  this.done();
+}, "initEvent");
+
+async_test(function() {
+  var e = new Event("");
+  do_test(this, e);
+  this.done();
+}, "Constructor");
+</script>

+ 22 - 0
Tests/LibWeb/Text/input/wpt-import/dom/events/Event-type.html

@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<title>Event.type</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-event-type">
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  var e = document.createEvent("Event")
+  assert_equals(e.type, "");
+}, "Event.type should initially be the empty string");
+test(function() {
+  var e = document.createEvent("Event")
+  e.initEvent("foo", false, false)
+  assert_equals(e.type, "foo")
+}, "Event.type should be initialized by initEvent");
+test(function() {
+  var e = new Event("bar")
+  assert_equals(e.type, "bar")
+}, "Event.type should be initialized by the constructor");
+</script>

Деякі файли не було показано, через те що забагато файлів було змінено