REGRESSION (r244995): Assertion failure when addEventListener to an SVGElement which...
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 25 Jul 2019 17:56:45 +0000 (17:56 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 25 Jul 2019 17:56:45 +0000 (17:56 +0000)
https://bugs.webkit.org/show_bug.cgi?id=200083

Patch by Said Abou-Hallawa <sabouhallawa@apple.com> on 2019-07-25
Reviewed by Ryosuke Niwa.

Source/WebCore:

When adding an event listener to an SVGElement, the same event listener
has to be add to all the instances of SVGElement in the shadow tree. See
SVGElement::addEventListener().

In r244995, an assertion was added to ensure if the event listener is
attached to an event target, the new event target has be the same as the
attached one. This assertion isn't correct for the event targets which
were copied from the targetElement sub tree of an SVGUseElement to the
shadow tree.

Test: svg/custom/add-event-listener-shadow-tree-element.html

* bindings/js/JSLazyEventListener.cpp:
(WebCore::isCloneInShadowTreeOfSVGUseElement):
(WebCore::JSLazyEventListener::checkValidityForEventTarget):

LayoutTests:

* svg/custom/add-event-listener-shadow-tree-element-expected.txt: Added.
* svg/custom/add-event-listener-shadow-tree-element.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@247826 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/svg/custom/add-event-listener-shadow-tree-element-expected.txt [new file with mode: 0644]
LayoutTests/svg/custom/add-event-listener-shadow-tree-element.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/JSLazyEventListener.cpp

index 973cd8d..cd6ef23 100644 (file)
@@ -1,3 +1,13 @@
+2019-07-25  Said Abou-Hallawa  <sabouhallawa@apple.com>
+
+        REGRESSION (r244995): Assertion failure when addEventListener to an SVGElement which has an. instance in shadow tree
+        https://bugs.webkit.org/show_bug.cgi?id=200083
+
+        Reviewed by Ryosuke Niwa.
+
+        * svg/custom/add-event-listener-shadow-tree-element-expected.txt: Added.
+        * svg/custom/add-event-listener-shadow-tree-element.html: Added.
+
 2019-07-25  Truitt Savell  <tsavell@apple.com>
 
         Unreviewed, rolling out r247821.
diff --git a/LayoutTests/svg/custom/add-event-listener-shadow-tree-element-expected.txt b/LayoutTests/svg/custom/add-event-listener-shadow-tree-element-expected.txt
new file mode 100644 (file)
index 0000000..2ff9c78
--- /dev/null
@@ -0,0 +1,2 @@
+PASS if it doesn't assert in debug builds.
+
diff --git a/LayoutTests/svg/custom/add-event-listener-shadow-tree-element.html b/LayoutTests/svg/custom/add-event-listener-shadow-tree-element.html
new file mode 100644 (file)
index 0000000..9ffdc91
--- /dev/null
@@ -0,0 +1,27 @@
+<html>
+<body onload=test()>
+   <svg>
+        <def>
+            <rect id="rect" width="100" height="100" fill="red"/>
+        </def>
+        <use id="use1" href="#rect"/>
+        <use id="use2" href="#use1"/>
+        <text y="120">PASS if it doesn't assert in debug builds.</text>
+    </svg>
+    <script>
+        function eventhandler() {
+            rect.setAttribute("fill", "green");
+            if (window.testRunner)
+                testRunner.notifyDone();
+        }
+        function test() {
+            if (window.testRunner) {
+                testRunner.dumpAsText();
+                testRunner.waitUntilDone();
+            }
+            use1.setAttribute("onfocusin", "eventhandler()");
+            use1.focus();
+        }
+    </script>
+</body>
+</html>
index c554a11..e1cd629 100644 (file)
@@ -1,3 +1,26 @@
+2019-07-25  Said Abou-Hallawa  <sabouhallawa@apple.com>
+
+        REGRESSION (r244995): Assertion failure when addEventListener to an SVGElement which has an. instance in shadow tree
+        https://bugs.webkit.org/show_bug.cgi?id=200083
+
+        Reviewed by Ryosuke Niwa.
+
+        When adding an event listener to an SVGElement, the same event listener
+        has to be add to all the instances of SVGElement in the shadow tree. See
+        SVGElement::addEventListener().
+
+        In r244995, an assertion was added to ensure if the event listener is
+        attached to an event target, the new event target has be the same as the
+        attached one. This assertion isn't correct for the event targets which 
+        were copied from the targetElement sub tree of an SVGUseElement to the
+        shadow tree.
+
+        Test: svg/custom/add-event-listener-shadow-tree-element.html
+
+        * bindings/js/JSLazyEventListener.cpp:
+        (WebCore::isCloneInShadowTreeOfSVGUseElement):
+        (WebCore::JSLazyEventListener::checkValidityForEventTarget):
+
 2019-07-25  Truitt Savell  <tsavell@apple.com>
 
         Unreviewed, rolling out r247821.
index 2d74f29..3a2f79d 100644 (file)
@@ -26,6 +26,7 @@
 #include "Frame.h"
 #include "JSNode.h"
 #include "QualifiedName.h"
+#include "SVGElement.h"
 #include "ScriptController.h"
 #include <JavaScriptCore/CatchScope.h>
 #include <JavaScriptCore/FunctionConstructor.h>
@@ -80,12 +81,29 @@ JSLazyEventListener::JSLazyEventListener(CreationArguments&& arguments, const St
 }
 
 #if !ASSERT_DISABLED
+static inline bool isCloneInShadowTreeOfSVGUseElement(Node& originalNode, EventTarget& eventTarget)
+{
+    if (!eventTarget.isNode())
+        return false;
+
+    auto& node = downcast<Node>(eventTarget);
+    if (!is<SVGElement>(node))
+        return false;
+
+    auto& element = downcast<SVGElement>(node);
+    if (!element.correspondingElement())
+        return false;
+
+    ASSERT(element.isInShadowTree());
+    return &originalNode == element.correspondingElement();
+}
+
 // This is to help find the underlying cause of <rdar://problem/24314027>.
 void JSLazyEventListener::checkValidityForEventTarget(EventTarget& eventTarget)
 {
     if (eventTarget.isNode()) {
         ASSERT(m_originalNode);
-        ASSERT(static_cast<EventTarget*>(m_originalNode.get()) == &eventTarget);
+        ASSERT(static_cast<EventTarget*>(m_originalNode.get()) == &eventTarget || isCloneInShadowTreeOfSVGUseElement(*m_originalNode, eventTarget));
     } else
         ASSERT(!m_originalNode);
 }