Bug 1097499 part 3 - Add a separate anonbox for text nodes. r=heycam

MozReview-Commit-ID: 1GfoFEGhyka
This commit is contained in:
Xidorn Quan
2016-04-22 09:18:41 +10:00
parent 3dc0ea538e
commit 15df861e15
17 changed files with 76 additions and 44 deletions

View File

@@ -3118,7 +3118,7 @@ ElementRestyler::MoveStyleContextsForContentChildren(
return false;
}
nsIAtom* pseudoTag = sc->GetPseudo();
if (pseudoTag && pseudoTag != nsCSSAnonBoxes::mozNonElement) {
if (pseudoTag && !nsCSSAnonBoxes::IsNonElement(pseudoTag)) {
return false;
}
aContextsToMove.AppendElement(sc);
@@ -3551,7 +3551,7 @@ ElementRestyler::ComputeRestyleResultFromFrame(nsIFrame* aSelf,
// where we have this kind of inheritance, we keep restyling past
// pseudos.
nsIAtom* pseudoTag = oldContext->GetPseudo();
if (pseudoTag && pseudoTag != nsCSSAnonBoxes::mozNonElement) {
if (pseudoTag && !nsCSSAnonBoxes::IsNonElement(pseudoTag)) {
LOG_RESTYLE_CONTINUE("the old style context is for a pseudo");
aRestyleResult = eRestyleResult_Continue;
aCanStopWithStyleChange = false;
@@ -3565,7 +3565,10 @@ ElementRestyler::ComputeRestyleResultFromFrame(nsIFrame* aSelf,
// be inheriting from a grandparent frame's style context (or a further
// ancestor).
nsIAtom* parentPseudoTag = parent->StyleContext()->GetPseudo();
if (parentPseudoTag && parentPseudoTag != nsCSSAnonBoxes::mozNonElement) {
if (parentPseudoTag &&
parentPseudoTag != nsCSSAnonBoxes::mozOtherNonElement) {
MOZ_ASSERT(parentPseudoTag != nsCSSAnonBoxes::mozText,
"Style of text node should not be parent of anything");
LOG_RESTYLE_CONTINUE("the old style context's parent is for a pseudo");
aRestyleResult = eRestyleResult_Continue;
// Parent style context pseudo-ness doesn't affect whether we can
@@ -3922,11 +3925,10 @@ ElementRestyler::RestyleSelf(nsIFrame* aSelf,
// continuation.
LOG_RESTYLE("using previous continuation's context");
newContext = prevContinuationContext;
}
else if (pseudoTag == nsCSSAnonBoxes::mozNonElement) {
} else if (nsCSSAnonBoxes::IsNonElement(pseudoTag)) {
NS_ASSERTION(aSelf->GetContent(),
"non pseudo-element frame without content node");
newContext = styleSet->ResolveStyleForNonElement(parentContext);
newContext = styleSet->ResolveStyleForNonElement(parentContext, pseudoTag);
}
else {
Element* element = ElementForStyleContext(mParentContent, aSelf, pseudoType);
@@ -4271,7 +4273,7 @@ ElementRestyler::RestyleSelf(nsIFrame* aSelf,
const CSSPseudoElementType extraPseudoType =
oldExtraContext->GetPseudoType();
NS_ASSERTION(extraPseudoTag &&
extraPseudoTag != nsCSSAnonBoxes::mozNonElement,
!nsCSSAnonBoxes::IsNonElement(extraPseudoTag),
"extra style context is not pseudo element");
Element* element = extraPseudoType != CSSPseudoElementType::AnonBox
? mContent->AsElement() : nullptr;

View File

@@ -3001,7 +3001,7 @@ nsCSSFrameConstructor::CreatePlaceholderFrameFor(nsIPresShell* aPresShell,
nsFrameState aTypeBit)
{
RefPtr<nsStyleContext> placeholderStyle = aPresShell->StyleSet()->
ResolveStyleForNonElement(aParentStyle);
ResolveStyleForNonElement(aParentStyle, nsCSSAnonBoxes::mozOtherNonElement);
// The placeholder frame gets a pseudo style context
nsPlaceholderFrame* placeholderFrame =
@@ -4960,7 +4960,8 @@ nsCSSFrameConstructor::ResolveStyleContext(nsStyleContext* aParentStyleContext,
NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
"shouldn't waste time creating style contexts for "
"comments and processing instructions");
result = styleSet->ResolveStyleForNonElement(aParentStyleContext);
result = styleSet->ResolveStyleForNonElement(aParentStyleContext,
nsCSSAnonBoxes::mozText);
}
// ServoRestyleManager does not handle transitions yet, and when it does
@@ -11103,9 +11104,9 @@ nsCSSFrameConstructor::CreateFloatingLetterFrame(
// get a proper style context for it (the one passed in is for the
// letter frame and will have the float property set on it; the text
// frame shouldn't have that set).
RefPtr<nsStyleContext> textSC;
StyleSetHandle styleSet = mPresShell->StyleSet();
textSC = styleSet->ResolveStyleForNonElement(aStyleContext);
RefPtr<nsStyleContext> textSC = styleSet->
ResolveStyleForNonElement(aStyleContext, nsCSSAnonBoxes::mozText);
aTextFrame->SetStyleContextWithoutNotification(textSC);
InitAndRestoreFrame(aState, aTextContent, letterFrame, aTextFrame);
@@ -11123,8 +11124,8 @@ nsCSSFrameConstructor::CreateFloatingLetterFrame(
// Repair the continuations style context
nsStyleContext* parentStyleContext = aStyleContext->GetParent();
if (parentStyleContext) {
RefPtr<nsStyleContext> newSC;
newSC = styleSet->ResolveStyleForNonElement(parentStyleContext);
RefPtr<nsStyleContext> newSC = styleSet->
ResolveStyleForNonElement(parentStyleContext, nsCSSAnonBoxes::mozText);
nextTextFrame->SetStyleContext(newSC);
}
}
@@ -11177,8 +11178,8 @@ nsCSSFrameConstructor::CreateLetterFrame(nsContainerFrame* aBlockFrame,
RefPtr<nsStyleContext> sc = GetFirstLetterStyle(blockContent,
parentStyleContext);
if (sc) {
RefPtr<nsStyleContext> textSC;
textSC = mPresShell->StyleSet()->ResolveStyleForNonElement(sc);
RefPtr<nsStyleContext> textSC = mPresShell->StyleSet()->
ResolveStyleForNonElement(sc, nsCSSAnonBoxes::mozText);
// Create a new text frame (the original one will be discarded)
// pass a temporary stylecontext, the correct one will be set
@@ -11376,8 +11377,8 @@ nsCSSFrameConstructor::RemoveFloatingFirstLetterFrames(
if (!textContent) {
return NS_OK;
}
RefPtr<nsStyleContext> newSC;
newSC = aPresShell->StyleSet()->ResolveStyleForNonElement(parentSC);
RefPtr<nsStyleContext> newSC = aPresShell->StyleSet()->
ResolveStyleForNonElement(parentSC, nsCSSAnonBoxes::mozText);
nsIFrame* newTextFrame = NS_NewTextFrame(aPresShell, newSC);
newTextFrame->Init(textContent, parentFrame, nullptr);
@@ -11449,8 +11450,8 @@ nsCSSFrameConstructor::RemoveFirstLetterFrames(nsIPresShell* aPresShell,
if (!textContent) {
break;
}
RefPtr<nsStyleContext> newSC;
newSC = aPresShell->StyleSet()->ResolveStyleForNonElement(parentSC);
RefPtr<nsStyleContext> newSC = aPresShell->StyleSet()->
ResolveStyleForNonElement(parentSC, nsCSSAnonBoxes::mozText);
textFrame = NS_NewTextFrame(aPresShell, newSC);
textFrame->Init(textContent, aFrame, nullptr);

View File

@@ -1372,7 +1372,8 @@ nsComboboxControlFrame::CreateFrameFor(nsIContent* aContent)
nsStyleSet::eSkipParentDisplayBasedStyleFixup);
RefPtr<nsStyleContext> textStyleContext;
textStyleContext = styleSet->ResolveStyleForNonElement(mStyleContext);
textStyleContext = styleSet->
ResolveStyleForNonElement(mStyleContext, nsCSSAnonBoxes::mozText);
// Start by creating our anonymous block frame
mDisplayFrame = new (shell) nsComboboxDisplayFrame(styleContext, this);

View File

@@ -91,7 +91,7 @@ nsGfxButtonControlFrame::CreateFrameFor(nsIContent* aContent)
nsPresContext* presContext = PresContext();
RefPtr<nsStyleContext> textStyleContext;
textStyleContext = presContext->StyleSet()->
ResolveStyleForNonElement(mStyleContext);
ResolveStyleForNonElement(mStyleContext, nsCSSAnonBoxes::mozText);
newFrame = NS_NewTextFrame(presContext->PresShell(), textStyleContext);
// initialize the text frame

View File

@@ -70,7 +70,8 @@ nsFirstLetterFrame::Init(nsIContent* aContent,
nsStyleContext* parentStyleContext = mStyleContext->GetParent();
if (parentStyleContext) {
newSC = PresContext()->StyleSet()->
ResolveStyleForNonElement(parentStyleContext);
ResolveStyleForNonElement(parentStyleContext,
nsCSSAnonBoxes::mozOtherNonElement);
SetStyleContextWithoutNotification(newSC);
}
}
@@ -331,7 +332,8 @@ nsFirstLetterFrame::CreateContinuationForFloatingParent(nsPresContext* aPresCont
nsStyleContext* parentSC = this->StyleContext()->GetParent();
if (parentSC) {
RefPtr<nsStyleContext> newSC;
newSC = presShell->StyleSet()->ResolveStyleForNonElement(parentSC);
newSC = presShell->StyleSet()->
ResolveStyleForNonElement(parentSC, nsCSSAnonBoxes::mozOtherNonElement);
continuation->SetStyleContext(newSC);
nsLayoutUtils::MarkDescendantsDirty(continuation);
}
@@ -385,7 +387,8 @@ nsFirstLetterFrame::DrainOverflowFrames(nsPresContext* aPresContext)
"should contain only text nodes");
nsStyleContext* parentSC = prevInFlow ? mStyleContext->GetParent() :
mStyleContext;
sc = aPresContext->StyleSet()->ResolveStyleForNonElement(parentSC);
sc = aPresContext->StyleSet()->
ResolveStyleForNonElement(parentSC, nsCSSAnonBoxes::mozText);
kid->SetStyleContext(sc);
nsLayoutUtils::MarkDescendantsDirty(kid);
}

View File

@@ -1004,7 +1004,7 @@ GetFirstNonAnonBoxDescendant(nsIFrame* aFrame)
// If aFrame isn't an anonymous container, then it'll do.
if (!pseudoTag || // No pseudotag.
!nsCSSAnonBoxes::IsAnonBox(pseudoTag) || // Pseudotag isn't anon.
pseudoTag == nsCSSAnonBoxes::mozNonElement) { // Text, not a container.
nsCSSAnonBoxes::IsNonElement(pseudoTag)) { // Text, not a container.
break;
}

View File

@@ -8330,7 +8330,7 @@ nsFrame::CorrectStyleParentFrame(nsIFrame* aProspectiveParent,
// Anon boxes are parented to their actual parent already, except
// for non-elements. Those should not be treated as an anon box.
if (aChildPseudo && aChildPseudo != nsCSSAnonBoxes::mozNonElement &&
if (aChildPseudo && !nsCSSAnonBoxes::IsNonElement(aChildPseudo) &&
nsCSSAnonBoxes::IsAnonBox(aChildPseudo)) {
NS_ASSERTION(aChildPseudo != nsCSSAnonBoxes::mozAnonymousBlock &&
aChildPseudo != nsCSSAnonBoxes::mozAnonymousPositionedBlock,

View File

@@ -96,7 +96,8 @@ ServoStyleSet::ResolveStyleFor(Element* aElement,
}
already_AddRefed<nsStyleContext>
ServoStyleSet::ResolveStyleForNonElement(nsStyleContext* aParentContext)
ServoStyleSet::ResolveStyleForNonElement(nsStyleContext* aParentContext,
nsIAtom* aPseudoTag)
{
MOZ_CRASH("stylo: not implemented");
}

View File

@@ -63,7 +63,8 @@ public:
TreeMatchContext& aTreeMatchContext);
already_AddRefed<nsStyleContext>
ResolveStyleForNonElement(nsStyleContext* aParentContext);
ResolveStyleForNonElement(nsStyleContext* aParentContext,
nsIAtom* aPseudoTag);
already_AddRefed<nsStyleContext>
ResolvePseudoElementStyle(dom::Element* aParentElement,

View File

@@ -119,7 +119,8 @@ public:
nsStyleContext* aParentContext,
TreeMatchContext& aTreeMatchContext);
inline already_AddRefed<nsStyleContext>
ResolveStyleForNonElement(nsStyleContext* aParentContext);
ResolveStyleForNonElement(nsStyleContext* aParentContext,
nsIAtom* aPseudoTag);
inline already_AddRefed<nsStyleContext>
ResolvePseudoElementStyle(dom::Element* aParentElement,
mozilla::CSSPseudoElementType aType,

View File

@@ -94,9 +94,10 @@ StyleSetHandle::Ptr::ResolveStyleFor(dom::Element* aElement,
}
already_AddRefed<nsStyleContext>
StyleSetHandle::Ptr::ResolveStyleForNonElement(nsStyleContext* aParentContext)
StyleSetHandle::Ptr::ResolveStyleForNonElement(nsStyleContext* aParentContext,
nsIAtom* aPseudoTag)
{
FORWARD(ResolveStyleForNonElement, (aParentContext));
FORWARD(ResolveStyleForNonElement, (aParentContext, aPseudoTag));
}
already_AddRefed<nsStyleContext>

View File

@@ -19,7 +19,13 @@
// OUTPUT_CLASS=nsCSSAnonBoxes
// MACRO_NAME=CSS_ANON_BOX
CSS_ANON_BOX(mozNonElement, ":-moz-non-element")
// ::-moz-text and ::-moz-other-non-element are non-elements which no
// rule will match.
CSS_ANON_BOX(mozText, ":-moz-text")
// This anonymous box has two uses:
// 1. placeholder frames,
// 2. nsFirstLetterFrames for content outside the ::first-letter.
CSS_ANON_BOX(mozOtherNonElement, ":-moz-other-non-element")
CSS_ANON_BOX(mozAnonymousBlock, ":-moz-anonymous-block")
CSS_ANON_BOX(mozAnonymousPositionedBlock, ":-moz-anonymous-positioned-block")

View File

@@ -23,6 +23,8 @@ public:
#ifdef MOZ_XUL
static bool IsTreePseudoElement(nsIAtom* aPseudo);
#endif
static bool IsNonElement(nsIAtom* aPseudo)
{ return aPseudo == mozText || aPseudo == mozOtherNonElement; }
#define CSS_ANON_BOX(_name, _value) static nsICSSAnonBoxPseudo* _name;
#include "nsCSSAnonBoxList.h"

View File

@@ -35,6 +35,7 @@
#include "nsColor.h"
#include "nsCSSPseudoClasses.h"
#include "nsCSSPseudoElements.h"
#include "nsCSSAnonBoxes.h"
#include "nsNameSpaceManager.h"
#include "nsXMLNameSpaceMap.h"
#include "nsError.h"
@@ -5927,6 +5928,13 @@ CSSParserImpl::ParsePseudoSelector(int32_t& aDataMask,
return eSelectorParsingStatus_Error;
}
if (nsCSSAnonBoxes::IsNonElement(pseudo)) {
// Non-element anonymous boxes should not match any rule.
REPORT_UNEXPECTED_TOKEN(PEPseudoSelUnknown);
UngetToken();
return eSelectorParsingStatus_Error;
}
// We currently allow :-moz-placeholder and ::-moz-placeholder. We have to
// be a bit stricter regarding the pseudo-element parsing rules.
if (pseudoElementType == CSSPseudoElementType::mozPlaceholder &&

View File

@@ -575,7 +575,7 @@ ShouldSuppressLineBreak(const nsStyleContext* aContext,
// which represents text frames, as well as ruby pseudos are excluded
// because we still want to set the flag for them.
if (aContext->GetPseudoType() == CSSPseudoElementType::AnonBox &&
aContext->GetPseudo() != nsCSSAnonBoxes::mozNonElement &&
!nsCSSAnonBoxes::IsNonElement(aContext->GetPseudo()) &&
!RubyUtils::IsRubyPseudo(aContext->GetPseudo())) {
return false;
}
@@ -744,7 +744,7 @@ nsStyleContext::ApplyStyleFixups(bool aSkipParentDisplayBasedStyleFixup)
containerDisp = containerContext->StyleDisplay();
}
if (ShouldBlockifyChildren(containerDisp) &&
GetPseudo() != nsCSSAnonBoxes::mozNonElement) {
!nsCSSAnonBoxes::IsNonElement(GetPseudo())) {
// NOTE: Technically, we shouldn't modify the 'display' value of
// positioned elements, since they aren't flex/grid items. However,
// we don't need to worry about checking for that, because if we're
@@ -815,7 +815,7 @@ nsStyleContext::ApplyStyleFixups(bool aSkipParentDisplayBasedStyleFixup)
* ...etc.
*/
if (disp->mDisplay == NS_STYLE_DISPLAY_INLINE &&
mPseudoTag != nsCSSAnonBoxes::mozNonElement &&
!nsCSSAnonBoxes::IsNonElement(mPseudoTag) &&
mParent) {
auto cbContext = mParent;
while (cbContext->StyleDisplay()->mDisplay == NS_STYLE_DISPLAY_CONTENTS) {

View File

@@ -1781,12 +1781,12 @@ nsStyleSet::ResolveStyleWithoutAnimation(dom::Element* aTarget,
}
already_AddRefed<nsStyleContext>
nsStyleSet::ResolveStyleForNonElement(nsStyleContext* aParentContext)
nsStyleSet::ResolveStyleForNonElement(nsStyleContext* aParentContext,
nsIAtom* aPseudoTag)
{
return GetContext(aParentContext, mRuleTree, nullptr,
nsCSSAnonBoxes::mozNonElement,
CSSPseudoElementType::AnonBox, nullptr,
eNoFlags);
MOZ_ASSERT(nsCSSAnonBoxes::IsNonElement(aPseudoTag));
return GetContext(aParentContext, mRuleTree, nullptr, aPseudoTag,
CSSPseudoElementType::AnonBox, nullptr, eNoFlags);
}
void

View File

@@ -166,11 +166,16 @@ class nsStyleSet final
// such as text nodes, placeholder frames, and the nsFirstLetterFrame
// for everything after the first letter.
//
// Perhaps this should go away and we shouldn't even create style
// contexts for such content nodes. However, not doing any rule
// matching for them is a first step.
// aPseudoTag can be either mozText or mozOtherNonElement.
//
// Perhaps mozOtherNonElement should go away and we shouldn't even
// create style contexts for such content nodes. However, not doing
// any rule matching for them is a first step.
// When text-combine-upright is not present, we may also want to avoid
// resolving style contexts for text frames as well.
already_AddRefed<nsStyleContext>
ResolveStyleForNonElement(nsStyleContext* aParentContext);
ResolveStyleForNonElement(nsStyleContext* aParentContext,
nsIAtom* aPseudoTag);
// Get a style context for a pseudo-element. aParentElement must be
// non-null. aPseudoID is the CSSPseudoElementType for the