Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
:dir pseudo class doesn't invalidate after removing dir content attri…
…bute from document element

https://bugs.webkit.org/show_bug.cgi?id=255568

Reviewed by Tim Nguyen and Antti Koivisto.

The bug was caused by dirAttributeChanged not calling HTMLElement::dirAttributeChanged not
updating the effective directionality state when removing a content attribute. Fixed the bug
by recursively invalidating the pseudo class state using updateEffectiveDirectionality,
which is now updated to take std::optional<TextDirection>.

Also removed redundant calls to HTMLElement::setUsesEffectiveTextDirection(true) in
HTMLElement::dirAttributeChanged.

* LayoutTests/fast/css/dir-ltr-removal-expected.html: Added.
* LayoutTests/fast/css/dir-ltr-removal.html: Added.
* LayoutTests/fast/css/dir-rtl-removal-expected.html: Added.
* LayoutTests/fast/css/dir-rtl-removal.html: Added.
* Source/WebCore/html/HTMLElement.cpp:
(WebCore::HTMLElement::dirAttributeChanged):
(WebCore::HTMLElement::updateEffectiveDirectionality):

Canonical link: https://commits.webkit.org/263357@main
  • Loading branch information
rniwa committed Apr 25, 2023
1 parent 4472b61 commit a3084fe
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 12 deletions.
10 changes: 10 additions & 0 deletions LayoutTests/fast/css/dir-ltr-removal-expected.html
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html dir="rtl">
<body>
<div class="box"></div>
<style>
body { text-align: left; }
.box { width: 100px; height: 100px; background: green; display: inline-block; }
</style>
</body>
</html>
18 changes: 18 additions & 0 deletions LayoutTests/fast/css/dir-ltr-removal.html
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html dir="rtl">
<body>
<div id="element" dir="ltr" class="box"></div><div id="host" dir="ltr"></div>
<style>
body { text-align: left; }
.box { width: 50px; height: 100px; background: green; display: inline-block; }
.box:dir(ltr) { background: red; }
#host { display: inline-block; }
</style>
<script>
host.attachShadow({mode: 'closed'}).innerHTML = '<div class="box"></div><style>.box { width: 50px; height: 100px; background: green; } .box:dir(ltr) { background: red; }</style>';
element.getBoundingClientRect();
element.removeAttribute('dir');
host.removeAttribute('dir');
</script>
</body>
</html>
9 changes: 9 additions & 0 deletions LayoutTests/fast/css/dir-rtl-removal-expected.html
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<body>
<div class="box"></div>
<style>
.box { width: 100px; height: 100px; background: green; }
</style>
</body>
</html>
17 changes: 17 additions & 0 deletions LayoutTests/fast/css/dir-rtl-removal.html
@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<body>
<div id="element" class="box"></div>
<div id="host" class="box"></div>
<style>
.box { width: 100px; height: 50px; background: green; }
.box:dir(rtl) { background: red; }
</style>
<script>
document.documentElement.setAttribute('dir', 'rtl');
host.attachShadow({mode: 'closed'}).innerHTML = '<div class="box"></div><style>.box { width: 100px; height: 50px; background: green; } .box:dir(rtl) { background: red; }</style>'
element.getBoundingClientRect();
document.documentElement.removeAttribute('dir');
</script>
</body>
</html>
22 changes: 11 additions & 11 deletions Source/WebCore/html/HTMLElement.cpp
Expand Up @@ -886,22 +886,19 @@ void HTMLElement::dirAttributeChanged(const AtomString& value)
isValid = false;
if (selfOrPrecedingNodesAffectDirAuto() && (!parent || !parent->selfOrPrecedingNodesAffectDirAuto()) && !is<HTMLBDIElement>(*this))
setHasDirAutoFlagRecursively(this, false);
if (parent && parent->usesEffectiveTextDirection() && !(is<HTMLInputElement>(*this) && downcast<HTMLInputElement>(*this).isTelephoneField())) {
setUsesEffectiveTextDirection(true);
if (parent && parent->usesEffectiveTextDirection() && !(is<HTMLInputElement>(*this) && downcast<HTMLInputElement>(*this).isTelephoneField()))
updateEffectiveDirectionality(parent->effectiveTextDirection());
} else
setUsesEffectiveTextDirection(false);
else
updateEffectiveDirectionality(std::nullopt);
break;
case TextDirectionDirective::LTR:
if (selfOrPrecedingNodesAffectDirAuto())
setHasDirAutoFlagRecursively(this, false);
setUsesEffectiveTextDirection(true);
updateEffectiveDirectionality(TextDirection::LTR);
break;
case TextDirectionDirective::RTL:
if (selfOrPrecedingNodesAffectDirAuto())
setHasDirAutoFlagRecursively(this, false);
setUsesEffectiveTextDirection(true);
updateEffectiveDirectionality(TextDirection::RTL);
break;
case TextDirectionDirective::Auto:
Expand All @@ -917,11 +914,13 @@ void HTMLElement::dirAttributeChanged(const AtomString& value)
}
}

void HTMLElement::updateEffectiveDirectionality(TextDirection direction)
void HTMLElement::updateEffectiveDirectionality(std::optional<TextDirection> direction)
{
Style::PseudoClassChangeInvalidation styleInvalidation(*this, CSSSelector::PseudoClassDir, Style::PseudoClassChangeInvalidation::AnyValue);
setUsesEffectiveTextDirection(true);
setEffectiveTextDirection(direction);
auto effectiveDirection = direction.value_or(TextDirection::LTR);
setUsesEffectiveTextDirection(!!direction);
if (direction)
setEffectiveTextDirection(effectiveDirection);
auto updateEffectiveTextDirectionOfShadowRoot = [&](HTMLElement& element) {
if (RefPtr shadowRootOfElement = element.shadowRoot()) {
for (auto& element : childrenOfType<HTMLElement>(*shadowRootOfElement))
Expand All @@ -937,8 +936,9 @@ void HTMLElement::updateEffectiveDirectionality(TextDirection direction)
}
updateEffectiveTextDirectionOfShadowRoot(element);
Style::PseudoClassChangeInvalidation styleInvalidation(element, CSSSelector::PseudoClassDir, Style::PseudoClassChangeInvalidation::AnyValue);
element.setUsesEffectiveTextDirection(true);
element.setEffectiveTextDirection(direction);
element.setUsesEffectiveTextDirection(!!direction);
if (direction)
element.setEffectiveTextDirection(effectiveDirection);
it.traverseNext();
}
}
Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/html/HTMLElement.h
Expand Up @@ -208,7 +208,7 @@ class HTMLElement : public StyledElement {
void mapLanguageAttributeToLocale(const AtomString&, MutableStyleProperties&);

void dirAttributeChanged(const AtomString&);
void updateEffectiveDirectionality(TextDirection);
void updateEffectiveDirectionality(std::optional<TextDirection>);
void adjustDirectionalityIfNeededAfterChildAttributeChanged(Element* child);
void adjustDirectionalityIfNeededAfterChildrenChanged(Element* beforeChange, ChildChange::Type);

Expand Down

0 comments on commit a3084fe

Please sign in to comment.