1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
23 * Daniel Glazman <glazman@netscape.com>
24 * Brian Ryner <bryner@brianryner.com>
25 * L. David Baron <dbaron@dbaron.org>, Mozilla Corporation
27 * Alternatively, the contents of this file may be used under the terms of
28 * either of the GNU General Public License Version 2 or later (the "GPL"),
29 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
42 * the container for the style sheets that apply to a presentation, and
43 * the internal API that the style system exposes for creating (and
44 * potentially re-creating) style contexts
47 #include "nsStyleSet.h"
48 #include "nsNetUtil.h"
49 #include "nsCSSStyleSheet.h"
50 #include "nsIDocument.h"
51 #include "nsRuleWalker.h"
52 #include "nsStyleContext.h"
53 #include "nsICSSStyleRule.h"
54 #include "nsCSSAnonBoxes.h"
55 #include "nsCSSPseudoElements.h"
56 #include "nsCSSRuleProcessor.h"
57 #include "nsIContent.h"
59 #include "nsContentUtils.h"
60 #include "nsRuleProcessorData.h"
61 #include "nsTransitionManager.h"
62 #include "nsIEventStateManager.h"
63 #include "mozilla/dom/Element.h"
65 using namespace mozilla::dom
;
67 NS_IMPL_ISUPPORTS1(nsEmptyStyleRule
, nsIStyleRule
)
70 nsEmptyStyleRule::MapRuleInfoInto(nsRuleData
* aRuleData
)
76 nsEmptyStyleRule::List(FILE* out
, PRInt32 aIndent
) const
81 static const nsStyleSet::sheetType gCSSSheetTypes
[] = {
82 nsStyleSet::eAgentSheet
,
83 nsStyleSet::eUserSheet
,
84 nsStyleSet::eDocSheet
,
85 nsStyleSet::eOverrideSheet
88 nsStyleSet::nsStyleSet()
90 mUnusedRuleNodeCount(0),
92 mInShutdown(PR_FALSE
),
93 mAuthorStyleDisabled(PR_FALSE
),
94 mInReconstruct(PR_FALSE
),
100 nsStyleSet::Init(nsPresContext
*aPresContext
)
102 mFirstLineRule
= new nsEmptyStyleRule
;
103 mFirstLetterRule
= new nsEmptyStyleRule
;
104 if (!mFirstLineRule
|| !mFirstLetterRule
) {
105 return NS_ERROR_OUT_OF_MEMORY
;
108 if (!BuildDefaultStyleData(aPresContext
)) {
109 mDefaultStyleData
.Destroy(0, aPresContext
);
110 return NS_ERROR_OUT_OF_MEMORY
;
113 mRuleTree
= nsRuleNode::CreateRootNode(aPresContext
);
115 mDefaultStyleData
.Destroy(0, aPresContext
);
116 return NS_ERROR_OUT_OF_MEMORY
;
119 GatherRuleProcessors(eTransitionSheet
);
125 nsStyleSet::BeginReconstruct()
127 NS_ASSERTION(!mInReconstruct
, "Unmatched begin/end?");
128 NS_ASSERTION(mRuleTree
, "Reconstructing before first construction?");
130 // Create a new rule tree root
131 nsRuleNode
* newTree
=
132 nsRuleNode::CreateRootNode(mRuleTree
->GetPresContext());
134 return NS_ERROR_OUT_OF_MEMORY
;
136 // Save the old rule tree so we can destroy it later
137 if (!mOldRuleTrees
.AppendElement(mRuleTree
)) {
139 return NS_ERROR_OUT_OF_MEMORY
;
142 // We need to keep mRoots so that the rule tree GC will only free the
143 // rule trees that really aren't referenced anymore (which should be
144 // all of them, if there are no bugs in reresolution code).
146 mInReconstruct
= PR_TRUE
;
153 nsStyleSet::EndReconstruct()
155 NS_ASSERTION(mInReconstruct
, "Unmatched begin/end?");
156 mInReconstruct
= PR_FALSE
;
158 for (PRInt32 i
= mRoots
.Length() - 1; i
>= 0; --i
) {
159 nsRuleNode
*n
= mRoots
[i
]->GetRuleNode();
160 while (n
->GetParent()) {
163 // Since nsStyleContext's mParent and mRuleNode are immutable, and
164 // style contexts own their parents, and nsStyleContext asserts in
165 // its constructor that the style context and its parent are in the
166 // same rule tree, we don't need to check any of the children of
167 // mRoots; we only need to check the rule nodes of mRoots
170 NS_ASSERTION(n
== mRuleTree
, "style context has old rule node");
173 // This *should* destroy the only element of mOldRuleTrees, but in
174 // case of some bugs (which would trigger the above assertions), it
180 nsStyleSet::SetQuirkStyleSheet(nsIStyleSheet
* aQuirkStyleSheet
)
182 NS_ASSERTION(aQuirkStyleSheet
, "Must have quirk sheet if this is called");
183 NS_ASSERTION(!mQuirkStyleSheet
, "Multiple calls to SetQuirkStyleSheet?");
184 NS_ASSERTION(mSheets
[eAgentSheet
].IndexOf(aQuirkStyleSheet
) != -1,
185 "Quirk style sheet not one of our agent sheets?");
186 mQuirkStyleSheet
= aQuirkStyleSheet
;
190 nsStyleSet::GatherRuleProcessors(sheetType aType
)
192 mRuleProcessors
[aType
] = nsnull
;
193 if (mAuthorStyleDisabled
&& (aType
== eDocSheet
||
194 aType
== ePresHintSheet
||
195 aType
== eStyleAttrSheet
)) {
196 //don't regather if this level is disabled
199 if (aType
== eTransitionSheet
) {
200 // We have no sheet for the transitions level; just a rule
201 // processor. (XXX: We should probably do this for the other
202 // non-CSS levels too!)
203 mRuleProcessors
[aType
] = PresContext()->TransitionManager();
206 if (mSheets
[aType
].Count()) {
211 case eOverrideSheet
: {
212 // levels containing CSS stylesheets
213 nsCOMArray
<nsIStyleSheet
>& sheets
= mSheets
[aType
];
214 nsTArray
<nsRefPtr
<nsCSSStyleSheet
> > cssSheets(sheets
.Count());
215 for (PRInt32 i
= 0, i_end
= sheets
.Count(); i
< i_end
; ++i
) {
216 nsRefPtr
<nsCSSStyleSheet
> cssSheet
= do_QueryObject(sheets
[i
]);
217 NS_ASSERTION(cssSheet
, "not a CSS sheet");
218 cssSheets
.AppendElement(cssSheet
);
220 mRuleProcessors
[aType
] = new nsCSSRuleProcessor(cssSheets
,
225 // levels containing non-CSS stylesheets
226 NS_ASSERTION(mSheets
[aType
].Count() == 1, "only one sheet per level");
227 mRuleProcessors
[aType
] = do_QueryInterface(mSheets
[aType
][0]);
236 nsStyleSet::AppendStyleSheet(sheetType aType
, nsIStyleSheet
*aSheet
)
238 NS_PRECONDITION(aSheet
, "null arg");
239 NS_ASSERTION(aSheet
->IsApplicable(),
240 "Inapplicable sheet being placed in style set");
241 mSheets
[aType
].RemoveObject(aSheet
);
242 if (!mSheets
[aType
].AppendObject(aSheet
))
243 return NS_ERROR_OUT_OF_MEMORY
;
246 return GatherRuleProcessors(aType
);
248 mDirty
|= 1 << aType
;
253 nsStyleSet::PrependStyleSheet(sheetType aType
, nsIStyleSheet
*aSheet
)
255 NS_PRECONDITION(aSheet
, "null arg");
256 NS_ASSERTION(aSheet
->IsApplicable(),
257 "Inapplicable sheet being placed in style set");
258 mSheets
[aType
].RemoveObject(aSheet
);
259 if (!mSheets
[aType
].InsertObjectAt(aSheet
, 0))
260 return NS_ERROR_OUT_OF_MEMORY
;
263 return GatherRuleProcessors(aType
);
265 mDirty
|= 1 << aType
;
270 nsStyleSet::RemoveStyleSheet(sheetType aType
, nsIStyleSheet
*aSheet
)
272 NS_PRECONDITION(aSheet
, "null arg");
273 NS_ASSERTION(aSheet
->IsComplete(),
274 "Incomplete sheet being removed from style set");
275 mSheets
[aType
].RemoveObject(aSheet
);
277 return GatherRuleProcessors(aType
);
279 mDirty
|= 1 << aType
;
284 nsStyleSet::ReplaceSheets(sheetType aType
,
285 const nsCOMArray
<nsIStyleSheet
> &aNewSheets
)
287 mSheets
[aType
].Clear();
288 if (!mSheets
[aType
].AppendObjects(aNewSheets
))
289 return NS_ERROR_OUT_OF_MEMORY
;
292 return GatherRuleProcessors(aType
);
294 mDirty
|= 1 << aType
;
299 nsStyleSet::GetAuthorStyleDisabled()
301 return mAuthorStyleDisabled
;
305 nsStyleSet::SetAuthorStyleDisabled(PRBool aStyleDisabled
)
307 if (aStyleDisabled
== !mAuthorStyleDisabled
) {
308 mAuthorStyleDisabled
= aStyleDisabled
;
310 mDirty
|= 1 << eDocSheet
|
311 1 << ePresHintSheet
|
312 1 << eStyleAttrSheet
;
318 // -------- Doc Sheets
321 nsStyleSet::AddDocStyleSheet(nsIStyleSheet
* aSheet
, nsIDocument
* aDocument
)
323 NS_PRECONDITION(aSheet
&& aDocument
, "null arg");
324 NS_ASSERTION(aSheet
->IsApplicable(),
325 "Inapplicable sheet being placed in style set");
327 nsCOMArray
<nsIStyleSheet
>& docSheets
= mSheets
[eDocSheet
];
329 docSheets
.RemoveObject(aSheet
);
330 // lowest index first
331 PRInt32 newDocIndex
= aDocument
->GetIndexOfStyleSheet(aSheet
);
332 PRInt32 count
= docSheets
.Count();
334 for (index
= 0; index
< count
; index
++) {
335 nsIStyleSheet
* sheet
= docSheets
.ObjectAt(index
);
336 PRInt32 sheetDocIndex
= aDocument
->GetIndexOfStyleSheet(sheet
);
337 if (sheetDocIndex
> newDocIndex
)
340 if (!docSheets
.InsertObjectAt(aSheet
, index
))
341 return NS_ERROR_OUT_OF_MEMORY
;
343 return GatherRuleProcessors(eDocSheet
);
345 mDirty
|= 1 << eDocSheet
;
351 nsStyleSet::BeginUpdate()
357 nsStyleSet::EndUpdate()
359 NS_ASSERTION(mBatching
> 0, "Unbalanced EndUpdate");
361 // We're not completely done yet.
365 for (int i
= 0; i
< eSheetTypeCount
; ++i
) {
366 if (mDirty
& (1 << i
)) {
367 nsresult rv
= GatherRuleProcessors(sheetType(i
));
368 NS_ENSURE_SUCCESS(rv
, rv
);
377 nsStyleSet::EnableQuirkStyleSheet(PRBool aEnable
)
382 nsCOMPtr
<nsIDOMCSSStyleSheet
> domSheet
=
383 do_QueryInterface(mQuirkStyleSheet
);
384 domSheet
->GetDisabled(&oldEnabled
);
385 oldEnabled
= !oldEnabled
;
388 mQuirkStyleSheet
->SetEnabled(aEnable
);
390 // This should always be OK, since SetEnabled should call
391 // ClearRuleCascades.
392 // Note that we can hit this codepath multiple times when document.open()
393 // (potentially implied) happens multiple times.
394 if (mRuleProcessors
[eAgentSheet
] && aEnable
!= oldEnabled
) {
395 static_cast<nsCSSRuleProcessor
*>(static_cast<nsIStyleRuleProcessor
*>(
396 mRuleProcessors
[eAgentSheet
]))->AssertQuirksChangeOK();
403 EnumRulesMatching(nsIStyleRuleProcessor
* aProcessor
, void* aData
)
405 T
* data
= static_cast<T
*>(aData
);
406 aProcessor
->RulesMatching(data
);
411 * |GetContext| implements sharing of style contexts (not just the data
412 * on the rule nodes) between siblings and cousins of the same
413 * generation. (It works for cousins of the same generation since
414 * |aParentContext| could itself be a shared context.)
416 already_AddRefed
<nsStyleContext
>
417 nsStyleSet::GetContext(nsStyleContext
* aParentContext
,
418 nsRuleNode
* aRuleNode
,
419 // aVisitedRuleNode may be null; if it is null
420 // it means that we don't need to force creation
421 // of a StyleIfVisited. (But if we make one
422 // because aParentContext has one, then aRuleNode
424 nsRuleNode
* aVisitedRuleNode
,
426 PRBool aIsVisitedLink
,
428 nsCSSPseudoElements::Type aPseudoType
)
430 NS_PRECONDITION((!aPseudoTag
&&
432 nsCSSPseudoElements::ePseudo_NotPseudoElement
) ||
434 nsCSSPseudoElements::GetPseudoType(aPseudoTag
) ==
438 if (aVisitedRuleNode
== aRuleNode
) {
439 // No need to force creation of a visited style in this case.
440 aVisitedRuleNode
= nsnull
;
443 // Ensure |aVisitedRuleNode != nsnull| corresponds to the need to
444 // create an if-visited style context, and that in that case, we have
445 // parentIfVisited set correctly.
446 nsStyleContext
*parentIfVisited
=
447 aParentContext
? aParentContext
->GetStyleIfVisited() : nsnull
;
448 if (parentIfVisited
) {
449 if (!aVisitedRuleNode
) {
450 aVisitedRuleNode
= aRuleNode
;
453 if (aVisitedRuleNode
) {
454 parentIfVisited
= aParentContext
;
459 // If this node is a link, we want its visited's style context's
460 // parent to be the regular style context of its parent, because
461 // only the visitedness of the relevant link should influence style.
462 parentIfVisited
= aParentContext
;
465 nsRefPtr
<nsStyleContext
> result
;
467 result
= aParentContext
->FindChildWithRules(aPseudoTag
, aRuleNode
,
473 fprintf(stdout
, "--- SharedSC %d ---\n", ++gSharedCount
);
475 fprintf(stdout
, "+++ NewSC %d +++\n", ++gNewCount
);
479 result
= NS_NewStyleContext(aParentContext
, aPseudoTag
, aPseudoType
,
480 aRuleNode
, PresContext());
483 if (aVisitedRuleNode
) {
484 nsRefPtr
<nsStyleContext
> resultIfVisited
=
485 NS_NewStyleContext(parentIfVisited
, aPseudoTag
, aPseudoType
,
486 aVisitedRuleNode
, PresContext());
487 if (!resultIfVisited
) {
490 if (!parentIfVisited
) {
491 mRoots
.AppendElement(resultIfVisited
);
493 resultIfVisited
->SetIsStyleIfVisited();
494 result
->SetStyleIfVisited(resultIfVisited
.forget());
496 PRBool relevantLinkVisited
=
497 aIsLink
? aIsVisitedLink
498 : (aParentContext
&& aParentContext
->RelevantLinkVisited());
499 if (relevantLinkVisited
) {
500 result
->AddStyleBit(NS_STYLE_RELEVANT_LINK_VISITED
);
504 mRoots
.AppendElement(result
);
507 NS_ASSERTION(result
->GetPseudoType() == aPseudoType
, "Unexpected type");
508 NS_ASSERTION(result
->GetPseudo() == aPseudoTag
, "Unexpected pseudo");
511 return result
.forget();
515 nsStyleSet::AddImportantRules(nsRuleNode
* aCurrLevelNode
,
516 nsRuleNode
* aLastPrevLevelNode
,
517 nsRuleWalker
* aRuleWalker
)
519 NS_ASSERTION(aCurrLevelNode
&&
520 aCurrLevelNode
!= aLastPrevLevelNode
, "How did we get here?");
522 nsAutoTArray
<nsIStyleRule
*, 16> importantRules
;
523 for (nsRuleNode
*node
= aCurrLevelNode
; node
!= aLastPrevLevelNode
;
524 node
= node
->GetParent()) {
525 // We guarantee that we never walk the root node here, so no need
526 // to null-check GetRule().
527 nsIStyleRule
* impRule
= node
->GetRule()->GetImportantRule();
529 importantRules
.AppendElement(impRule
);
532 NS_ASSERTION(importantRules
.Length() != 0,
533 "Why did we think there were important rules?");
535 for (PRUint32 i
= importantRules
.Length(); i
-- != 0; ) {
536 aRuleWalker
->Forward(importantRules
[i
]);
542 nsStyleSet::AssertNoImportantRules(nsRuleNode
* aCurrLevelNode
,
543 nsRuleNode
* aLastPrevLevelNode
)
548 for (nsRuleNode
*node
= aCurrLevelNode
; node
!= aLastPrevLevelNode
;
549 node
= node
->GetParent()) {
550 nsIStyleRule
* rule
= node
->GetRule();
552 NS_ASSERTION(!rule
->GetImportantRule(), "Unexpected important rule");
558 nsStyleSet::AssertNoCSSRules(nsRuleNode
* aCurrLevelNode
,
559 nsRuleNode
* aLastPrevLevelNode
)
564 for (nsRuleNode
*node
= aCurrLevelNode
; node
!= aLastPrevLevelNode
;
565 node
= node
->GetParent()) {
566 nsIStyleRule
*rule
= node
->GetRule();
567 nsCOMPtr
<nsICSSStyleRule
> cssRule(do_QueryInterface(rule
));
568 NS_ASSERTION(!cssRule
|| !cssRule
->Selector(), "Unexpected CSS rule");
573 // Enumerate the rules in a way that cares about the order of the rules.
575 nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc
,
576 void* aData
, nsIContent
* aContent
,
577 nsRuleWalker
* aRuleWalker
)
581 // 1. UA normal rules = Agent normal
582 // 2. User normal rules = User normal
583 // 3. Presentation hints = PresHint normal
584 // 4. Author normal rules = Document normal
585 // 5. Override normal rules = Override normal
586 // 6. Author !important rules = Document !important
587 // 7. Override !important rules = Override !important
588 // 8. User !important rules = User !important
589 // 9. UA !important rules = Agent !important
592 aRuleWalker
->SetLevel(eAgentSheet
, PR_FALSE
, PR_TRUE
);
593 if (mRuleProcessors
[eAgentSheet
])
594 (*aCollectorFunc
)(mRuleProcessors
[eAgentSheet
], aData
);
595 nsRuleNode
* lastAgentRN
= aRuleWalker
->CurrentNode();
596 PRBool haveImportantUARules
= !aRuleWalker
->GetCheckForImportantRules();
598 aRuleWalker
->SetLevel(eUserSheet
, PR_FALSE
, PR_TRUE
);
599 PRBool skipUserStyles
=
600 aContent
&& aContent
->IsInNativeAnonymousSubtree();
601 if (!skipUserStyles
&& mRuleProcessors
[eUserSheet
]) // NOTE: different
602 (*aCollectorFunc
)(mRuleProcessors
[eUserSheet
], aData
);
603 nsRuleNode
* lastUserRN
= aRuleWalker
->CurrentNode();
604 PRBool haveImportantUserRules
= !aRuleWalker
->GetCheckForImportantRules();
606 aRuleWalker
->SetLevel(ePresHintSheet
, PR_FALSE
, PR_FALSE
);
607 if (mRuleProcessors
[ePresHintSheet
])
608 (*aCollectorFunc
)(mRuleProcessors
[ePresHintSheet
], aData
);
609 nsRuleNode
* lastPresHintRN
= aRuleWalker
->CurrentNode();
611 aRuleWalker
->SetLevel(eDocSheet
, PR_FALSE
, PR_TRUE
);
612 PRBool cutOffInheritance
= PR_FALSE
;
613 if (mBindingManager
&& aContent
) {
614 // We can supply additional document-level sheets that should be walked.
615 mBindingManager
->WalkRules(aCollectorFunc
,
616 static_cast<RuleProcessorData
*>(aData
),
619 if (!skipUserStyles
&& !cutOffInheritance
&&
620 mRuleProcessors
[eDocSheet
]) // NOTE: different
621 (*aCollectorFunc
)(mRuleProcessors
[eDocSheet
], aData
);
622 aRuleWalker
->SetLevel(eStyleAttrSheet
, PR_FALSE
,
623 aRuleWalker
->GetCheckForImportantRules());
624 if (mRuleProcessors
[eStyleAttrSheet
])
625 (*aCollectorFunc
)(mRuleProcessors
[eStyleAttrSheet
], aData
);
626 nsRuleNode
* lastDocRN
= aRuleWalker
->CurrentNode();
627 PRBool haveImportantDocRules
= !aRuleWalker
->GetCheckForImportantRules();
629 aRuleWalker
->SetLevel(eOverrideSheet
, PR_FALSE
, PR_TRUE
);
630 if (mRuleProcessors
[eOverrideSheet
])
631 (*aCollectorFunc
)(mRuleProcessors
[eOverrideSheet
], aData
);
632 nsRuleNode
* lastOvrRN
= aRuleWalker
->CurrentNode();
633 PRBool haveImportantOverrideRules
= !aRuleWalker
->GetCheckForImportantRules();
635 if (haveImportantDocRules
) {
636 aRuleWalker
->SetLevel(eDocSheet
, PR_TRUE
, PR_FALSE
);
637 AddImportantRules(lastDocRN
, lastPresHintRN
, aRuleWalker
); // doc
641 AssertNoImportantRules(lastDocRN
, lastPresHintRN
);
645 if (haveImportantOverrideRules
) {
646 aRuleWalker
->SetLevel(eOverrideSheet
, PR_TRUE
, PR_FALSE
);
647 AddImportantRules(lastOvrRN
, lastDocRN
, aRuleWalker
); // override
651 AssertNoImportantRules(lastOvrRN
, lastDocRN
);
656 AssertNoCSSRules(lastPresHintRN
, lastUserRN
);
657 AssertNoImportantRules(lastPresHintRN
, lastUserRN
); // preshints
660 if (haveImportantUserRules
) {
661 aRuleWalker
->SetLevel(eUserSheet
, PR_TRUE
, PR_FALSE
);
662 AddImportantRules(lastUserRN
, lastAgentRN
, aRuleWalker
); //user
666 AssertNoImportantRules(lastUserRN
, lastAgentRN
);
670 if (haveImportantUARules
) {
671 aRuleWalker
->SetLevel(eAgentSheet
, PR_TRUE
, PR_FALSE
);
672 AddImportantRules(lastAgentRN
, mRuleTree
, aRuleWalker
); //agent
676 AssertNoImportantRules(lastAgentRN
, mRuleTree
);
681 nsRuleNode
*lastImportantRN
= aRuleWalker
->CurrentNode();
683 aRuleWalker
->SetLevel(eTransitionSheet
, PR_FALSE
, PR_FALSE
);
684 (*aCollectorFunc
)(mRuleProcessors
[eTransitionSheet
], aData
);
686 AssertNoCSSRules(aRuleWalker
->CurrentNode(), lastImportantRN
);
687 AssertNoImportantRules(aRuleWalker
->CurrentNode(), lastImportantRN
);
692 // Enumerate all the rules in a way that doesn't care about the order
693 // of the rules and doesn't walk !important-rules.
695 nsStyleSet::WalkRuleProcessors(nsIStyleRuleProcessor::EnumFunc aFunc
,
696 RuleProcessorData
* aData
,
697 PRBool aWalkAllXBLStylesheets
)
699 if (mRuleProcessors
[eAgentSheet
])
700 (*aFunc
)(mRuleProcessors
[eAgentSheet
], aData
);
702 PRBool skipUserStyles
= aData
->mElement
->IsInNativeAnonymousSubtree();
703 if (!skipUserStyles
&& mRuleProcessors
[eUserSheet
]) // NOTE: different
704 (*aFunc
)(mRuleProcessors
[eUserSheet
], aData
);
706 if (mRuleProcessors
[ePresHintSheet
])
707 (*aFunc
)(mRuleProcessors
[ePresHintSheet
], aData
);
709 PRBool cutOffInheritance
= PR_FALSE
;
710 if (mBindingManager
) {
711 // We can supply additional document-level sheets that should be walked.
712 if (aWalkAllXBLStylesheets
) {
713 mBindingManager
->WalkAllRules(aFunc
, aData
);
715 mBindingManager
->WalkRules(aFunc
, aData
, &cutOffInheritance
);
718 if (!skipUserStyles
&& !cutOffInheritance
&&
719 mRuleProcessors
[eDocSheet
]) // NOTE: different
720 (*aFunc
)(mRuleProcessors
[eDocSheet
], aData
);
721 if (mRuleProcessors
[eStyleAttrSheet
])
722 (*aFunc
)(mRuleProcessors
[eStyleAttrSheet
], aData
);
723 if (mRuleProcessors
[eOverrideSheet
])
724 (*aFunc
)(mRuleProcessors
[eOverrideSheet
], aData
);
725 (*aFunc
)(mRuleProcessors
[eTransitionSheet
], aData
);
728 PRBool
nsStyleSet::BuildDefaultStyleData(nsPresContext
* aPresContext
)
730 NS_ASSERTION(!mDefaultStyleData
.mResetData
&&
731 !mDefaultStyleData
.mInheritedData
,
732 "leaking default style data");
733 mDefaultStyleData
.mResetData
= new (aPresContext
) nsResetStyleData
;
734 if (!mDefaultStyleData
.mResetData
)
736 mDefaultStyleData
.mInheritedData
= new (aPresContext
) nsInheritedStyleData
;
737 if (!mDefaultStyleData
.mInheritedData
)
740 #define SSARG_PRESCONTEXT aPresContext
742 #define CREATE_DATA(name, type, args) \
743 if (!(mDefaultStyleData.m##type##Data->m##name##Data = \
744 new (aPresContext) nsStyle##name args)) \
747 #define STYLE_STRUCT_INHERITED(name, checkdata_cb, ctor_args) \
748 CREATE_DATA(name, Inherited, ctor_args)
749 #define STYLE_STRUCT_RESET(name, checkdata_cb, ctor_args) \
750 CREATE_DATA(name, Reset, ctor_args)
752 #include "nsStyleStructList.h"
754 #undef STYLE_STRUCT_INHERITED
755 #undef STYLE_STRUCT_RESET
756 #undef SSARG_PRESCONTEXT
761 already_AddRefed
<nsStyleContext
>
762 nsStyleSet::ResolveStyleFor(Element
* aElement
,
763 nsStyleContext
* aParentContext
)
765 NS_ENSURE_FALSE(mInShutdown
, nsnull
);
766 NS_ASSERTION(aElement
, "aElement must not be null");
768 nsRuleWalker
ruleWalker(mRuleTree
);
769 ElementRuleProcessorData
data(PresContext(), aElement
, &ruleWalker
);
770 FileRules(EnumRulesMatching
<ElementRuleProcessorData
>, &data
, aElement
,
773 nsRuleNode
*ruleNode
= ruleWalker
.CurrentNode();
774 nsRuleNode
*visitedRuleNode
= nsnull
;
776 if (ruleWalker
.HaveRelevantLink()) {
777 ruleWalker
.ResetForVisitedMatching();
778 FileRules(EnumRulesMatching
<ElementRuleProcessorData
>, &data
, aElement
,
780 visitedRuleNode
= ruleWalker
.CurrentNode();
783 return GetContext(aParentContext
, ruleNode
, visitedRuleNode
,
785 data
.ContentState().HasState(NS_EVENT_STATE_VISITED
),
786 nsnull
, nsCSSPseudoElements::ePseudo_NotPseudoElement
);
789 already_AddRefed
<nsStyleContext
>
790 nsStyleSet::ResolveStyleForRules(nsStyleContext
* aParentContext
,
791 const nsCOMArray
<nsIStyleRule
> &aRules
)
793 NS_ENSURE_FALSE(mInShutdown
, nsnull
);
795 nsRuleWalker
ruleWalker(mRuleTree
);
796 // FIXME: Perhaps this should be passed in, but it probably doesn't
798 ruleWalker
.SetLevel(eDocSheet
, PR_FALSE
, PR_FALSE
);
799 for (PRInt32 i
= 0; i
< aRules
.Count(); i
++) {
800 ruleWalker
.Forward(aRules
.ObjectAt(i
));
803 return GetContext(aParentContext
, ruleWalker
.CurrentNode(), nsnull
,
805 nsnull
, nsCSSPseudoElements::ePseudo_NotPseudoElement
);
808 already_AddRefed
<nsStyleContext
>
809 nsStyleSet::ResolveStyleByAddingRules(nsStyleContext
* aBaseContext
,
810 const nsCOMArray
<nsIStyleRule
> &aRules
)
812 NS_ENSURE_FALSE(mInShutdown
, nsnull
);
814 nsRuleWalker
ruleWalker(mRuleTree
);
815 ruleWalker
.SetCurrentNode(aBaseContext
->GetRuleNode());
816 // FIXME: Perhaps this should be passed in, but it probably doesn't
818 ruleWalker
.SetLevel(eDocSheet
, PR_FALSE
, PR_FALSE
);
819 for (PRInt32 i
= 0; i
< aRules
.Count(); i
++) {
820 ruleWalker
.Forward(aRules
.ObjectAt(i
));
823 nsRuleNode
*ruleNode
= ruleWalker
.CurrentNode();
824 nsRuleNode
*visitedRuleNode
= nsnull
;
826 if (aBaseContext
->GetStyleIfVisited()) {
827 ruleWalker
.SetCurrentNode(aBaseContext
->GetStyleIfVisited()->GetRuleNode());
828 for (PRInt32 i
= 0; i
< aRules
.Count(); i
++) {
829 ruleWalker
.Forward(aRules
.ObjectAt(i
));
831 visitedRuleNode
= ruleWalker
.CurrentNode();
834 return GetContext(aBaseContext
->GetParent(), ruleNode
, visitedRuleNode
,
835 aBaseContext
->IsLinkContext(),
836 aBaseContext
->RelevantLinkVisited(),
837 aBaseContext
->GetPseudo(),
838 aBaseContext
->GetPseudoType());
841 already_AddRefed
<nsStyleContext
>
842 nsStyleSet::ResolveStyleForNonElement(nsStyleContext
* aParentContext
)
844 return GetContext(aParentContext
, mRuleTree
, nsnull
,
846 nsCSSAnonBoxes::mozNonElement
,
847 nsCSSPseudoElements::ePseudo_AnonBox
);
851 nsStyleSet::WalkRestrictionRule(nsCSSPseudoElements::Type aPseudoType
,
852 nsRuleWalker
* aRuleWalker
)
854 // This needs to match GetPseudoRestriction in nsRuleNode.cpp.
855 aRuleWalker
->SetLevel(eAgentSheet
, PR_FALSE
, PR_FALSE
);
856 if (aPseudoType
== nsCSSPseudoElements::ePseudo_firstLetter
)
857 aRuleWalker
->Forward(mFirstLetterRule
);
858 else if (aPseudoType
== nsCSSPseudoElements::ePseudo_firstLine
)
859 aRuleWalker
->Forward(mFirstLineRule
);
862 already_AddRefed
<nsStyleContext
>
863 nsStyleSet::ResolvePseudoElementStyle(Element
* aParentElement
,
864 nsCSSPseudoElements::Type aType
,
865 nsStyleContext
* aParentContext
)
867 NS_ENSURE_FALSE(mInShutdown
, nsnull
);
869 NS_ASSERTION(aType
< nsCSSPseudoElements::ePseudo_PseudoElementCount
,
870 "must have pseudo element type");
871 NS_ASSERTION(aParentElement
, "Must have parent element");
873 nsRuleWalker
ruleWalker(mRuleTree
);
874 PseudoElementRuleProcessorData
data(PresContext(), aParentElement
,
876 WalkRestrictionRule(aType
, &ruleWalker
);
877 FileRules(EnumRulesMatching
<PseudoElementRuleProcessorData
>, &data
,
878 aParentElement
, &ruleWalker
);
880 nsRuleNode
*ruleNode
= ruleWalker
.CurrentNode();
881 nsRuleNode
*visitedRuleNode
= nsnull
;
883 if (ruleWalker
.HaveRelevantLink()) {
884 ruleWalker
.ResetForVisitedMatching();
885 FileRules(EnumRulesMatching
<PseudoElementRuleProcessorData
>, &data
,
886 aParentElement
, &ruleWalker
);
887 visitedRuleNode
= ruleWalker
.CurrentNode();
890 return GetContext(aParentContext
, ruleNode
, visitedRuleNode
,
891 // For pseudos, |data.IsLink()| being true means that
892 // our parent node is a link.
894 nsCSSPseudoElements::GetPseudoAtom(aType
), aType
);
897 already_AddRefed
<nsStyleContext
>
898 nsStyleSet::ProbePseudoElementStyle(Element
* aParentElement
,
899 nsCSSPseudoElements::Type aType
,
900 nsStyleContext
* aParentContext
)
902 NS_ENSURE_FALSE(mInShutdown
, nsnull
);
904 NS_ASSERTION(aType
< nsCSSPseudoElements::ePseudo_PseudoElementCount
,
905 "must have pseudo element type");
906 NS_ASSERTION(aParentElement
, "aParentElement must not be null");
908 nsIAtom
* pseudoTag
= nsCSSPseudoElements::GetPseudoAtom(aType
);
909 nsRuleWalker
ruleWalker(mRuleTree
);
910 PseudoElementRuleProcessorData
data(PresContext(), aParentElement
,
912 WalkRestrictionRule(aType
, &ruleWalker
);
913 // not the root if there was a restriction rule
914 nsRuleNode
*adjustedRoot
= ruleWalker
.CurrentNode();
915 FileRules(EnumRulesMatching
<PseudoElementRuleProcessorData
>, &data
,
916 aParentElement
, &ruleWalker
);
918 nsRuleNode
*ruleNode
= ruleWalker
.CurrentNode();
919 if (ruleNode
== adjustedRoot
) {
923 nsRuleNode
*visitedRuleNode
= nsnull
;
925 if (ruleWalker
.HaveRelevantLink()) {
926 ruleWalker
.ResetForVisitedMatching();
927 FileRules(EnumRulesMatching
<PseudoElementRuleProcessorData
>, &data
,
928 aParentElement
, &ruleWalker
);
929 visitedRuleNode
= ruleWalker
.CurrentNode();
932 nsRefPtr
<nsStyleContext
> result
=
933 GetContext(aParentContext
, ruleNode
, visitedRuleNode
,
934 // For pseudos, |data.IsLink()| being true means that
935 // our parent node is a link.
939 // For :before and :after pseudo-elements, having display: none or no
940 // 'content' property is equivalent to not having the pseudo-element
943 (pseudoTag
== nsCSSPseudoElements::before
||
944 pseudoTag
== nsCSSPseudoElements::after
)) {
945 const nsStyleDisplay
*display
= result
->GetStyleDisplay();
946 const nsStyleContent
*content
= result
->GetStyleContent();
947 // XXXldb What is contentCount for |content: ""|?
948 if (display
->mDisplay
== NS_STYLE_DISPLAY_NONE
||
949 content
->ContentCount() == 0) {
954 return result
.forget();
957 already_AddRefed
<nsStyleContext
>
958 nsStyleSet::ResolveAnonymousBoxStyle(nsIAtom
* aPseudoTag
,
959 nsStyleContext
* aParentContext
)
961 NS_ENSURE_FALSE(mInShutdown
, nsnull
);
964 PRBool isAnonBox
= nsCSSAnonBoxes::IsAnonBox(aPseudoTag
)
966 && !nsCSSAnonBoxes::IsTreePseudoElement(aPseudoTag
)
969 NS_PRECONDITION(isAnonBox
, "Unexpected pseudo");
972 nsRuleWalker
ruleWalker(mRuleTree
);
973 AnonBoxRuleProcessorData
data(PresContext(), aPseudoTag
, &ruleWalker
);
974 FileRules(EnumRulesMatching
<AnonBoxRuleProcessorData
>, &data
, nsnull
,
977 return GetContext(aParentContext
, ruleWalker
.CurrentNode(), nsnull
,
979 aPseudoTag
, nsCSSPseudoElements::ePseudo_AnonBox
);
983 already_AddRefed
<nsStyleContext
>
984 nsStyleSet::ResolveXULTreePseudoStyle(Element
* aParentElement
,
986 nsStyleContext
* aParentContext
,
987 nsICSSPseudoComparator
* aComparator
)
989 NS_ENSURE_FALSE(mInShutdown
, nsnull
);
991 NS_ASSERTION(aPseudoTag
, "must have pseudo tag");
992 NS_ASSERTION(nsCSSAnonBoxes::IsTreePseudoElement(aPseudoTag
),
993 "Unexpected pseudo");
995 nsRuleWalker
ruleWalker(mRuleTree
);
996 XULTreeRuleProcessorData
data(PresContext(), aParentElement
, &ruleWalker
,
997 aPseudoTag
, aComparator
);
998 FileRules(EnumRulesMatching
<XULTreeRuleProcessorData
>, &data
, aParentElement
,
1001 nsRuleNode
*ruleNode
= ruleWalker
.CurrentNode();
1002 nsRuleNode
*visitedRuleNode
= nsnull
;
1004 if (ruleWalker
.HaveRelevantLink()) {
1005 ruleWalker
.ResetForVisitedMatching();
1006 FileRules(EnumRulesMatching
<XULTreeRuleProcessorData
>, &data
,
1007 aParentElement
, &ruleWalker
);
1008 visitedRuleNode
= ruleWalker
.CurrentNode();
1011 return GetContext(aParentContext
, ruleNode
, visitedRuleNode
,
1012 // For pseudos, |data.IsLink()| being true means that
1013 // our parent node is a link.
1015 aPseudoTag
, nsCSSPseudoElements::ePseudo_XULTree
);
1020 nsStyleSet::AppendFontFaceRules(nsPresContext
* aPresContext
,
1021 nsTArray
<nsFontFaceRuleContainer
>& aArray
)
1023 NS_ENSURE_FALSE(mInShutdown
, PR_FALSE
);
1025 for (PRUint32 i
= 0; i
< NS_ARRAY_LENGTH(gCSSSheetTypes
); ++i
) {
1026 nsCSSRuleProcessor
*ruleProc
= static_cast<nsCSSRuleProcessor
*>
1027 (mRuleProcessors
[gCSSSheetTypes
[i
]].get());
1028 if (ruleProc
&& !ruleProc
->AppendFontFaceRules(aPresContext
, aArray
))
1035 nsStyleSet::BeginShutdown(nsPresContext
* aPresContext
)
1038 mRoots
.Clear(); // no longer valid, since we won't keep it up to date
1042 nsStyleSet::Shutdown(nsPresContext
* aPresContext
)
1044 mRuleTree
->Destroy();
1047 // We can have old rule trees either because:
1048 // (1) we failed the assertions in EndReconstruct, or
1049 // (2) we're shutting down within a reconstruct (see bug 462392)
1050 for (PRUint32 i
= mOldRuleTrees
.Length(); i
> 0; ) {
1052 mOldRuleTrees
[i
]->Destroy();
1054 mOldRuleTrees
.Clear();
1056 mDefaultStyleData
.Destroy(0, aPresContext
);
1059 static const PRUint32 kGCInterval
= 300;
1062 nsStyleSet::NotifyStyleContextDestroyed(nsPresContext
* aPresContext
,
1063 nsStyleContext
* aStyleContext
)
1068 // Remove style contexts from mRoots even if mOldRuleTree is non-null. This
1069 // could be a style context from the new ruletree!
1070 if (!aStyleContext
->GetParent()) {
1071 mRoots
.RemoveElement(aStyleContext
);
1077 if (mUnusedRuleNodeCount
>= kGCInterval
) {
1083 nsStyleSet::GCRuleTrees()
1085 mUnusedRuleNodeCount
= 0;
1087 // Mark the style context tree by marking all style contexts which
1088 // have no parent, which will mark all descendants. This will reach
1089 // style contexts in the undisplayed map and "additional style
1090 // contexts" since they are descendants of the roots.
1091 for (PRInt32 i
= mRoots
.Length() - 1; i
>= 0; --i
) {
1095 // Sweep the rule tree.
1100 NS_ASSERTION(!deleted
, "Root node must not be gc'd");
1102 // Sweep the old rule trees.
1103 for (PRUint32 i
= mOldRuleTrees
.Length(); i
> 0; ) {
1105 if (mOldRuleTrees
[i
]->Sweep()) {
1106 // It was deleted, as it should be.
1107 mOldRuleTrees
.RemoveElementAt(i
);
1109 NS_NOTREACHED("old rule tree still referenced");
1114 static inline nsRuleNode
*
1115 SkipTransitionRules(nsRuleNode
* aRuleNode
, Element
* aElement
, PRBool isPseudo
)
1117 nsRuleNode
* ruleNode
= aRuleNode
;
1118 while (!ruleNode
->IsRoot() &&
1119 ruleNode
->GetLevel() == nsStyleSet::eTransitionSheet
) {
1120 ruleNode
= ruleNode
->GetParent();
1122 if (ruleNode
!= aRuleNode
) {
1123 NS_ASSERTION(aElement
, "How can we have transition rules but no element?");
1124 // Need to do an animation restyle, just like
1125 // nsTransitionManager::WalkTransitionRule would.
1126 nsRestyleHint hint
= isPseudo
? eRestyle_Subtree
: eRestyle_Self
;
1127 aRuleNode
->GetPresContext()->PresShell()->RestyleForAnimation(aElement
,
1133 already_AddRefed
<nsStyleContext
>
1134 nsStyleSet::ReparentStyleContext(nsStyleContext
* aStyleContext
,
1135 nsStyleContext
* aNewParentContext
,
1138 if (!aStyleContext
) {
1139 NS_NOTREACHED("must have style context");
1143 // This short-circuit is OK because we don't call TryStartingTransition
1144 // during style reresolution if the style context pointer hasn't changed.
1145 if (aStyleContext
->GetParent() == aNewParentContext
) {
1146 aStyleContext
->AddRef();
1147 return aStyleContext
;
1150 nsIAtom
* pseudoTag
= aStyleContext
->GetPseudo();
1151 nsCSSPseudoElements::Type pseudoType
= aStyleContext
->GetPseudoType();
1152 nsRuleNode
* ruleNode
= aStyleContext
->GetRuleNode();
1154 // Skip transition rules as needed just like
1155 // nsTransitionManager::WalkTransitionRule would.
1156 PRBool skipTransitionRules
= PresContext()->IsProcessingRestyles() &&
1157 !PresContext()->IsProcessingAnimationStyleChange();
1158 if (skipTransitionRules
) {
1159 // Make sure that we're not using transition rules for our new style
1160 // context. If we need them, an animation restyle will provide.
1162 SkipTransitionRules(ruleNode
, aElement
,
1164 nsCSSPseudoElements::ePseudo_NotPseudoElement
);
1167 nsRuleNode
* visitedRuleNode
= nsnull
;
1168 nsStyleContext
* visitedContext
= aStyleContext
->GetStyleIfVisited();
1169 // Reparenting a style context just changes where we inherit from,
1170 // not what rules we match or what our DOM looks like. In
1171 // particular, it doesn't change whether this is a style context for
1173 if (visitedContext
) {
1174 visitedRuleNode
= visitedContext
->GetRuleNode();
1175 // Again, skip transition rules as needed
1176 if (skipTransitionRules
) {
1178 SkipTransitionRules(visitedRuleNode
, aElement
,
1180 nsCSSPseudoElements::ePseudo_NotPseudoElement
);
1184 return GetContext(aNewParentContext
, ruleNode
, visitedRuleNode
,
1185 aStyleContext
->IsLinkContext(),
1186 aStyleContext
->RelevantLinkVisited(),
1187 pseudoTag
, pseudoType
);
1190 struct StatefulData
: public StateRuleProcessorData
{
1191 StatefulData(nsPresContext
* aPresContext
,
1192 Element
* aElement
, nsEventStates aStateMask
)
1193 : StateRuleProcessorData(aPresContext
, aElement
, aStateMask
),
1194 mHint(nsRestyleHint(0))
1196 nsRestyleHint mHint
;
1199 static PRBool
SheetHasDocumentStateStyle(nsIStyleRuleProcessor
* aProcessor
,
1202 StatefulData
* data
= (StatefulData
*)aData
;
1203 if (aProcessor
->HasDocumentStateDependentStyle(data
)) {
1204 data
->mHint
= eRestyle_Self
;
1205 return PR_FALSE
; // don't continue
1207 return PR_TRUE
; // continue
1210 // Test if style is dependent on a document state.
1212 nsStyleSet::HasDocumentStateDependentStyle(nsPresContext
* aPresContext
,
1213 nsIContent
* aContent
,
1214 nsEventStates aStateMask
)
1216 if (!aContent
|| !aContent
->IsElement())
1219 StatefulData
data(aPresContext
, aContent
->AsElement(), aStateMask
);
1220 WalkRuleProcessors(SheetHasDocumentStateStyle
, &data
, PR_TRUE
);
1221 return data
.mHint
!= 0;
1224 static PRBool
SheetHasStatefulStyle(nsIStyleRuleProcessor
* aProcessor
,
1227 StatefulData
* data
= (StatefulData
*)aData
;
1228 nsRestyleHint hint
= aProcessor
->HasStateDependentStyle(data
);
1229 data
->mHint
= nsRestyleHint(data
->mHint
| hint
);
1230 return PR_TRUE
; // continue
1233 // Test if style is dependent on content state
1235 nsStyleSet::HasStateDependentStyle(nsPresContext
* aPresContext
,
1237 nsEventStates aStateMask
)
1239 StatefulData
data(aPresContext
, aElement
, aStateMask
);
1240 WalkRuleProcessors(SheetHasStatefulStyle
, &data
, PR_FALSE
);
1244 struct AttributeData
: public AttributeRuleProcessorData
{
1245 AttributeData(nsPresContext
* aPresContext
,
1246 Element
* aElement
, nsIAtom
* aAttribute
, PRInt32 aModType
,
1247 PRBool aAttrHasChanged
)
1248 : AttributeRuleProcessorData(aPresContext
, aElement
, aAttribute
, aModType
,
1250 mHint(nsRestyleHint(0))
1252 nsRestyleHint mHint
;
1256 SheetHasAttributeStyle(nsIStyleRuleProcessor
* aProcessor
, void *aData
)
1258 AttributeData
* data
= (AttributeData
*)aData
;
1259 nsRestyleHint hint
= aProcessor
->HasAttributeDependentStyle(data
);
1260 data
->mHint
= nsRestyleHint(data
->mHint
| hint
);
1261 return PR_TRUE
; // continue
1264 // Test if style is dependent on content state
1266 nsStyleSet::HasAttributeDependentStyle(nsPresContext
* aPresContext
,
1268 nsIAtom
* aAttribute
,
1270 PRBool aAttrHasChanged
)
1272 AttributeData
data(aPresContext
, aElement
, aAttribute
,
1273 aModType
, aAttrHasChanged
);
1274 WalkRuleProcessors(SheetHasAttributeStyle
, &data
, PR_FALSE
);
1279 nsStyleSet::MediumFeaturesChanged(nsPresContext
* aPresContext
)
1281 // We can't use WalkRuleProcessors without a content node.
1282 PRBool stylesChanged
= PR_FALSE
;
1283 for (PRUint32 i
= 0; i
< NS_ARRAY_LENGTH(mRuleProcessors
); ++i
) {
1284 nsIStyleRuleProcessor
*processor
= mRuleProcessors
[i
];
1288 PRBool thisChanged
= processor
->MediumFeaturesChanged(aPresContext
);
1289 stylesChanged
= stylesChanged
|| thisChanged
;
1292 if (mBindingManager
) {
1293 PRBool thisChanged
= PR_FALSE
;
1294 mBindingManager
->MediumFeaturesChanged(aPresContext
, &thisChanged
);
1295 stylesChanged
= stylesChanged
|| thisChanged
;
1298 return stylesChanged
;
1301 nsCSSStyleSheet::EnsureUniqueInnerResult
1302 nsStyleSet::EnsureUniqueInnerOnCSSSheets()
1304 nsAutoTArray
<nsCSSStyleSheet
*, 32> queue
;
1305 for (PRUint32 i
= 0; i
< NS_ARRAY_LENGTH(gCSSSheetTypes
); ++i
) {
1306 nsCOMArray
<nsIStyleSheet
> &sheets
= mSheets
[gCSSSheetTypes
[i
]];
1307 for (PRUint32 j
= 0, j_end
= sheets
.Count(); j
< j_end
; ++j
) {
1308 nsCSSStyleSheet
*sheet
= static_cast<nsCSSStyleSheet
*>(sheets
[j
]);
1309 if (!queue
.AppendElement(sheet
)) {
1310 return nsCSSStyleSheet::eUniqueInner_CloneFailed
;
1315 if (mBindingManager
) {
1316 mBindingManager
->AppendAllSheets(queue
);
1319 nsCSSStyleSheet::EnsureUniqueInnerResult res
=
1320 nsCSSStyleSheet::eUniqueInner_AlreadyUnique
;
1321 while (!queue
.IsEmpty()) {
1322 PRUint32 idx
= queue
.Length() - 1;
1323 nsCSSStyleSheet
*sheet
= queue
[idx
];
1324 queue
.RemoveElementAt(idx
);
1326 nsCSSStyleSheet::EnsureUniqueInnerResult sheetRes
=
1327 sheet
->EnsureUniqueInner();
1328 if (sheetRes
== nsCSSStyleSheet::eUniqueInner_CloneFailed
) {
1331 if (sheetRes
== nsCSSStyleSheet::eUniqueInner_ClonedInner
) {
1335 // Enqueue all the sheet's children.
1336 if (!sheet
->AppendAllChildSheets(queue
)) {
1337 return nsCSSStyleSheet::eUniqueInner_CloneFailed
;