Title: [220313] trunk
Revision
220313
Author
carlo...@webkit.org
Date
2017-08-05 01:08:16 -0700 (Sat, 05 Aug 2017)

Log Message

getClientRects doesn't work with list box option elements
https://bugs.webkit.org/show_bug.cgi?id=175016

Reviewed by Darin Adler.

Source/WebCore:

Since HTMLOptionElement and HTMLOptGroupElement don't have a renderer, we are always returning an empty list
from getClientRects. This is working fine in both chromium and firefox, option elements return its own bounding
box and group elements return the bounding box of the group label and all its children items.

Test: fast/dom/HTMLSelectElement/listbox-items-client-rects.html

* dom/Element.cpp:
(WebCore::listBoxElementBoundingBox): Helper function to return the bounding box of a HTMLOptionElement or
HTMLOptGroupElement element.
(WebCore::Element::getClientRects): Use listBoxElementBoundingBox() in case of HTMLOptionElement or
HTMLOptGroupElement.
(WebCore::Element::boundingClientRect): Ditto.

LayoutTests:

Add new test to check list box option elements client rects.

* fast/dom/HTMLSelectElement/listbox-items-client-rects-expected.txt: Added.
* fast/dom/HTMLSelectElement/listbox-items-client-rects.html: Added.
* platform/ios-simulator-wk2/fast/dom/HTMLSelectElement/listbox-items-client-rects-expected.txt: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (220312 => 220313)


--- trunk/LayoutTests/ChangeLog	2017-08-05 07:57:55 UTC (rev 220312)
+++ trunk/LayoutTests/ChangeLog	2017-08-05 08:08:16 UTC (rev 220313)
@@ -1,3 +1,16 @@
+2017-08-05  Carlos Garcia Campos  <cgar...@igalia.com>
+
+        getClientRects doesn't work with list box option elements
+        https://bugs.webkit.org/show_bug.cgi?id=175016
+
+        Reviewed by Darin Adler.
+
+        Add new test to check list box option elements client rects.
+
+        * fast/dom/HTMLSelectElement/listbox-items-client-rects-expected.txt: Added.
+        * fast/dom/HTMLSelectElement/listbox-items-client-rects.html: Added.
+        * platform/ios-simulator-wk2/fast/dom/HTMLSelectElement/listbox-items-client-rects-expected.txt: Added.
+
 2017-08-04  Youenn Fablet  <you...@apple.com>
 
         [Cache API] Add Cache and CacheStorage IDL definitions

Added: trunk/LayoutTests/fast/dom/HTMLSelectElement/listbox-items-client-rects-expected.txt (0 => 220313)


--- trunk/LayoutTests/fast/dom/HTMLSelectElement/listbox-items-client-rects-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/HTMLSelectElement/listbox-items-client-rects-expected.txt	2017-08-05 08:08:16 UTC (rev 220313)
@@ -0,0 +1,60 @@
+PASS listBoundingBoxes.length is 1
+PASS listBoundingBoxes[0].left is listBoundingBox.left
+PASS listBoundingBoxes[0].right is listBoundingBox.right
+PASS listBoundingBoxes[0].top is listBoundingBox.top
+PASS listBoundingBoxes[0].bottom is listBoundingBox.bottom
+PASS listBoundingBoxes[0].width is listBoundingBox.width
+PASS listBoundingBoxes[0].height is listBoundingBox.height
+PASS groupBoundingBoxes.length is 1
+PASS groupBoundingBoxes[0].left is groupBoundingBox.left
+PASS groupBoundingBoxes[0].right is groupBoundingBox.right
+PASS groupBoundingBoxes[0].top is groupBoundingBox.top
+PASS groupBoundingBoxes[0].bottom is groupBoundingBox.bottom
+PASS groupBoundingBoxes[0].width is groupBoundingBox.width
+PASS groupBoundingBoxes[0].height is groupBoundingBox.height
+PASS option1BoundingBoxes.length is 1
+PASS option1BoundingBoxes[0].left is option1BoundingBox.left
+PASS option1BoundingBoxes[0].right is option1BoundingBox.right
+PASS option1BoundingBoxes[0].top is option1BoundingBox.top
+PASS option1BoundingBoxes[0].bottom is option1BoundingBox.bottom
+PASS option1BoundingBoxes[0].width is option1BoundingBox.width
+PASS option1BoundingBoxes[0].height is option1BoundingBox.height
+PASS option2BoundingBoxes.length is 1
+PASS option2BoundingBoxes[0].left is option2BoundingBox.left
+PASS option2BoundingBoxes[0].right is option2BoundingBox.right
+PASS option2BoundingBoxes[0].top is option2BoundingBox.top
+PASS option2BoundingBoxes[0].bottom is option2BoundingBox.bottom
+PASS option2BoundingBoxes[0].width is option2BoundingBox.width
+PASS option2BoundingBoxes[0].height is option2BoundingBox.height
+PASS option3BoundingBoxes.length is 1
+PASS option3BoundingBoxes[0].left is option3BoundingBox.left
+PASS option3BoundingBoxes[0].right is option3BoundingBox.right
+PASS option3BoundingBoxes[0].top is option3BoundingBox.top
+PASS option3BoundingBoxes[0].bottom is option3BoundingBox.bottom
+PASS option3BoundingBoxes[0].width is option3BoundingBox.width
+PASS option3BoundingBoxes[0].height is option3BoundingBox.height
+PASS groupBoundingBox.left is listBoundingBox.left + border
+PASS groupBoundingBox.top is listBoundingBox.top + border
+PASS groupBoundingBox.right is listBoundingBox.right - border
+PASS groupBoundingBox.bottom is groupBoundingBox.top + 3 * optionHeight
+PASS groupBoundingBox.width is listBoundingBox.width - 2 * border
+PASS groupBoundingBox.height is 3 * optionHeight
+PASS option1BoundingBox.left is listBoundingBox.left + border
+PASS option1BoundingBox.top is listBoundingBox.top + border + optionHeight
+PASS option1BoundingBox.right is listBoundingBox.right - border
+PASS option1BoundingBox.bottom is option1BoundingBox.top + option1BoundingBox.height
+PASS option1BoundingBox.width is listBoundingBox.width - 2 * border
+PASS option2BoundingBox.left is listBoundingBox.left + border
+PASS option2BoundingBox.top is listBoundingBox.top + border + 2 * optionHeight
+PASS option2BoundingBox.right is listBoundingBox.right - border
+PASS option2BoundingBox.bottom is option2BoundingBox.top + option2BoundingBox.height
+PASS option2BoundingBox.width is listBoundingBox.width - 2 * border
+PASS option3BoundingBox.left is listBoundingBox.left + border
+PASS option3BoundingBox.top is listBoundingBox.top + border + 3 * optionHeight
+PASS option3BoundingBox.right is listBoundingBox.right - border
+PASS option3BoundingBox.bottom is option3BoundingBox.top + option3BoundingBox.height
+PASS option3BoundingBox.width is listBoundingBox.width - 2 * border
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/dom/HTMLSelectElement/listbox-items-client-rects.html (0 => 220313)


--- trunk/LayoutTests/fast/dom/HTMLSelectElement/listbox-items-client-rects.html	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/HTMLSelectElement/listbox-items-client-rects.html	2017-08-05 08:08:16 UTC (rev 220313)
@@ -0,0 +1,119 @@
+<script src=""
+<style>
+    select {
+        width: 100px;
+        height: 150px;
+        padding: 0px;
+        outline: 1px;
+    }
+    select::-webkit-scrollbar { display: none; }
+</style>
+<div id="testArea">
+    <select id="list" multiple>
+      <optgroup id="group" label="Group">
+        <option id="option1">Option 1</option>
+        <option id="option2">Option 2</option>
+      </optgroup>
+      <option id="option3">Option 3</option>
+    </select>
+    <br><br>
+</div>
+<div id="console"></div>
+<script>
+    if (window.testRunner)
+        testRunner.dumpAsText();
+
+    var list = document.getElementById('list');
+    var listBoundingBox = list.getBoundingClientRect();
+    var listBoundingBoxes = list.getClientRects();
+
+    shouldBe("listBoundingBoxes.length", "1");
+    shouldBe("listBoundingBoxes[0].left", "listBoundingBox.left");
+    shouldBe("listBoundingBoxes[0].right", "listBoundingBox.right");
+    shouldBe("listBoundingBoxes[0].top", "listBoundingBox.top");
+    shouldBe("listBoundingBoxes[0].bottom", "listBoundingBox.bottom");
+    shouldBe("listBoundingBoxes[0].width", "listBoundingBox.width");
+    shouldBe("listBoundingBoxes[0].height", "listBoundingBox.height");
+
+    var group = document.getElementById('group')
+    var groupBoundingBox = group.getBoundingClientRect();
+    var groupBoundingBoxes = group.getClientRects();
+
+    shouldBe("groupBoundingBoxes.length", "1");
+    shouldBe("groupBoundingBoxes[0].left", "groupBoundingBox.left");
+    shouldBe("groupBoundingBoxes[0].right", "groupBoundingBox.right");
+    shouldBe("groupBoundingBoxes[0].top", "groupBoundingBox.top");
+    shouldBe("groupBoundingBoxes[0].bottom", "groupBoundingBox.bottom");
+    shouldBe("groupBoundingBoxes[0].width", "groupBoundingBox.width");
+    shouldBe("groupBoundingBoxes[0].height", "groupBoundingBox.height");
+
+    var option1 = document.getElementById('option1');
+    var option1BoundingBox = option1.getBoundingClientRect();
+    var option1BoundingBoxes = option1.getClientRects();
+
+    shouldBe("option1BoundingBoxes.length", "1");
+    shouldBe("option1BoundingBoxes[0].left", "option1BoundingBox.left");
+    shouldBe("option1BoundingBoxes[0].right", "option1BoundingBox.right");
+    shouldBe("option1BoundingBoxes[0].top", "option1BoundingBox.top");
+    shouldBe("option1BoundingBoxes[0].bottom", "option1BoundingBox.bottom");
+    shouldBe("option1BoundingBoxes[0].width", "option1BoundingBox.width");
+    shouldBe("option1BoundingBoxes[0].height", "option1BoundingBox.height");
+
+    var option2 = document.getElementById('option2');
+    var option2BoundingBox = option2.getBoundingClientRect();
+    var option2BoundingBoxes = option2.getClientRects();
+
+    shouldBe("option2BoundingBoxes.length", "1");
+    shouldBe("option2BoundingBoxes[0].left", "option2BoundingBox.left");
+    shouldBe("option2BoundingBoxes[0].right", "option2BoundingBox.right");
+    shouldBe("option2BoundingBoxes[0].top", "option2BoundingBox.top");
+    shouldBe("option2BoundingBoxes[0].bottom", "option2BoundingBox.bottom");
+    shouldBe("option2BoundingBoxes[0].width", "option2BoundingBox.width");
+    shouldBe("option2BoundingBoxes[0].height", "option2BoundingBox.height");
+
+    var option3 = document.getElementById('option3');
+    var option3BoundingBox = option3.getBoundingClientRect();
+    var option3BoundingBoxes = option3.getClientRects();
+
+    shouldBe("option3BoundingBoxes.length", "1");
+    shouldBe("option3BoundingBoxes[0].left", "option3BoundingBox.left");
+    shouldBe("option3BoundingBoxes[0].right", "option3BoundingBox.right");
+    shouldBe("option3BoundingBoxes[0].top", "option3BoundingBox.top");
+    shouldBe("option3BoundingBoxes[0].bottom", "option3BoundingBox.bottom");
+    shouldBe("option3BoundingBoxes[0].width", "option3BoundingBox.width");
+    shouldBe("option3BoundingBoxes[0].height", "option3BoundingBox.height");
+
+    var border = 1;
+    var optionHeight = option1BoundingBox.height;
+
+    shouldBe("groupBoundingBox.left", "listBoundingBox.left + border");
+    shouldBe("groupBoundingBox.top", "listBoundingBox.top + border");
+    shouldBe("groupBoundingBox.right", "listBoundingBox.right - border");
+    shouldBe("groupBoundingBox.bottom", "groupBoundingBox.top + 3 * optionHeight");
+    shouldBe("groupBoundingBox.width", "listBoundingBox.width - 2 * border");
+    shouldBe("groupBoundingBox.height", "3 * optionHeight");
+
+    shouldBe("option1BoundingBox.left", "listBoundingBox.left + border");
+    shouldBe("option1BoundingBox.top", "listBoundingBox.top + border + optionHeight");
+    shouldBe("option1BoundingBox.right", "listBoundingBox.right - border");
+    shouldBe("option1BoundingBox.bottom", "option1BoundingBox.top + option1BoundingBox.height");
+    shouldBe("option1BoundingBox.width", "listBoundingBox.width - 2 * border");
+
+    shouldBe("option2BoundingBox.left", "listBoundingBox.left + border");
+    shouldBe("option2BoundingBox.top", "listBoundingBox.top + border + 2 * optionHeight");
+    shouldBe("option2BoundingBox.right", "listBoundingBox.right - border");
+    shouldBe("option2BoundingBox.bottom", "option2BoundingBox.top + option2BoundingBox.height");
+    shouldBe("option2BoundingBox.width", "listBoundingBox.width - 2 * border");
+
+    shouldBe("option3BoundingBox.left", "listBoundingBox.left + border");
+    shouldBe("option3BoundingBox.top", "listBoundingBox.top + border + 3 * optionHeight");
+    shouldBe("option3BoundingBox.right", "listBoundingBox.right - border");
+    shouldBe("option3BoundingBox.bottom", "option3BoundingBox.top + option3BoundingBox.height");
+    shouldBe("option3BoundingBox.width", "listBoundingBox.width - 2 * border");
+
+    if (window.testRunner) {
+        var area = document.getElementById('testArea');
+        area.parentNode.removeChild(area);
+    }
+</script>
+<script src=""

Added: trunk/LayoutTests/platform/ios-simulator-wk2/fast/dom/HTMLSelectElement/listbox-items-client-rects-expected.txt (0 => 220313)


--- trunk/LayoutTests/platform/ios-simulator-wk2/fast/dom/HTMLSelectElement/listbox-items-client-rects-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/ios-simulator-wk2/fast/dom/HTMLSelectElement/listbox-items-client-rects-expected.txt	2017-08-05 08:08:16 UTC (rev 220313)
@@ -0,0 +1,60 @@
+PASS listBoundingBoxes.length is 1
+PASS listBoundingBoxes[0].left is listBoundingBox.left
+PASS listBoundingBoxes[0].right is listBoundingBox.right
+PASS listBoundingBoxes[0].top is listBoundingBox.top
+PASS listBoundingBoxes[0].bottom is listBoundingBox.bottom
+PASS listBoundingBoxes[0].width is listBoundingBox.width
+PASS listBoundingBoxes[0].height is listBoundingBox.height
+FAIL groupBoundingBoxes.length should be 1. Was 0.
+FAIL groupBoundingBoxes[0].left should be 0. Threw exception TypeError: undefined is not an object (evaluating 'groupBoundingBoxes[0].left')
+FAIL groupBoundingBoxes[0].right should be 0. Threw exception TypeError: undefined is not an object (evaluating 'groupBoundingBoxes[0].right')
+FAIL groupBoundingBoxes[0].top should be 0. Threw exception TypeError: undefined is not an object (evaluating 'groupBoundingBoxes[0].top')
+FAIL groupBoundingBoxes[0].bottom should be 0. Threw exception TypeError: undefined is not an object (evaluating 'groupBoundingBoxes[0].bottom')
+FAIL groupBoundingBoxes[0].width should be 0. Threw exception TypeError: undefined is not an object (evaluating 'groupBoundingBoxes[0].width')
+FAIL groupBoundingBoxes[0].height should be 0. Threw exception TypeError: undefined is not an object (evaluating 'groupBoundingBoxes[0].height')
+FAIL option1BoundingBoxes.length should be 1. Was 0.
+FAIL option1BoundingBoxes[0].left should be 0. Threw exception TypeError: undefined is not an object (evaluating 'option1BoundingBoxes[0].left')
+FAIL option1BoundingBoxes[0].right should be 0. Threw exception TypeError: undefined is not an object (evaluating 'option1BoundingBoxes[0].right')
+FAIL option1BoundingBoxes[0].top should be 0. Threw exception TypeError: undefined is not an object (evaluating 'option1BoundingBoxes[0].top')
+FAIL option1BoundingBoxes[0].bottom should be 0. Threw exception TypeError: undefined is not an object (evaluating 'option1BoundingBoxes[0].bottom')
+FAIL option1BoundingBoxes[0].width should be 0. Threw exception TypeError: undefined is not an object (evaluating 'option1BoundingBoxes[0].width')
+FAIL option1BoundingBoxes[0].height should be 0. Threw exception TypeError: undefined is not an object (evaluating 'option1BoundingBoxes[0].height')
+FAIL option2BoundingBoxes.length should be 1. Was 0.
+FAIL option2BoundingBoxes[0].left should be 0. Threw exception TypeError: undefined is not an object (evaluating 'option2BoundingBoxes[0].left')
+FAIL option2BoundingBoxes[0].right should be 0. Threw exception TypeError: undefined is not an object (evaluating 'option2BoundingBoxes[0].right')
+FAIL option2BoundingBoxes[0].top should be 0. Threw exception TypeError: undefined is not an object (evaluating 'option2BoundingBoxes[0].top')
+FAIL option2BoundingBoxes[0].bottom should be 0. Threw exception TypeError: undefined is not an object (evaluating 'option2BoundingBoxes[0].bottom')
+FAIL option2BoundingBoxes[0].width should be 0. Threw exception TypeError: undefined is not an object (evaluating 'option2BoundingBoxes[0].width')
+FAIL option2BoundingBoxes[0].height should be 0. Threw exception TypeError: undefined is not an object (evaluating 'option2BoundingBoxes[0].height')
+FAIL option3BoundingBoxes.length should be 1. Was 0.
+FAIL option3BoundingBoxes[0].left should be 0. Threw exception TypeError: undefined is not an object (evaluating 'option3BoundingBoxes[0].left')
+FAIL option3BoundingBoxes[0].right should be 0. Threw exception TypeError: undefined is not an object (evaluating 'option3BoundingBoxes[0].right')
+FAIL option3BoundingBoxes[0].top should be 0. Threw exception TypeError: undefined is not an object (evaluating 'option3BoundingBoxes[0].top')
+FAIL option3BoundingBoxes[0].bottom should be 0. Threw exception TypeError: undefined is not an object (evaluating 'option3BoundingBoxes[0].bottom')
+FAIL option3BoundingBoxes[0].width should be 0. Threw exception TypeError: undefined is not an object (evaluating 'option3BoundingBoxes[0].width')
+FAIL option3BoundingBoxes[0].height should be 0. Threw exception TypeError: undefined is not an object (evaluating 'option3BoundingBoxes[0].height')
+FAIL groupBoundingBox.left should be 9. Was 0.
+FAIL groupBoundingBox.top should be 9. Was 0.
+FAIL groupBoundingBox.right should be 107. Was 0.
+PASS groupBoundingBox.bottom is groupBoundingBox.top + 3 * optionHeight
+FAIL groupBoundingBox.width should be 98. Was 0.
+PASS groupBoundingBox.height is 3 * optionHeight
+FAIL option1BoundingBox.left should be 9. Was 0.
+FAIL option1BoundingBox.top should be 9. Was 0.
+FAIL option1BoundingBox.right should be 107. Was 0.
+PASS option1BoundingBox.bottom is option1BoundingBox.top + option1BoundingBox.height
+FAIL option1BoundingBox.width should be 98. Was 0.
+FAIL option2BoundingBox.left should be 9. Was 0.
+FAIL option2BoundingBox.top should be 9. Was 0.
+FAIL option2BoundingBox.right should be 107. Was 0.
+PASS option2BoundingBox.bottom is option2BoundingBox.top + option2BoundingBox.height
+FAIL option2BoundingBox.width should be 98. Was 0.
+FAIL option3BoundingBox.left should be 9. Was 0.
+FAIL option3BoundingBox.top should be 9. Was 0.
+FAIL option3BoundingBox.right should be 107. Was 0.
+PASS option3BoundingBox.bottom is option3BoundingBox.top + option3BoundingBox.height
+FAIL option3BoundingBox.width should be 98. Was 0.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Modified: trunk/Source/WebCore/ChangeLog (220312 => 220313)


--- trunk/Source/WebCore/ChangeLog	2017-08-05 07:57:55 UTC (rev 220312)
+++ trunk/Source/WebCore/ChangeLog	2017-08-05 08:08:16 UTC (rev 220313)
@@ -1,3 +1,23 @@
+2017-08-05  Carlos Garcia Campos  <cgar...@igalia.com>
+
+        getClientRects doesn't work with list box option elements
+        https://bugs.webkit.org/show_bug.cgi?id=175016
+
+        Reviewed by Darin Adler.
+
+        Since HTMLOptionElement and HTMLOptGroupElement don't have a renderer, we are always returning an empty list
+        from getClientRects. This is working fine in both chromium and firefox, option elements return its own bounding
+        box and group elements return the bounding box of the group label and all its children items.
+
+        Test: fast/dom/HTMLSelectElement/listbox-items-client-rects.html
+
+        * dom/Element.cpp:
+        (WebCore::listBoxElementBoundingBox): Helper function to return the bounding box of a HTMLOptionElement or
+        HTMLOptGroupElement element.
+        (WebCore::Element::getClientRects): Use listBoxElementBoundingBox() in case of HTMLOptionElement or
+        HTMLOptGroupElement.
+        (WebCore::Element::boundingClientRect): Ditto.
+
 2017-08-04  Youenn Fablet  <you...@apple.com>
 
         [Cache API] Add Cache and CacheStorage IDL definitions

Modified: trunk/Source/WebCore/dom/Element.cpp (220312 => 220313)


--- trunk/Source/WebCore/dom/Element.cpp	2017-08-05 07:57:55 UTC (rev 220312)
+++ trunk/Source/WebCore/dom/Element.cpp	2017-08-05 08:08:16 UTC (rev 220313)
@@ -61,7 +61,10 @@
 #include "HTMLLabelElement.h"
 #include "HTMLNameCollection.h"
 #include "HTMLObjectElement.h"
+#include "HTMLOptGroupElement.h"
+#include "HTMLOptionElement.h"
 #include "HTMLParserIdioms.h"
+#include "HTMLSelectElement.h"
 #include "HTMLTemplateElement.h"
 #include "IdChangeInvalidation.h"
 #include "IdTargetObserverRegistry.h"
@@ -78,6 +81,7 @@
 #include "PointerLockController.h"
 #include "RenderFlowThread.h"
 #include "RenderLayer.h"
+#include "RenderListBox.h"
 #include "RenderNamedFlowFragment.h"
 #include "RenderRegion.h"
 #include "RenderTheme.h"
@@ -1145,20 +1149,66 @@
     return absoluteEventBoundsOfElementAndDescendants(includesFixedPositionElements);
 }
 
+static std::optional<std::pair<RenderObject*, LayoutRect>> listBoxElementBoundingBox(Element& element)
+{
+    HTMLSelectElement* selectElement;
+    bool isGroup;
+    if (is<HTMLOptionElement>(element)) {
+        selectElement = downcast<HTMLOptionElement>(element).ownerSelectElement();
+        isGroup = false;
+    } else if (is<HTMLOptGroupElement>(element)) {
+        selectElement = downcast<HTMLOptGroupElement>(element).ownerSelectElement();
+        isGroup = true;
+    } else
+        return std::nullopt;
+
+    if (!selectElement || !selectElement->renderer() || !is<RenderListBox>(selectElement->renderer()))
+        return std::nullopt;
+
+    auto& renderer = downcast<RenderListBox>(*selectElement->renderer());
+    std::optional<LayoutRect> boundingBox;
+    int optionIndex = 0;
+    for (auto* item : selectElement->listItems()) {
+        if (item == &element) {
+            LayoutPoint additionOffset;
+            boundingBox = renderer.itemBoundingBoxRect(additionOffset, optionIndex);
+            if (!isGroup)
+                break;
+        } else if (isGroup && boundingBox) {
+            if (item->parentNode() != &element)
+                break;
+            LayoutPoint additionOffset;
+            boundingBox->setHeight(boundingBox->height() + renderer.itemBoundingBoxRect(additionOffset, optionIndex).height());
+        }
+        ++optionIndex;
+    }
+
+    if (!boundingBox)
+        return std::nullopt;
+
+    return std::pair<RenderObject*, LayoutRect> { &renderer, boundingBox.value() };
+}
+
 Ref<DOMRectList> Element::getClientRects()
 {
     document().updateLayoutIgnorePendingStylesheets();
 
-    RenderBoxModelObject* renderBoxModelObject = this->renderBoxModelObject();
-    if (!renderBoxModelObject)
-        return DOMRectList::create();
+    RenderObject* renderer = this->renderer();
+    Vector<FloatQuad> quads;
 
+    if (auto pair = listBoxElementBoundingBox(*this)) {
+        renderer = pair.value().first;
+        quads.append(renderer->localToAbsoluteQuad(FloatQuad { pair.value().second }));
+    } else if (auto* renderBoxModelObject = this->renderBoxModelObject())
+        renderBoxModelObject->absoluteQuads(quads);
+
     // FIXME: Handle SVG elements.
     // FIXME: Handle table/inline-table with a caption.
 
-    Vector<FloatQuad> quads;
-    renderBoxModelObject->absoluteQuads(quads);
-    document().convertAbsoluteToClientQuads(quads, renderBoxModelObject->style());
+    if (quads.isEmpty())
+        return DOMRectList::create();
+
+    document().convertAbsoluteToClientQuads(quads, renderer->style());
     return DOMRectList::create(quads);
 }
 
@@ -1166,18 +1216,19 @@
 {
     document().updateLayoutIgnorePendingStylesheets();
 
+    RenderObject* renderer = this->renderer();
     Vector<FloatQuad> quads;
-    if (isSVGElement() && renderer() && !renderer()->isSVGRoot()) {
+    if (isSVGElement() && renderer && !renderer->isSVGRoot()) {
         // Get the bounding rectangle from the SVG model.
         SVGElement& svgElement = downcast<SVGElement>(*this);
         FloatRect localRect;
         if (svgElement.getBoundingBox(localRect))
-            quads.append(renderer()->localToAbsoluteQuad(localRect));
-    } else {
-        // Get the bounding rectangle from the box model.
-        if (renderBoxModelObject())
-            renderBoxModelObject()->absoluteQuads(quads);
-    }
+            quads.append(renderer->localToAbsoluteQuad(localRect));
+    } else if (auto pair = listBoxElementBoundingBox(*this)) {
+        renderer = pair.value().first;
+        quads.append(renderer->localToAbsoluteQuad(FloatQuad { pair.value().second }));
+    } else if (auto* renderBoxModelObject = this->renderBoxModelObject())
+        renderBoxModelObject->absoluteQuads(quads);
 
     if (quads.isEmpty())
         return { };
@@ -1186,7 +1237,7 @@
     for (size_t i = 1; i < quads.size(); ++i)
         result.unite(quads[i].boundingBox());
 
-    document().convertAbsoluteToClientRect(result, renderer()->style());
+    document().convertAbsoluteToClientRect(result, renderer->style());
     return result;
 }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to