Bug 1469108: Propagate directionality to the shadow tree. r=smaug

Make it so that directionality of the ShadowRoot descendants is computed based
on the host and it's ancestors, but don't touch the dir=auto code, since I don't
think anybody agrees with what needs to happen there, and I think in general
it shouldn't be accounted for.

MozReview-Commit-ID: AZMBZ5m1SQf
This commit is contained in:
Emilio Cobos Álvarez 2018-06-15 19:16:16 -07:00
Родитель c43cef31fc
Коммит b20d01787e
6 изменённых файлов: 183 добавлений и 26 удалений

Просмотреть файл

@ -213,6 +213,7 @@
#include "mozilla/AutoRestore.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/ShadowRoot.h"
#include "nsUnicodeProperties.h"
#include "nsTextFragment.h"
#include "nsAttrValue.h"
@ -222,6 +223,7 @@
namespace mozilla {
using mozilla::dom::Element;
using mozilla::dom::ShadowRoot;
/**
* Returns true if aElement is one of the elements whose text content should not
@ -276,6 +278,8 @@ GetDirectionFromChar(uint32_t ch)
}
}
// FIXME(bug 1100912): Should ShadowRoot children affect the host if it's
// dir=auto? Probably not at least in closed mode.
inline static bool
NodeAffectsDirAutoAncestor(nsINode* aTextNode)
{
@ -625,49 +629,67 @@ RecomputeDirectionality(Element* aElement, bool aNotify)
MOZ_ASSERT(!aElement->HasDirAuto(),
"RecomputeDirectionality called with dir=auto");
Directionality dir = eDir_LTR;
if (aElement->HasValidDir()) {
dir = aElement->GetDirectionality();
} else {
Element* parent = aElement->GetParentElement();
if (parent) {
// If the element doesn't have an explicit dir attribute with a valid
// value, the directionality is the same as the parent element (but
// don't propagate the parent directionality if it isn't set yet).
Directionality parentDir = parent->GetDirectionality();
return aElement->GetDirectionality();
}
Directionality dir = eDir_LTR;
if (nsINode* parent = aElement->GetParentNode()) {
if (ShadowRoot* shadow = ShadowRoot::FromNode(parent)) {
parent = shadow->GetHost();
}
if (parent && parent->IsElement()) {
// If the node doesn't have an explicit dir attribute with a valid value,
// the directionality is the same as the parent element (but don't propagate
// the parent directionality if it isn't set yet).
Directionality parentDir = parent->AsElement()->GetDirectionality();
if (parentDir != eDir_NotSet) {
dir = parentDir;
}
} else {
// If there is no parent element and no dir attribute, the directionality
// is LTR.
dir = eDir_LTR;
}
}
aElement->SetDirectionality(dir, aNotify);
}
return dir;
}
void
SetDirectionalityOnDescendants(Element* aElement, Directionality aDir,
static void
SetDirectionalityOnDescendantsInternal(nsINode* aNode,
Directionality aDir,
bool aNotify)
{
for (nsIContent* child = aElement->GetFirstChild(); child; ) {
if (Element* element = Element::FromNode(aNode)) {
if (ShadowRoot* shadow = element->GetShadowRoot()) {
SetDirectionalityOnDescendantsInternal(shadow, aDir, aNotify);
}
}
for (nsIContent* child = aNode->GetFirstChild(); child; ) {
if (!child->IsElement()) {
child = child->GetNextNode(aElement);
child = child->GetNextNode(aNode);
continue;
}
Element* element = child->AsElement();
if (element->HasValidDir() || element->HasDirAuto()) {
child = child->GetNextNonChildNode(aElement);
child = child->GetNextNonChildNode(aNode);
continue;
}
element->SetDirectionality(aDir, aNotify);
child = child->GetNextNode(aElement);
if (ShadowRoot* shadow = element->GetShadowRoot()) {
SetDirectionalityOnDescendantsInternal(shadow, aDir, aNotify);
}
element->SetDirectionality(aDir, aNotify);
child = child->GetNextNode(aNode);
}
}
// We want the public version of this only to acc
void
SetDirectionalityOnDescendants(Element* aElement, Directionality aDir,
bool aNotify)
{
return SetDirectionalityOnDescendantsInternal(aElement, aDir, aNotify);
}
/**

Просмотреть файл

@ -129331,6 +129331,30 @@
{}
]
],
"css/css-scoping/shadow-directionality-001.tentative.html": [
[
"/css/css-scoping/shadow-directionality-001.tentative.html",
[
[
"/css/css-scoping/reference/green-box.html",
"=="
]
],
{}
]
],
"css/css-scoping/shadow-directionality-002.tentative.html": [
[
"/css/css-scoping/shadow-directionality-002.tentative.html",
[
[
"/css/css-scoping/reference/green-box.html",
"=="
]
],
{}
]
],
"css/css-scoping/shadow-disabled-sheet-001.html": [
[
"/css/css-scoping/shadow-disabled-sheet-001.html",
@ -182915,6 +182939,18 @@
{}
]
],
"shadow-dom/directionality-001.tentative.html": [
[
"/shadow-dom/directionality-001.tentative.html",
[
[
"/shadow-dom/directionality-001-ref.html",
"=="
]
],
{}
]
],
"shadow-dom/layout-slot-no-longer-assigned.html": [
[
"/shadow-dom/layout-slot-no-longer-assigned.html",
@ -295386,6 +295422,11 @@
{}
]
],
"shadow-dom/directionality-001-ref.html": [
[
{}
]
],
"shadow-dom/reference/empty.html": [
[
{}
@ -522941,6 +522982,14 @@
"46913ea7e47811b11be898de5c3bd0a330ea6637",
"testharness"
],
"css/css-scoping/shadow-directionality-001.tentative.html": [
"51cf8c6780bb66f64082a0054f24f64c09b0258f",
"reftest"
],
"css/css-scoping/shadow-directionality-002.tentative.html": [
"c5cc9738b5b81a728c7cc16569360bd65b857ab3",
"reftest"
],
"css/css-scoping/shadow-disabled-sheet-001.html": [
"3de2d23c1b3339b964ec2c009832a3207a3b9dc4",
"reftest"
@ -523378,7 +523427,7 @@
"reftest"
],
"css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-004.html": [
"1e5377c120916557dc1525b38c9cf7eb86ae0151",
"3740c52d7bd26a3353721931ae2a6299db395968",
"reftest"
],
"css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-005.html": [
@ -539602,7 +539651,7 @@
"reftest"
],
"css/css-values/calc-rounding-001.html": [
"c3071454184ca1bd97443cfb6298447d16d79b2f",
"a74b631cd97db18ef120a0a5e7132c9e14b67f81",
"testharness"
],
"css/css-values/calc-serialization.html": [
@ -547362,7 +547411,7 @@
"testharness"
],
"css/cssom/getComputedStyle-detached-subtree.html": [
"01978ca7ea08cbf61b28e9d77753fe5852bcbff9",
"886f72b4eaa82d3aeb4de5c5b27f71369dbe0186",
"testharness"
],
"css/cssom/getComputedStyle-dynamic-subdoc.html": [
@ -610377,6 +610426,14 @@
"61f7da763fa4eb6f21077868caf0a07a4a9e44ae",
"testharness"
],
"shadow-dom/directionality-001-ref.html": [
"818d966e37de205936380fd47605f13b5aa505d7",
"support"
],
"shadow-dom/directionality-001.tentative.html": [
"763fd90e8ed83fb616379997735a5c283f0bd869",
"reftest"
],
"shadow-dom/event-composed-path-after-dom-mutation.html": [
"69ea3efc8230a0ed31968f24379289c6691d77d1",
"testharness"

Просмотреть файл

@ -0,0 +1,34 @@
<!doctype html>
<title>CSS Test: directionality propagation in Shadow DOM.</title>
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
<link rel="help" href="https://html.spec.whatwg.org/#the-dir-attribute">
<link rel="help" href="https://github.com/whatwg/html/issues/3699">
<link rel="match" href="reference/green-box.html">
<style>
div { width: 100px; }
</style>
<p>Test passes if you see a single 100px by 100px green box below.</p>
<div id="host1"></div>
<div id="host2" dir="rtl"></div>
<div id="host3"></div>
<div id="host4" dir="rtl"></div>
<script>
host1.attachShadow({ mode: "open" }).innerHTML = `
<style>:dir(ltr) { background: green; height: 25px; }</style>
<div></div>
`;
host2.attachShadow({ mode: "open" }).innerHTML = `
<style>:dir(rtl) { background: green; height: 25px; }</style>
<div></div>
`;
host3.attachShadow({ mode: "open" }).innerHTML = `
<style>:dir(rtl) { background: green; height: 25px; }</style>
<div></div>
`;
host4.attachShadow({ mode: "open" }).innerHTML = `
<style>span:dir(ltr) { display: block; background: green; height: 25px; }</style>
<div dir="ltr"><span></span></div>
`;
document.body.offsetTop;
host3.setAttribute("dir", "rtl");
</script>

Просмотреть файл

@ -0,0 +1,19 @@
<!doctype html>
<title>CSS Test: directionality propagation in Shadow DOM, appending a shadow host.</title>
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
<link rel="help" href="https://html.spec.whatwg.org/#the-dir-attribute">
<link rel="help" href="https://github.com/whatwg/html/issues/3699">
<link rel="match" href="reference/green-box.html">
<p>Test passes if you see a single 100px by 100px green box below.</p>
<style>
div { width: 100px; }
</style>
<div id="host-parent" dir="rtl"></div>
<script>
let host = document.createElement("div");
host.attachShadow({ mode: "open" }).innerHTML = `
<style>:dir(rtl) { background: green; height: 100px; width: 100px; }</style>
<div></div>
`;
document.getElementById("host-parent").appendChild(host);
</script>

Просмотреть файл

@ -0,0 +1,6 @@
<!doctype html>
<title>CSS Test Reference</title>
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
<div dir="rtl"> 123 456 <span><span> 789 101112 </span></span></div>
<div dir="rtl"> 123 456 <span dir="ltr"><span> 789 101112 </span></span></div>
<div dir="rtl"> 123 456 <span><span> 789 101112 </span></span></div>

Просмотреть файл

@ -0,0 +1,19 @@
<!doctype html>
<title>Test: directionality propagation in Shadow DOM.</title>
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
<link rel="help" href="https://html.spec.whatwg.org/#the-dir-attribute">
<link rel="help" href="https://github.com/whatwg/html/issues/3699">
<link rel="match" href="directionality-001-ref.html">
<div id="host0" dir="rtl"><span> 789 101112 </span></div>
<div id="host1" dir="rtl"><span> 789 101112 </span></div>
<div id="host2" dir="rtl"><span> 789 101112 </span></div>
<script>
host0.attachShadow({mode: 'closed'}).innerHTML =
'<div> 123 456 <span><slot></slot></span></div>';
host1.attachShadow({mode: 'closed'}).innerHTML =
'<div> 123 456 <span dir="ltr"><slot></slot></span></div>';
host2.attachShadow({mode: 'closed'}).innerHTML =
'<div> 123 456 <span><slot dir="ltr"></slot></span></div>';
</script>