Skip to content
Permalink
Browse files
vw units doesn't get updated inside shadow trees as frame is resized
https://bugs.webkit.org/show_bug.cgi?id=216240

Reviewed by Simon Fraser.

The bug was caused by Document::updateViewportUnitsOnResize only updating the style resolver of
the document and invalidating styles of nodes in the document tree. Fixed the bug by also
updating the style resolver and invalidating styles of nodes in each shadow tree.

* Source/WebCore/dom/Document.cpp:
(WebCore::Document::updateViewportUnitsOnResize):
* Source/WebCore/style/StyleScope.cpp:
(WebCore::Style::Scope::didChangeViewportSize): Added. Moved from updateViewportUnitsOnResize.
* Source/WebCore/style/StyleScope.h:

* LayoutTests/fast/shadow-dom/shadow-style-invalidation-vw-units-expected.html: Added.
* LayoutTests/fast/shadow-dom/shadow-style-invalidation-vw-units.html: Added.

Canonical link: https://commits.webkit.org/252149@main
  • Loading branch information
rniwa committed Jul 5, 2022
1 parent 554e2e8 commit 50df76018d8408eaaa055b9b11c470887e1e47be
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 11 deletions.
@@ -0,0 +1,6 @@
<!DOCTYPE html>
<html>
<body>
<div style="width: 100px; height: 100px; background: green;"></div>
</body>
</html>
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<body>
<script>

const iframe = document.createElement('iframe');
iframe.scrolling = 'no';
iframe.style = 'border: none; width: 50px; height: 50px; overflow: hidden';
iframe.src = `data:text/html,<!DOCTYPE html><style>head,html,body { padding: 0; margin: 0; }</style>
<div style="width: 100vw; height: 50vw; background: green"></div>
<div style="width: 100px; height: 100px; background: red;"><div id="host"></div></div>
<script>host.attachShadow({mode: 'closed'}).innerHTML =
'<style> div { width: 100vw; height: 50vw; background: green; }</style><div></div>';
host.getBoundingClientRect();
</sc` + `ript>`;
iframe.onload = () => {
iframe.style.width = '100px';
iframe.style.height = '100px';
}
document.body.appendChild(iframe);

</script>
</body>
</html>
@@ -4351,17 +4351,7 @@ void Document::evaluateMediaQueriesAndReportChanges()

void Document::updateViewportUnitsOnResize()
{
if (!hasStyleWithViewportUnits())
return;

styleScope().resolver().clearCachedDeclarationsAffectedByViewportUnits();

// FIXME: Ideally, we should save the list of elements that have viewport units and only iterate over those.
for (RefPtr element = ElementTraversal::firstWithin(rootNode()); element; element = ElementTraversal::nextIncludingPseudo(*element)) {
auto* renderer = element->renderer();
if (renderer && renderer->style().usesViewportUnits())
element->invalidateStyle();
}
styleScope().didChangeViewportSize();
}

void Document::setNeedsDOMWindowResizeEvent()
@@ -758,6 +758,35 @@ void Scope::didChangeStyleSheetEnvironment()
scheduleUpdate(UpdateType::ContentsOrInterpretation);
}

void Scope::didChangeViewportSize()
{
Ref<ContainerNode> rootNode = m_document;
if (m_shadowRoot)
rootNode = *m_shadowRoot;
else {
if (!m_document.hasStyleWithViewportUnits())
return;

for (auto* descendantShadowRoot : m_document.inDocumentShadowRoots()) {
if (descendantShadowRoot->mode() == ShadowRootMode::UserAgent)
continue;
descendantShadowRoot->styleScope().didChangeViewportSize();
}
}

auto* resolver = resolverIfExists();
if (!resolver)
return;
resolver->clearCachedDeclarationsAffectedByViewportUnits();

// FIXME: Ideally, we should save the list of elements that have viewport units and only iterate over those.
for (RefPtr element = ElementTraversal::firstWithin(rootNode); element; element = ElementTraversal::nextIncludingPseudo(*element)) {
auto* renderer = element->renderer();
if (renderer && renderer->style().usesViewportUnits())
element->invalidateStyle();
}
}

void Scope::invalidateMatchedDeclarationsCache()
{
if (!m_shadowRoot) {
@@ -107,6 +107,8 @@ class Scope : public CanMakeWeakPtr<Scope> {
// The change is assumed to potentially affect all author and user stylesheets including shadow roots.
WEBCORE_EXPORT void didChangeStyleSheetEnvironment();

void didChangeViewportSize();

void invalidateMatchedDeclarationsCache();

bool hasPendingUpdate() const { return m_pendingUpdate || m_hasDescendantWithPendingUpdate; }

0 comments on commit 50df760

Please sign in to comment.