Bug 1465572: Ensure <slot> disables whitespace optimizations. r?bz
The whitespace optimization code only knows about the light tree.
It's not a great idea to try to put flattened tree children of a slot through
there, since the children may not be assigned to the same slot, or to any slot
(in which case we crash).
We should probably rename XBLInvolved to ShadowDOMOrXBLInvolved too, I guess.
Note that the ShadowRoot case already sets the bit on Init().
MozReview-Commit-ID: 91lmE7OxlnA
--- a/dom/base/ChildIterator.cpp
+++ b/dom/base/ChildIterator.cpp
@@ -149,21 +149,26 @@ FlattenedChildIterator::Init(bool aIgnor
}
bool
FlattenedChildIterator::ComputeWhetherXBLIsInvolved() const
{
MOZ_ASSERT(mXBLInvolved.isNothing());
// We set mXBLInvolved to true if either the node we're iterating has a
// binding with content attached to it (in which case it is handled in Init),
- // or the node is generated XBL content and has an <xbl:children> child.
+ // the node is generated XBL content and has an <xbl:children> child, or the
+ // node is a <slot> element.
if (!mParent->GetBindingParent()) {
return false;
}
+ if (mParentAsSlot) {
+ return true;
+ }
+
for (nsIContent* child = mParent->GetFirstChild();
child;
child = child->GetNextSibling()) {
if (child->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
MOZ_ASSERT(child->GetBindingParent());
return true;
}
}
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -7690,17 +7690,17 @@ nsCSSFrameConstructor::ContentRangeInser
frameType = insertion.mParentFrame->Type();
}
}
AutoFrameConstructionItemList items(this);
ParentType parentType = GetParentType(frameType);
FlattenedChildIterator iter(insertion.mContainer);
- bool haveNoXBLChildren = (!iter.XBLInvolved() || !iter.GetNextChild());
+ bool haveNoXBLChildren = !iter.XBLInvolved() || !iter.GetNextChild();
if (aStartChild->GetPreviousSibling() &&
parentType == eTypeBlock && haveNoXBLChildren) {
// If there's a text node in the normal content list just before the
// new nodes, and it has no frame, make a frame construction item for
// it, because it might need a frame now. No need to do this if our
// parent type is not block, though, since WipeContainingBlock
// already handles that sitation.
AddTextItemIfNeeded(state, insertion, aStartChild->GetPreviousSibling(),
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -129044,16 +129044,28 @@
[
"/css/css-scoping/reference/green-box.html",
"=="
]
],
{}
]
],
+ "css/css-scoping/whitespace-crash-001.html": [
+ [
+ "/css/css-scoping/whitespace-crash-001.html",
+ [
+ [
+ "/css/css-scoping/reference/green-box.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/css-scrollbars/viewport-scrollbar-body.html": [
[
"/css/css-scrollbars/viewport-scrollbar-body.html",
[
[
"/css/css-scrollbars/viewport-scrollbar-body-ref.html",
"=="
]
@@ -520035,16 +520047,20 @@
"css/css-scoping/stylesheet-title-001.html": [
"2e49b6d74d2021144444ca77e62acbc6aeffac2a",
"reftest"
],
"css/css-scoping/stylesheet-title-002.html": [
"5816d3d7af3c4bef07f4a299ab65c74b7b8d80f9",
"testharness"
],
+ "css/css-scoping/whitespace-crash-001.html": [
+ "ffcc7ce387110d170772e0c9178991a2377753ad",
+ "reftest"
+ ],
"css/css-scroll-anchoring/OWNERS": [
"d9c8054b356c9273a054a83abeb9be0626c23921",
"support"
],
"css/css-scroll-anchoring/README.md": [
"31205944cbcf321f7aa77e3bef0f8835cc7b6d13",
"support"
],
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-scoping/whitespace-crash-001.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Scoping: Dynamic shadow root creation and whitespace optimization crash.</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="help" href="https://drafts.csswg.org/css-scoping/#selectors-data-model">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1465572">
+<link rel="match" href="reference/green-box.html"/>
+<p>Test passes if you see a single 100px by 100px green box below.</p>
+<!--
+ It's important for the test-case that there's whitespace inside the host,
+ and that it's not assigned to any slot.
+-->
+<div id="host">
+ <div style="display: inline" slot="the-slot"></div>
+</div>
+<script>
+ // Flush layout before creating a ShadowRoot, so that the whitespace ends up
+ // suppressed.
+ document.body.offsetTop;
+ host.attachShadow({ mode: "open" }).innerHTML = `
+ <style>
+ ::slotted(div) {
+ width: 100px;
+ height: 100px;
+ background: green;
+ }
+ </style>
+ <slot name="the-slot"></slot>
+ `;
+ document.body.offsetTop;
+ host.firstElementChild.style.display = "block"; // or anything else that reframes the <div>.
+</script>