Diff
Modified: trunk/LayoutTests/imported/w3c/ChangeLog (233488 => 233489)
--- trunk/LayoutTests/imported/w3c/ChangeLog 2018-07-04 00:05:39 UTC (rev 233488)
+++ trunk/LayoutTests/imported/w3c/ChangeLog 2018-07-04 00:06:32 UTC (rev 233489)
@@ -1,5 +1,30 @@
2018-07-03 Chris Dumez <[email protected]>
+ Improve window.event compliance: Should not be set when target is in shadow tree
+ https://bugs.webkit.org/show_bug.cgi?id=186266
+
+ Reviewed by Ryosuke Niwa.
+
+ Re-sync dom/events web-platform-tests from 59d4a411a8e to gain test coverage.
+
+ * web-platform-tests/dom/events/Event-returnValue-expected.txt:
+ * web-platform-tests/dom/events/Event-returnValue.html:
+ * web-platform-tests/dom/events/event-global-expected.txt: Added.
+ * web-platform-tests/dom/events/event-global-extra.window.js: Added.
+ (async_test.t.frame.onload.t.step_func_done):
+ * web-platform-tests/dom/events/event-global.html: Added.
+ * web-platform-tests/dom/events/event-global.worker-expected.txt: Added.
+ * web-platform-tests/dom/events/event-global.worker.html: Added.
+ * web-platform-tests/dom/events/event-global.worker.js: Added.
+ * web-platform-tests/dom/events/relatedTarget.window.js: Added.
+ (test):
+ (test.t.input.oninput.t.step_func):
+ * web-platform-tests/dom/events/resources/event-global-extra-frame.html: Added.
+ * web-platform-tests/dom/events/resources/w3c-import.log: Added.
+ * web-platform-tests/dom/events/w3c-import.log:
+
+2018-07-03 Chris Dumez <[email protected]>
+
Implement support for Element.toggleAttribute
https://bugs.webkit.org/show_bug.cgi?id=186883
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/Event-returnValue-expected.txt (233488 => 233489)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/Event-returnValue-expected.txt 2018-07-04 00:05:39 UTC (rev 233488)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/Event-returnValue-expected.txt 2018-07-04 00:06:32 UTC (rev 233489)
@@ -5,5 +5,5 @@
PASS preventDefault() should change returnValue if cancelable is true.
PASS returnValue should change returnValue if cancelable is true.
PASS initEvent should unset returnValue.
-FAIL returnValue=true should have no effect once the canceled flag was set. assert_true: expected true got false
+PASS returnValue=true should have no effect once the canceled flag was set.
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/Event-returnValue.html (233488 => 233489)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/Event-returnValue.html 2018-07-04 00:05:39 UTC (rev 233488)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/Event-returnValue.html 2018-07-04 00:06:32 UTC (rev 233489)
@@ -53,7 +53,7 @@
assert_true(ev.returnValue, "returnValue");
}, "initEvent should unset returnValue.");
test(function() {
- var ev = new Event("foo");
+ var ev = new Event("foo", {"cancelable": true});
ev.preventDefault();
ev.returnValue = true;// no-op
assert_true(ev.defaultPrevented);
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/event-global-expected.txt (0 => 233489)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/event-global-expected.txt (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/event-global-expected.txt 2018-07-04 00:06:32 UTC (rev 233489)
@@ -0,0 +1,8 @@
+
+PASS 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)
+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
+
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/event-global-extra.window.js (0 => 233489)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/event-global-extra.window.js (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/event-global-extra.window.js 2018-07-04 00:06:32 UTC (rev 233489)
@@ -0,0 +1,90 @@
+const otherWindow = document.body.appendChild(document.createElement("iframe")).contentWindow;
+
+["EventTarget", "XMLHttpRequest"].forEach(constructorName => {
+ async_test(t => {
+ const eventTarget = new otherWindow[constructorName]();
+ eventTarget.addEventListener("hi", t.step_func_done(e => {
+ assert_equals(otherWindow.event, undefined);
+ assert_equals(e, window.event);
+ }));
+ eventTarget.dispatchEvent(new Event("hi"));
+ }, "window.event for constructors from another global: " + constructorName);
+});
+
+// XXX: It would be good to test a subclass of EventTarget once we sort out
+// https://github.com/heycam/webidl/issues/540
+
+async_test(t => {
+ const element = document.body.appendChild(otherWindow.document.createElement("meh"));
+ element.addEventListener("yo", t.step_func_done(e => {
+ assert_equals(e, window.event);
+ }));
+ element.dispatchEvent(new Event("yo"));
+}, "window.event and element from another document");
+
+async_test(t => {
+ const doc = otherWindow.document,
+ element = doc.body.appendChild(doc.createElement("meh")),
+ child = element.appendChild(doc.createElement("bleh"));
+ element.addEventListener("yoyo", t.step_func(e => {
+ document.body.appendChild(element);
+ assert_equals(element.ownerDocument, document);
+ assert_equals(window.event, e);
+ assert_equals(otherWindow.event, undefined);
+ }), true);
+ element.addEventListener("yoyo", t.step_func(e => {
+ assert_equals(element.ownerDocument, document);
+ assert_equals(window.event, e);
+ assert_equals(otherWindow.event, undefined);
+ }), true);
+ child.addEventListener("yoyo", t.step_func_done(e => {
+ assert_equals(child.ownerDocument, document);
+ assert_equals(window.event, e);
+ assert_equals(otherWindow.event, undefined);
+ }));
+ child.dispatchEvent(new Event("yoyo"));
+}, "window.event and moving an element post-dispatch");
+
+test(t => {
+ const host = document.createElement("div"),
+ shadow = host.attachShadow({ mode: "open" }),
+ child = shadow.appendChild(document.createElement("trala")),
+ furtherChild = child.appendChild(document.createElement("waddup"));
+ let counter = 0;
+ host.addEventListener("hi", t.step_func(e => {
+ assert_equals(window.event, e);
+ assert_equals(counter++, 3);
+ }));
+ child.addEventListener("hi", t.step_func(e => {
+ assert_equals(window.event, e);
+ assert_equals(counter++, 2);
+ }));
+ furtherChild.addEventListener("hi", t.step_func(e => {
+ host.appendChild(child);
+ assert_equals(window.event, e);
+ assert_equals(counter++, 0);
+ }));
+ furtherChild.addEventListener("hi", t.step_func(e => {
+ assert_equals(window.event, e);
+ assert_equals(counter++, 1);
+ }));
+ furtherChild.dispatchEvent(new Event("hi", { composed: true, bubbles: true }));
+ assert_equals(counter, 4);
+}, "window.event should not be affected by nodes moving post-dispatch");
+
+async_test(t => {
+ const frame = document.body.appendChild(document.createElement("iframe"));
+ frame.src = ""
+ frame._onload_ = t.step_func_done(() => {
+ const event = new Event("hi");
+ document.addEventListener("hi", frame.contentWindow.listener); // listener intentionally not wrapped in t.step_func
+ document.addEventListener("hi", t.step_func(e => {
+ assert_equals(event, e);
+ assert_equals(window.event, e);
+ }));
+ document.dispatchEvent(event);
+ assert_equals(frameState.event, event);
+ assert_equals(frameState.windowEvent, event);
+ assert_equals(frameState.parentEvent, undefined);
+ });
+}, "Listener from a different global");
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/event-global.html (0 => 233489)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/event-global.html (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/event-global.html 2018-07-04 00:06:32 UTC (rev 233489)
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<title>window.event tests</title>
+<link rel="author" title="Mike Taylor" href=""
+<script src=""
+<script src=""
+<div id=log></div>
+<script>
+test(t => {
+ assert_own_property(window, "event");
+ assert_equals(window.event, undefined);
+}, "event exists on window, which is initially set to undefined");
+
+async_test(t => {
+ let target = document.createElement("div");
+ assert_equals(window.event, undefined, "undefined before dispatch");
+
+ let clickEvent = new Event("click");
+ target.addEventListener("click", t.step_func_done(e => {
+ assert_equals(window.event, clickEvent, "window.event set to current event during dispatch");
+ }));
+
+ target.dispatchEvent(clickEvent);
+ assert_equals(window.event, undefined, "undefined after dispatch");
+}, "window.event is only defined during dispatch");
+
+async_test(t => {
+ let parent = document.createElement("div");
+ let root = parent.attachShadow({mode: "closed"});
+ let span = document.createElement("span");
+ root.appendChild(span);
+
+ span.addEventListener("test", t.step_func(e => {
+ assert_equals(window.event, undefined);
+ assert_not_equals(window.event, e);
+ }));
+
+ parent.addEventListener("test", t.step_func_done(e => {
+ assert_equals(window.event, e);
+ assert_not_equals(window.event, undefined);
+ }));
+
+ parent.dispatchEvent(new Event("test", {composed: true}));
+}, "window.event is undefined if the target is in a shadow tree (event dispatched outside shadow tree)");
+
+async_test(t => {
+ let parent = document.createElement("div");
+ let root = parent.attachShadow({mode: "closed"});
+ let span = document.createElement("span");
+ root.appendChild(span);
+ let shadowNode = root.firstElementChild;
+
+ shadowNode.addEventListener("test", t.step_func((e) => {
+ assert_not_equals(window.event, e);
+ assert_equals(window.event, undefined);
+ }));
+
+ parent.addEventListener("test", t.step_func_done(e => {
+ assert_equals(window.event, e);
+ assert_not_equals(window.event, undefined);
+ }));
+
+ shadowNode.dispatchEvent(new Event("test", {composed: true, bubbles: true}));
+}, "window.event is undefined if the target is in a shadow tree (event dispatched inside shadow tree)");
+
+async_test(t => {
+ let target1 = document.createElement("div");
+ let target2 = document.createElement("div");
+
+ target2.addEventListener("dude", t.step_func(() => {
+ assert_equals(window.event.type, "dude");
+ }));
+
+ target1.addEventListener("cool", t.step_func_done(() => {
+ assert_equals(window.event.type, "cool", "got expected event from global event during dispatch");
+ target2.dispatchEvent(new Event("dude"));
+ assert_equals(window.event.type, "cool", "got expected event from global event after handling a different event handler callback");
+ }));
+
+ target1.dispatchEvent(new Event("cool"));
+}, "window.event is set to the current event during dispatch");
+
+async_test(t => {
+ let target = document.createElement("div");
+
+ target.addEventListener("click", t.step_func_done(e => {
+ assert_equals(e, window.event);
+ }));
+
+ target.dispatchEvent(new Event("click"));
+}, "window.event is set to the current event, which is the event passed to dispatch");
+</script>
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/event-global.worker-expected.txt (0 => 233489)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/event-global.worker-expected.txt (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/event-global.worker-expected.txt 2018-07-04 00:06:32 UTC (rev 233489)
@@ -0,0 +1,3 @@
+
+PASS There's no self.event (that's why we call it window.event) in workers
+
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/event-global.worker.html (0 => 233489)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/event-global.worker.html (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/event-global.worker.html 2018-07-04 00:06:32 UTC (rev 233489)
@@ -0,0 +1 @@
+<!-- This file is required for WebKit test infrastructure to run the templated test -->
\ No newline at end of file
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/event-global.worker.js (0 => 233489)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/event-global.worker.js (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/event-global.worker.js 2018-07-04 00:06:32 UTC (rev 233489)
@@ -0,0 +1,14 @@
+importScripts("/resources/testharness.js");
+test(t => {
+ let seen = false;
+ const event = new Event("hi");
+ assert_equals(self.event, undefined);
+ self.addEventListener("hi", t.step_func(e => {
+ seen = true;
+ assert_equals(self.event, undefined);
+ assert_equals(e, event);
+ }));
+ self.dispatchEvent(event);
+ assert_true(seen);
+}, "There's no self.event (that's why we call it window.event) in workers");
+done();
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/relatedTarget.window.js (0 => 233489)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/relatedTarget.window.js (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/relatedTarget.window.js 2018-07-04 00:06:32 UTC (rev 233489)
@@ -0,0 +1,81 @@
+// https://dom.spec.whatwg.org/#concept-event-dispatch
+
+const host = document.createElement("div"),
+ child = host.appendChild(document.createElement("p")),
+ shadow = host.attachShadow({ mode: "closed" }),
+ slot = shadow.appendChild(document.createElement("slot"));
+
+test(() => {
+ for (target of [shadow, slot]) {
+ for (relatedTarget of [new XMLHttpRequest(), self, host]) {
+ const event = new FocusEvent("demo", { relatedTarget: relatedTarget });
+ target.dispatchEvent(event);
+ assert_equals(event.target, null);
+ assert_equals(event.relatedTarget, null);
+ }
+ }
+}, "Reset if target pointed to a shadow tree");
+
+test(() => {
+ for (relatedTarget of [shadow, slot]) {
+ for (target of [new XMLHttpRequest(), self, host]) {
+ const event = new FocusEvent("demo", { relatedTarget: relatedTarget });
+ target.dispatchEvent(event);
+ assert_equals(event.target, target);
+ assert_equals(event.relatedTarget, host);
+ }
+ }
+}, "Retarget a shadow-tree relatedTarget");
+
+test(t => {
+ const shadowChild = shadow.appendChild(document.createElement("div"));
+ shadowChild.addEventListener("demo", t.step_func(() => document.body.appendChild(shadowChild)));
+ const event = new FocusEvent("demo", { relatedTarget: new XMLHttpRequest() });
+ shadowChild.dispatchEvent(event);
+ assert_equals(shadowChild.parentNode, document.body);
+ assert_equals(event.target, null);
+ assert_equals(event.relatedTarget, null);
+ shadowChild.remove();
+}, "Reset if target pointed to a shadow tree pre-dispatch");
+
+test(t => {
+ const shadowChild = shadow.appendChild(document.createElement("div"));
+ document.body.addEventListener("demo", t.step_func(() => document.body.appendChild(shadowChild)));
+ const event = new FocusEvent("demo", { relatedTarget: shadowChild });
+ document.body.dispatchEvent(event);
+ assert_equals(shadowChild.parentNode, document.body);
+ assert_equals(event.target, document.body);
+ assert_equals(event.relatedTarget, host);
+ shadowChild.remove();
+}, "Retarget a shadow-tree relatedTarget, part 2");
+
+test(t => {
+ const event = new FocusEvent("heya", { relatedTarget: shadow, cancelable: true }),
+ callback = t.unreached_func();
+ host.addEventListener("heya", callback);
+ t.add_cleanup(() => host.removeEventListener("heya", callback));
+ event.preventDefault();
+ assert_true(event.defaultPrevented);
+ assert_false(host.dispatchEvent(event));
+ assert_equals(event.target, null);
+ assert_equals(event.relatedTarget, null);
+ // Check that the dispatch flag is cleared
+ event.initEvent("x");
+ assert_equals(event.type, "x");
+}, "Reset targets on early return");
+
+test(t => {
+ const input = document.body.appendChild(document.createElement("input")),
+ event = new MouseEvent("click", { relatedTarget: shadow });
+ let seen = false;
+ t.add_cleanup(() => input.remove());
+ input.type = "checkbox";
+ input._oninput_ = t.step_func(() => {
+ assert_equals(event.target, null);
+ assert_equals(event.relatedTarget, null);
+ assert_equals(event.composedPath().length, 0);
+ seen = true;
+ });
+ assert_true(input.dispatchEvent(event));
+ assert_true(seen);
+}, "Reset targets before activation behavior");
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/resources/event-global-extra-frame.html (0 => 233489)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/resources/event-global-extra-frame.html (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/resources/event-global-extra-frame.html 2018-07-04 00:06:32 UTC (rev 233489)
@@ -0,0 +1,9 @@
+<script>
+function listener(e) {
+ parent.frameState = {
+ event: e,
+ windowEvent: window.event,
+ parentEvent: parent.event
+ }
+}
+</script>
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/resources/w3c-import.log (0 => 233489)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/resources/w3c-import.log (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/resources/w3c-import.log 2018-07-04 00:06:32 UTC (rev 233489)
@@ -0,0 +1,17 @@
+The tests in this directory were imported from the W3C repository.
+Do NOT modify these tests directly in WebKit.
+Instead, create a pull request on the WPT github:
+ https://github.com/web-platform-tests/wpt
+
+Then run the Tools/Scripts/import-w3c-tests in WebKit to reimport
+
+Do NOT modify or remove this file.
+
+------------------------------------------------------------------------
+Properties requiring vendor prefixes:
+None
+Property values requiring vendor prefixes:
+None
+------------------------------------------------------------------------
+List of files:
+/LayoutTests/imported/w3c/web-platform-tests/dom/events/resources/event-global-extra-frame.html
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/w3c-import.log (233488 => 233489)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/w3c-import.log 2018-07-04 00:05:39 UTC (rev 233488)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/dom/events/w3c-import.log 2018-07-04 00:06:32 UTC (rev 233489)
@@ -1,7 +1,7 @@
The tests in this directory were imported from the W3C repository.
Do NOT modify these tests directly in WebKit.
Instead, create a pull request on the WPT github:
- https://github.com/w3c/web-platform-tests
+ https://github.com/web-platform-tests/wpt
Then run the Tools/Scripts/import-w3c-tests in WebKit to reimport
@@ -62,3 +62,7 @@
/LayoutTests/imported/w3c/web-platform-tests/dom/events/EventTarget-dispatchEvent.html
/LayoutTests/imported/w3c/web-platform-tests/dom/events/EventTarget-removeEventListener.html
/LayoutTests/imported/w3c/web-platform-tests/dom/events/event-disabled-dynamic.html
+/LayoutTests/imported/w3c/web-platform-tests/dom/events/event-global-extra.window.js
+/LayoutTests/imported/w3c/web-platform-tests/dom/events/event-global.html
+/LayoutTests/imported/w3c/web-platform-tests/dom/events/event-global.worker.js
+/LayoutTests/imported/w3c/web-platform-tests/dom/events/relatedTarget.window.js
Modified: trunk/Source/WebCore/ChangeLog (233488 => 233489)
--- trunk/Source/WebCore/ChangeLog 2018-07-04 00:05:39 UTC (rev 233488)
+++ trunk/Source/WebCore/ChangeLog 2018-07-04 00:06:32 UTC (rev 233489)
@@ -1,5 +1,25 @@
2018-07-03 Chris Dumez <[email protected]>
+ Improve window.event compliance: Should not be set when target is in shadow tree
+ https://bugs.webkit.org/show_bug.cgi?id=186266
+
+ Reviewed by Ryosuke Niwa.
+
+ Stop exposing window.event to Shadow DOM by not setting window.event if the event's target
+ is a Node inside a shadow tree. This is as per the latest DOM specification:
+ - https://github.com/whatwg/dom/pull/407
+
+ This aligns our behavior with Blink as well:
+ - https://bugs.chromium.org/p/chromium/issues/detail?id=779461
+
+ Tests: imported/w3c/web-platform-tests/dom/events/event-global.html
+ imported/w3c/web-platform-tests/dom/events/event-global.worker.html
+
+ * bindings/js/JSEventListener.cpp:
+ (WebCore::JSEventListener::handleEvent):
+
+2018-07-03 Chris Dumez <[email protected]>
+
[Cocoa] Disable vnode guard related simulated crashes for WKTR / DRT and WebSQL
https://bugs.webkit.org/show_bug.cgi?id=187270
<rdar://problem/40674034>
Modified: trunk/Source/WebCore/bindings/js/JSEventListener.cpp (233488 => 233489)
--- trunk/Source/WebCore/bindings/js/JSEventListener.cpp 2018-07-04 00:05:39 UTC (rev 233488)
+++ trunk/Source/WebCore/bindings/js/JSEventListener.cpp 2018-07-04 00:06:32 UTC (rev 233489)
@@ -157,8 +157,12 @@
ASSERT(!args.hasOverflowed());
Event* savedEvent = globalObject->currentEvent();
- globalObject->setCurrentEvent(&event);
+ // window.event should not be set when the target is inside a shadow tree, as per the DOM specification.
+ bool isTargetInsideShadowTree = is<Node>(event.currentTarget()) && downcast<Node>(*event.currentTarget()).isInShadowTree();
+ if (!isTargetInsideShadowTree)
+ globalObject->setCurrentEvent(&event);
+
VMEntryScope entryScope(vm, vm.entryScope ? vm.entryScope->globalObject() : globalObject);
InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(&scriptExecutionContext, callType, callData);