From 67b3af80251368ea2d695a86fbfa2c54ac16d6dd Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 9 Sep 2022 11:44:42 +0200 Subject: [PATCH] LibWeb: Avoid layout in Element.client{Width,Height} if possible When querying the HTML element (in strict mode) or the BODY element (in quirks mode), we return the viewport dimensions. Layout doesn't change the size of the viewport, so we can actually reorder the steps here and avoid performing layout in some cases. This removes a bunch of synchronous layouts on pages with reCAPTCHA. --- Userland/Libraries/LibWeb/DOM/Element.cpp | 28 +++++++++++++---------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/Userland/Libraries/LibWeb/DOM/Element.cpp b/Userland/Libraries/LibWeb/DOM/Element.cpp index 1d0b715c1e..d37e314f03 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.cpp +++ b/Userland/Libraries/LibWeb/DOM/Element.cpp @@ -629,12 +629,7 @@ int Element::client_left() const // https://drafts.csswg.org/cssom-view/#dom-element-clientwidth int Element::client_width() const { - // NOTE: Ensure that layout is up-to-date before looking at metrics. - const_cast(document()).update_layout(); - - // 1. If the element has no associated CSS layout box or if the CSS layout box is inline, return zero. - if (!paint_box()) - return 0; + // NOTE: We do step 2 before step 1 here since step 2 can exit early without needing to perform layout. // 2. If the element is the root element and the element’s node document is not in quirks mode, // or if the element is the HTML body element and the element’s node document is in quirks mode, @@ -644,6 +639,13 @@ int Element::client_width() const return document().browsing_context()->viewport_rect().width(); } + // NOTE: Ensure that layout is up-to-date before looking at metrics. + const_cast(document()).update_layout(); + + // 1. If the element has no associated CSS layout box or if the CSS layout box is inline, return zero. + if (!paint_box()) + return 0; + // 3. Return the width of the padding edge excluding the width of any rendered scrollbar between the padding edge and the border edge, // ignoring any transforms that apply to the element and its ancestors. return paint_box()->absolute_padding_box_rect().width(); @@ -652,12 +654,7 @@ int Element::client_width() const // https://drafts.csswg.org/cssom-view/#dom-element-clientheight int Element::client_height() const { - // NOTE: Ensure that layout is up-to-date before looking at metrics. - const_cast(document()).update_layout(); - - // 1. If the element has no associated CSS layout box or if the CSS layout box is inline, return zero. - if (!paint_box()) - return 0; + // NOTE: We do step 2 before step 1 here since step 2 can exit early without needing to perform layout. // 2. If the element is the root element and the element’s node document is not in quirks mode, // or if the element is the HTML body element and the element’s node document is in quirks mode, @@ -667,6 +664,13 @@ int Element::client_height() const return document().browsing_context()->viewport_rect().height(); } + // NOTE: Ensure that layout is up-to-date before looking at metrics. + const_cast(document()).update_layout(); + + // 1. If the element has no associated CSS layout box or if the CSS layout box is inline, return zero. + if (!paint_box()) + return 0; + // 3. Return the height of the padding edge excluding the height of any rendered scrollbar between the padding edge and the border edge, // ignoring any transforms that apply to the element and its ancestors. return paint_box()->absolute_padding_box_rect().height();