Hit test with clipPath referencing parent element causes infinite recursion
https://bugs.webkit.org/show_bug.cgi?id=209773
<rdar://problem/60002347>

Reviewed by Geoffrey Garen.

Source/WebCore:

Upon further investigation, the original fix for the hit test in RenderSVGResourceClipper to prevent
infinite recursion was incomplete, as something such as a use element could easily cause another cycle which
would not be detected by the initial fix.  Instead, by maintaining a set of visited elements, we can prevent
visiting the same element twice, and thus breaking any cycles which might occur in the SVG document.  We
track these elements within the SVGHitTestCycleDetectionScope class, where the set of visited elements are
maintained statically, and instances of the class will manage the scope, as an RAII-style object.

This is covered by an existing test, but includes additional test cases which illustrate the more complex
document structure.

Tests: svg/hittest/svg-clip-path-child-element-with-use-root.html
       svg/hittest/svg-clip-path-child-element-with-use.html

* rendering/svg/RenderSVGContainer.cpp:
(WebCore::RenderSVGContainer::nodeAtFloatPoint):
* rendering/svg/RenderSVGImage.cpp:
(WebCore::RenderSVGImage::nodeAtFloatPoint):
* rendering/svg/RenderSVGResourceClipper.cpp:
(WebCore::RenderSVGResourceClipper::hitTestClipContent):
* rendering/svg/RenderSVGRoot.cpp:
(WebCore::RenderSVGRoot::nodeAtPoint):
* rendering/svg/RenderSVGShape.cpp:
(WebCore::RenderSVGShape::nodeAtFloatPoint):
* rendering/svg/RenderSVGText.cpp:
(WebCore::RenderSVGText::nodeAtFloatPoint):
* rendering/svg/SVGRenderSupport.cpp:
(WebCore::SVGRenderSupport::pointInClippingArea):
(WebCore::SVGHitTestCycleDetectionScope::SVGHitTestCycleDetectionScope):
(WebCore::SVGHitTestCycleDetectionScope::~SVGHitTestCycleDetectionScope):
(WebCore::SVGHitTestCycleDetectionScope::visitedElements):
(WebCore::SVGHitTestCycleDetectionScope::isEmpty):
(WebCore::SVGHitTestCycleDetectionScope::isVisiting):
* rendering/svg/SVGRenderSupport.h:

LayoutTests:

* svg/hittest/svg-clip-path-child-element-with-use-expected.txt: Added.
* svg/hittest/svg-clip-path-child-element-with-use-root-expected.txt: Added.
* svg/hittest/svg-clip-path-child-element-with-use-root.html: Added.
* svg/hittest/svg-clip-path-child-element-with-use.html: Added.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@259722 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/svg/hittest/svg-clip-path-child-element-with-use.html b/LayoutTests/svg/hittest/svg-clip-path-child-element-with-use.html
new file mode 100644
index 0000000..c94d842
--- /dev/null
+++ b/LayoutTests/svg/hittest/svg-clip-path-child-element-with-use.html
@@ -0,0 +1,21 @@
+<style>
+.path { -webkit-clip-path: url(#clippath); }
+</style>
+<script>
+function loadevent() {
+    document.caretRangeFromPoint(37, 70);
+    if (window.testRunner) {
+        document.body.innerText = "Tests SVG hit test with a recursive clipPath.  Test passes if WebKit does not crash.  PASS";
+        testRunner.dumpAsText();
+    }
+}
+</script>
+<body onload=loadevent()>
+<svg contentScriptType="text/ecmascript">
+<path d="M16 8 L32 56" class="path" />
+<g id="group">
+    <text clip-path="url(#clippath)" to="currentColor">Text</text>
+</g>
+<clipPath id="clippath" clipPathUnits="objectBoundingBox">
+    <use href="#group"/>
+</clipPath>