Title: [139154] trunk
Revision
139154
Author
[email protected]
Date
2013-01-08 20:46:50 -0800 (Tue, 08 Jan 2013)

Log Message

Make NodeRenderingContext::parentRenderer and nextRenderer top layer aware
https://bugs.webkit.org/show_bug.cgi?id=103477

Reviewed by Hajime Morita.

Source/WebCore:

Original patch by Elliott Sprehn (minor code and layout tests added).

Instead of using adjustInsertionPointForTopLayerElement and reassigning
pointers passed by reference we should just make nextRenderer and parentRenderer
handle the top layer properly. Right now they would return the wrong values
since we only correctly handle the top layer during renderer creation.

This makes handling of top layer elements consistent with handling of
other special renderering systems like flow threads.

Tests: fast/dom/HTMLDialogElement/modal-dialog-in-replaced-renderer.html
       fast/dom/HTMLDialogElement/modal-dialog-in-table-column.html
       fast/dom/HTMLDialogElement/modal-dialog-sibling.html

* dom/NodeRenderingContext.cpp:
(WebCore::isRendererReparented): Added this helper function. We must skip
renderers that are reparented in nextRenderer and previousRenderer.
(WebCore):
(WebCore::adjustInsertionPointForTopLayerElement): Removed this method.
(WebCore::NodeRenderingContext::nextRenderer):
(WebCore::NodeRenderingContext::previousRenderer):
(WebCore::NodeRenderingContext::parentRenderer):
(WebCore::NodeRenderingContext::createRendererForElementIfNeeded):

LayoutTests:

* fast/dom/HTMLDialogElement/modal-dialog-in-replaced-renderer-expected.html: Added.
* fast/dom/HTMLDialogElement/modal-dialog-in-replaced-renderer.html: Added.
* fast/dom/HTMLDialogElement/modal-dialog-in-table-column-expected.html: Added.
* fast/dom/HTMLDialogElement/modal-dialog-in-table-column.html: Added.
* fast/dom/HTMLDialogElement/modal-dialog-sibling-expected.html: Added.
* fast/dom/HTMLDialogElement/modal-dialog-sibling.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (139153 => 139154)


--- trunk/LayoutTests/ChangeLog	2013-01-09 04:41:41 UTC (rev 139153)
+++ trunk/LayoutTests/ChangeLog	2013-01-09 04:46:50 UTC (rev 139154)
@@ -1,3 +1,17 @@
+2013-01-08  Matt Falkenhagen  <[email protected]>
+
+        Make NodeRenderingContext::parentRenderer and nextRenderer top layer aware
+        https://bugs.webkit.org/show_bug.cgi?id=103477
+
+        Reviewed by Hajime Morita.
+
+        * fast/dom/HTMLDialogElement/modal-dialog-in-replaced-renderer-expected.html: Added.
+        * fast/dom/HTMLDialogElement/modal-dialog-in-replaced-renderer.html: Added.
+        * fast/dom/HTMLDialogElement/modal-dialog-in-table-column-expected.html: Added.
+        * fast/dom/HTMLDialogElement/modal-dialog-in-table-column.html: Added.
+        * fast/dom/HTMLDialogElement/modal-dialog-sibling-expected.html: Added.
+        * fast/dom/HTMLDialogElement/modal-dialog-sibling.html: Added.
+
 2013-01-08  Hayato Ito  <[email protected]>
 
         [Shadow DOM] The MouseEvent offsetX and offsetY attributes must return the coordinates relative to the origin of the padding edge of the relative target after retargeting.

Added: trunk/LayoutTests/fast/dom/HTMLDialogElement/modal-dialog-in-replaced-renderer-expected.html (0 => 139154)


--- trunk/LayoutTests/fast/dom/HTMLDialogElement/modal-dialog-in-replaced-renderer-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/HTMLDialogElement/modal-dialog-in-replaced-renderer-expected.html	2013-01-09 04:46:50 UTC (rev 139154)
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+if (window.internals)
+    internals.settings.setDialogElementEnabled(true);
+</script>
+<style>
+dialog {
+    background: green;
+    border-color: green;
+}
+div {
+    content: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPAQMAAAABGAcJAAAAA1BMVEUAgACc+aWRAAAADElEQVR42mNgIAEAAAAtAAH7KhMqAAAAAElFTkSuQmCC);
+}
+</style>
+<body>
+<p>Bug <a href="" Make
+NodeRenderingContext::parentRenderer and nextRenderer top layer aware
+<p>The test passes if you see a green square near the top and green rectangle in the center of the viewport.
+<div></div>
+<dialog id="dialog"></dialog>
+<script>
+document.getElementById('dialog').showModal();
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/fast/dom/HTMLDialogElement/modal-dialog-in-replaced-renderer.html (0 => 139154)


--- trunk/LayoutTests/fast/dom/HTMLDialogElement/modal-dialog-in-replaced-renderer.html	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/HTMLDialogElement/modal-dialog-in-replaced-renderer.html	2013-01-09 04:46:50 UTC (rev 139154)
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+if (window.internals)
+    internals.settings.setDialogElementEnabled(true);
+</script>
+<style>
+dialog {
+    background: green;
+    border-color: green;
+}
+div {
+    content: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPAQMAAAABGAcJAAAAA1BMVEUAgACc+aWRAAAADElEQVR42mNgIAEAAAAtAAH7KhMqAAAAAElFTkSuQmCC);
+}
+</style>
+<body>
+<p>Bug <a href="" Make
+NodeRenderingContext::parentRenderer and nextRenderer top layer aware
+<p>The test passes if you see a green square near the top and green rectangle in the center of the viewport.
+<div>
+<dialog id="dialog"></dialog>
+</div>
+<script>
+document.getElementById('dialog').showModal();
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/fast/dom/HTMLDialogElement/modal-dialog-in-table-column-expected.html (0 => 139154)


--- trunk/LayoutTests/fast/dom/HTMLDialogElement/modal-dialog-in-table-column-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/HTMLDialogElement/modal-dialog-in-table-column-expected.html	2013-01-09 04:46:50 UTC (rev 139154)
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+if (window.internals)
+    internals.settings.setDialogElementEnabled(true);
+</script>
+<style>
+dialog {
+    background: green;
+    border-color: green;
+}
+</style>
+<body>
+<p>Bug <a href="" Make
+NodeRenderingContext::parentRenderer and nextRenderer top layer aware
+<p>The test passes if you see a green rectangle in the center of the viewport.
+<dialog id="dialog"></dialog>
+<script>
+document.getElementById('dialog').showModal();
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/fast/dom/HTMLDialogElement/modal-dialog-in-table-column.html (0 => 139154)


--- trunk/LayoutTests/fast/dom/HTMLDialogElement/modal-dialog-in-table-column.html	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/HTMLDialogElement/modal-dialog-in-table-column.html	2013-01-09 04:46:50 UTC (rev 139154)
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+if (window.internals)
+    internals.settings.setDialogElementEnabled(true);
+</script>
+<style>
+dialog {
+    background: green;
+    border-color: green;
+}
+div {
+    display: table-column;
+}
+</style>
+<body>
+<p>Bug <a href="" Make
+NodeRenderingContext::parentRenderer and nextRenderer top layer aware
+<p>The test passes if you see a green rectangle in the center of the viewport.
+<div>
+<dialog id="dialog"></dialog>
+</div>
+<script>
+document.getElementById('dialog').showModal();
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/fast/dom/HTMLDialogElement/modal-dialog-sibling-expected.html (0 => 139154)


--- trunk/LayoutTests/fast/dom/HTMLDialogElement/modal-dialog-sibling-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/HTMLDialogElement/modal-dialog-sibling-expected.html	2013-01-09 04:46:50 UTC (rev 139154)
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+if (window.internals)
+    internals.settings.setDialogElementEnabled(true);
+</script>
+<style>
+dialog {
+    background: green;
+    border-color: green;
+}
+</style>
+<body>
+<p>Bug <a href="" Make
+NodeRenderingContext::parentRenderer and nextRenderer top layer aware
+<p>The test passes if you see a green rectangle in the center of the viewport.
+<dialog id="dialog"></dialog>
+<script>
+document.getElementById('dialog').showModal();
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/fast/dom/HTMLDialogElement/modal-dialog-sibling.html (0 => 139154)


--- trunk/LayoutTests/fast/dom/HTMLDialogElement/modal-dialog-sibling.html	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/HTMLDialogElement/modal-dialog-sibling.html	2013-01-09 04:46:50 UTC (rev 139154)
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+if (window.internals)
+    internals.settings.setDialogElementEnabled(true);
+</script>
+<style>
+dialog {
+    background: green;
+    border-color: green;
+}
+</style>
+<body>
+<p>Bug <a href="" Make
+NodeRenderingContext::parentRenderer and nextRenderer top layer aware
+<p>The test passes if you see a green rectangle in the center of the viewport.
+<div style="display: none" id="div"></div>
+<dialog id="dialog"></dialog>
+<script>
+document.getElementById('dialog').showModal();
+document.getElementById('dialog').offsetTop;  // force a layout/renderer creation
+document.getElementById('div').style.display = 'block';
+</script>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (139153 => 139154)


--- trunk/Source/WebCore/ChangeLog	2013-01-09 04:41:41 UTC (rev 139153)
+++ trunk/Source/WebCore/ChangeLog	2013-01-09 04:46:50 UTC (rev 139154)
@@ -1,3 +1,34 @@
+2013-01-08  Matt Falkenhagen  <[email protected]>
+
+        Make NodeRenderingContext::parentRenderer and nextRenderer top layer aware
+        https://bugs.webkit.org/show_bug.cgi?id=103477
+
+        Reviewed by Hajime Morita.
+
+        Original patch by Elliott Sprehn (minor code and layout tests added).
+
+        Instead of using adjustInsertionPointForTopLayerElement and reassigning
+        pointers passed by reference we should just make nextRenderer and parentRenderer
+        handle the top layer properly. Right now they would return the wrong values
+        since we only correctly handle the top layer during renderer creation.
+
+        This makes handling of top layer elements consistent with handling of
+        other special renderering systems like flow threads.
+
+        Tests: fast/dom/HTMLDialogElement/modal-dialog-in-replaced-renderer.html
+               fast/dom/HTMLDialogElement/modal-dialog-in-table-column.html
+               fast/dom/HTMLDialogElement/modal-dialog-sibling.html
+
+        * dom/NodeRenderingContext.cpp:
+        (WebCore::isRendererReparented): Added this helper function. We must skip
+        renderers that are reparented in nextRenderer and previousRenderer.
+        (WebCore):
+        (WebCore::adjustInsertionPointForTopLayerElement): Removed this method.
+        (WebCore::NodeRenderingContext::nextRenderer):
+        (WebCore::NodeRenderingContext::previousRenderer):
+        (WebCore::NodeRenderingContext::parentRenderer):
+        (WebCore::NodeRenderingContext::createRendererForElementIfNeeded):
+
 2013-01-08  Kent Tamura  <[email protected]>
 
         REGRESSION(r135836): Invalid user input for input[type=number] should be cleared by input.value=""

Modified: trunk/Source/WebCore/dom/NodeRenderingContext.cpp (139153 => 139154)


--- trunk/Source/WebCore/dom/NodeRenderingContext.cpp	2013-01-09 04:41:41 UTC (rev 139153)
+++ trunk/Source/WebCore/dom/NodeRenderingContext.cpp	2013-01-09 04:46:50 UTC (rev 139154)
@@ -73,11 +73,38 @@
 {
 }
 
+static bool isRendererReparented(const RenderObject* renderer)
+{
+    if (!renderer->node()->isElementNode())
+        return false;
+    if (renderer->style() && !renderer->style()->flowThread().isEmpty())
+        return true;
+#if ENABLE(DIALOG_ELEMENT)
+    if (toElement(renderer->node())->isInTopLayer())
+        return true;
+#endif
+    return false;
+}
+
 RenderObject* NodeRenderingContext::nextRenderer() const
 {
     if (RenderObject* renderer = m_node->renderer())
         return renderer->nextSibling();
 
+#if ENABLE(DIALOG_ELEMENT)
+    Element* element = m_node->isElementNode() ? toElement(m_node) : 0;
+    if (element && element->isInTopLayer()) {
+        const Vector<RefPtr<Element> >& topLayerElements = element->document()->topLayerElements();
+        size_t position = topLayerElements.find(element);
+        ASSERT(position != notFound);
+        for (size_t i = position + 1; i < topLayerElements.size(); ++i) {
+            if (RenderObject* renderer = topLayerElements[i]->renderer())
+                return renderer;
+        }
+        return 0;
+    }
+#endif
+
     if (m_parentFlowRenderer)
         return m_parentFlowRenderer->nextRendererForNode(m_node);
 
@@ -87,12 +114,9 @@
         return 0;
 
     for (Node* sibling = NodeRenderingTraversal::nextSibling(m_node); sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) {
-        if (RenderObject* renderer = sibling->renderer()) {
-            // Renderers for elements attached to a flow thread should be skipped because they are parented differently.
-            if (renderer->node()->isElementNode() && renderer->style() && !renderer->style()->flowThread().isEmpty())
-                continue;
+        RenderObject* renderer = sibling->renderer();
+        if (renderer && !isRendererReparented(renderer))
             return renderer;
-        }
     }
 
     return 0;
@@ -103,18 +127,22 @@
     if (RenderObject* renderer = m_node->renderer())
         return renderer->previousSibling();
 
+#if ENABLE(DIALOG_ELEMENT)
+    // FIXME: This doesn't work correctly for things in the top layer that are
+    // display: none. We'd need to duplicate the logic in nextRenderer, but since
+    // nothing needs that yet just assert.
+    ASSERT(!m_node->isElementNode() || !toElement(m_node)->isInTopLayer());
+#endif
+
     if (m_parentFlowRenderer)
         return m_parentFlowRenderer->previousRendererForNode(m_node);
 
     // FIXME: We should have the same O(N^2) avoidance as nextRenderer does
     // however, when I tried adding it, several tests failed.
     for (Node* sibling = NodeRenderingTraversal::previousSibling(m_node); sibling; sibling = NodeRenderingTraversal::previousSibling(sibling)) {
-        if (RenderObject* renderer = sibling->renderer()) {
-            // Renderers for elements attached to a flow thread should be skipped because they are parented differently.
-            if (renderer->node()->isElementNode() && renderer->style() && !renderer->style()->flowThread().isEmpty())
-                continue;
+        RenderObject* renderer = sibling->renderer();
+        if (renderer && !isRendererReparented(renderer))
             return renderer;
-        }
     }
 
     return 0;
@@ -124,6 +152,21 @@
 {
     if (RenderObject* renderer = m_node->renderer())
         return renderer->parent();
+
+#if ENABLE(DIALOG_ELEMENT)
+    if (m_node->isElementNode() && toElement(m_node)->isInTopLayer()) {
+        // The parent renderer of top layer elements is the RenderView, but only
+        // if the normal parent would have had a renderer.
+        // FIXME: This behavior isn't quite right as the spec for top layer
+        // only talks about display: none ancestors so putting a <dialog> inside
+        // an <optgroup> seems like it should still work even though this check
+        // will prevent it.
+        if (!m_renderingParent || !m_renderingParent->renderer())
+            return 0;
+        return m_node->document()->renderView();
+    }
+#endif
+
     if (m_parentFlowRenderer)
         return m_parentFlowRenderer;
 
@@ -195,26 +238,6 @@
     return m_node->parentNode() && m_node->parentNode()->isShadowRoot();
 }
 
-#if ENABLE(DIALOG_ELEMENT)
-static void adjustInsertionPointForTopLayerElement(Element* element, RenderObject*& parentRenderer, RenderObject*& nextRenderer)
-{
-    parentRenderer = parentRenderer->view();
-    nextRenderer = 0;
-    const Vector<RefPtr<Element> >& topLayerElements = element->document()->topLayerElements();
-    size_t topLayerPosition = topLayerElements.find(element);
-    ASSERT(topLayerPosition != notFound);
-    // Find the next top layer renderer that's stacked above this element. Note that the immediate next element in the top layer
-    // stack might not have a renderer (due to display: none, or possibly it is not attached yet).
-    for (size_t i = topLayerPosition + 1; i < topLayerElements.size(); ++i) {
-        nextRenderer = topLayerElements[i]->renderer();
-        if (nextRenderer) {
-            ASSERT(nextRenderer->parent() == parentRenderer);
-            break;
-        }
-    }
-}
-#endif
-
 void NodeRenderingContext::createRendererForElementIfNeeded()
 {
     ASSERT(!m_node->renderer());
@@ -233,11 +256,6 @@
 
     RenderObject* parentRenderer = this->parentRenderer();
     RenderObject* nextRenderer = this->nextRenderer();
-    
-#if ENABLE(DIALOG_ELEMENT)
-    if (element->isInTopLayer())
-        adjustInsertionPointForTopLayerElement(element, parentRenderer, nextRenderer);
-#endif
 
     Document* document = element->document();
     RenderObject* newRenderer = element->createRenderer(document->renderArena(), m_style.get());
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to