Skip to content
Browse files
:lang pseudo class should work across shadow boundaries

Reviewed by Antti Koivisto.

Fixed the bug that :lang pseudo class doesn't work across shadow boundaries.

* Source/WebCore/dom/Element.cpp:
(WebCore::Element::computeInheritedLanguage const): Walk up the shadow-including ancestors.
Note that we don't use parentElementInComposedTree as we don't want to traverse up to a slot.

* LayoutTests/fast/shadow-dom/lang-pseudo-class-across-shadow-boundaries-expected.html: Added.
* LayoutTests/fast/shadow-dom/lang-pseudo-class-across-shadow-boundaries.html: Added.

Canonical link:
  • Loading branch information
rniwa committed Jul 3, 2022
1 parent ab3c0b8 commit d8c2040cc29812679728f3dd3f5d5011b9e4626c
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 2 deletions.
@@ -0,0 +1,7 @@
<!DOCTYPE html>
<p>Test passes if you see a single 100px by 100px green box below.</p>
<div style="width: 100px; height: 100px; background: green;"></div>
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<p>Test passes if you see a single 100px by 100px green box below.</p>
#testCases div { width: 100px; height: 25px; }
#host1:lang(zh) { background: green; }
#host3 > :lang(ja) { background: green; }
#host4 > div { background: red; }
<div id="testCases">
<div id="host1" lang="zh"><div></div></div>
<div id="host2" lang="de"><div></div></div>
<div id="host3" lang="ja"><div></div></div>
<div id="host4"><div></div></div>
host1.attachShadow({mode: 'closed'}).innerHTML = '<slot></slot>';
host2.attachShadow({mode: 'closed'}).innerHTML = '<style> div { width: 100px; height: 25px; background: red; } div:lang(de) { background: green; } </style><div></div>';
host3.attachShadow({mode: 'closed'}).innerHTML = '<slot lang="en"></slot>';
host4.attachShadow({mode: 'closed'}).innerHTML = '<style> :lang(ja)::slotted(*) { background: green !important; } </style><slot lang="ja"></slot>';
@@ -3829,8 +3829,8 @@ unsigned Element::rareDataChildIndex() const
AtomString Element::computeInheritedLanguage() const
// The language property is inherited, so we iterate over the parents to find the first language.
for (auto& element : lineageOfType<Element>(*this)) {
if (auto* elementData = element.elementData()) {
for (auto* element = this; element; element = element->parentOrShadowHostElement()) {
if (auto* elementData = element->elementData()) {
if (auto* attribute = elementData->findLanguageAttribute())
return attribute->value();

0 comments on commit d8c2040

Please sign in to comment.