Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: 364b06df0efb23bab2ae49198c6b6df89c043172
https://github.com/WebKit/WebKit/commit/364b06df0efb23bab2ae49198c6b6df89c043172
Author: Alan Baradlay <[email protected]>
Date: 2026-08-26 (Wed, 26 Aug 2026)
Changed paths:
M LayoutTests/fast/dynamic/display-none-iframe-async-layout-expected.html
A
LayoutTests/imported/w3c/web-platform-tests/css/css-animations/display-none-ancestor-does-not-cancel-subframe-animations-expected.txt
A
LayoutTests/imported/w3c/web-platform-tests/css/css-animations/display-none-ancestor-does-not-cancel-subframe-animations.html
A
LayoutTests/imported/w3c/web-platform-tests/css/cssom/computed-style-in-subframe-reflects-owner-document-expected.txt
A
LayoutTests/imported/w3c/web-platform-tests/css/cssom/computed-style-in-subframe-reflects-owner-document.html
A
LayoutTests/imported/w3c/web-platform-tests/html/rendering/replaced-elements/embedded-content/iframe-display-animated-to-none-content-not-laid-out-expected.txt
A
LayoutTests/imported/w3c/web-platform-tests/html/rendering/replaced-elements/embedded-content/iframe-display-animated-to-none-content-not-laid-out.html
A
LayoutTests/imported/w3c/web-platform-tests/html/rendering/replaced-elements/embedded-content/iframe-display-none-content-not-laid-out-expected.txt
A
LayoutTests/imported/w3c/web-platform-tests/html/rendering/replaced-elements/embedded-content/iframe-display-none-content-not-laid-out-while-parent-restyles-expected.txt
A
LayoutTests/imported/w3c/web-platform-tests/html/rendering/replaced-elements/embedded-content/iframe-display-none-content-not-laid-out-while-parent-restyles.html
A
LayoutTests/imported/w3c/web-platform-tests/html/rendering/replaced-elements/embedded-content/iframe-display-none-content-not-laid-out.html
A
LayoutTests/imported/w3c/web-platform-tests/html/rendering/replaced-elements/embedded-content/iframe-display-none-preserves-content-scroll-offset.tentative-expected.txt
A
LayoutTests/imported/w3c/web-platform-tests/html/rendering/replaced-elements/embedded-content/iframe-display-none-preserves-content-scroll-offset.tentative.html
A
LayoutTests/imported/w3c/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-display-none-content-stays-editable-expected.txt
A
LayoutTests/imported/w3c/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-display-none-content-stays-editable.html
A
LayoutTests/imported/w3c/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-display-none-still-loads-images-expected.txt
A
LayoutTests/imported/w3c/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-display-none-still-loads-images.html
M Source/WebCore/dom/Document.cpp
M Source/WebCore/dom/Document.h
M Source/WebCore/html/parser/HTMLResourcePreloader.cpp
M Source/WebCore/page/LocalFrame.cpp
M Source/WebCore/rendering/updating/RenderTreeUpdater.cpp
M Source/WebCore/rendering/updating/RenderTreeUpdater.h
M Source/WebCore/style/StyleExtractor.cpp
Log Message:
-----------
marketwatch.com: "Subscribe now" drop-down does not render anything
https://bugs.webkit.org/show_bug.cgi?id=321146
<rdar://181639379>
Reviewed by Antti Koivisto.
<div style="display: none; width: 300px">
<iframe srcdoc="<div style='width: 250px; height: 169px'></div>"></iframe>
</div>
The box inside should measure 0x0 while the ancestor is display:none. Instead
it was 250x169. We build a render tree for the content of such a
frame so script can ask for geometry, but nothing gives that content document's
view a size, so it lays out against a 0x0 viewport and the
geometry answers describe nothing. Build no render tree at all under a frame
whose owner element generates no box, and build it back when the
owner does.
Tests:
imported/w3c/web-platform-tests/css/css-animations/display-none-ancestor-does-not-cancel-subframe-animations.html
imported/w3c/web-platform-tests/css/cssom/computed-style-in-subframe-reflects-owner-document.html
imported/w3c/web-platform-tests/html/rendering/replaced-elements/embedded-content/iframe-display-animated-to-none-content-not-laid-out.html
imported/w3c/web-platform-tests/html/rendering/replaced-elements/embedded-content/iframe-display-none-content-not-laid-out.html
imported/w3c/web-platform-tests/html/rendering/replaced-elements/embedded-content/iframe-display-none-content-not-laid-out-while-parent-restyles.html
imported/w3c/web-platform-tests/html/rendering/replaced-elements/embedded-content/iframe-display-none-preserves-content-scroll-offset.tentative.html
imported/w3c/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-display-none-content-stays-editable.html
imported/w3c/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-display-none-still-loads-images.html
* Source/WebCore/dom/Document.h:
* Source/WebCore/dom/Document.cpp:
(WebCore::Document::ownerElementGeneratesBox const):
The question, answered from the owner element having a renderer rather than
from its
display value, since it also generates no box inside a display:none subtree
and when a shadow root leaves it unslotted.
An owner element in a document with no render tree has no renderer whatever
its display is,
so that case recurses, which is what keeps nested unrendered frames hidden.
A missing renderer settles nothing until the owner element itself has been
styled, since every subframe is created
while the parser is still building the tree around its owner element. Without
that an iframe's initial empty
document never gets a tree, so it never resolves style and never reports what
it should. Asked of the owner
element rather than of its document, so an unrelated restyle elsewhere in the
parent does not make a settled
frame look undecided and build a tree only to take it down again.
(WebCore::Document::updateRenderTreeForOwnerElementBox):
Builds or tears down this document's render tree to match. Called from the
owner
document's style update rather than from the display change itself: an owner
element
losing its renderer may be having it replaced rather than
removed, and nothing at the time of the change can tell those apart, so the
tree is settled from state afterwards. That also makes it idempotent.
(WebCore::Document::updateRenderTreesForDescendantFrames):
Runs the above over every descendant frame once this document has resolved
style.
Collects the documents first, because tearing a tree down can detach a frame
mid-walk.
(WebCore::Document::createRenderTree):
Withholds the tree for a frame whose owner generates no box. Needed here as
well because a subframe's
first document arrives through setDocument(), before any style update of the
owner.
(WebCore::Document::destroyRenderTree):
Takes whether the document is going away. A frame becoming unrendered is
still here, so its renderers
come down with RendererUpdate rather than a Full teardown, keeping animations
and hover state.
(WebCore::Document::updateStyleIfNeeded):
(WebCore::Document::enqueuePaintTimingEntryIfNeeded):
A frame that stops being rendered keeps a view that is still visually
non-empty from
before, so ContentfulPaintChecker was reached with no RenderView.
(WebCore::Document::hitTest):
Checked for a render tree, flushed layout - which resolves owner documents
and can take that tree away - then
used it. Re-checks after the flush.
* Source/WebCore/html/parser/HTMLResourcePreloader.cpp:
(WebCore::HTMLResourcePreloader::preload): Asserted that a document with a
frame has a render view, which a
frame whose owner element generates no box no longer does. Nothing below it
needs one: the media query
evaluator checks view() and documentElement(), and takes renderView() as a
pointer that may be null.
* Source/WebCore/page/LocalFrame.cpp:
(WebCore::LocalFrame::setPrinting):
Printing a display:none frame still works, so the tree is reconciled when
printing starts and stops.
* Source/WebCore/rendering/updating/RenderTreeUpdater.cpp:
(WebCore::RenderTreeUpdater::tearDownRenderersForDisplayNoneFrame):
TeardownType is private, so the RendererUpdate teardown gets a named entry
point like the others.
* Source/WebCore/rendering/updating/RenderTreeUpdater.h:
* Source/WebCore/style/StyleExtractor.cpp:
(WebCore::Style::Extractor::updateStyleIfNeededForProperty): A child's tree
is decided by the parent's style update, and this only flushed the
child, so a resolved value read after the owner was shown came back as the
computed value.
* LayoutTests/fast/dynamic/display-none-iframe-async-layout-expected.html:
Updated for the new behavior.
Canonical link: https://commits.webkit.org/319910@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications