delegate Range rect methods to container element

Instead of always returning zeros, delegate getBoundingClientRect and
getClientRects to the common ancestor container element. Return zeros
only when the range is collapsed or has no element ancestor.
This commit is contained in:
egrs committed 2026-03-09 10:09:11 +01:00
1 parent 4586fb1d13
commit e239f69f69
2 files changed
+52 -7

No files matched your search

+29 -2
View File
@@ -1023,7 +1023,7 @@
}
</script>
<script id=getBoundingClientRect>
<script id=getBoundingClientRect_collapsed>
{
const range = new Range();
const rect = range.getBoundingClientRect();
@@ -1035,10 +1035,37 @@
}
</script>
<script id=getClientRects>
<script id=getBoundingClientRect_element>
{
const range = new Range();
const p = document.getElementById('p1');
range.selectNodeContents(p);
const rect = range.getBoundingClientRect();
testing.expectTrue(rect instanceof DOMRect);
// Non-collapsed range delegates to the container element
const elemRect = p.getBoundingClientRect();
testing.expectEqual(elemRect.x, rect.x);
testing.expectEqual(elemRect.y, rect.y);
testing.expectEqual(elemRect.width, rect.width);
testing.expectEqual(elemRect.height, rect.height);
}
</script>
<script id=getClientRects_collapsed>
{
const range = new Range();
const rects = range.getClientRects();
testing.expectEqual(0, rects.length);
}
</script>
<script id=getClientRects_element>
{
const range = new Range();
const p = document.getElementById('p1');
range.selectNodeContents(p);
const rects = range.getClientRects();
const elemRects = p.getClientRects();
testing.expectEqual(elemRects.length, rects.length);
}
</script>
+23 -5
View File
@@ -644,13 +644,31 @@ fn nextAfterSubtree(node: *Node, root: *Node) ?*Node {
return null;
}
// Headless browser has no layout — return a zero-valued DOMRect.
pub fn getBoundingClientRect(_: *const Range) DOMRect {
return .{ ._x = 0, ._y = 0, ._width = 0, ._height = 0 };
pub fn getBoundingClientRect(self: *const Range, page: *Page) DOMRect {
if (self._proto.getCollapsed()) {
return .{ ._x = 0, ._y = 0, ._width = 0, ._height = 0 };
}
const element = self.getContainerElement() orelse {
return .{ ._x = 0, ._y = 0, ._width = 0, ._height = 0 };
};
return element.getBoundingClientRect(page);
}
pub fn getClientRects(_: *const Range) []DOMRect {
return &.{};
pub fn getClientRects(self: *const Range, page: *Page) ![]DOMRect {
if (self._proto.getCollapsed()) {
return &.{};
}
const element = self.getContainerElement() orelse {
return &.{};
};
return element.getClientRects(page);
}
fn getContainerElement(self: *const Range) ?*Node.Element {
const container = self._proto.getCommonAncestorContainer();
if (container.is(Node.Element)) |el| return el;
const parent = container.parentNode() orelse return null;
return parent.is(Node.Element);
}
pub const JsApi = struct {