1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 * the container for the style sheets that apply to a presentation, and
8 * the internal API that the style system exposes for creating (and
9 * potentially re-creating) style contexts
12 #include "mozilla/Util.h"
14 #include "nsStyleSet.h"
15 #include "nsCSSStyleSheet.h"
16 #include "nsIDocumentInlines.h"
17 #include "nsRuleWalker.h"
18 #include "nsStyleContext.h"
19 #include "mozilla/css/StyleRule.h"
20 #include "nsCSSAnonBoxes.h"
21 #include "nsCSSPseudoElements.h"
22 #include "nsCSSRuleProcessor.h"
23 #include "nsDataHashtable.h"
24 #include "nsIContent.h"
25 #include "nsRuleData.h"
26 #include "nsRuleProcessorData.h"
27 #include "nsTransitionManager.h"
28 #include "nsAnimationManager.h"
29 #include "nsEventStates.h"
30 #include "nsStyleSheetService.h"
31 #include "mozilla/dom/Element.h"
32 #include "GeckoProfiler.h"
34 using namespace mozilla
;
35 using namespace mozilla::dom
;
37 NS_IMPL_ISUPPORTS1(nsEmptyStyleRule
, nsIStyleRule
)
40 nsEmptyStyleRule::MapRuleInfoInto(nsRuleData
* aRuleData
)
46 nsEmptyStyleRule::List(FILE* out
, int32_t aIndent
) const
48 for (int32_t index
= aIndent
; --index
>= 0; ) fputs(" ", out
);
49 fputs("[empty style rule] {}\n", out
);
53 NS_IMPL_ISUPPORTS1(nsInitialStyleRule
, nsIStyleRule
)
56 nsInitialStyleRule::MapRuleInfoInto(nsRuleData
* aRuleData
)
58 // Iterate over the property groups
59 for (nsStyleStructID sid
= nsStyleStructID(0);
60 sid
< nsStyleStructID_Length
; sid
= nsStyleStructID(sid
+ 1)) {
61 if (aRuleData
->mSIDs
& (1 << sid
)) {
62 // Iterate over nsCSSValues within the property group
63 nsCSSValue
* const value_start
=
64 aRuleData
->mValueStorage
+ aRuleData
->mValueOffsets
[sid
];
65 for (nsCSSValue
*value
= value_start
,
66 *value_end
= value
+ nsCSSProps::PropertyCountInStruct(sid
);
67 value
!= value_end
; ++value
) {
68 // If MathML is disabled take care not to set MathML properties (or we
69 // will trigger assertions in nsRuleNode)
70 if (sid
== eStyleStruct_Font
&&
71 !aRuleData
->mPresContext
->Document()->GetMathMLEnabled()) {
72 size_t index
= value
- value_start
;
73 if (index
== nsCSSProps::PropertyIndexInStruct(
74 eCSSProperty_script_level
) ||
75 index
== nsCSSProps::PropertyIndexInStruct(
76 eCSSProperty_script_size_multiplier
) ||
77 index
== nsCSSProps::PropertyIndexInStruct(
78 eCSSProperty_script_min_size
)) {
82 if (value
->GetUnit() == eCSSUnit_Null
) {
83 value
->SetInitialValue();
92 nsInitialStyleRule::List(FILE* out
, int32_t aIndent
) const
94 for (int32_t index
= aIndent
; --index
>= 0; ) fputs(" ", out
);
95 fputs("[initial style rule] {}\n", out
);
99 static const nsStyleSet::sheetType gCSSSheetTypes
[] = {
100 nsStyleSet::eAgentSheet
,
101 nsStyleSet::eUserSheet
,
102 nsStyleSet::eDocSheet
,
103 nsStyleSet::eScopedDocSheet
,
104 nsStyleSet::eOverrideSheet
107 nsStyleSet::nsStyleSet()
108 : mRuleTree(nullptr),
111 mAuthorStyleDisabled(false),
112 mInReconstruct(false),
114 mUnusedRuleNodeCount(0)
119 nsStyleSet::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf
) const
121 size_t n
= aMallocSizeOf(this);
123 for (int i
= 0; i
< eSheetTypeCount
; i
++) {
124 if (mRuleProcessors
[i
]) {
125 n
+= mRuleProcessors
[i
]->SizeOfIncludingThis(aMallocSizeOf
);
127 n
+= mSheets
[i
].SizeOfExcludingThis(nullptr, aMallocSizeOf
);
130 for (uint32_t i
= 0; i
< mScopedDocSheetRuleProcessors
.Length(); i
++) {
131 n
+= mScopedDocSheetRuleProcessors
[i
]->SizeOfIncludingThis(aMallocSizeOf
);
133 n
+= mScopedDocSheetRuleProcessors
.SizeOfExcludingThis(aMallocSizeOf
);
135 n
+= mRoots
.SizeOfExcludingThis(aMallocSizeOf
);
136 n
+= mOldRuleTrees
.SizeOfExcludingThis(aMallocSizeOf
);
142 nsStyleSet::Init(nsPresContext
*aPresContext
)
144 mFirstLineRule
= new nsEmptyStyleRule
;
145 mFirstLetterRule
= new nsEmptyStyleRule
;
146 mPlaceholderRule
= new nsEmptyStyleRule
;
148 mRuleTree
= nsRuleNode::CreateRootNode(aPresContext
);
150 GatherRuleProcessors(eAnimationSheet
);
151 GatherRuleProcessors(eTransitionSheet
);
155 nsStyleSet::BeginReconstruct()
157 NS_ASSERTION(!mInReconstruct
, "Unmatched begin/end?");
158 NS_ASSERTION(mRuleTree
, "Reconstructing before first construction?");
160 // Create a new rule tree root
161 nsRuleNode
* newTree
=
162 nsRuleNode::CreateRootNode(mRuleTree
->PresContext());
164 return NS_ERROR_OUT_OF_MEMORY
;
166 // Save the old rule tree so we can destroy it later
167 if (!mOldRuleTrees
.AppendElement(mRuleTree
)) {
169 return NS_ERROR_OUT_OF_MEMORY
;
172 // We need to keep mRoots so that the rule tree GC will only free the
173 // rule trees that really aren't referenced anymore (which should be
174 // all of them, if there are no bugs in reresolution code).
176 mInReconstruct
= true;
183 nsStyleSet::EndReconstruct()
185 NS_ASSERTION(mInReconstruct
, "Unmatched begin/end?");
186 mInReconstruct
= false;
188 for (int32_t i
= mRoots
.Length() - 1; i
>= 0; --i
) {
189 nsRuleNode
*n
= mRoots
[i
]->RuleNode();
190 while (n
->GetParent()) {
193 // Since nsStyleContext's mParent and mRuleNode are immutable, and
194 // style contexts own their parents, and nsStyleContext asserts in
195 // its constructor that the style context and its parent are in the
196 // same rule tree, we don't need to check any of the children of
197 // mRoots; we only need to check the rule nodes of mRoots
200 NS_ASSERTION(n
== mRuleTree
, "style context has old rule node");
203 // This *should* destroy the only element of mOldRuleTrees, but in
204 // case of some bugs (which would trigger the above assertions), it
210 nsStyleSet::SetQuirkStyleSheet(nsIStyleSheet
* aQuirkStyleSheet
)
212 NS_ASSERTION(aQuirkStyleSheet
, "Must have quirk sheet if this is called");
213 NS_ASSERTION(!mQuirkStyleSheet
, "Multiple calls to SetQuirkStyleSheet?");
214 NS_ASSERTION(mSheets
[eAgentSheet
].IndexOf(aQuirkStyleSheet
) != -1,
215 "Quirk style sheet not one of our agent sheets?");
216 mQuirkStyleSheet
= aQuirkStyleSheet
;
219 typedef nsDataHashtable
<nsPtrHashKey
<nsINode
>, uint32_t> ScopeDepthCache
;
221 // Returns the depth of a style scope element, with 1 being the depth of
222 // a style scope element that has no ancestor style scope elements. The
223 // depth does not count intervening non-scope elements.
225 GetScopeDepth(nsINode
* aScopeElement
, ScopeDepthCache
& aCache
)
227 nsINode
* parent
= aScopeElement
->GetParent();
228 if (!parent
|| !parent
->IsElementInStyleScope()) {
232 uint32_t depth
= aCache
.Get(aScopeElement
);
234 for (nsINode
* n
= parent
; n
; n
= n
->GetParent()) {
235 if (n
->IsScopedStyleRoot()) {
236 depth
= GetScopeDepth(n
, aCache
) + 1;
237 aCache
.Put(aScopeElement
, depth
);
245 struct ScopedSheetOrder
247 nsCSSStyleSheet
* mSheet
;
251 bool operator==(const ScopedSheetOrder
& aRHS
) const
253 return mDepth
== aRHS
.mDepth
&&
254 mOrder
== aRHS
.mOrder
;
257 bool operator<(const ScopedSheetOrder
& aRHS
) const
259 if (mDepth
!= aRHS
.mDepth
) {
260 return mDepth
< aRHS
.mDepth
;
262 return mOrder
< aRHS
.mOrder
;
266 // Sorts aSheets such that style sheets for ancestor scopes come
267 // before those for descendant scopes, and with sheets for a single
268 // scope in document order.
270 SortStyleSheetsByScope(nsTArray
<nsCSSStyleSheet
*>& aSheets
)
272 uint32_t n
= aSheets
.Length();
277 ScopeDepthCache cache
;
280 nsTArray
<ScopedSheetOrder
> sheets
;
283 // For each sheet, record the depth of its scope element and its original
285 for (uint32_t i
= 0; i
< n
; i
++) {
286 sheets
[i
].mSheet
= aSheets
[i
];
287 sheets
[i
].mDepth
= GetScopeDepth(aSheets
[i
]->GetScopeElement(), cache
);
288 sheets
[i
].mOrder
= i
;
291 // Sort by depth first, then document order.
294 for (uint32_t i
= 0; i
< n
; i
++) {
295 aSheets
[i
] = sheets
[i
].mSheet
;
300 nsStyleSet::GatherRuleProcessors(sheetType aType
)
302 mRuleProcessors
[aType
] = nullptr;
303 if (aType
== eScopedDocSheet
) {
304 for (uint32_t i
= 0; i
< mScopedDocSheetRuleProcessors
.Length(); i
++) {
305 nsIStyleRuleProcessor
* processor
= mScopedDocSheetRuleProcessors
[i
].get();
307 static_cast<nsCSSRuleProcessor
*>(processor
)->GetScopeElement();
308 scope
->ClearIsScopedStyleRoot();
310 mScopedDocSheetRuleProcessors
.Clear();
312 if (mAuthorStyleDisabled
&& (aType
== eDocSheet
||
313 aType
== eScopedDocSheet
||
314 aType
== eStyleAttrSheet
)) {
315 // Don't regather if this level is disabled. Note that we gather
316 // preshint sheets no matter what, but then skip them for some
317 // elements later if mAuthorStyleDisabled.
320 if (aType
== eAnimationSheet
) {
321 // We have no sheet for the animations level; just a rule
322 // processor. (XXX: We should probably do this for the other
323 // non-CSS levels too!)
324 mRuleProcessors
[aType
] = PresContext()->AnimationManager();
327 if (aType
== eTransitionSheet
) {
328 // We have no sheet for the transitions level; just a rule
329 // processor. (XXX: We should probably do this for the other
330 // non-CSS levels too!)
331 mRuleProcessors
[aType
] = PresContext()->TransitionManager();
334 if (aType
== eScopedDocSheet
) {
335 // Create a rule processor for each scope.
336 uint32_t count
= mSheets
[eScopedDocSheet
].Count();
338 // Gather the scoped style sheets into an array as
339 // nsCSSStyleSheets, and mark all of their scope elements
340 // as scoped style roots.
341 nsTArray
<nsCSSStyleSheet
*> sheets(count
);
342 for (uint32_t i
= 0; i
< count
; i
++) {
343 nsRefPtr
<nsCSSStyleSheet
> sheet
=
344 do_QueryObject(mSheets
[eScopedDocSheet
].ObjectAt(i
));
345 sheets
.AppendElement(sheet
);
347 Element
* scope
= sheet
->GetScopeElement();
348 scope
->SetIsScopedStyleRoot();
351 // Sort the scoped style sheets so that those for the same scope are
352 // adjacent and that ancestor scopes come before descendent scopes.
353 SortStyleSheetsByScope(sheets
);
355 uint32_t start
= 0, end
;
357 // Find the range of style sheets with the same scope.
358 Element
* scope
= sheets
[start
]->GetScopeElement();
360 while (end
< count
&& sheets
[end
]->GetScopeElement() == scope
) {
364 scope
->SetIsScopedStyleRoot();
366 // Create a rule processor for the scope.
367 nsTArray
< nsRefPtr
<nsCSSStyleSheet
> > sheetsForScope
;
368 sheetsForScope
.AppendElements(sheets
.Elements() + start
, end
- start
);
369 mScopedDocSheetRuleProcessors
.AppendElement
370 (new nsCSSRuleProcessor(sheetsForScope
, uint8_t(aType
), scope
));
373 } while (start
< count
);
377 if (mSheets
[aType
].Count()) {
382 case eOverrideSheet
: {
383 // levels containing CSS stylesheets (apart from eScopedDocSheet)
384 nsCOMArray
<nsIStyleSheet
>& sheets
= mSheets
[aType
];
385 nsTArray
<nsRefPtr
<nsCSSStyleSheet
> > cssSheets(sheets
.Count());
386 for (int32_t i
= 0, i_end
= sheets
.Count(); i
< i_end
; ++i
) {
387 nsRefPtr
<nsCSSStyleSheet
> cssSheet
= do_QueryObject(sheets
[i
]);
388 NS_ASSERTION(cssSheet
, "not a CSS sheet");
389 cssSheets
.AppendElement(cssSheet
);
391 mRuleProcessors
[aType
] =
392 new nsCSSRuleProcessor(cssSheets
, uint8_t(aType
), nullptr);
396 // levels containing non-CSS stylesheets
397 NS_ASSERTION(mSheets
[aType
].Count() == 1, "only one sheet per level");
398 mRuleProcessors
[aType
] = do_QueryInterface(mSheets
[aType
][0]);
407 IsScopedStyleSheet(nsIStyleSheet
* aSheet
)
409 nsRefPtr
<nsCSSStyleSheet
> cssSheet
= do_QueryObject(aSheet
);
410 NS_ASSERTION(cssSheet
, "expected aSheet to be an nsCSSStyleSheet");
412 return cssSheet
->GetScopeElement();
416 nsStyleSet::AppendStyleSheet(sheetType aType
, nsIStyleSheet
*aSheet
)
418 NS_PRECONDITION(aSheet
, "null arg");
419 NS_ASSERTION(aSheet
->IsApplicable(),
420 "Inapplicable sheet being placed in style set");
421 mSheets
[aType
].RemoveObject(aSheet
);
422 if (!mSheets
[aType
].AppendObject(aSheet
))
423 return NS_ERROR_OUT_OF_MEMORY
;
426 return GatherRuleProcessors(aType
);
428 mDirty
|= 1 << aType
;
433 nsStyleSet::PrependStyleSheet(sheetType aType
, nsIStyleSheet
*aSheet
)
435 NS_PRECONDITION(aSheet
, "null arg");
436 NS_ASSERTION(aSheet
->IsApplicable(),
437 "Inapplicable sheet being placed in style set");
438 mSheets
[aType
].RemoveObject(aSheet
);
439 if (!mSheets
[aType
].InsertObjectAt(aSheet
, 0))
440 return NS_ERROR_OUT_OF_MEMORY
;
443 return GatherRuleProcessors(aType
);
445 mDirty
|= 1 << aType
;
450 nsStyleSet::RemoveStyleSheet(sheetType aType
, nsIStyleSheet
*aSheet
)
452 NS_PRECONDITION(aSheet
, "null arg");
453 NS_ASSERTION(aSheet
->IsComplete(),
454 "Incomplete sheet being removed from style set");
455 mSheets
[aType
].RemoveObject(aSheet
);
457 return GatherRuleProcessors(aType
);
459 mDirty
|= 1 << aType
;
464 nsStyleSet::ReplaceSheets(sheetType aType
,
465 const nsCOMArray
<nsIStyleSheet
> &aNewSheets
)
467 mSheets
[aType
].Clear();
468 if (!mSheets
[aType
].AppendObjects(aNewSheets
))
469 return NS_ERROR_OUT_OF_MEMORY
;
472 return GatherRuleProcessors(aType
);
474 mDirty
|= 1 << aType
;
479 nsStyleSet::InsertStyleSheetBefore(sheetType aType
, nsIStyleSheet
*aNewSheet
,
480 nsIStyleSheet
*aReferenceSheet
)
482 NS_PRECONDITION(aNewSheet
&& aReferenceSheet
, "null arg");
483 NS_ASSERTION(aNewSheet
->IsApplicable(),
484 "Inapplicable sheet being placed in style set");
486 mSheets
[aType
].RemoveObject(aNewSheet
);
487 int32_t idx
= mSheets
[aType
].IndexOf(aReferenceSheet
);
489 return NS_ERROR_INVALID_ARG
;
491 if (!mSheets
[aType
].InsertObjectAt(aNewSheet
, idx
))
492 return NS_ERROR_OUT_OF_MEMORY
;
495 return GatherRuleProcessors(aType
);
497 mDirty
|= 1 << aType
;
502 nsStyleSet::GetAuthorStyleDisabled()
504 return mAuthorStyleDisabled
;
508 nsStyleSet::SetAuthorStyleDisabled(bool aStyleDisabled
)
510 if (aStyleDisabled
== !mAuthorStyleDisabled
) {
511 mAuthorStyleDisabled
= aStyleDisabled
;
513 mDirty
|= 1 << eDocSheet
|
514 1 << eScopedDocSheet
|
515 1 << eStyleAttrSheet
;
521 // -------- Doc Sheets
524 nsStyleSet::AddDocStyleSheet(nsIStyleSheet
* aSheet
, nsIDocument
* aDocument
)
526 NS_PRECONDITION(aSheet
&& aDocument
, "null arg");
527 NS_ASSERTION(aSheet
->IsApplicable(),
528 "Inapplicable sheet being placed in style set");
530 sheetType type
= IsScopedStyleSheet(aSheet
) ?
533 nsCOMArray
<nsIStyleSheet
>& sheets
= mSheets
[type
];
535 sheets
.RemoveObject(aSheet
);
536 nsStyleSheetService
*sheetService
= nsStyleSheetService::GetInstance();
538 // lowest index first
539 int32_t newDocIndex
= aDocument
->GetIndexOfStyleSheet(aSheet
);
541 int32_t count
= sheets
.Count();
543 for (index
= 0; index
< count
; index
++) {
544 nsIStyleSheet
* sheet
= sheets
.ObjectAt(index
);
545 int32_t sheetDocIndex
= aDocument
->GetIndexOfStyleSheet(sheet
);
546 if (sheetDocIndex
> newDocIndex
)
549 // If the sheet is not owned by the document it can be an author
550 // sheet registered at nsStyleSheetService or an additional author
551 // sheet on the document, which means the new
552 // doc sheet should end up before it.
553 if (sheetDocIndex
< 0 &&
555 sheetService
->AuthorStyleSheets()->IndexOf(sheet
) >= 0) ||
556 sheet
== aDocument
->FirstAdditionalAuthorSheet()))
559 if (!sheets
.InsertObjectAt(aSheet
, index
))
560 return NS_ERROR_OUT_OF_MEMORY
;
562 return GatherRuleProcessors(type
);
569 nsStyleSet::RemoveDocStyleSheet(nsIStyleSheet
*aSheet
)
571 nsRefPtr
<nsCSSStyleSheet
> cssSheet
= do_QueryObject(aSheet
);
572 bool isScoped
= cssSheet
&& cssSheet
->GetScopeElement();
573 return RemoveStyleSheet(isScoped
? eScopedDocSheet
: eDocSheet
, aSheet
);
578 nsStyleSet::BeginUpdate()
584 nsStyleSet::EndUpdate()
586 NS_ASSERTION(mBatching
> 0, "Unbalanced EndUpdate");
588 // We're not completely done yet.
592 for (int i
= 0; i
< eSheetTypeCount
; ++i
) {
593 if (mDirty
& (1 << i
)) {
594 nsresult rv
= GatherRuleProcessors(sheetType(i
));
595 NS_ENSURE_SUCCESS(rv
, rv
);
604 nsStyleSet::EnableQuirkStyleSheet(bool aEnable
)
609 nsCOMPtr
<nsIDOMCSSStyleSheet
> domSheet
=
610 do_QueryInterface(mQuirkStyleSheet
);
611 domSheet
->GetDisabled(&oldEnabled
);
612 oldEnabled
= !oldEnabled
;
615 mQuirkStyleSheet
->SetEnabled(aEnable
);
617 // This should always be OK, since SetEnabled should call
618 // ClearRuleCascades.
619 // Note that we can hit this codepath multiple times when document.open()
620 // (potentially implied) happens multiple times.
621 if (mRuleProcessors
[eAgentSheet
] && aEnable
!= oldEnabled
) {
622 static_cast<nsCSSRuleProcessor
*>(static_cast<nsIStyleRuleProcessor
*>(
623 mRuleProcessors
[eAgentSheet
]))->AssertQuirksChangeOK();
630 EnumRulesMatching(nsIStyleRuleProcessor
* aProcessor
, void* aData
)
632 T
* data
= static_cast<T
*>(aData
);
633 aProcessor
->RulesMatching(data
);
638 IsMoreSpecificThanAnimation(nsRuleNode
*aRuleNode
)
640 return !aRuleNode
->IsRoot() &&
641 (aRuleNode
->GetLevel() == nsStyleSet::eTransitionSheet
||
642 aRuleNode
->IsImportantRule());
646 GetAnimationRule(nsRuleNode
*aRuleNode
)
648 nsRuleNode
*n
= aRuleNode
;
649 while (IsMoreSpecificThanAnimation(n
)) {
653 if (n
->IsRoot() || n
->GetLevel() != nsStyleSet::eAnimationSheet
) {
661 ReplaceAnimationRule(nsRuleNode
*aOldRuleNode
,
662 nsIStyleRule
*aOldAnimRule
,
663 nsIStyleRule
*aNewAnimRule
)
665 nsTArray
<nsRuleNode
*> moreSpecificNodes
;
667 nsRuleNode
*n
= aOldRuleNode
;
668 while (IsMoreSpecificThanAnimation(n
)) {
669 moreSpecificNodes
.AppendElement(n
);
674 NS_ABORT_IF_FALSE(n
->GetRule() == aOldAnimRule
, "wrong rule");
675 NS_ABORT_IF_FALSE(n
->GetLevel() == nsStyleSet::eAnimationSheet
,
680 NS_ABORT_IF_FALSE(!IsMoreSpecificThanAnimation(n
) &&
682 n
->GetLevel() != nsStyleSet::eAnimationSheet
),
686 n
= n
->Transition(aNewAnimRule
, nsStyleSet::eAnimationSheet
, false);
689 for (uint32_t i
= moreSpecificNodes
.Length(); i
-- != 0; ) {
690 nsRuleNode
*oldNode
= moreSpecificNodes
[i
];
691 n
= n
->Transition(oldNode
->GetRule(), oldNode
->GetLevel(),
692 oldNode
->IsImportantRule());
699 * |GetContext| implements sharing of style contexts (not just the data
700 * on the rule nodes) between siblings and cousins of the same
701 * generation. (It works for cousins of the same generation since
702 * |aParentContext| could itself be a shared context.)
704 already_AddRefed
<nsStyleContext
>
705 nsStyleSet::GetContext(nsStyleContext
* aParentContext
,
706 nsRuleNode
* aRuleNode
,
707 // aVisitedRuleNode may be null; if it is null
708 // it means that we don't need to force creation
709 // of a StyleIfVisited. (But if we make one
710 // because aParentContext has one, then aRuleNode
712 nsRuleNode
* aVisitedRuleNode
,
714 nsCSSPseudoElements::Type aPseudoType
,
715 Element
* aElementForAnimation
,
718 NS_PRECONDITION((!aPseudoTag
&&
720 nsCSSPseudoElements::ePseudo_NotPseudoElement
) ||
722 nsCSSPseudoElements::GetPseudoType(aPseudoTag
) ==
726 if (aVisitedRuleNode
== aRuleNode
) {
727 // No need to force creation of a visited style in this case.
728 aVisitedRuleNode
= nullptr;
731 // Ensure |aVisitedRuleNode != nullptr| corresponds to the need to
732 // create an if-visited style context, and that in that case, we have
733 // parentIfVisited set correctly.
734 nsStyleContext
*parentIfVisited
=
735 aParentContext
? aParentContext
->GetStyleIfVisited() : nullptr;
736 if (parentIfVisited
) {
737 if (!aVisitedRuleNode
) {
738 aVisitedRuleNode
= aRuleNode
;
741 if (aVisitedRuleNode
) {
742 parentIfVisited
= aParentContext
;
746 if (aFlags
& eIsLink
) {
747 // If this node is a link, we want its visited's style context's
748 // parent to be the regular style context of its parent, because
749 // only the visitedness of the relevant link should influence style.
750 parentIfVisited
= aParentContext
;
753 nsRefPtr
<nsStyleContext
> result
;
755 result
= aParentContext
->FindChildWithRules(aPseudoTag
, aRuleNode
,
757 aFlags
& eIsVisitedLink
);
761 fprintf(stdout
, "--- SharedSC %d ---\n", ++gSharedCount
);
763 fprintf(stdout
, "+++ NewSC %d +++\n", ++gNewCount
);
767 result
= NS_NewStyleContext(aParentContext
, aPseudoTag
, aPseudoType
,
768 aRuleNode
, aFlags
& eSkipFlexItemStyleFixup
);
771 if (aVisitedRuleNode
) {
772 nsRefPtr
<nsStyleContext
> resultIfVisited
=
773 NS_NewStyleContext(parentIfVisited
, aPseudoTag
, aPseudoType
,
775 aFlags
& eSkipFlexItemStyleFixup
);
776 if (!resultIfVisited
) {
779 if (!parentIfVisited
) {
780 mRoots
.AppendElement(resultIfVisited
);
782 resultIfVisited
->SetIsStyleIfVisited();
783 result
->SetStyleIfVisited(resultIfVisited
.forget());
785 bool relevantLinkVisited
= (aFlags
& eIsLink
) ?
786 (aFlags
& eIsVisitedLink
) :
787 (aParentContext
&& aParentContext
->RelevantLinkVisited());
789 if (relevantLinkVisited
) {
790 result
->AddStyleBit(NS_STYLE_RELEVANT_LINK_VISITED
);
793 if (!aParentContext
) {
794 mRoots
.AppendElement(result
);
798 NS_ASSERTION(result
->GetPseudoType() == aPseudoType
, "Unexpected type");
799 NS_ASSERTION(result
->GetPseudo() == aPseudoTag
, "Unexpected pseudo");
802 if (aFlags
& eDoAnimation
) {
803 // Normally the animation manager has already added the correct
804 // style rule. However, if the animation-name just changed, it
805 // might have been wrong. So ask it to double-check based on the
806 // resulting style context.
807 nsIStyleRule
*oldAnimRule
= GetAnimationRule(aRuleNode
);
808 nsIStyleRule
*animRule
= PresContext()->AnimationManager()->
809 CheckAnimationRule(result
, aElementForAnimation
);
810 NS_ABORT_IF_FALSE(result
->RuleNode() == aRuleNode
,
811 "unexpected rule node");
812 NS_ABORT_IF_FALSE(!result
->GetStyleIfVisited() == !aVisitedRuleNode
,
813 "unexpected visited rule node");
814 NS_ABORT_IF_FALSE(!aVisitedRuleNode
||
815 result
->GetStyleIfVisited()->RuleNode() ==
817 "unexpected visited rule node");
818 if (oldAnimRule
!= animRule
) {
819 nsRuleNode
*ruleNode
=
820 ReplaceAnimationRule(aRuleNode
, oldAnimRule
, animRule
);
821 nsRuleNode
*visitedRuleNode
= aVisitedRuleNode
822 ? ReplaceAnimationRule(aVisitedRuleNode
, oldAnimRule
, animRule
)
824 result
= GetContext(aParentContext
, ruleNode
, visitedRuleNode
,
825 aPseudoTag
, aPseudoType
, nullptr,
826 aFlags
& ~eDoAnimation
);
830 if (aElementForAnimation
&& aElementForAnimation
->IsHTML(nsGkAtoms::body
) &&
831 aPseudoType
== nsCSSPseudoElements::ePseudo_NotPseudoElement
&&
832 PresContext()->CompatibilityMode() == eCompatibility_NavQuirks
) {
833 nsIDocument
* doc
= aElementForAnimation
->GetCurrentDoc();
834 if (doc
&& doc
->GetBodyElement() == aElementForAnimation
) {
835 // Update the prescontext's body color
836 PresContext()->SetBodyTextColor(result
->StyleColor()->mColor
);
840 return result
.forget();
844 nsStyleSet::AddImportantRules(nsRuleNode
* aCurrLevelNode
,
845 nsRuleNode
* aLastPrevLevelNode
,
846 nsRuleWalker
* aRuleWalker
)
848 NS_ASSERTION(aCurrLevelNode
&&
849 aCurrLevelNode
!= aLastPrevLevelNode
, "How did we get here?");
851 nsAutoTArray
<nsIStyleRule
*, 16> importantRules
;
852 for (nsRuleNode
*node
= aCurrLevelNode
; node
!= aLastPrevLevelNode
;
853 node
= node
->GetParent()) {
854 // We guarantee that we never walk the root node here, so no need
855 // to null-check GetRule(). Furthermore, it must be a CSS rule.
856 NS_ASSERTION(nsRefPtr
<css::StyleRule
>(do_QueryObject(node
->GetRule())),
857 "Unexpected non-CSS rule");
859 nsIStyleRule
* impRule
=
860 static_cast<css::StyleRule
*>(node
->GetRule())->GetImportantRule();
862 importantRules
.AppendElement(impRule
);
865 NS_ASSERTION(importantRules
.Length() != 0,
866 "Why did we think there were important rules?");
868 for (uint32_t i
= importantRules
.Length(); i
-- != 0; ) {
869 aRuleWalker
->Forward(importantRules
[i
]);
875 nsStyleSet::AssertNoImportantRules(nsRuleNode
* aCurrLevelNode
,
876 nsRuleNode
* aLastPrevLevelNode
)
881 for (nsRuleNode
*node
= aCurrLevelNode
; node
!= aLastPrevLevelNode
;
882 node
= node
->GetParent()) {
883 nsRefPtr
<css::StyleRule
> rule(do_QueryObject(node
->GetRule()));
884 NS_ASSERTION(rule
, "Unexpected non-CSS rule");
886 NS_ASSERTION(!rule
->GetImportantRule(), "Unexpected important rule");
891 nsStyleSet::AssertNoCSSRules(nsRuleNode
* aCurrLevelNode
,
892 nsRuleNode
* aLastPrevLevelNode
)
897 for (nsRuleNode
*node
= aCurrLevelNode
; node
!= aLastPrevLevelNode
;
898 node
= node
->GetParent()) {
899 nsIStyleRule
*rule
= node
->GetRule();
900 nsRefPtr
<css::StyleRule
> cssRule(do_QueryObject(rule
));
901 NS_ASSERTION(!cssRule
|| !cssRule
->Selector(), "Unexpected CSS rule");
906 // Enumerate the rules in a way that cares about the order of the rules.
908 nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc
,
909 RuleProcessorData
* aData
, Element
* aElement
,
910 nsRuleWalker
* aRuleWalker
)
912 PROFILER_LABEL("nsStyleSet", "FileRules");
916 // - UA normal rules = Agent normal
917 // - User normal rules = User normal
918 // - Presentation hints = PresHint normal
919 // - Author normal rules = Document normal
920 // - Override normal rules = Override normal
921 // - animation rules = Animation normal
922 // - Author !important rules = Document !important
923 // - Override !important rules = Override !important
924 // - User !important rules = User !important
925 // - UA !important rules = Agent !important
926 // - transition rules = Transition normal
929 // Save off the last rule before we start walking our agent sheets;
930 // this will be either the root or one of the restriction rules.
931 nsRuleNode
* lastRestrictionRN
= aRuleWalker
->CurrentNode();
933 aRuleWalker
->SetLevel(eAgentSheet
, false, true);
934 if (mRuleProcessors
[eAgentSheet
])
935 (*aCollectorFunc
)(mRuleProcessors
[eAgentSheet
], aData
);
936 nsRuleNode
* lastAgentRN
= aRuleWalker
->CurrentNode();
937 bool haveImportantUARules
= !aRuleWalker
->GetCheckForImportantRules();
939 aRuleWalker
->SetLevel(eUserSheet
, false, true);
940 bool skipUserStyles
=
941 aElement
&& aElement
->IsInNativeAnonymousSubtree();
942 if (!skipUserStyles
&& mRuleProcessors
[eUserSheet
]) // NOTE: different
943 (*aCollectorFunc
)(mRuleProcessors
[eUserSheet
], aData
);
944 nsRuleNode
* lastUserRN
= aRuleWalker
->CurrentNode();
945 bool haveImportantUserRules
= !aRuleWalker
->GetCheckForImportantRules();
947 aRuleWalker
->SetLevel(ePresHintSheet
, false, false);
948 if (mRuleProcessors
[ePresHintSheet
])
949 (*aCollectorFunc
)(mRuleProcessors
[ePresHintSheet
], aData
);
950 nsRuleNode
* lastPresHintRN
= aRuleWalker
->CurrentNode();
952 aRuleWalker
->SetLevel(eDocSheet
, false, true);
953 bool cutOffInheritance
= false;
954 if (mBindingManager
&& aElement
) {
955 // We can supply additional document-level sheets that should be walked.
956 mBindingManager
->WalkRules(aCollectorFunc
,
957 static_cast<ElementDependentRuleProcessorData
*>(aData
),
960 if (!skipUserStyles
&& !cutOffInheritance
&& // NOTE: different
961 mRuleProcessors
[eDocSheet
])
962 (*aCollectorFunc
)(mRuleProcessors
[eDocSheet
], aData
);
963 nsRuleNode
* lastDocRN
= aRuleWalker
->CurrentNode();
964 bool haveImportantDocRules
= !aRuleWalker
->GetCheckForImportantRules();
965 nsTArray
<nsRuleNode
*> lastScopedRNs
;
966 nsTArray
<bool> haveImportantScopedRules
;
967 bool haveAnyImportantScopedRules
= false;
968 if (!skipUserStyles
&& !cutOffInheritance
&&
969 aElement
&& aElement
->IsElementInStyleScope()) {
970 lastScopedRNs
.SetLength(mScopedDocSheetRuleProcessors
.Length());
971 haveImportantScopedRules
.SetLength(mScopedDocSheetRuleProcessors
.Length());
972 for (uint32_t i
= 0; i
< mScopedDocSheetRuleProcessors
.Length(); i
++) {
973 aRuleWalker
->SetLevel(eScopedDocSheet
, false, true);
974 nsCSSRuleProcessor
* processor
=
975 static_cast<nsCSSRuleProcessor
*>(mScopedDocSheetRuleProcessors
[i
].get());
976 aData
->mScope
= processor
->GetScopeElement();
977 (*aCollectorFunc
)(mScopedDocSheetRuleProcessors
[i
], aData
);
978 lastScopedRNs
[i
] = aRuleWalker
->CurrentNode();
979 haveImportantScopedRules
[i
] = !aRuleWalker
->GetCheckForImportantRules();
980 haveAnyImportantScopedRules
= haveAnyImportantScopedRules
|| haveImportantScopedRules
[i
];
982 aData
->mScope
= nullptr;
984 nsRuleNode
* lastScopedRN
= aRuleWalker
->CurrentNode();
985 aRuleWalker
->SetLevel(eStyleAttrSheet
, false, true);
986 if (mRuleProcessors
[eStyleAttrSheet
])
987 (*aCollectorFunc
)(mRuleProcessors
[eStyleAttrSheet
], aData
);
988 nsRuleNode
* lastStyleAttrRN
= aRuleWalker
->CurrentNode();
989 bool haveImportantStyleAttrRules
= !aRuleWalker
->GetCheckForImportantRules();
991 aRuleWalker
->SetLevel(eOverrideSheet
, false, true);
992 if (mRuleProcessors
[eOverrideSheet
])
993 (*aCollectorFunc
)(mRuleProcessors
[eOverrideSheet
], aData
);
994 nsRuleNode
* lastOvrRN
= aRuleWalker
->CurrentNode();
995 bool haveImportantOverrideRules
= !aRuleWalker
->GetCheckForImportantRules();
997 // This needs to match IsMoreSpecificThanAnimation() above.
998 aRuleWalker
->SetLevel(eAnimationSheet
, false, false);
999 (*aCollectorFunc
)(mRuleProcessors
[eAnimationSheet
], aData
);
1001 if (haveAnyImportantScopedRules
) {
1002 for (uint32_t i
= lastScopedRNs
.Length(); i
-- != 0; ) {
1003 aRuleWalker
->SetLevel(eScopedDocSheet
, true, false);
1004 nsRuleNode
* startRN
= lastScopedRNs
[i
];
1005 nsRuleNode
* endRN
= i
== 0 ? lastDocRN
: lastScopedRNs
[i
- 1];
1006 if (haveImportantScopedRules
[i
]) {
1007 AddImportantRules(startRN
, endRN
, aRuleWalker
); // scoped
1011 AssertNoImportantRules(startRN
, endRN
);
1018 AssertNoImportantRules(lastScopedRN
, lastDocRN
);
1022 if (haveImportantDocRules
) {
1023 aRuleWalker
->SetLevel(eDocSheet
, true, false);
1024 AddImportantRules(lastDocRN
, lastPresHintRN
, aRuleWalker
); // doc
1028 AssertNoImportantRules(lastDocRN
, lastPresHintRN
);
1032 if (haveImportantStyleAttrRules
) {
1033 aRuleWalker
->SetLevel(eStyleAttrSheet
, true, false);
1034 AddImportantRules(lastStyleAttrRN
, lastScopedRN
, aRuleWalker
); // style attr
1038 AssertNoImportantRules(lastStyleAttrRN
, lastScopedRN
);
1042 if (haveImportantOverrideRules
) {
1043 aRuleWalker
->SetLevel(eOverrideSheet
, true, false);
1044 AddImportantRules(lastOvrRN
, lastStyleAttrRN
, aRuleWalker
); // override
1048 AssertNoImportantRules(lastOvrRN
, lastStyleAttrRN
);
1053 AssertNoCSSRules(lastPresHintRN
, lastUserRN
);
1056 if (haveImportantUserRules
) {
1057 aRuleWalker
->SetLevel(eUserSheet
, true, false);
1058 AddImportantRules(lastUserRN
, lastAgentRN
, aRuleWalker
); //user
1062 AssertNoImportantRules(lastUserRN
, lastAgentRN
);
1066 if (haveImportantUARules
) {
1067 aRuleWalker
->SetLevel(eAgentSheet
, true, false);
1068 AddImportantRules(lastAgentRN
, lastRestrictionRN
, aRuleWalker
); //agent
1072 AssertNoImportantRules(lastAgentRN
, lastRestrictionRN
);
1077 AssertNoCSSRules(lastRestrictionRN
, mRuleTree
);
1081 nsRuleNode
*lastImportantRN
= aRuleWalker
->CurrentNode();
1083 aRuleWalker
->SetLevel(eTransitionSheet
, false, false);
1084 (*aCollectorFunc
)(mRuleProcessors
[eTransitionSheet
], aData
);
1086 AssertNoCSSRules(aRuleWalker
->CurrentNode(), lastImportantRN
);
1091 // Enumerate all the rules in a way that doesn't care about the order
1092 // of the rules and doesn't walk !important-rules.
1094 nsStyleSet::WalkRuleProcessors(nsIStyleRuleProcessor::EnumFunc aFunc
,
1095 ElementDependentRuleProcessorData
* aData
,
1096 bool aWalkAllXBLStylesheets
)
1098 if (mRuleProcessors
[eAgentSheet
])
1099 (*aFunc
)(mRuleProcessors
[eAgentSheet
], aData
);
1101 bool skipUserStyles
= aData
->mElement
->IsInNativeAnonymousSubtree();
1102 if (!skipUserStyles
&& mRuleProcessors
[eUserSheet
]) // NOTE: different
1103 (*aFunc
)(mRuleProcessors
[eUserSheet
], aData
);
1105 if (mRuleProcessors
[ePresHintSheet
])
1106 (*aFunc
)(mRuleProcessors
[ePresHintSheet
], aData
);
1108 bool cutOffInheritance
= false;
1109 if (mBindingManager
) {
1110 // We can supply additional document-level sheets that should be walked.
1111 if (aWalkAllXBLStylesheets
) {
1112 mBindingManager
->WalkAllRules(aFunc
, aData
);
1114 mBindingManager
->WalkRules(aFunc
, aData
, &cutOffInheritance
);
1117 if (!skipUserStyles
&& !cutOffInheritance
) {
1118 if (mRuleProcessors
[eDocSheet
]) // NOTE: different
1119 (*aFunc
)(mRuleProcessors
[eDocSheet
], aData
);
1120 if (aData
->mElement
->IsElementInStyleScope()) {
1121 for (uint32_t i
= 0; i
< mScopedDocSheetRuleProcessors
.Length(); i
++)
1122 (*aFunc
)(mScopedDocSheetRuleProcessors
[i
], aData
);
1125 if (mRuleProcessors
[eStyleAttrSheet
])
1126 (*aFunc
)(mRuleProcessors
[eStyleAttrSheet
], aData
);
1127 if (mRuleProcessors
[eOverrideSheet
])
1128 (*aFunc
)(mRuleProcessors
[eOverrideSheet
], aData
);
1129 (*aFunc
)(mRuleProcessors
[eAnimationSheet
], aData
);
1130 (*aFunc
)(mRuleProcessors
[eTransitionSheet
], aData
);
1133 already_AddRefed
<nsStyleContext
>
1134 nsStyleSet::ResolveStyleFor(Element
* aElement
,
1135 nsStyleContext
* aParentContext
)
1137 TreeMatchContext
treeContext(true, nsRuleWalker::eRelevantLinkUnvisited
,
1138 aElement
->OwnerDoc());
1139 return ResolveStyleFor(aElement
, aParentContext
, treeContext
);
1142 already_AddRefed
<nsStyleContext
>
1143 nsStyleSet::ResolveStyleFor(Element
* aElement
,
1144 nsStyleContext
* aParentContext
,
1145 TreeMatchContext
& aTreeMatchContext
)
1147 NS_ENSURE_FALSE(mInShutdown
, nullptr);
1148 NS_ASSERTION(aElement
, "aElement must not be null");
1150 nsRuleWalker
ruleWalker(mRuleTree
, mAuthorStyleDisabled
);
1151 aTreeMatchContext
.ResetForUnvisitedMatching();
1152 ElementRuleProcessorData
data(PresContext(), aElement
, &ruleWalker
,
1154 FileRules(EnumRulesMatching
<ElementRuleProcessorData
>, &data
, aElement
,
1157 nsRuleNode
*ruleNode
= ruleWalker
.CurrentNode();
1158 nsRuleNode
*visitedRuleNode
= nullptr;
1160 if (aTreeMatchContext
.HaveRelevantLink()) {
1161 aTreeMatchContext
.ResetForVisitedMatching();
1163 FileRules(EnumRulesMatching
<ElementRuleProcessorData
>, &data
, aElement
,
1165 visitedRuleNode
= ruleWalker
.CurrentNode();
1168 uint32_t flags
= eDoAnimation
;
1169 if (nsCSSRuleProcessor::IsLink(aElement
)) {
1172 if (nsCSSRuleProcessor::GetContentState(aElement
, aTreeMatchContext
).
1173 HasState(NS_EVENT_STATE_VISITED
)) {
1174 flags
|= eIsVisitedLink
;
1176 if (aTreeMatchContext
.mSkippingFlexItemStyleFixup
) {
1177 flags
|= eSkipFlexItemStyleFixup
;
1180 return GetContext(aParentContext
, ruleNode
, visitedRuleNode
,
1181 nullptr, nsCSSPseudoElements::ePseudo_NotPseudoElement
,
1185 already_AddRefed
<nsStyleContext
>
1186 nsStyleSet::ResolveStyleForRules(nsStyleContext
* aParentContext
,
1187 const nsTArray
< nsCOMPtr
<nsIStyleRule
> > &aRules
)
1189 NS_ENSURE_FALSE(mInShutdown
, nullptr);
1191 nsRuleWalker
ruleWalker(mRuleTree
, mAuthorStyleDisabled
);
1192 // FIXME: Perhaps this should be passed in, but it probably doesn't
1194 ruleWalker
.SetLevel(eDocSheet
, false, false);
1195 for (uint32_t i
= 0; i
< aRules
.Length(); i
++) {
1196 ruleWalker
.ForwardOnPossiblyCSSRule(aRules
.ElementAt(i
));
1199 return GetContext(aParentContext
, ruleWalker
.CurrentNode(), nullptr,
1200 nullptr, nsCSSPseudoElements::ePseudo_NotPseudoElement
,
1204 already_AddRefed
<nsStyleContext
>
1205 nsStyleSet::ResolveStyleForRules(nsStyleContext
* aParentContext
,
1206 nsStyleContext
* aOldStyle
,
1207 const nsTArray
<RuleAndLevel
>& aRules
)
1209 nsRuleWalker
ruleWalker(mRuleTree
, mAuthorStyleDisabled
);
1210 for (int32_t i
= aRules
.Length() - 1; i
>= 0; --i
) {
1211 ruleWalker
.SetLevel(aRules
[i
].mLevel
, false, false);
1212 ruleWalker
.ForwardOnPossiblyCSSRule(aRules
[i
].mRule
);
1215 uint32_t flags
= eNoFlags
;
1216 if (aOldStyle
->IsLinkContext()) {
1219 if (aOldStyle
->RelevantLinkVisited()) {
1220 flags
|= eIsVisitedLink
;
1223 return GetContext(aParentContext
, ruleWalker
.CurrentNode(), nullptr,
1224 nullptr, nsCSSPseudoElements::ePseudo_NotPseudoElement
,
1228 already_AddRefed
<nsStyleContext
>
1229 nsStyleSet::ResolveStyleByAddingRules(nsStyleContext
* aBaseContext
,
1230 const nsCOMArray
<nsIStyleRule
> &aRules
)
1232 NS_ENSURE_FALSE(mInShutdown
, nullptr);
1234 nsRuleWalker
ruleWalker(mRuleTree
, mAuthorStyleDisabled
);
1235 ruleWalker
.SetCurrentNode(aBaseContext
->RuleNode());
1236 // FIXME: Perhaps this should be passed in, but it probably doesn't
1238 ruleWalker
.SetLevel(eDocSheet
, false, false);
1239 for (int32_t i
= 0; i
< aRules
.Count(); i
++) {
1240 ruleWalker
.ForwardOnPossiblyCSSRule(aRules
.ObjectAt(i
));
1243 nsRuleNode
*ruleNode
= ruleWalker
.CurrentNode();
1244 nsRuleNode
*visitedRuleNode
= nullptr;
1246 if (aBaseContext
->GetStyleIfVisited()) {
1247 ruleWalker
.SetCurrentNode(aBaseContext
->GetStyleIfVisited()->RuleNode());
1248 for (int32_t i
= 0; i
< aRules
.Count(); i
++) {
1249 ruleWalker
.ForwardOnPossiblyCSSRule(aRules
.ObjectAt(i
));
1251 visitedRuleNode
= ruleWalker
.CurrentNode();
1254 uint32_t flags
= eNoFlags
;
1255 if (aBaseContext
->IsLinkContext()) {
1258 if (aBaseContext
->RelevantLinkVisited()) {
1259 flags
|= eIsVisitedLink
;
1261 return GetContext(aBaseContext
->GetParent(), ruleNode
, visitedRuleNode
,
1262 aBaseContext
->GetPseudo(),
1263 aBaseContext
->GetPseudoType(),
1267 already_AddRefed
<nsStyleContext
>
1268 nsStyleSet::ResolveStyleForNonElement(nsStyleContext
* aParentContext
)
1270 return GetContext(aParentContext
, mRuleTree
, nullptr,
1271 nsCSSAnonBoxes::mozNonElement
,
1272 nsCSSPseudoElements::ePseudo_AnonBox
, nullptr,
1277 nsStyleSet::WalkRestrictionRule(nsCSSPseudoElements::Type aPseudoType
,
1278 nsRuleWalker
* aRuleWalker
)
1280 // This needs to match GetPseudoRestriction in nsRuleNode.cpp.
1281 aRuleWalker
->SetLevel(eAgentSheet
, false, false);
1282 if (aPseudoType
== nsCSSPseudoElements::ePseudo_firstLetter
)
1283 aRuleWalker
->Forward(mFirstLetterRule
);
1284 else if (aPseudoType
== nsCSSPseudoElements::ePseudo_firstLine
)
1285 aRuleWalker
->Forward(mFirstLineRule
);
1286 else if (aPseudoType
== nsCSSPseudoElements::ePseudo_mozPlaceholder
)
1287 aRuleWalker
->Forward(mPlaceholderRule
);
1290 already_AddRefed
<nsStyleContext
>
1291 nsStyleSet::ResolvePseudoElementStyle(Element
* aParentElement
,
1292 nsCSSPseudoElements::Type aType
,
1293 nsStyleContext
* aParentContext
)
1295 NS_ENSURE_FALSE(mInShutdown
, nullptr);
1297 NS_ASSERTION(aType
< nsCSSPseudoElements::ePseudo_PseudoElementCount
,
1298 "must have pseudo element type");
1299 NS_ASSERTION(aParentElement
, "Must have parent element");
1301 nsRuleWalker
ruleWalker(mRuleTree
, mAuthorStyleDisabled
);
1302 TreeMatchContext
treeContext(true, nsRuleWalker::eRelevantLinkUnvisited
,
1303 aParentElement
->OwnerDoc());
1304 PseudoElementRuleProcessorData
data(PresContext(), aParentElement
,
1305 &ruleWalker
, aType
, treeContext
);
1306 WalkRestrictionRule(aType
, &ruleWalker
);
1307 FileRules(EnumRulesMatching
<PseudoElementRuleProcessorData
>, &data
,
1308 aParentElement
, &ruleWalker
);
1310 nsRuleNode
*ruleNode
= ruleWalker
.CurrentNode();
1311 nsRuleNode
*visitedRuleNode
= nullptr;
1313 if (treeContext
.HaveRelevantLink()) {
1314 treeContext
.ResetForVisitedMatching();
1316 WalkRestrictionRule(aType
, &ruleWalker
);
1317 FileRules(EnumRulesMatching
<PseudoElementRuleProcessorData
>, &data
,
1318 aParentElement
, &ruleWalker
);
1319 visitedRuleNode
= ruleWalker
.CurrentNode();
1322 // For pseudos, |data.IsLink()| being true means that
1323 // our parent node is a link.
1324 // Also: Flex containers shouldn't have pseudo-elements, so given that we're
1325 // looking up pseudo-element style, make sure we're not treating our node as
1327 uint32_t flags
= eSkipFlexItemStyleFixup
;
1328 if (aType
== nsCSSPseudoElements::ePseudo_before
||
1329 aType
== nsCSSPseudoElements::ePseudo_after
) {
1330 flags
|= eDoAnimation
;
1333 return GetContext(aParentContext
, ruleNode
, visitedRuleNode
,
1334 nsCSSPseudoElements::GetPseudoAtom(aType
), aType
,
1335 aParentElement
, flags
);
1338 already_AddRefed
<nsStyleContext
>
1339 nsStyleSet::ProbePseudoElementStyle(Element
* aParentElement
,
1340 nsCSSPseudoElements::Type aType
,
1341 nsStyleContext
* aParentContext
)
1343 TreeMatchContext
treeContext(true, nsRuleWalker::eRelevantLinkUnvisited
,
1344 aParentElement
->OwnerDoc());
1345 return ProbePseudoElementStyle(aParentElement
, aType
, aParentContext
,
1349 already_AddRefed
<nsStyleContext
>
1350 nsStyleSet::ProbePseudoElementStyle(Element
* aParentElement
,
1351 nsCSSPseudoElements::Type aType
,
1352 nsStyleContext
* aParentContext
,
1353 TreeMatchContext
& aTreeMatchContext
)
1355 NS_ENSURE_FALSE(mInShutdown
, nullptr);
1357 NS_ASSERTION(aType
< nsCSSPseudoElements::ePseudo_PseudoElementCount
,
1358 "must have pseudo element type");
1359 NS_ASSERTION(aParentElement
, "aParentElement must not be null");
1361 nsIAtom
* pseudoTag
= nsCSSPseudoElements::GetPseudoAtom(aType
);
1362 nsRuleWalker
ruleWalker(mRuleTree
, mAuthorStyleDisabled
);
1363 aTreeMatchContext
.ResetForUnvisitedMatching();
1364 PseudoElementRuleProcessorData
data(PresContext(), aParentElement
,
1365 &ruleWalker
, aType
, aTreeMatchContext
);
1366 WalkRestrictionRule(aType
, &ruleWalker
);
1367 // not the root if there was a restriction rule
1368 nsRuleNode
*adjustedRoot
= ruleWalker
.CurrentNode();
1369 FileRules(EnumRulesMatching
<PseudoElementRuleProcessorData
>, &data
,
1370 aParentElement
, &ruleWalker
);
1372 nsRuleNode
*ruleNode
= ruleWalker
.CurrentNode();
1373 if (ruleNode
== adjustedRoot
) {
1377 nsRuleNode
*visitedRuleNode
= nullptr;
1379 if (aTreeMatchContext
.HaveRelevantLink()) {
1380 aTreeMatchContext
.ResetForVisitedMatching();
1382 WalkRestrictionRule(aType
, &ruleWalker
);
1383 FileRules(EnumRulesMatching
<PseudoElementRuleProcessorData
>, &data
,
1384 aParentElement
, &ruleWalker
);
1385 visitedRuleNode
= ruleWalker
.CurrentNode();
1388 // For pseudos, |data.IsLink()| being true means that
1389 // our parent node is a link.
1390 // Also: Flex containers shouldn't have pseudo-elements, so given that we're
1391 // looking up pseudo-element style, make sure we're not treating our node as
1393 uint32_t flags
= eSkipFlexItemStyleFixup
;
1394 if (aType
== nsCSSPseudoElements::ePseudo_before
||
1395 aType
== nsCSSPseudoElements::ePseudo_after
) {
1396 flags
|= eDoAnimation
;
1399 nsRefPtr
<nsStyleContext
> result
=
1400 GetContext(aParentContext
, ruleNode
, visitedRuleNode
,
1402 aParentElement
, flags
);
1404 // For :before and :after pseudo-elements, having display: none or no
1405 // 'content' property is equivalent to not having the pseudo-element
1408 (pseudoTag
== nsCSSPseudoElements::before
||
1409 pseudoTag
== nsCSSPseudoElements::after
)) {
1410 const nsStyleDisplay
*display
= result
->StyleDisplay();
1411 const nsStyleContent
*content
= result
->StyleContent();
1412 // XXXldb What is contentCount for |content: ""|?
1413 if (display
->mDisplay
== NS_STYLE_DISPLAY_NONE
||
1414 content
->ContentCount() == 0) {
1419 return result
.forget();
1422 already_AddRefed
<nsStyleContext
>
1423 nsStyleSet::ResolveAnonymousBoxStyle(nsIAtom
* aPseudoTag
,
1424 nsStyleContext
* aParentContext
)
1426 NS_ENSURE_FALSE(mInShutdown
, nullptr);
1429 bool isAnonBox
= nsCSSAnonBoxes::IsAnonBox(aPseudoTag
)
1431 && !nsCSSAnonBoxes::IsTreePseudoElement(aPseudoTag
)
1434 NS_PRECONDITION(isAnonBox
, "Unexpected pseudo");
1437 nsRuleWalker
ruleWalker(mRuleTree
, mAuthorStyleDisabled
);
1438 AnonBoxRuleProcessorData
data(PresContext(), aPseudoTag
, &ruleWalker
);
1439 FileRules(EnumRulesMatching
<AnonBoxRuleProcessorData
>, &data
, nullptr,
1442 if (aPseudoTag
== nsCSSAnonBoxes::pageContent
) {
1443 // Add any @page rules that are specified.
1444 nsTArray
<nsCSSPageRule
*> rules
;
1445 nsTArray
<css::ImportantRule
*> importantRules
;
1446 nsPresContext
* presContext
= PresContext();
1447 presContext
->StyleSet()->AppendPageRules(presContext
, rules
);
1448 for (uint32_t i
= 0, i_end
= rules
.Length(); i
!= i_end
; ++i
) {
1449 ruleWalker
.Forward(rules
[i
]);
1450 css::ImportantRule
* importantRule
= rules
[i
]->GetImportantRule();
1451 if (importantRule
) {
1452 importantRules
.AppendElement(importantRule
);
1455 for (uint32_t i
= 0, i_end
= importantRules
.Length(); i
!= i_end
; ++i
) {
1456 ruleWalker
.Forward(importantRules
[i
]);
1460 return GetContext(aParentContext
, ruleWalker
.CurrentNode(), nullptr,
1461 aPseudoTag
, nsCSSPseudoElements::ePseudo_AnonBox
,
1466 already_AddRefed
<nsStyleContext
>
1467 nsStyleSet::ResolveXULTreePseudoStyle(Element
* aParentElement
,
1468 nsIAtom
* aPseudoTag
,
1469 nsStyleContext
* aParentContext
,
1470 nsICSSPseudoComparator
* aComparator
)
1472 NS_ENSURE_FALSE(mInShutdown
, nullptr);
1474 NS_ASSERTION(aPseudoTag
, "must have pseudo tag");
1475 NS_ASSERTION(nsCSSAnonBoxes::IsTreePseudoElement(aPseudoTag
),
1476 "Unexpected pseudo");
1478 nsRuleWalker
ruleWalker(mRuleTree
, mAuthorStyleDisabled
);
1479 TreeMatchContext
treeContext(true, nsRuleWalker::eRelevantLinkUnvisited
,
1480 aParentElement
->OwnerDoc());
1481 XULTreeRuleProcessorData
data(PresContext(), aParentElement
, &ruleWalker
,
1482 aPseudoTag
, aComparator
, treeContext
);
1483 FileRules(EnumRulesMatching
<XULTreeRuleProcessorData
>, &data
, aParentElement
,
1486 nsRuleNode
*ruleNode
= ruleWalker
.CurrentNode();
1487 nsRuleNode
*visitedRuleNode
= nullptr;
1489 if (treeContext
.HaveRelevantLink()) {
1490 treeContext
.ResetForVisitedMatching();
1492 FileRules(EnumRulesMatching
<XULTreeRuleProcessorData
>, &data
,
1493 aParentElement
, &ruleWalker
);
1494 visitedRuleNode
= ruleWalker
.CurrentNode();
1497 return GetContext(aParentContext
, ruleNode
, visitedRuleNode
,
1498 // For pseudos, |data.IsLink()| being true means that
1499 // our parent node is a link.
1500 aPseudoTag
, nsCSSPseudoElements::ePseudo_XULTree
,
1506 nsStyleSet::AppendFontFaceRules(nsPresContext
* aPresContext
,
1507 nsTArray
<nsFontFaceRuleContainer
>& aArray
)
1509 NS_ENSURE_FALSE(mInShutdown
, false);
1511 for (uint32_t i
= 0; i
< ArrayLength(gCSSSheetTypes
); ++i
) {
1512 if (gCSSSheetTypes
[i
] == eScopedDocSheet
)
1514 nsCSSRuleProcessor
*ruleProc
= static_cast<nsCSSRuleProcessor
*>
1515 (mRuleProcessors
[gCSSSheetTypes
[i
]].get());
1516 if (ruleProc
&& !ruleProc
->AppendFontFaceRules(aPresContext
, aArray
))
1523 nsStyleSet::AppendKeyframesRules(nsPresContext
* aPresContext
,
1524 nsTArray
<nsCSSKeyframesRule
*>& aArray
)
1526 NS_ENSURE_FALSE(mInShutdown
, false);
1528 for (uint32_t i
= 0; i
< ArrayLength(gCSSSheetTypes
); ++i
) {
1529 if (gCSSSheetTypes
[i
] == eScopedDocSheet
)
1531 nsCSSRuleProcessor
*ruleProc
= static_cast<nsCSSRuleProcessor
*>
1532 (mRuleProcessors
[gCSSSheetTypes
[i
]].get());
1533 if (ruleProc
&& !ruleProc
->AppendKeyframesRules(aPresContext
, aArray
))
1540 nsStyleSet::AppendPageRules(nsPresContext
* aPresContext
,
1541 nsTArray
<nsCSSPageRule
*>& aArray
)
1543 NS_ENSURE_FALSE(mInShutdown
, false);
1545 for (uint32_t i
= 0; i
< NS_ARRAY_LENGTH(gCSSSheetTypes
); ++i
) {
1546 if (gCSSSheetTypes
[i
] == eScopedDocSheet
)
1548 nsCSSRuleProcessor
* ruleProc
= static_cast<nsCSSRuleProcessor
*>
1549 (mRuleProcessors
[gCSSSheetTypes
[i
]].get());
1550 if (ruleProc
&& !ruleProc
->AppendPageRules(aPresContext
, aArray
))
1557 nsStyleSet::BeginShutdown(nsPresContext
* aPresContext
)
1560 mRoots
.Clear(); // no longer valid, since we won't keep it up to date
1564 nsStyleSet::Shutdown(nsPresContext
* aPresContext
)
1566 mRuleTree
->Destroy();
1567 mRuleTree
= nullptr;
1569 // We can have old rule trees either because:
1570 // (1) we failed the assertions in EndReconstruct, or
1571 // (2) we're shutting down within a reconstruct (see bug 462392)
1572 for (uint32_t i
= mOldRuleTrees
.Length(); i
> 0; ) {
1574 mOldRuleTrees
[i
]->Destroy();
1576 mOldRuleTrees
.Clear();
1579 static const uint32_t kGCInterval
= 300;
1582 nsStyleSet::NotifyStyleContextDestroyed(nsPresContext
* aPresContext
,
1583 nsStyleContext
* aStyleContext
)
1588 // Remove style contexts from mRoots even if mOldRuleTree is non-null. This
1589 // could be a style context from the new ruletree!
1590 if (!aStyleContext
->GetParent()) {
1591 mRoots
.RemoveElement(aStyleContext
);
1597 if (mUnusedRuleNodeCount
>= kGCInterval
) {
1603 nsStyleSet::GCRuleTrees()
1605 mUnusedRuleNodeCount
= 0;
1607 // Mark the style context tree by marking all style contexts which
1608 // have no parent, which will mark all descendants. This will reach
1609 // style contexts in the undisplayed map and "additional style
1610 // contexts" since they are descendants of the roots.
1611 for (int32_t i
= mRoots
.Length() - 1; i
>= 0; --i
) {
1615 // Sweep the rule tree.
1620 NS_ASSERTION(!deleted
, "Root node must not be gc'd");
1622 // Sweep the old rule trees.
1623 for (uint32_t i
= mOldRuleTrees
.Length(); i
> 0; ) {
1625 if (mOldRuleTrees
[i
]->Sweep()) {
1626 // It was deleted, as it should be.
1627 mOldRuleTrees
.RemoveElementAt(i
);
1629 NS_NOTREACHED("old rule tree still referenced");
1634 static inline nsRuleNode
*
1635 SkipAnimationRules(nsRuleNode
* aRuleNode
, Element
* aElement
, bool isPseudo
)
1637 nsRuleNode
* ruleNode
= aRuleNode
;
1638 while (!ruleNode
->IsRoot() &&
1639 (ruleNode
->GetLevel() == nsStyleSet::eTransitionSheet
||
1640 ruleNode
->GetLevel() == nsStyleSet::eAnimationSheet
)) {
1641 ruleNode
= ruleNode
->GetParent();
1643 if (ruleNode
!= aRuleNode
) {
1644 NS_ASSERTION(aElement
, "How can we have transition rules but no element?");
1645 // Need to do an animation restyle, just like
1646 // nsTransitionManager::WalkTransitionRule and
1647 // nsAnimationManager::GetAnimationRule would.
1648 nsRestyleHint hint
= isPseudo
? eRestyle_Subtree
: eRestyle_Self
;
1649 aRuleNode
->PresContext()->PresShell()->RestyleForAnimation(aElement
, hint
);
1654 already_AddRefed
<nsStyleContext
>
1655 nsStyleSet::ReparentStyleContext(nsStyleContext
* aStyleContext
,
1656 nsStyleContext
* aNewParentContext
,
1659 if (!aStyleContext
) {
1660 NS_NOTREACHED("must have style context");
1664 // This short-circuit is OK because we don't call TryStartingTransition
1665 // during style reresolution if the style context pointer hasn't changed.
1666 if (aStyleContext
->GetParent() == aNewParentContext
) {
1667 nsRefPtr
<nsStyleContext
> ret
= aStyleContext
;
1668 return ret
.forget();
1671 nsIAtom
* pseudoTag
= aStyleContext
->GetPseudo();
1672 nsCSSPseudoElements::Type pseudoType
= aStyleContext
->GetPseudoType();
1673 nsRuleNode
* ruleNode
= aStyleContext
->RuleNode();
1675 // Skip transition rules as needed just like
1676 // nsTransitionManager::WalkTransitionRule would.
1677 bool skipAnimationRules
= PresContext()->IsProcessingRestyles() &&
1678 !PresContext()->IsProcessingAnimationStyleChange();
1679 if (skipAnimationRules
) {
1680 // Make sure that we're not using transition rules or animation rules for
1681 // our new style context. If we need them, an animation restyle will
1684 SkipAnimationRules(ruleNode
, aElement
,
1686 nsCSSPseudoElements::ePseudo_NotPseudoElement
);
1689 nsRuleNode
* visitedRuleNode
= nullptr;
1690 nsStyleContext
* visitedContext
= aStyleContext
->GetStyleIfVisited();
1691 // Reparenting a style context just changes where we inherit from,
1692 // not what rules we match or what our DOM looks like. In
1693 // particular, it doesn't change whether this is a style context for
1695 if (visitedContext
) {
1696 visitedRuleNode
= visitedContext
->RuleNode();
1697 // Again, skip transition rules as needed
1698 if (skipAnimationRules
) {
1699 // FIXME do something here for animations?
1701 SkipAnimationRules(visitedRuleNode
, aElement
,
1703 nsCSSPseudoElements::ePseudo_NotPseudoElement
);
1707 uint32_t flags
= eNoFlags
;
1708 if (aStyleContext
->IsLinkContext()) {
1712 // If we're a style context for a link, then we already know whether
1713 // our relevant link is visited, since that does not depend on our
1714 // parent. Otherwise, we need to match aNewParentContext.
1715 bool relevantLinkVisited
= aStyleContext
->IsLinkContext() ?
1716 aStyleContext
->RelevantLinkVisited() :
1717 aNewParentContext
->RelevantLinkVisited();
1719 if (relevantLinkVisited
) {
1720 flags
|= eIsVisitedLink
;
1723 if (pseudoType
== nsCSSPseudoElements::ePseudo_NotPseudoElement
||
1724 pseudoType
== nsCSSPseudoElements::ePseudo_before
||
1725 pseudoType
== nsCSSPseudoElements::ePseudo_after
) {
1726 flags
|= eDoAnimation
;
1729 if (aElement
&& aElement
->IsRootOfAnonymousSubtree()) {
1730 // For anonymous subtree roots, don't tweak "display" value based on
1731 // whether or not the parent is styled as a flex container. (If the parent
1732 // has anonymous-subtree kids, then we know it's not actually going to get
1733 // a flex container frame, anyway.)
1734 flags
|= eSkipFlexItemStyleFixup
;
1737 return GetContext(aNewParentContext
, ruleNode
, visitedRuleNode
,
1738 pseudoTag
, pseudoType
,
1742 struct MOZ_STACK_CLASS StatefulData
: public StateRuleProcessorData
{
1743 StatefulData(nsPresContext
* aPresContext
, Element
* aElement
,
1744 nsEventStates aStateMask
, TreeMatchContext
& aTreeMatchContext
)
1745 : StateRuleProcessorData(aPresContext
, aElement
, aStateMask
,
1747 mHint(nsRestyleHint(0))
1749 nsRestyleHint mHint
;
1752 static bool SheetHasDocumentStateStyle(nsIStyleRuleProcessor
* aProcessor
,
1755 StatefulData
* data
= (StatefulData
*)aData
;
1756 if (aProcessor
->HasDocumentStateDependentStyle(data
)) {
1757 data
->mHint
= eRestyle_Self
;
1758 return false; // don't continue
1760 return true; // continue
1763 // Test if style is dependent on a document state.
1765 nsStyleSet::HasDocumentStateDependentStyle(nsPresContext
* aPresContext
,
1766 nsIContent
* aContent
,
1767 nsEventStates aStateMask
)
1769 if (!aContent
|| !aContent
->IsElement())
1772 TreeMatchContext
treeContext(false, nsRuleWalker::eLinksVisitedOrUnvisited
,
1773 aContent
->OwnerDoc());
1774 StatefulData
data(aPresContext
, aContent
->AsElement(), aStateMask
,
1776 WalkRuleProcessors(SheetHasDocumentStateStyle
, &data
, true);
1777 return data
.mHint
!= 0;
1780 static bool SheetHasStatefulStyle(nsIStyleRuleProcessor
* aProcessor
,
1783 StatefulData
* data
= (StatefulData
*)aData
;
1784 nsRestyleHint hint
= aProcessor
->HasStateDependentStyle(data
);
1785 data
->mHint
= nsRestyleHint(data
->mHint
| hint
);
1786 return true; // continue
1789 // Test if style is dependent on content state
1791 nsStyleSet::HasStateDependentStyle(nsPresContext
* aPresContext
,
1793 nsEventStates aStateMask
)
1795 TreeMatchContext
treeContext(false, nsRuleWalker::eLinksVisitedOrUnvisited
,
1796 aElement
->OwnerDoc());
1797 StatefulData
data(aPresContext
, aElement
, aStateMask
, treeContext
);
1798 WalkRuleProcessors(SheetHasStatefulStyle
, &data
, false);
1802 struct MOZ_STACK_CLASS AttributeData
: public AttributeRuleProcessorData
{
1803 AttributeData(nsPresContext
* aPresContext
,
1804 Element
* aElement
, nsIAtom
* aAttribute
, int32_t aModType
,
1805 bool aAttrHasChanged
, TreeMatchContext
& aTreeMatchContext
)
1806 : AttributeRuleProcessorData(aPresContext
, aElement
, aAttribute
, aModType
,
1807 aAttrHasChanged
, aTreeMatchContext
),
1808 mHint(nsRestyleHint(0))
1810 nsRestyleHint mHint
;
1814 SheetHasAttributeStyle(nsIStyleRuleProcessor
* aProcessor
, void *aData
)
1816 AttributeData
* data
= (AttributeData
*)aData
;
1817 nsRestyleHint hint
= aProcessor
->HasAttributeDependentStyle(data
);
1818 data
->mHint
= nsRestyleHint(data
->mHint
| hint
);
1819 return true; // continue
1822 // Test if style is dependent on content state
1824 nsStyleSet::HasAttributeDependentStyle(nsPresContext
* aPresContext
,
1826 nsIAtom
* aAttribute
,
1828 bool aAttrHasChanged
)
1830 TreeMatchContext
treeContext(false, nsRuleWalker::eLinksVisitedOrUnvisited
,
1831 aElement
->OwnerDoc());
1832 AttributeData
data(aPresContext
, aElement
, aAttribute
,
1833 aModType
, aAttrHasChanged
, treeContext
);
1834 WalkRuleProcessors(SheetHasAttributeStyle
, &data
, false);
1839 nsStyleSet::MediumFeaturesChanged(nsPresContext
* aPresContext
)
1841 // We can't use WalkRuleProcessors without a content node.
1842 bool stylesChanged
= false;
1843 for (uint32_t i
= 0; i
< ArrayLength(mRuleProcessors
); ++i
) {
1844 nsIStyleRuleProcessor
*processor
= mRuleProcessors
[i
];
1848 bool thisChanged
= processor
->MediumFeaturesChanged(aPresContext
);
1849 stylesChanged
= stylesChanged
|| thisChanged
;
1851 for (uint32_t i
= 0; i
< mScopedDocSheetRuleProcessors
.Length(); ++i
) {
1852 nsIStyleRuleProcessor
*processor
= mScopedDocSheetRuleProcessors
[i
];
1853 bool thisChanged
= processor
->MediumFeaturesChanged(aPresContext
);
1854 stylesChanged
= stylesChanged
|| thisChanged
;
1857 if (mBindingManager
) {
1858 bool thisChanged
= false;
1859 mBindingManager
->MediumFeaturesChanged(aPresContext
, &thisChanged
);
1860 stylesChanged
= stylesChanged
|| thisChanged
;
1863 return stylesChanged
;
1866 nsCSSStyleSheet::EnsureUniqueInnerResult
1867 nsStyleSet::EnsureUniqueInnerOnCSSSheets()
1869 nsAutoTArray
<nsCSSStyleSheet
*, 32> queue
;
1870 for (uint32_t i
= 0; i
< ArrayLength(gCSSSheetTypes
); ++i
) {
1871 nsCOMArray
<nsIStyleSheet
> &sheets
= mSheets
[gCSSSheetTypes
[i
]];
1872 for (uint32_t j
= 0, j_end
= sheets
.Count(); j
< j_end
; ++j
) {
1873 nsCSSStyleSheet
*sheet
= static_cast<nsCSSStyleSheet
*>(sheets
[j
]);
1874 if (!queue
.AppendElement(sheet
)) {
1875 return nsCSSStyleSheet::eUniqueInner_CloneFailed
;
1880 if (mBindingManager
) {
1881 mBindingManager
->AppendAllSheets(queue
);
1884 nsCSSStyleSheet::EnsureUniqueInnerResult res
=
1885 nsCSSStyleSheet::eUniqueInner_AlreadyUnique
;
1886 while (!queue
.IsEmpty()) {
1887 uint32_t idx
= queue
.Length() - 1;
1888 nsCSSStyleSheet
*sheet
= queue
[idx
];
1889 queue
.RemoveElementAt(idx
);
1891 nsCSSStyleSheet::EnsureUniqueInnerResult sheetRes
=
1892 sheet
->EnsureUniqueInner();
1893 if (sheetRes
== nsCSSStyleSheet::eUniqueInner_CloneFailed
) {
1896 if (sheetRes
== nsCSSStyleSheet::eUniqueInner_ClonedInner
) {
1900 // Enqueue all the sheet's children.
1901 if (!sheet
->AppendAllChildSheets(queue
)) {
1902 return nsCSSStyleSheet::eUniqueInner_CloneFailed
;
1909 nsStyleSet::InitialStyleRule()
1911 if (!mInitialStyleRule
) {
1912 mInitialStyleRule
= new nsInitialStyleRule
;
1914 return mInitialStyleRule
;