1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/style/nsStyleSet.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,2077 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* 1.10 + * the container for the style sheets that apply to a presentation, and 1.11 + * the internal API that the style system exposes for creating (and 1.12 + * potentially re-creating) style contexts 1.13 + */ 1.14 + 1.15 +#include "mozilla/ArrayUtils.h" 1.16 +#include "mozilla/EventStates.h" 1.17 +#include "mozilla/MemoryReporting.h" 1.18 + 1.19 +#include "nsStyleSet.h" 1.20 +#include "nsCSSStyleSheet.h" 1.21 +#include "nsIDocumentInlines.h" 1.22 +#include "nsRuleWalker.h" 1.23 +#include "nsStyleContext.h" 1.24 +#include "mozilla/css/StyleRule.h" 1.25 +#include "nsCSSAnonBoxes.h" 1.26 +#include "nsCSSPseudoElements.h" 1.27 +#include "nsCSSRuleProcessor.h" 1.28 +#include "nsDataHashtable.h" 1.29 +#include "nsIContent.h" 1.30 +#include "nsRuleData.h" 1.31 +#include "nsRuleProcessorData.h" 1.32 +#include "nsTransitionManager.h" 1.33 +#include "nsAnimationManager.h" 1.34 +#include "nsStyleSheetService.h" 1.35 +#include "mozilla/dom/Element.h" 1.36 +#include "GeckoProfiler.h" 1.37 +#include "nsHTMLCSSStyleSheet.h" 1.38 +#include "nsHTMLStyleSheet.h" 1.39 +#include "nsCSSRules.h" 1.40 + 1.41 +using namespace mozilla; 1.42 +using namespace mozilla::dom; 1.43 + 1.44 +NS_IMPL_ISUPPORTS(nsEmptyStyleRule, nsIStyleRule) 1.45 + 1.46 +/* virtual */ void 1.47 +nsEmptyStyleRule::MapRuleInfoInto(nsRuleData* aRuleData) 1.48 +{ 1.49 +} 1.50 + 1.51 +#ifdef DEBUG 1.52 +/* virtual */ void 1.53 +nsEmptyStyleRule::List(FILE* out, int32_t aIndent) const 1.54 +{ 1.55 + for (int32_t index = aIndent; --index >= 0; ) fputs(" ", out); 1.56 + fputs("[empty style rule] {}\n", out); 1.57 +} 1.58 +#endif 1.59 + 1.60 +NS_IMPL_ISUPPORTS(nsInitialStyleRule, nsIStyleRule) 1.61 + 1.62 +/* virtual */ void 1.63 +nsInitialStyleRule::MapRuleInfoInto(nsRuleData* aRuleData) 1.64 +{ 1.65 + // Iterate over the property groups 1.66 + for (nsStyleStructID sid = nsStyleStructID(0); 1.67 + sid < nsStyleStructID_Length; sid = nsStyleStructID(sid + 1)) { 1.68 + if (aRuleData->mSIDs & (1 << sid)) { 1.69 + // Iterate over nsCSSValues within the property group 1.70 + nsCSSValue * const value_start = 1.71 + aRuleData->mValueStorage + aRuleData->mValueOffsets[sid]; 1.72 + for (nsCSSValue *value = value_start, 1.73 + *value_end = value + nsCSSProps::PropertyCountInStruct(sid); 1.74 + value != value_end; ++value) { 1.75 + // If MathML is disabled take care not to set MathML properties (or we 1.76 + // will trigger assertions in nsRuleNode) 1.77 + if (sid == eStyleStruct_Font && 1.78 + !aRuleData->mPresContext->Document()->GetMathMLEnabled()) { 1.79 + size_t index = value - value_start; 1.80 + if (index == nsCSSProps::PropertyIndexInStruct( 1.81 + eCSSProperty_script_level) || 1.82 + index == nsCSSProps::PropertyIndexInStruct( 1.83 + eCSSProperty_script_size_multiplier) || 1.84 + index == nsCSSProps::PropertyIndexInStruct( 1.85 + eCSSProperty_script_min_size) || 1.86 + index == nsCSSProps::PropertyIndexInStruct( 1.87 + eCSSProperty_math_variant) || 1.88 + index == nsCSSProps::PropertyIndexInStruct( 1.89 + eCSSProperty_math_display)) { 1.90 + continue; 1.91 + } 1.92 + } 1.93 + if (value->GetUnit() == eCSSUnit_Null) { 1.94 + value->SetInitialValue(); 1.95 + } 1.96 + } 1.97 + } 1.98 + } 1.99 +} 1.100 + 1.101 +#ifdef DEBUG 1.102 +/* virtual */ void 1.103 +nsInitialStyleRule::List(FILE* out, int32_t aIndent) const 1.104 +{ 1.105 + for (int32_t index = aIndent; --index >= 0; ) fputs(" ", out); 1.106 + fputs("[initial style rule] {}\n", out); 1.107 +} 1.108 +#endif 1.109 + 1.110 +NS_IMPL_ISUPPORTS(nsDisableTextZoomStyleRule, nsIStyleRule) 1.111 + 1.112 +/* virtual */ void 1.113 +nsDisableTextZoomStyleRule::MapRuleInfoInto(nsRuleData* aRuleData) 1.114 +{ 1.115 + if (!(aRuleData->mSIDs & NS_STYLE_INHERIT_BIT(Font))) 1.116 + return; 1.117 + 1.118 + nsCSSValue* value = aRuleData->ValueForTextZoom(); 1.119 + if (value->GetUnit() == eCSSUnit_Null) 1.120 + value->SetNoneValue(); 1.121 +} 1.122 + 1.123 +#ifdef DEBUG 1.124 +/* virtual */ void 1.125 +nsDisableTextZoomStyleRule::List(FILE* out, int32_t aIndent) const 1.126 +{ 1.127 + for (int32_t index = aIndent; --index >= 0; ) fputs(" ", out); 1.128 + fputs("[disable text zoom style rule] {}\n", out); 1.129 +} 1.130 +#endif 1.131 + 1.132 +static const nsStyleSet::sheetType gCSSSheetTypes[] = { 1.133 + // From lowest to highest in cascading order. 1.134 + nsStyleSet::eAgentSheet, 1.135 + nsStyleSet::eUserSheet, 1.136 + nsStyleSet::eDocSheet, 1.137 + nsStyleSet::eScopedDocSheet, 1.138 + nsStyleSet::eOverrideSheet 1.139 +}; 1.140 + 1.141 +nsStyleSet::nsStyleSet() 1.142 + : mRuleTree(nullptr), 1.143 + mBatching(0), 1.144 + mInShutdown(false), 1.145 + mAuthorStyleDisabled(false), 1.146 + mInReconstruct(false), 1.147 + mInitFontFeatureValuesLookup(true), 1.148 + mDirty(0), 1.149 + mUnusedRuleNodeCount(0) 1.150 +{ 1.151 +} 1.152 + 1.153 +size_t 1.154 +nsStyleSet::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const 1.155 +{ 1.156 + size_t n = aMallocSizeOf(this); 1.157 + 1.158 + for (int i = 0; i < eSheetTypeCount; i++) { 1.159 + if (mRuleProcessors[i]) { 1.160 + n += mRuleProcessors[i]->SizeOfIncludingThis(aMallocSizeOf); 1.161 + } 1.162 + n += mSheets[i].SizeOfExcludingThis(nullptr, aMallocSizeOf); 1.163 + } 1.164 + 1.165 + for (uint32_t i = 0; i < mScopedDocSheetRuleProcessors.Length(); i++) { 1.166 + n += mScopedDocSheetRuleProcessors[i]->SizeOfIncludingThis(aMallocSizeOf); 1.167 + } 1.168 + n += mScopedDocSheetRuleProcessors.SizeOfExcludingThis(aMallocSizeOf); 1.169 + 1.170 + n += mRoots.SizeOfExcludingThis(aMallocSizeOf); 1.171 + n += mOldRuleTrees.SizeOfExcludingThis(aMallocSizeOf); 1.172 + 1.173 + return n; 1.174 +} 1.175 + 1.176 +void 1.177 +nsStyleSet::Init(nsPresContext *aPresContext) 1.178 +{ 1.179 + mFirstLineRule = new nsEmptyStyleRule; 1.180 + mFirstLetterRule = new nsEmptyStyleRule; 1.181 + mPlaceholderRule = new nsEmptyStyleRule; 1.182 + mDisableTextZoomStyleRule = new nsDisableTextZoomStyleRule; 1.183 + 1.184 + mRuleTree = nsRuleNode::CreateRootNode(aPresContext); 1.185 + 1.186 + GatherRuleProcessors(eAnimationSheet); 1.187 + GatherRuleProcessors(eTransitionSheet); 1.188 +} 1.189 + 1.190 +nsresult 1.191 +nsStyleSet::BeginReconstruct() 1.192 +{ 1.193 + NS_ASSERTION(!mInReconstruct, "Unmatched begin/end?"); 1.194 + NS_ASSERTION(mRuleTree, "Reconstructing before first construction?"); 1.195 + 1.196 + // Create a new rule tree root 1.197 + nsRuleNode* newTree = 1.198 + nsRuleNode::CreateRootNode(mRuleTree->PresContext()); 1.199 + if (!newTree) 1.200 + return NS_ERROR_OUT_OF_MEMORY; 1.201 + 1.202 + // Save the old rule tree so we can destroy it later 1.203 + if (!mOldRuleTrees.AppendElement(mRuleTree)) { 1.204 + newTree->Destroy(); 1.205 + return NS_ERROR_OUT_OF_MEMORY; 1.206 + } 1.207 + 1.208 + // We need to keep mRoots so that the rule tree GC will only free the 1.209 + // rule trees that really aren't referenced anymore (which should be 1.210 + // all of them, if there are no bugs in reresolution code). 1.211 + 1.212 + mInReconstruct = true; 1.213 + mRuleTree = newTree; 1.214 + 1.215 + return NS_OK; 1.216 +} 1.217 + 1.218 +void 1.219 +nsStyleSet::EndReconstruct() 1.220 +{ 1.221 + NS_ASSERTION(mInReconstruct, "Unmatched begin/end?"); 1.222 + mInReconstruct = false; 1.223 +#ifdef DEBUG 1.224 + for (int32_t i = mRoots.Length() - 1; i >= 0; --i) { 1.225 + nsRuleNode *n = mRoots[i]->RuleNode(); 1.226 + while (n->GetParent()) { 1.227 + n = n->GetParent(); 1.228 + } 1.229 + // Since nsStyleContext's mParent and mRuleNode are immutable, and 1.230 + // style contexts own their parents, and nsStyleContext asserts in 1.231 + // its constructor that the style context and its parent are in the 1.232 + // same rule tree, we don't need to check any of the children of 1.233 + // mRoots; we only need to check the rule nodes of mRoots 1.234 + // themselves. 1.235 + 1.236 + NS_ASSERTION(n == mRuleTree, "style context has old rule node"); 1.237 + } 1.238 +#endif 1.239 + // This *should* destroy the only element of mOldRuleTrees, but in 1.240 + // case of some bugs (which would trigger the above assertions), it 1.241 + // won't. 1.242 + GCRuleTrees(); 1.243 +} 1.244 + 1.245 +void 1.246 +nsStyleSet::SetQuirkStyleSheet(nsIStyleSheet* aQuirkStyleSheet) 1.247 +{ 1.248 + NS_ASSERTION(aQuirkStyleSheet, "Must have quirk sheet if this is called"); 1.249 + NS_ASSERTION(!mQuirkStyleSheet, "Multiple calls to SetQuirkStyleSheet?"); 1.250 + NS_ASSERTION(mSheets[eAgentSheet].IndexOf(aQuirkStyleSheet) != -1, 1.251 + "Quirk style sheet not one of our agent sheets?"); 1.252 + mQuirkStyleSheet = aQuirkStyleSheet; 1.253 +} 1.254 + 1.255 +typedef nsDataHashtable<nsPtrHashKey<nsINode>, uint32_t> ScopeDepthCache; 1.256 + 1.257 +// Returns the depth of a style scope element, with 1 being the depth of 1.258 +// a style scope element that has no ancestor style scope elements. The 1.259 +// depth does not count intervening non-scope elements. 1.260 +static uint32_t 1.261 +GetScopeDepth(nsINode* aScopeElement, ScopeDepthCache& aCache) 1.262 +{ 1.263 + nsINode* parent = aScopeElement->GetParent(); 1.264 + if (!parent || !parent->IsElementInStyleScope()) { 1.265 + return 1; 1.266 + } 1.267 + 1.268 + uint32_t depth = aCache.Get(aScopeElement); 1.269 + if (!depth) { 1.270 + for (nsINode* n = parent; n; n = n->GetParent()) { 1.271 + if (n->IsScopedStyleRoot()) { 1.272 + depth = GetScopeDepth(n, aCache) + 1; 1.273 + aCache.Put(aScopeElement, depth); 1.274 + break; 1.275 + } 1.276 + } 1.277 + } 1.278 + return depth; 1.279 +} 1.280 + 1.281 +struct ScopedSheetOrder 1.282 +{ 1.283 + nsCSSStyleSheet* mSheet; 1.284 + uint32_t mDepth; 1.285 + uint32_t mOrder; 1.286 + 1.287 + bool operator==(const ScopedSheetOrder& aRHS) const 1.288 + { 1.289 + return mDepth == aRHS.mDepth && 1.290 + mOrder == aRHS.mOrder; 1.291 + } 1.292 + 1.293 + bool operator<(const ScopedSheetOrder& aRHS) const 1.294 + { 1.295 + if (mDepth != aRHS.mDepth) { 1.296 + return mDepth < aRHS.mDepth; 1.297 + } 1.298 + return mOrder < aRHS.mOrder; 1.299 + } 1.300 +}; 1.301 + 1.302 +// Sorts aSheets such that style sheets for ancestor scopes come 1.303 +// before those for descendant scopes, and with sheets for a single 1.304 +// scope in document order. 1.305 +static void 1.306 +SortStyleSheetsByScope(nsTArray<nsCSSStyleSheet*>& aSheets) 1.307 +{ 1.308 + uint32_t n = aSheets.Length(); 1.309 + if (n == 1) { 1.310 + return; 1.311 + } 1.312 + 1.313 + ScopeDepthCache cache; 1.314 + 1.315 + nsTArray<ScopedSheetOrder> sheets; 1.316 + sheets.SetLength(n); 1.317 + 1.318 + // For each sheet, record the depth of its scope element and its original 1.319 + // document order. 1.320 + for (uint32_t i = 0; i < n; i++) { 1.321 + sheets[i].mSheet = aSheets[i]; 1.322 + sheets[i].mDepth = GetScopeDepth(aSheets[i]->GetScopeElement(), cache); 1.323 + sheets[i].mOrder = i; 1.324 + } 1.325 + 1.326 + // Sort by depth first, then document order. 1.327 + sheets.Sort(); 1.328 + 1.329 + for (uint32_t i = 0; i < n; i++) { 1.330 + aSheets[i] = sheets[i].mSheet; 1.331 + } 1.332 +} 1.333 + 1.334 +nsresult 1.335 +nsStyleSet::GatherRuleProcessors(sheetType aType) 1.336 +{ 1.337 + mRuleProcessors[aType] = nullptr; 1.338 + if (aType == eScopedDocSheet) { 1.339 + for (uint32_t i = 0; i < mScopedDocSheetRuleProcessors.Length(); i++) { 1.340 + nsIStyleRuleProcessor* processor = mScopedDocSheetRuleProcessors[i].get(); 1.341 + Element* scope = 1.342 + static_cast<nsCSSRuleProcessor*>(processor)->GetScopeElement(); 1.343 + scope->ClearIsScopedStyleRoot(); 1.344 + } 1.345 + mScopedDocSheetRuleProcessors.Clear(); 1.346 + } 1.347 + if (mAuthorStyleDisabled && (aType == eDocSheet || 1.348 + aType == eScopedDocSheet || 1.349 + aType == eStyleAttrSheet)) { 1.350 + // Don't regather if this level is disabled. Note that we gather 1.351 + // preshint sheets no matter what, but then skip them for some 1.352 + // elements later if mAuthorStyleDisabled. 1.353 + return NS_OK; 1.354 + } 1.355 + switch (aType) { 1.356 + // handle the types for which have a rule processor that does not 1.357 + // implement the style sheet interface. 1.358 + case eAnimationSheet: 1.359 + MOZ_ASSERT(mSheets[aType].Count() == 0); 1.360 + mRuleProcessors[aType] = PresContext()->AnimationManager(); 1.361 + return NS_OK; 1.362 + case eTransitionSheet: 1.363 + MOZ_ASSERT(mSheets[aType].Count() == 0); 1.364 + mRuleProcessors[aType] = PresContext()->TransitionManager(); 1.365 + return NS_OK; 1.366 + case eStyleAttrSheet: 1.367 + MOZ_ASSERT(mSheets[aType].Count() == 0); 1.368 + mRuleProcessors[aType] = PresContext()->Document()->GetInlineStyleSheet(); 1.369 + return NS_OK; 1.370 + case ePresHintSheet: 1.371 + MOZ_ASSERT(mSheets[aType].Count() == 0); 1.372 + mRuleProcessors[aType] = PresContext()->Document()->GetAttributeStyleSheet(); 1.373 + return NS_OK; 1.374 + default: 1.375 + // keep going 1.376 + break; 1.377 + } 1.378 + if (aType == eScopedDocSheet) { 1.379 + // Create a rule processor for each scope. 1.380 + uint32_t count = mSheets[eScopedDocSheet].Count(); 1.381 + if (count) { 1.382 + // Gather the scoped style sheets into an array as 1.383 + // nsCSSStyleSheets, and mark all of their scope elements 1.384 + // as scoped style roots. 1.385 + nsTArray<nsCSSStyleSheet*> sheets(count); 1.386 + for (uint32_t i = 0; i < count; i++) { 1.387 + nsRefPtr<nsCSSStyleSheet> sheet = 1.388 + do_QueryObject(mSheets[eScopedDocSheet].ObjectAt(i)); 1.389 + sheets.AppendElement(sheet); 1.390 + 1.391 + Element* scope = sheet->GetScopeElement(); 1.392 + scope->SetIsScopedStyleRoot(); 1.393 + } 1.394 + 1.395 + // Sort the scoped style sheets so that those for the same scope are 1.396 + // adjacent and that ancestor scopes come before descendent scopes. 1.397 + SortStyleSheetsByScope(sheets); 1.398 + 1.399 + uint32_t start = 0, end; 1.400 + do { 1.401 + // Find the range of style sheets with the same scope. 1.402 + Element* scope = sheets[start]->GetScopeElement(); 1.403 + end = start + 1; 1.404 + while (end < count && sheets[end]->GetScopeElement() == scope) { 1.405 + end++; 1.406 + } 1.407 + 1.408 + scope->SetIsScopedStyleRoot(); 1.409 + 1.410 + // Create a rule processor for the scope. 1.411 + nsTArray< nsRefPtr<nsCSSStyleSheet> > sheetsForScope; 1.412 + sheetsForScope.AppendElements(sheets.Elements() + start, end - start); 1.413 + mScopedDocSheetRuleProcessors.AppendElement 1.414 + (new nsCSSRuleProcessor(sheetsForScope, uint8_t(aType), scope)); 1.415 + 1.416 + start = end; 1.417 + } while (start < count); 1.418 + } 1.419 + return NS_OK; 1.420 + } 1.421 + if (mSheets[aType].Count()) { 1.422 + switch (aType) { 1.423 + case eAgentSheet: 1.424 + case eUserSheet: 1.425 + case eDocSheet: 1.426 + case eOverrideSheet: { 1.427 + // levels containing CSS stylesheets (apart from eScopedDocSheet) 1.428 + nsCOMArray<nsIStyleSheet>& sheets = mSheets[aType]; 1.429 + nsTArray<nsRefPtr<nsCSSStyleSheet> > cssSheets(sheets.Count()); 1.430 + for (int32_t i = 0, i_end = sheets.Count(); i < i_end; ++i) { 1.431 + nsRefPtr<nsCSSStyleSheet> cssSheet = do_QueryObject(sheets[i]); 1.432 + NS_ASSERTION(cssSheet, "not a CSS sheet"); 1.433 + cssSheets.AppendElement(cssSheet); 1.434 + } 1.435 + mRuleProcessors[aType] = 1.436 + new nsCSSRuleProcessor(cssSheets, uint8_t(aType), nullptr); 1.437 + } break; 1.438 + 1.439 + default: 1.440 + // levels containing non-CSS stylesheets 1.441 + NS_ASSERTION(mSheets[aType].Count() == 1, "only one sheet per level"); 1.442 + mRuleProcessors[aType] = do_QueryInterface(mSheets[aType][0]); 1.443 + break; 1.444 + } 1.445 + } 1.446 + 1.447 + return NS_OK; 1.448 +} 1.449 + 1.450 +static bool 1.451 +IsScopedStyleSheet(nsIStyleSheet* aSheet) 1.452 +{ 1.453 + nsRefPtr<nsCSSStyleSheet> cssSheet = do_QueryObject(aSheet); 1.454 + NS_ASSERTION(cssSheet, "expected aSheet to be an nsCSSStyleSheet"); 1.455 + 1.456 + return cssSheet->GetScopeElement(); 1.457 +} 1.458 + 1.459 +nsresult 1.460 +nsStyleSet::AppendStyleSheet(sheetType aType, nsIStyleSheet *aSheet) 1.461 +{ 1.462 + NS_PRECONDITION(aSheet, "null arg"); 1.463 + NS_ASSERTION(aSheet->IsApplicable(), 1.464 + "Inapplicable sheet being placed in style set"); 1.465 + mSheets[aType].RemoveObject(aSheet); 1.466 + if (!mSheets[aType].AppendObject(aSheet)) 1.467 + return NS_ERROR_OUT_OF_MEMORY; 1.468 + 1.469 + return DirtyRuleProcessors(aType); 1.470 +} 1.471 + 1.472 +nsresult 1.473 +nsStyleSet::PrependStyleSheet(sheetType aType, nsIStyleSheet *aSheet) 1.474 +{ 1.475 + NS_PRECONDITION(aSheet, "null arg"); 1.476 + NS_ASSERTION(aSheet->IsApplicable(), 1.477 + "Inapplicable sheet being placed in style set"); 1.478 + mSheets[aType].RemoveObject(aSheet); 1.479 + if (!mSheets[aType].InsertObjectAt(aSheet, 0)) 1.480 + return NS_ERROR_OUT_OF_MEMORY; 1.481 + 1.482 + return DirtyRuleProcessors(aType); 1.483 +} 1.484 + 1.485 +nsresult 1.486 +nsStyleSet::RemoveStyleSheet(sheetType aType, nsIStyleSheet *aSheet) 1.487 +{ 1.488 + NS_PRECONDITION(aSheet, "null arg"); 1.489 + NS_ASSERTION(aSheet->IsComplete(), 1.490 + "Incomplete sheet being removed from style set"); 1.491 + mSheets[aType].RemoveObject(aSheet); 1.492 + 1.493 + return DirtyRuleProcessors(aType); 1.494 +} 1.495 + 1.496 +nsresult 1.497 +nsStyleSet::ReplaceSheets(sheetType aType, 1.498 + const nsCOMArray<nsIStyleSheet> &aNewSheets) 1.499 +{ 1.500 + mSheets[aType].Clear(); 1.501 + if (!mSheets[aType].AppendObjects(aNewSheets)) 1.502 + return NS_ERROR_OUT_OF_MEMORY; 1.503 + 1.504 + return DirtyRuleProcessors(aType); 1.505 +} 1.506 + 1.507 +nsresult 1.508 +nsStyleSet::InsertStyleSheetBefore(sheetType aType, nsIStyleSheet *aNewSheet, 1.509 + nsIStyleSheet *aReferenceSheet) 1.510 +{ 1.511 + NS_PRECONDITION(aNewSheet && aReferenceSheet, "null arg"); 1.512 + NS_ASSERTION(aNewSheet->IsApplicable(), 1.513 + "Inapplicable sheet being placed in style set"); 1.514 + 1.515 + mSheets[aType].RemoveObject(aNewSheet); 1.516 + int32_t idx = mSheets[aType].IndexOf(aReferenceSheet); 1.517 + if (idx < 0) 1.518 + return NS_ERROR_INVALID_ARG; 1.519 + 1.520 + if (!mSheets[aType].InsertObjectAt(aNewSheet, idx)) 1.521 + return NS_ERROR_OUT_OF_MEMORY; 1.522 + 1.523 + return DirtyRuleProcessors(aType); 1.524 +} 1.525 + 1.526 +nsresult 1.527 +nsStyleSet::DirtyRuleProcessors(sheetType aType) 1.528 +{ 1.529 + if (!mBatching) 1.530 + return GatherRuleProcessors(aType); 1.531 + 1.532 + mDirty |= 1 << aType; 1.533 + return NS_OK; 1.534 +} 1.535 + 1.536 +bool 1.537 +nsStyleSet::GetAuthorStyleDisabled() 1.538 +{ 1.539 + return mAuthorStyleDisabled; 1.540 +} 1.541 + 1.542 +nsresult 1.543 +nsStyleSet::SetAuthorStyleDisabled(bool aStyleDisabled) 1.544 +{ 1.545 + if (aStyleDisabled == !mAuthorStyleDisabled) { 1.546 + mAuthorStyleDisabled = aStyleDisabled; 1.547 + BeginUpdate(); 1.548 + mDirty |= 1 << eDocSheet | 1.549 + 1 << eScopedDocSheet | 1.550 + 1 << eStyleAttrSheet; 1.551 + return EndUpdate(); 1.552 + } 1.553 + return NS_OK; 1.554 +} 1.555 + 1.556 +// -------- Doc Sheets 1.557 + 1.558 +nsresult 1.559 +nsStyleSet::AddDocStyleSheet(nsIStyleSheet* aSheet, nsIDocument* aDocument) 1.560 +{ 1.561 + NS_PRECONDITION(aSheet && aDocument, "null arg"); 1.562 + NS_ASSERTION(aSheet->IsApplicable(), 1.563 + "Inapplicable sheet being placed in style set"); 1.564 + 1.565 + sheetType type = IsScopedStyleSheet(aSheet) ? 1.566 + eScopedDocSheet : 1.567 + eDocSheet; 1.568 + nsCOMArray<nsIStyleSheet>& sheets = mSheets[type]; 1.569 + 1.570 + sheets.RemoveObject(aSheet); 1.571 + nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance(); 1.572 + 1.573 + // lowest index first 1.574 + int32_t newDocIndex = aDocument->GetIndexOfStyleSheet(aSheet); 1.575 + 1.576 + int32_t count = sheets.Count(); 1.577 + int32_t index; 1.578 + for (index = 0; index < count; index++) { 1.579 + nsIStyleSheet* sheet = sheets.ObjectAt(index); 1.580 + int32_t sheetDocIndex = aDocument->GetIndexOfStyleSheet(sheet); 1.581 + if (sheetDocIndex > newDocIndex) 1.582 + break; 1.583 + 1.584 + // If the sheet is not owned by the document it can be an author 1.585 + // sheet registered at nsStyleSheetService or an additional author 1.586 + // sheet on the document, which means the new 1.587 + // doc sheet should end up before it. 1.588 + if (sheetDocIndex < 0 && 1.589 + ((sheetService && 1.590 + sheetService->AuthorStyleSheets()->IndexOf(sheet) >= 0) || 1.591 + sheet == aDocument->FirstAdditionalAuthorSheet())) 1.592 + break; 1.593 + } 1.594 + if (!sheets.InsertObjectAt(aSheet, index)) 1.595 + return NS_ERROR_OUT_OF_MEMORY; 1.596 + 1.597 + return DirtyRuleProcessors(type); 1.598 +} 1.599 + 1.600 +nsresult 1.601 +nsStyleSet::RemoveDocStyleSheet(nsIStyleSheet *aSheet) 1.602 +{ 1.603 + nsRefPtr<nsCSSStyleSheet> cssSheet = do_QueryObject(aSheet); 1.604 + bool isScoped = cssSheet && cssSheet->GetScopeElement(); 1.605 + return RemoveStyleSheet(isScoped ? eScopedDocSheet : eDocSheet, aSheet); 1.606 +} 1.607 + 1.608 +// Batching 1.609 +void 1.610 +nsStyleSet::BeginUpdate() 1.611 +{ 1.612 + ++mBatching; 1.613 +} 1.614 + 1.615 +nsresult 1.616 +nsStyleSet::EndUpdate() 1.617 +{ 1.618 + NS_ASSERTION(mBatching > 0, "Unbalanced EndUpdate"); 1.619 + if (--mBatching) { 1.620 + // We're not completely done yet. 1.621 + return NS_OK; 1.622 + } 1.623 + 1.624 + for (int i = 0; i < eSheetTypeCount; ++i) { 1.625 + if (mDirty & (1 << i)) { 1.626 + nsresult rv = GatherRuleProcessors(sheetType(i)); 1.627 + NS_ENSURE_SUCCESS(rv, rv); 1.628 + } 1.629 + } 1.630 + 1.631 + mDirty = 0; 1.632 + return NS_OK; 1.633 +} 1.634 + 1.635 +void 1.636 +nsStyleSet::EnableQuirkStyleSheet(bool aEnable) 1.637 +{ 1.638 +#ifdef DEBUG 1.639 + bool oldEnabled; 1.640 + { 1.641 + nsCOMPtr<nsIDOMCSSStyleSheet> domSheet = 1.642 + do_QueryInterface(mQuirkStyleSheet); 1.643 + domSheet->GetDisabled(&oldEnabled); 1.644 + oldEnabled = !oldEnabled; 1.645 + } 1.646 +#endif 1.647 + mQuirkStyleSheet->SetEnabled(aEnable); 1.648 +#ifdef DEBUG 1.649 + // This should always be OK, since SetEnabled should call 1.650 + // ClearRuleCascades. 1.651 + // Note that we can hit this codepath multiple times when document.open() 1.652 + // (potentially implied) happens multiple times. 1.653 + if (mRuleProcessors[eAgentSheet] && aEnable != oldEnabled) { 1.654 + static_cast<nsCSSRuleProcessor*>(static_cast<nsIStyleRuleProcessor*>( 1.655 + mRuleProcessors[eAgentSheet]))->AssertQuirksChangeOK(); 1.656 + } 1.657 +#endif 1.658 +} 1.659 + 1.660 +template<class T> 1.661 +static bool 1.662 +EnumRulesMatching(nsIStyleRuleProcessor* aProcessor, void* aData) 1.663 +{ 1.664 + T* data = static_cast<T*>(aData); 1.665 + aProcessor->RulesMatching(data); 1.666 + return true; 1.667 +} 1.668 + 1.669 +static inline bool 1.670 +IsMoreSpecificThanAnimation(nsRuleNode *aRuleNode) 1.671 +{ 1.672 + return !aRuleNode->IsRoot() && 1.673 + (aRuleNode->GetLevel() == nsStyleSet::eTransitionSheet || 1.674 + aRuleNode->IsImportantRule()); 1.675 +} 1.676 + 1.677 +static nsIStyleRule* 1.678 +GetAnimationRule(nsRuleNode *aRuleNode) 1.679 +{ 1.680 + nsRuleNode *n = aRuleNode; 1.681 + while (IsMoreSpecificThanAnimation(n)) { 1.682 + n = n->GetParent(); 1.683 + } 1.684 + 1.685 + if (n->IsRoot() || n->GetLevel() != nsStyleSet::eAnimationSheet) { 1.686 + return nullptr; 1.687 + } 1.688 + 1.689 + return n->GetRule(); 1.690 +} 1.691 + 1.692 +static nsRuleNode* 1.693 +ReplaceAnimationRule(nsRuleNode *aOldRuleNode, 1.694 + nsIStyleRule *aOldAnimRule, 1.695 + nsIStyleRule *aNewAnimRule) 1.696 +{ 1.697 + nsTArray<nsRuleNode*> moreSpecificNodes; 1.698 + 1.699 + nsRuleNode *n = aOldRuleNode; 1.700 + while (IsMoreSpecificThanAnimation(n)) { 1.701 + moreSpecificNodes.AppendElement(n); 1.702 + n = n->GetParent(); 1.703 + } 1.704 + 1.705 + if (aOldAnimRule) { 1.706 + NS_ABORT_IF_FALSE(n->GetRule() == aOldAnimRule, "wrong rule"); 1.707 + NS_ABORT_IF_FALSE(n->GetLevel() == nsStyleSet::eAnimationSheet, 1.708 + "wrong level"); 1.709 + n = n->GetParent(); 1.710 + } 1.711 + 1.712 + NS_ABORT_IF_FALSE(!IsMoreSpecificThanAnimation(n) && 1.713 + (n->IsRoot() || 1.714 + n->GetLevel() != nsStyleSet::eAnimationSheet), 1.715 + "wrong level"); 1.716 + 1.717 + if (aNewAnimRule) { 1.718 + n = n->Transition(aNewAnimRule, nsStyleSet::eAnimationSheet, false); 1.719 + } 1.720 + 1.721 + for (uint32_t i = moreSpecificNodes.Length(); i-- != 0; ) { 1.722 + nsRuleNode *oldNode = moreSpecificNodes[i]; 1.723 + n = n->Transition(oldNode->GetRule(), oldNode->GetLevel(), 1.724 + oldNode->IsImportantRule()); 1.725 + } 1.726 + 1.727 + return n; 1.728 +} 1.729 + 1.730 +/** 1.731 + * |GetContext| implements sharing of style contexts (not just the data 1.732 + * on the rule nodes) between siblings and cousins of the same 1.733 + * generation. (It works for cousins of the same generation since 1.734 + * |aParentContext| could itself be a shared context.) 1.735 + */ 1.736 +already_AddRefed<nsStyleContext> 1.737 +nsStyleSet::GetContext(nsStyleContext* aParentContext, 1.738 + nsRuleNode* aRuleNode, 1.739 + // aVisitedRuleNode may be null; if it is null 1.740 + // it means that we don't need to force creation 1.741 + // of a StyleIfVisited. (But if we make one 1.742 + // because aParentContext has one, then aRuleNode 1.743 + // should be used.) 1.744 + nsRuleNode* aVisitedRuleNode, 1.745 + nsIAtom* aPseudoTag, 1.746 + nsCSSPseudoElements::Type aPseudoType, 1.747 + Element* aElementForAnimation, 1.748 + uint32_t aFlags) 1.749 +{ 1.750 + NS_PRECONDITION((!aPseudoTag && 1.751 + aPseudoType == 1.752 + nsCSSPseudoElements::ePseudo_NotPseudoElement) || 1.753 + (aPseudoTag && 1.754 + nsCSSPseudoElements::GetPseudoType(aPseudoTag) == 1.755 + aPseudoType), 1.756 + "Pseudo mismatch"); 1.757 + 1.758 + if (aVisitedRuleNode == aRuleNode) { 1.759 + // No need to force creation of a visited style in this case. 1.760 + aVisitedRuleNode = nullptr; 1.761 + } 1.762 + 1.763 + // Ensure |aVisitedRuleNode != nullptr| corresponds to the need to 1.764 + // create an if-visited style context, and that in that case, we have 1.765 + // parentIfVisited set correctly. 1.766 + nsStyleContext *parentIfVisited = 1.767 + aParentContext ? aParentContext->GetStyleIfVisited() : nullptr; 1.768 + if (parentIfVisited) { 1.769 + if (!aVisitedRuleNode) { 1.770 + aVisitedRuleNode = aRuleNode; 1.771 + } 1.772 + } else { 1.773 + if (aVisitedRuleNode) { 1.774 + parentIfVisited = aParentContext; 1.775 + } 1.776 + } 1.777 + 1.778 + if (aFlags & eIsLink) { 1.779 + // If this node is a link, we want its visited's style context's 1.780 + // parent to be the regular style context of its parent, because 1.781 + // only the visitedness of the relevant link should influence style. 1.782 + parentIfVisited = aParentContext; 1.783 + } 1.784 + 1.785 + nsRefPtr<nsStyleContext> result; 1.786 + if (aParentContext) 1.787 + result = aParentContext->FindChildWithRules(aPseudoTag, aRuleNode, 1.788 + aVisitedRuleNode, 1.789 + aFlags & eIsVisitedLink); 1.790 + 1.791 +#ifdef NOISY_DEBUG 1.792 + if (result) 1.793 + fprintf(stdout, "--- SharedSC %d ---\n", ++gSharedCount); 1.794 + else 1.795 + fprintf(stdout, "+++ NewSC %d +++\n", ++gNewCount); 1.796 +#endif 1.797 + 1.798 + if (!result) { 1.799 + result = NS_NewStyleContext(aParentContext, aPseudoTag, aPseudoType, 1.800 + aRuleNode, aFlags & eSkipFlexItemStyleFixup); 1.801 + if (aVisitedRuleNode) { 1.802 + nsRefPtr<nsStyleContext> resultIfVisited = 1.803 + NS_NewStyleContext(parentIfVisited, aPseudoTag, aPseudoType, 1.804 + aVisitedRuleNode, 1.805 + aFlags & eSkipFlexItemStyleFixup); 1.806 + if (!parentIfVisited) { 1.807 + mRoots.AppendElement(resultIfVisited); 1.808 + } 1.809 + resultIfVisited->SetIsStyleIfVisited(); 1.810 + result->SetStyleIfVisited(resultIfVisited.forget()); 1.811 + 1.812 + bool relevantLinkVisited = (aFlags & eIsLink) ? 1.813 + (aFlags & eIsVisitedLink) : 1.814 + (aParentContext && aParentContext->RelevantLinkVisited()); 1.815 + 1.816 + if (relevantLinkVisited) { 1.817 + result->AddStyleBit(NS_STYLE_RELEVANT_LINK_VISITED); 1.818 + } 1.819 + } 1.820 + if (!aParentContext) { 1.821 + mRoots.AppendElement(result); 1.822 + } 1.823 + } 1.824 + else { 1.825 + NS_ASSERTION(result->GetPseudoType() == aPseudoType, "Unexpected type"); 1.826 + NS_ASSERTION(result->GetPseudo() == aPseudoTag, "Unexpected pseudo"); 1.827 + } 1.828 + 1.829 + if (aFlags & eDoAnimation) { 1.830 + // Normally the animation manager has already added the correct 1.831 + // style rule. However, if the animation-name just changed, it 1.832 + // might have been wrong. So ask it to double-check based on the 1.833 + // resulting style context. 1.834 + nsIStyleRule *oldAnimRule = GetAnimationRule(aRuleNode); 1.835 + nsIStyleRule *animRule = PresContext()->AnimationManager()-> 1.836 + CheckAnimationRule(result, aElementForAnimation); 1.837 + NS_ABORT_IF_FALSE(result->RuleNode() == aRuleNode, 1.838 + "unexpected rule node"); 1.839 + NS_ABORT_IF_FALSE(!result->GetStyleIfVisited() == !aVisitedRuleNode, 1.840 + "unexpected visited rule node"); 1.841 + NS_ABORT_IF_FALSE(!aVisitedRuleNode || 1.842 + result->GetStyleIfVisited()->RuleNode() == 1.843 + aVisitedRuleNode, 1.844 + "unexpected visited rule node"); 1.845 + NS_ABORT_IF_FALSE(!aVisitedRuleNode || 1.846 + oldAnimRule == GetAnimationRule(aVisitedRuleNode), 1.847 + "animation rule mismatch between rule nodes"); 1.848 + if (oldAnimRule != animRule) { 1.849 + nsRuleNode *ruleNode = 1.850 + ReplaceAnimationRule(aRuleNode, oldAnimRule, animRule); 1.851 + nsRuleNode *visitedRuleNode = aVisitedRuleNode 1.852 + ? ReplaceAnimationRule(aVisitedRuleNode, oldAnimRule, animRule) 1.853 + : nullptr; 1.854 + NS_ABORT_IF_FALSE(!visitedRuleNode || 1.855 + GetAnimationRule(ruleNode) == 1.856 + GetAnimationRule(visitedRuleNode), 1.857 + "animation rule mismatch between rule nodes"); 1.858 + result = GetContext(aParentContext, ruleNode, visitedRuleNode, 1.859 + aPseudoTag, aPseudoType, nullptr, 1.860 + aFlags & ~eDoAnimation); 1.861 + } 1.862 + } 1.863 + 1.864 + if (aElementForAnimation && aElementForAnimation->IsHTML(nsGkAtoms::body) && 1.865 + aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement && 1.866 + PresContext()->CompatibilityMode() == eCompatibility_NavQuirks) { 1.867 + nsIDocument* doc = aElementForAnimation->GetCurrentDoc(); 1.868 + if (doc && doc->GetBodyElement() == aElementForAnimation) { 1.869 + // Update the prescontext's body color 1.870 + PresContext()->SetBodyTextColor(result->StyleColor()->mColor); 1.871 + } 1.872 + } 1.873 + 1.874 + return result.forget(); 1.875 +} 1.876 + 1.877 +void 1.878 +nsStyleSet::AddImportantRules(nsRuleNode* aCurrLevelNode, 1.879 + nsRuleNode* aLastPrevLevelNode, 1.880 + nsRuleWalker* aRuleWalker) 1.881 +{ 1.882 + NS_ASSERTION(aCurrLevelNode && 1.883 + aCurrLevelNode != aLastPrevLevelNode, "How did we get here?"); 1.884 + 1.885 + nsAutoTArray<nsIStyleRule*, 16> importantRules; 1.886 + for (nsRuleNode *node = aCurrLevelNode; node != aLastPrevLevelNode; 1.887 + node = node->GetParent()) { 1.888 + // We guarantee that we never walk the root node here, so no need 1.889 + // to null-check GetRule(). Furthermore, it must be a CSS rule. 1.890 + NS_ASSERTION(nsRefPtr<css::StyleRule>(do_QueryObject(node->GetRule())), 1.891 + "Unexpected non-CSS rule"); 1.892 + 1.893 + nsIStyleRule* impRule = 1.894 + static_cast<css::StyleRule*>(node->GetRule())->GetImportantRule(); 1.895 + if (impRule) 1.896 + importantRules.AppendElement(impRule); 1.897 + } 1.898 + 1.899 + NS_ASSERTION(importantRules.Length() != 0, 1.900 + "Why did we think there were important rules?"); 1.901 + 1.902 + for (uint32_t i = importantRules.Length(); i-- != 0; ) { 1.903 + aRuleWalker->Forward(importantRules[i]); 1.904 + } 1.905 +} 1.906 + 1.907 +#ifdef DEBUG 1.908 +void 1.909 +nsStyleSet::AssertNoImportantRules(nsRuleNode* aCurrLevelNode, 1.910 + nsRuleNode* aLastPrevLevelNode) 1.911 +{ 1.912 + if (!aCurrLevelNode) 1.913 + return; 1.914 + 1.915 + for (nsRuleNode *node = aCurrLevelNode; node != aLastPrevLevelNode; 1.916 + node = node->GetParent()) { 1.917 + nsRefPtr<css::StyleRule> rule(do_QueryObject(node->GetRule())); 1.918 + NS_ASSERTION(rule, "Unexpected non-CSS rule"); 1.919 + 1.920 + NS_ASSERTION(!rule->GetImportantRule(), "Unexpected important rule"); 1.921 + } 1.922 +} 1.923 + 1.924 +void 1.925 +nsStyleSet::AssertNoCSSRules(nsRuleNode* aCurrLevelNode, 1.926 + nsRuleNode* aLastPrevLevelNode) 1.927 +{ 1.928 + if (!aCurrLevelNode) 1.929 + return; 1.930 + 1.931 + for (nsRuleNode *node = aCurrLevelNode; node != aLastPrevLevelNode; 1.932 + node = node->GetParent()) { 1.933 + nsIStyleRule *rule = node->GetRule(); 1.934 + nsRefPtr<css::StyleRule> cssRule(do_QueryObject(rule)); 1.935 + NS_ASSERTION(!cssRule || !cssRule->Selector(), "Unexpected CSS rule"); 1.936 + } 1.937 +} 1.938 +#endif 1.939 + 1.940 +// Enumerate the rules in a way that cares about the order of the rules. 1.941 +void 1.942 +nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc, 1.943 + RuleProcessorData* aData, Element* aElement, 1.944 + nsRuleWalker* aRuleWalker) 1.945 +{ 1.946 + PROFILER_LABEL("nsStyleSet", "FileRules"); 1.947 + 1.948 + // Cascading order: 1.949 + // [least important] 1.950 + // - UA normal rules = Agent normal 1.951 + // - User normal rules = User normal 1.952 + // - Presentation hints = PresHint normal 1.953 + // - Author normal rules = Document normal 1.954 + // - Override normal rules = Override normal 1.955 + // - animation rules = Animation normal 1.956 + // - Author !important rules = Document !important 1.957 + // - Override !important rules = Override !important 1.958 + // - User !important rules = User !important 1.959 + // - UA !important rules = Agent !important 1.960 + // - transition rules = Transition normal 1.961 + // [most important] 1.962 + 1.963 + // Save off the last rule before we start walking our agent sheets; 1.964 + // this will be either the root or one of the restriction rules. 1.965 + nsRuleNode* lastRestrictionRN = aRuleWalker->CurrentNode(); 1.966 + 1.967 + aRuleWalker->SetLevel(eAgentSheet, false, true); 1.968 + if (mRuleProcessors[eAgentSheet]) 1.969 + (*aCollectorFunc)(mRuleProcessors[eAgentSheet], aData); 1.970 + nsRuleNode* lastAgentRN = aRuleWalker->CurrentNode(); 1.971 + bool haveImportantUARules = !aRuleWalker->GetCheckForImportantRules(); 1.972 + 1.973 + aRuleWalker->SetLevel(eUserSheet, false, true); 1.974 + bool skipUserStyles = 1.975 + aElement && aElement->IsInNativeAnonymousSubtree(); 1.976 + if (!skipUserStyles && mRuleProcessors[eUserSheet]) // NOTE: different 1.977 + (*aCollectorFunc)(mRuleProcessors[eUserSheet], aData); 1.978 + nsRuleNode* lastUserRN = aRuleWalker->CurrentNode(); 1.979 + bool haveImportantUserRules = !aRuleWalker->GetCheckForImportantRules(); 1.980 + 1.981 + aRuleWalker->SetLevel(ePresHintSheet, false, false); 1.982 + if (mRuleProcessors[ePresHintSheet]) 1.983 + (*aCollectorFunc)(mRuleProcessors[ePresHintSheet], aData); 1.984 + nsRuleNode* lastPresHintRN = aRuleWalker->CurrentNode(); 1.985 + 1.986 + aRuleWalker->SetLevel(eDocSheet, false, true); 1.987 + bool cutOffInheritance = false; 1.988 + if (mBindingManager && aElement) { 1.989 + // We can supply additional document-level sheets that should be walked. 1.990 + mBindingManager->WalkRules(aCollectorFunc, 1.991 + static_cast<ElementDependentRuleProcessorData*>(aData), 1.992 + &cutOffInheritance); 1.993 + } 1.994 + if (!skipUserStyles && !cutOffInheritance && // NOTE: different 1.995 + mRuleProcessors[eDocSheet]) 1.996 + (*aCollectorFunc)(mRuleProcessors[eDocSheet], aData); 1.997 + nsRuleNode* lastDocRN = aRuleWalker->CurrentNode(); 1.998 + bool haveImportantDocRules = !aRuleWalker->GetCheckForImportantRules(); 1.999 + nsTArray<nsRuleNode*> lastScopedRNs; 1.1000 + nsTArray<bool> haveImportantScopedRules; 1.1001 + bool haveAnyImportantScopedRules = false; 1.1002 + if (!skipUserStyles && !cutOffInheritance && 1.1003 + aElement && aElement->IsElementInStyleScope()) { 1.1004 + lastScopedRNs.SetLength(mScopedDocSheetRuleProcessors.Length()); 1.1005 + haveImportantScopedRules.SetLength(mScopedDocSheetRuleProcessors.Length()); 1.1006 + for (uint32_t i = 0; i < mScopedDocSheetRuleProcessors.Length(); i++) { 1.1007 + aRuleWalker->SetLevel(eScopedDocSheet, false, true); 1.1008 + nsCSSRuleProcessor* processor = 1.1009 + static_cast<nsCSSRuleProcessor*>(mScopedDocSheetRuleProcessors[i].get()); 1.1010 + aData->mScope = processor->GetScopeElement(); 1.1011 + (*aCollectorFunc)(mScopedDocSheetRuleProcessors[i], aData); 1.1012 + lastScopedRNs[i] = aRuleWalker->CurrentNode(); 1.1013 + haveImportantScopedRules[i] = !aRuleWalker->GetCheckForImportantRules(); 1.1014 + haveAnyImportantScopedRules = haveAnyImportantScopedRules || haveImportantScopedRules[i]; 1.1015 + } 1.1016 + aData->mScope = nullptr; 1.1017 + } 1.1018 + nsRuleNode* lastScopedRN = aRuleWalker->CurrentNode(); 1.1019 + aRuleWalker->SetLevel(eStyleAttrSheet, false, true); 1.1020 + if (mRuleProcessors[eStyleAttrSheet]) 1.1021 + (*aCollectorFunc)(mRuleProcessors[eStyleAttrSheet], aData); 1.1022 + nsRuleNode* lastStyleAttrRN = aRuleWalker->CurrentNode(); 1.1023 + bool haveImportantStyleAttrRules = !aRuleWalker->GetCheckForImportantRules(); 1.1024 + 1.1025 + aRuleWalker->SetLevel(eOverrideSheet, false, true); 1.1026 + if (mRuleProcessors[eOverrideSheet]) 1.1027 + (*aCollectorFunc)(mRuleProcessors[eOverrideSheet], aData); 1.1028 + nsRuleNode* lastOvrRN = aRuleWalker->CurrentNode(); 1.1029 + bool haveImportantOverrideRules = !aRuleWalker->GetCheckForImportantRules(); 1.1030 + 1.1031 + // This needs to match IsMoreSpecificThanAnimation() above. 1.1032 + aRuleWalker->SetLevel(eAnimationSheet, false, false); 1.1033 + (*aCollectorFunc)(mRuleProcessors[eAnimationSheet], aData); 1.1034 + 1.1035 + if (haveAnyImportantScopedRules) { 1.1036 + for (uint32_t i = lastScopedRNs.Length(); i-- != 0; ) { 1.1037 + aRuleWalker->SetLevel(eScopedDocSheet, true, false); 1.1038 + nsRuleNode* startRN = lastScopedRNs[i]; 1.1039 + nsRuleNode* endRN = i == 0 ? lastDocRN : lastScopedRNs[i - 1]; 1.1040 + if (haveImportantScopedRules[i]) { 1.1041 + AddImportantRules(startRN, endRN, aRuleWalker); // scoped 1.1042 + } 1.1043 +#ifdef DEBUG 1.1044 + else { 1.1045 + AssertNoImportantRules(startRN, endRN); 1.1046 + } 1.1047 +#endif 1.1048 + } 1.1049 + } 1.1050 +#ifdef DEBUG 1.1051 + else { 1.1052 + AssertNoImportantRules(lastScopedRN, lastDocRN); 1.1053 + } 1.1054 +#endif 1.1055 + 1.1056 + if (haveImportantDocRules) { 1.1057 + aRuleWalker->SetLevel(eDocSheet, true, false); 1.1058 + AddImportantRules(lastDocRN, lastPresHintRN, aRuleWalker); // doc 1.1059 + } 1.1060 +#ifdef DEBUG 1.1061 + else { 1.1062 + AssertNoImportantRules(lastDocRN, lastPresHintRN); 1.1063 + } 1.1064 +#endif 1.1065 + 1.1066 + if (haveImportantStyleAttrRules) { 1.1067 + aRuleWalker->SetLevel(eStyleAttrSheet, true, false); 1.1068 + AddImportantRules(lastStyleAttrRN, lastScopedRN, aRuleWalker); // style attr 1.1069 + } 1.1070 +#ifdef DEBUG 1.1071 + else { 1.1072 + AssertNoImportantRules(lastStyleAttrRN, lastScopedRN); 1.1073 + } 1.1074 +#endif 1.1075 + 1.1076 + if (haveImportantOverrideRules) { 1.1077 + aRuleWalker->SetLevel(eOverrideSheet, true, false); 1.1078 + AddImportantRules(lastOvrRN, lastStyleAttrRN, aRuleWalker); // override 1.1079 + } 1.1080 +#ifdef DEBUG 1.1081 + else { 1.1082 + AssertNoImportantRules(lastOvrRN, lastStyleAttrRN); 1.1083 + } 1.1084 +#endif 1.1085 + 1.1086 +#ifdef DEBUG 1.1087 + AssertNoCSSRules(lastPresHintRN, lastUserRN); 1.1088 +#endif 1.1089 + 1.1090 + if (haveImportantUserRules) { 1.1091 + aRuleWalker->SetLevel(eUserSheet, true, false); 1.1092 + AddImportantRules(lastUserRN, lastAgentRN, aRuleWalker); //user 1.1093 + } 1.1094 +#ifdef DEBUG 1.1095 + else { 1.1096 + AssertNoImportantRules(lastUserRN, lastAgentRN); 1.1097 + } 1.1098 +#endif 1.1099 + 1.1100 + if (haveImportantUARules) { 1.1101 + aRuleWalker->SetLevel(eAgentSheet, true, false); 1.1102 + AddImportantRules(lastAgentRN, lastRestrictionRN, aRuleWalker); //agent 1.1103 + } 1.1104 +#ifdef DEBUG 1.1105 + else { 1.1106 + AssertNoImportantRules(lastAgentRN, lastRestrictionRN); 1.1107 + } 1.1108 +#endif 1.1109 + 1.1110 +#ifdef DEBUG 1.1111 + AssertNoCSSRules(lastRestrictionRN, mRuleTree); 1.1112 +#endif 1.1113 + 1.1114 +#ifdef DEBUG 1.1115 + nsRuleNode *lastImportantRN = aRuleWalker->CurrentNode(); 1.1116 +#endif 1.1117 + aRuleWalker->SetLevel(eTransitionSheet, false, false); 1.1118 + (*aCollectorFunc)(mRuleProcessors[eTransitionSheet], aData); 1.1119 +#ifdef DEBUG 1.1120 + AssertNoCSSRules(aRuleWalker->CurrentNode(), lastImportantRN); 1.1121 +#endif 1.1122 + 1.1123 +} 1.1124 + 1.1125 +// Enumerate all the rules in a way that doesn't care about the order 1.1126 +// of the rules and doesn't walk !important-rules. 1.1127 +void 1.1128 +nsStyleSet::WalkRuleProcessors(nsIStyleRuleProcessor::EnumFunc aFunc, 1.1129 + ElementDependentRuleProcessorData* aData, 1.1130 + bool aWalkAllXBLStylesheets) 1.1131 +{ 1.1132 + if (mRuleProcessors[eAgentSheet]) 1.1133 + (*aFunc)(mRuleProcessors[eAgentSheet], aData); 1.1134 + 1.1135 + bool skipUserStyles = aData->mElement->IsInNativeAnonymousSubtree(); 1.1136 + if (!skipUserStyles && mRuleProcessors[eUserSheet]) // NOTE: different 1.1137 + (*aFunc)(mRuleProcessors[eUserSheet], aData); 1.1138 + 1.1139 + if (mRuleProcessors[ePresHintSheet]) 1.1140 + (*aFunc)(mRuleProcessors[ePresHintSheet], aData); 1.1141 + 1.1142 + bool cutOffInheritance = false; 1.1143 + if (mBindingManager) { 1.1144 + // We can supply additional document-level sheets that should be walked. 1.1145 + if (aWalkAllXBLStylesheets) { 1.1146 + mBindingManager->WalkAllRules(aFunc, aData); 1.1147 + } else { 1.1148 + mBindingManager->WalkRules(aFunc, aData, &cutOffInheritance); 1.1149 + } 1.1150 + } 1.1151 + if (!skipUserStyles && !cutOffInheritance) { 1.1152 + if (mRuleProcessors[eDocSheet]) // NOTE: different 1.1153 + (*aFunc)(mRuleProcessors[eDocSheet], aData); 1.1154 + if (aData->mElement->IsElementInStyleScope()) { 1.1155 + for (uint32_t i = 0; i < mScopedDocSheetRuleProcessors.Length(); i++) 1.1156 + (*aFunc)(mScopedDocSheetRuleProcessors[i], aData); 1.1157 + } 1.1158 + } 1.1159 + if (mRuleProcessors[eStyleAttrSheet]) 1.1160 + (*aFunc)(mRuleProcessors[eStyleAttrSheet], aData); 1.1161 + if (mRuleProcessors[eOverrideSheet]) 1.1162 + (*aFunc)(mRuleProcessors[eOverrideSheet], aData); 1.1163 + (*aFunc)(mRuleProcessors[eAnimationSheet], aData); 1.1164 + (*aFunc)(mRuleProcessors[eTransitionSheet], aData); 1.1165 +} 1.1166 + 1.1167 +static void 1.1168 +InitStyleScopes(TreeMatchContext& aTreeContext, Element* aElement) 1.1169 +{ 1.1170 + if (aElement->IsElementInStyleScope()) { 1.1171 + aTreeContext.InitStyleScopes(aElement->GetParentElement()); 1.1172 + } 1.1173 +} 1.1174 + 1.1175 +already_AddRefed<nsStyleContext> 1.1176 +nsStyleSet::ResolveStyleFor(Element* aElement, 1.1177 + nsStyleContext* aParentContext) 1.1178 +{ 1.1179 + TreeMatchContext treeContext(true, nsRuleWalker::eRelevantLinkUnvisited, 1.1180 + aElement->OwnerDoc()); 1.1181 + InitStyleScopes(treeContext, aElement); 1.1182 + return ResolveStyleFor(aElement, aParentContext, treeContext); 1.1183 +} 1.1184 + 1.1185 +already_AddRefed<nsStyleContext> 1.1186 +nsStyleSet::ResolveStyleFor(Element* aElement, 1.1187 + nsStyleContext* aParentContext, 1.1188 + TreeMatchContext& aTreeMatchContext) 1.1189 +{ 1.1190 + NS_ENSURE_FALSE(mInShutdown, nullptr); 1.1191 + NS_ASSERTION(aElement, "aElement must not be null"); 1.1192 + 1.1193 + nsRuleWalker ruleWalker(mRuleTree, mAuthorStyleDisabled); 1.1194 + aTreeMatchContext.ResetForUnvisitedMatching(); 1.1195 + ElementRuleProcessorData data(PresContext(), aElement, &ruleWalker, 1.1196 + aTreeMatchContext); 1.1197 + WalkDisableTextZoomRule(aElement, &ruleWalker); 1.1198 + FileRules(EnumRulesMatching<ElementRuleProcessorData>, &data, aElement, 1.1199 + &ruleWalker); 1.1200 + 1.1201 + nsRuleNode *ruleNode = ruleWalker.CurrentNode(); 1.1202 + nsRuleNode *visitedRuleNode = nullptr; 1.1203 + 1.1204 + if (aTreeMatchContext.HaveRelevantLink()) { 1.1205 + aTreeMatchContext.ResetForVisitedMatching(); 1.1206 + ruleWalker.Reset(); 1.1207 + FileRules(EnumRulesMatching<ElementRuleProcessorData>, &data, aElement, 1.1208 + &ruleWalker); 1.1209 + visitedRuleNode = ruleWalker.CurrentNode(); 1.1210 + } 1.1211 + 1.1212 + uint32_t flags = eDoAnimation; 1.1213 + if (nsCSSRuleProcessor::IsLink(aElement)) { 1.1214 + flags |= eIsLink; 1.1215 + } 1.1216 + if (nsCSSRuleProcessor::GetContentState(aElement, aTreeMatchContext). 1.1217 + HasState(NS_EVENT_STATE_VISITED)) { 1.1218 + flags |= eIsVisitedLink; 1.1219 + } 1.1220 + if (aTreeMatchContext.mSkippingFlexItemStyleFixup) { 1.1221 + flags |= eSkipFlexItemStyleFixup; 1.1222 + } 1.1223 + 1.1224 + return GetContext(aParentContext, ruleNode, visitedRuleNode, 1.1225 + nullptr, nsCSSPseudoElements::ePseudo_NotPseudoElement, 1.1226 + aElement, flags); 1.1227 +} 1.1228 + 1.1229 +already_AddRefed<nsStyleContext> 1.1230 +nsStyleSet::ResolveStyleForRules(nsStyleContext* aParentContext, 1.1231 + const nsTArray< nsCOMPtr<nsIStyleRule> > &aRules) 1.1232 +{ 1.1233 + NS_ENSURE_FALSE(mInShutdown, nullptr); 1.1234 + 1.1235 + nsRuleWalker ruleWalker(mRuleTree, mAuthorStyleDisabled); 1.1236 + // FIXME: Perhaps this should be passed in, but it probably doesn't 1.1237 + // matter. 1.1238 + ruleWalker.SetLevel(eDocSheet, false, false); 1.1239 + for (uint32_t i = 0; i < aRules.Length(); i++) { 1.1240 + ruleWalker.ForwardOnPossiblyCSSRule(aRules.ElementAt(i)); 1.1241 + } 1.1242 + 1.1243 + return GetContext(aParentContext, ruleWalker.CurrentNode(), nullptr, 1.1244 + nullptr, nsCSSPseudoElements::ePseudo_NotPseudoElement, 1.1245 + nullptr, eNoFlags); 1.1246 +} 1.1247 + 1.1248 +already_AddRefed<nsStyleContext> 1.1249 +nsStyleSet::ResolveStyleForRules(nsStyleContext* aParentContext, 1.1250 + nsStyleContext* aOldStyle, 1.1251 + const nsTArray<RuleAndLevel>& aRules) 1.1252 +{ 1.1253 + nsRuleWalker ruleWalker(mRuleTree, mAuthorStyleDisabled); 1.1254 + for (int32_t i = aRules.Length() - 1; i >= 0; --i) { 1.1255 + ruleWalker.SetLevel(aRules[i].mLevel, false, false); 1.1256 + ruleWalker.ForwardOnPossiblyCSSRule(aRules[i].mRule); 1.1257 + } 1.1258 + 1.1259 + uint32_t flags = eNoFlags; 1.1260 + if (aOldStyle->IsLinkContext()) { 1.1261 + flags |= eIsLink; 1.1262 + } 1.1263 + if (aOldStyle->RelevantLinkVisited()) { 1.1264 + flags |= eIsVisitedLink; 1.1265 + } 1.1266 + 1.1267 + return GetContext(aParentContext, ruleWalker.CurrentNode(), nullptr, 1.1268 + nullptr, nsCSSPseudoElements::ePseudo_NotPseudoElement, 1.1269 + nullptr, flags); 1.1270 +} 1.1271 + 1.1272 +already_AddRefed<nsStyleContext> 1.1273 +nsStyleSet::ResolveStyleByAddingRules(nsStyleContext* aBaseContext, 1.1274 + const nsCOMArray<nsIStyleRule> &aRules) 1.1275 +{ 1.1276 + NS_ENSURE_FALSE(mInShutdown, nullptr); 1.1277 + 1.1278 + nsRuleWalker ruleWalker(mRuleTree, mAuthorStyleDisabled); 1.1279 + ruleWalker.SetCurrentNode(aBaseContext->RuleNode()); 1.1280 + // FIXME: Perhaps this should be passed in, but it probably doesn't 1.1281 + // matter. 1.1282 + ruleWalker.SetLevel(eDocSheet, false, false); 1.1283 + for (int32_t i = 0; i < aRules.Count(); i++) { 1.1284 + ruleWalker.ForwardOnPossiblyCSSRule(aRules.ObjectAt(i)); 1.1285 + } 1.1286 + 1.1287 + nsRuleNode *ruleNode = ruleWalker.CurrentNode(); 1.1288 + nsRuleNode *visitedRuleNode = nullptr; 1.1289 + 1.1290 + if (aBaseContext->GetStyleIfVisited()) { 1.1291 + ruleWalker.SetCurrentNode(aBaseContext->GetStyleIfVisited()->RuleNode()); 1.1292 + for (int32_t i = 0; i < aRules.Count(); i++) { 1.1293 + ruleWalker.ForwardOnPossiblyCSSRule(aRules.ObjectAt(i)); 1.1294 + } 1.1295 + visitedRuleNode = ruleWalker.CurrentNode(); 1.1296 + } 1.1297 + 1.1298 + uint32_t flags = eNoFlags; 1.1299 + if (aBaseContext->IsLinkContext()) { 1.1300 + flags |= eIsLink; 1.1301 + } 1.1302 + if (aBaseContext->RelevantLinkVisited()) { 1.1303 + flags |= eIsVisitedLink; 1.1304 + } 1.1305 + return GetContext(aBaseContext->GetParent(), ruleNode, visitedRuleNode, 1.1306 + aBaseContext->GetPseudo(), 1.1307 + aBaseContext->GetPseudoType(), 1.1308 + nullptr, flags); 1.1309 +} 1.1310 + 1.1311 +already_AddRefed<nsStyleContext> 1.1312 +nsStyleSet::ResolveStyleForNonElement(nsStyleContext* aParentContext) 1.1313 +{ 1.1314 + return GetContext(aParentContext, mRuleTree, nullptr, 1.1315 + nsCSSAnonBoxes::mozNonElement, 1.1316 + nsCSSPseudoElements::ePseudo_AnonBox, nullptr, 1.1317 + eNoFlags); 1.1318 +} 1.1319 + 1.1320 +void 1.1321 +nsStyleSet::WalkRestrictionRule(nsCSSPseudoElements::Type aPseudoType, 1.1322 + nsRuleWalker* aRuleWalker) 1.1323 +{ 1.1324 + // This needs to match GetPseudoRestriction in nsRuleNode.cpp. 1.1325 + aRuleWalker->SetLevel(eAgentSheet, false, false); 1.1326 + if (aPseudoType == nsCSSPseudoElements::ePseudo_firstLetter) 1.1327 + aRuleWalker->Forward(mFirstLetterRule); 1.1328 + else if (aPseudoType == nsCSSPseudoElements::ePseudo_firstLine) 1.1329 + aRuleWalker->Forward(mFirstLineRule); 1.1330 + else if (aPseudoType == nsCSSPseudoElements::ePseudo_mozPlaceholder) 1.1331 + aRuleWalker->Forward(mPlaceholderRule); 1.1332 +} 1.1333 + 1.1334 +void 1.1335 +nsStyleSet::WalkDisableTextZoomRule(Element* aElement, nsRuleWalker* aRuleWalker) 1.1336 +{ 1.1337 + aRuleWalker->SetLevel(eAgentSheet, false, false); 1.1338 + if (aElement->IsSVG(nsGkAtoms::text)) 1.1339 + aRuleWalker->Forward(mDisableTextZoomStyleRule); 1.1340 +} 1.1341 + 1.1342 +already_AddRefed<nsStyleContext> 1.1343 +nsStyleSet::ResolvePseudoElementStyle(Element* aParentElement, 1.1344 + nsCSSPseudoElements::Type aType, 1.1345 + nsStyleContext* aParentContext, 1.1346 + Element* aPseudoElement) 1.1347 +{ 1.1348 + NS_ENSURE_FALSE(mInShutdown, nullptr); 1.1349 + 1.1350 + NS_ASSERTION(aType < nsCSSPseudoElements::ePseudo_PseudoElementCount, 1.1351 + "must have pseudo element type"); 1.1352 + NS_ASSERTION(aParentElement, "Must have parent element"); 1.1353 + 1.1354 + nsRuleWalker ruleWalker(mRuleTree, mAuthorStyleDisabled); 1.1355 + TreeMatchContext treeContext(true, nsRuleWalker::eRelevantLinkUnvisited, 1.1356 + aParentElement->OwnerDoc()); 1.1357 + InitStyleScopes(treeContext, aParentElement); 1.1358 + PseudoElementRuleProcessorData data(PresContext(), aParentElement, 1.1359 + &ruleWalker, aType, treeContext, 1.1360 + aPseudoElement); 1.1361 + WalkRestrictionRule(aType, &ruleWalker); 1.1362 + FileRules(EnumRulesMatching<PseudoElementRuleProcessorData>, &data, 1.1363 + aParentElement, &ruleWalker); 1.1364 + 1.1365 + nsRuleNode *ruleNode = ruleWalker.CurrentNode(); 1.1366 + nsRuleNode *visitedRuleNode = nullptr; 1.1367 + 1.1368 + if (treeContext.HaveRelevantLink()) { 1.1369 + treeContext.ResetForVisitedMatching(); 1.1370 + ruleWalker.Reset(); 1.1371 + WalkRestrictionRule(aType, &ruleWalker); 1.1372 + FileRules(EnumRulesMatching<PseudoElementRuleProcessorData>, &data, 1.1373 + aParentElement, &ruleWalker); 1.1374 + visitedRuleNode = ruleWalker.CurrentNode(); 1.1375 + } 1.1376 + 1.1377 + // For pseudos, |data.IsLink()| being true means that 1.1378 + // our parent node is a link. 1.1379 + uint32_t flags = eNoFlags; 1.1380 + if (aType == nsCSSPseudoElements::ePseudo_before || 1.1381 + aType == nsCSSPseudoElements::ePseudo_after) { 1.1382 + flags |= eDoAnimation; 1.1383 + } else { 1.1384 + // Flex containers don't expect to have any pseudo-element children aside 1.1385 + // from ::before and ::after. So if we have such a child, we're not 1.1386 + // actually in a flex container, and we should skip flex-item style fixup. 1.1387 + flags |= eSkipFlexItemStyleFixup; 1.1388 + } 1.1389 + 1.1390 + return GetContext(aParentContext, ruleNode, visitedRuleNode, 1.1391 + nsCSSPseudoElements::GetPseudoAtom(aType), aType, 1.1392 + aParentElement, flags); 1.1393 +} 1.1394 + 1.1395 +already_AddRefed<nsStyleContext> 1.1396 +nsStyleSet::ProbePseudoElementStyle(Element* aParentElement, 1.1397 + nsCSSPseudoElements::Type aType, 1.1398 + nsStyleContext* aParentContext) 1.1399 +{ 1.1400 + TreeMatchContext treeContext(true, nsRuleWalker::eRelevantLinkUnvisited, 1.1401 + aParentElement->OwnerDoc()); 1.1402 + InitStyleScopes(treeContext, aParentElement); 1.1403 + return ProbePseudoElementStyle(aParentElement, aType, aParentContext, 1.1404 + treeContext); 1.1405 +} 1.1406 + 1.1407 +already_AddRefed<nsStyleContext> 1.1408 +nsStyleSet::ProbePseudoElementStyle(Element* aParentElement, 1.1409 + nsCSSPseudoElements::Type aType, 1.1410 + nsStyleContext* aParentContext, 1.1411 + TreeMatchContext& aTreeMatchContext, 1.1412 + Element* aPseudoElement) 1.1413 +{ 1.1414 + NS_ENSURE_FALSE(mInShutdown, nullptr); 1.1415 + 1.1416 + NS_ASSERTION(aType < nsCSSPseudoElements::ePseudo_PseudoElementCount, 1.1417 + "must have pseudo element type"); 1.1418 + NS_ASSERTION(aParentElement, "aParentElement must not be null"); 1.1419 + 1.1420 + nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType); 1.1421 + nsRuleWalker ruleWalker(mRuleTree, mAuthorStyleDisabled); 1.1422 + aTreeMatchContext.ResetForUnvisitedMatching(); 1.1423 + PseudoElementRuleProcessorData data(PresContext(), aParentElement, 1.1424 + &ruleWalker, aType, aTreeMatchContext, 1.1425 + aPseudoElement); 1.1426 + WalkRestrictionRule(aType, &ruleWalker); 1.1427 + // not the root if there was a restriction rule 1.1428 + nsRuleNode *adjustedRoot = ruleWalker.CurrentNode(); 1.1429 + FileRules(EnumRulesMatching<PseudoElementRuleProcessorData>, &data, 1.1430 + aParentElement, &ruleWalker); 1.1431 + 1.1432 + nsRuleNode *ruleNode = ruleWalker.CurrentNode(); 1.1433 + if (ruleNode == adjustedRoot) { 1.1434 + return nullptr; 1.1435 + } 1.1436 + 1.1437 + nsRuleNode *visitedRuleNode = nullptr; 1.1438 + 1.1439 + if (aTreeMatchContext.HaveRelevantLink()) { 1.1440 + aTreeMatchContext.ResetForVisitedMatching(); 1.1441 + ruleWalker.Reset(); 1.1442 + WalkRestrictionRule(aType, &ruleWalker); 1.1443 + FileRules(EnumRulesMatching<PseudoElementRuleProcessorData>, &data, 1.1444 + aParentElement, &ruleWalker); 1.1445 + visitedRuleNode = ruleWalker.CurrentNode(); 1.1446 + } 1.1447 + 1.1448 + // For pseudos, |data.IsLink()| being true means that 1.1449 + // our parent node is a link. 1.1450 + uint32_t flags = eNoFlags; 1.1451 + if (aType == nsCSSPseudoElements::ePseudo_before || 1.1452 + aType == nsCSSPseudoElements::ePseudo_after) { 1.1453 + flags |= eDoAnimation; 1.1454 + } else { 1.1455 + // Flex containers don't expect to have any pseudo-element children aside 1.1456 + // from ::before and ::after. So if we have such a child, we're not 1.1457 + // actually in a flex container, and we should skip flex-item style fixup. 1.1458 + flags |= eSkipFlexItemStyleFixup; 1.1459 + } 1.1460 + 1.1461 + nsRefPtr<nsStyleContext> result = 1.1462 + GetContext(aParentContext, ruleNode, visitedRuleNode, 1.1463 + pseudoTag, aType, 1.1464 + aParentElement, flags); 1.1465 + 1.1466 + // For :before and :after pseudo-elements, having display: none or no 1.1467 + // 'content' property is equivalent to not having the pseudo-element 1.1468 + // at all. 1.1469 + if (result && 1.1470 + (pseudoTag == nsCSSPseudoElements::before || 1.1471 + pseudoTag == nsCSSPseudoElements::after)) { 1.1472 + const nsStyleDisplay *display = result->StyleDisplay(); 1.1473 + const nsStyleContent *content = result->StyleContent(); 1.1474 + // XXXldb What is contentCount for |content: ""|? 1.1475 + if (display->mDisplay == NS_STYLE_DISPLAY_NONE || 1.1476 + content->ContentCount() == 0) { 1.1477 + result = nullptr; 1.1478 + } 1.1479 + } 1.1480 + 1.1481 + return result.forget(); 1.1482 +} 1.1483 + 1.1484 +already_AddRefed<nsStyleContext> 1.1485 +nsStyleSet::ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag, 1.1486 + nsStyleContext* aParentContext) 1.1487 +{ 1.1488 + NS_ENSURE_FALSE(mInShutdown, nullptr); 1.1489 + 1.1490 +#ifdef DEBUG 1.1491 + bool isAnonBox = nsCSSAnonBoxes::IsAnonBox(aPseudoTag) 1.1492 +#ifdef MOZ_XUL 1.1493 + && !nsCSSAnonBoxes::IsTreePseudoElement(aPseudoTag) 1.1494 +#endif 1.1495 + ; 1.1496 + NS_PRECONDITION(isAnonBox, "Unexpected pseudo"); 1.1497 +#endif 1.1498 + 1.1499 + nsRuleWalker ruleWalker(mRuleTree, mAuthorStyleDisabled); 1.1500 + AnonBoxRuleProcessorData data(PresContext(), aPseudoTag, &ruleWalker); 1.1501 + FileRules(EnumRulesMatching<AnonBoxRuleProcessorData>, &data, nullptr, 1.1502 + &ruleWalker); 1.1503 + 1.1504 + if (aPseudoTag == nsCSSAnonBoxes::pageContent) { 1.1505 + // Add any @page rules that are specified. 1.1506 + nsTArray<nsCSSPageRule*> rules; 1.1507 + nsTArray<css::ImportantRule*> importantRules; 1.1508 + nsPresContext* presContext = PresContext(); 1.1509 + presContext->StyleSet()->AppendPageRules(presContext, rules); 1.1510 + for (uint32_t i = 0, i_end = rules.Length(); i != i_end; ++i) { 1.1511 + ruleWalker.Forward(rules[i]); 1.1512 + css::ImportantRule* importantRule = rules[i]->GetImportantRule(); 1.1513 + if (importantRule) { 1.1514 + importantRules.AppendElement(importantRule); 1.1515 + } 1.1516 + } 1.1517 + for (uint32_t i = 0, i_end = importantRules.Length(); i != i_end; ++i) { 1.1518 + ruleWalker.Forward(importantRules[i]); 1.1519 + } 1.1520 + } 1.1521 + 1.1522 + return GetContext(aParentContext, ruleWalker.CurrentNode(), nullptr, 1.1523 + aPseudoTag, nsCSSPseudoElements::ePseudo_AnonBox, 1.1524 + nullptr, eNoFlags); 1.1525 +} 1.1526 + 1.1527 +#ifdef MOZ_XUL 1.1528 +already_AddRefed<nsStyleContext> 1.1529 +nsStyleSet::ResolveXULTreePseudoStyle(Element* aParentElement, 1.1530 + nsIAtom* aPseudoTag, 1.1531 + nsStyleContext* aParentContext, 1.1532 + nsICSSPseudoComparator* aComparator) 1.1533 +{ 1.1534 + NS_ENSURE_FALSE(mInShutdown, nullptr); 1.1535 + 1.1536 + NS_ASSERTION(aPseudoTag, "must have pseudo tag"); 1.1537 + NS_ASSERTION(nsCSSAnonBoxes::IsTreePseudoElement(aPseudoTag), 1.1538 + "Unexpected pseudo"); 1.1539 + 1.1540 + nsRuleWalker ruleWalker(mRuleTree, mAuthorStyleDisabled); 1.1541 + TreeMatchContext treeContext(true, nsRuleWalker::eRelevantLinkUnvisited, 1.1542 + aParentElement->OwnerDoc()); 1.1543 + InitStyleScopes(treeContext, aParentElement); 1.1544 + XULTreeRuleProcessorData data(PresContext(), aParentElement, &ruleWalker, 1.1545 + aPseudoTag, aComparator, treeContext); 1.1546 + FileRules(EnumRulesMatching<XULTreeRuleProcessorData>, &data, aParentElement, 1.1547 + &ruleWalker); 1.1548 + 1.1549 + nsRuleNode *ruleNode = ruleWalker.CurrentNode(); 1.1550 + nsRuleNode *visitedRuleNode = nullptr; 1.1551 + 1.1552 + if (treeContext.HaveRelevantLink()) { 1.1553 + treeContext.ResetForVisitedMatching(); 1.1554 + ruleWalker.Reset(); 1.1555 + FileRules(EnumRulesMatching<XULTreeRuleProcessorData>, &data, 1.1556 + aParentElement, &ruleWalker); 1.1557 + visitedRuleNode = ruleWalker.CurrentNode(); 1.1558 + } 1.1559 + 1.1560 + return GetContext(aParentContext, ruleNode, visitedRuleNode, 1.1561 + // For pseudos, |data.IsLink()| being true means that 1.1562 + // our parent node is a link. 1.1563 + aPseudoTag, nsCSSPseudoElements::ePseudo_XULTree, 1.1564 + nullptr, eNoFlags); 1.1565 +} 1.1566 +#endif 1.1567 + 1.1568 +bool 1.1569 +nsStyleSet::AppendFontFaceRules(nsPresContext* aPresContext, 1.1570 + nsTArray<nsFontFaceRuleContainer>& aArray) 1.1571 +{ 1.1572 + NS_ENSURE_FALSE(mInShutdown, false); 1.1573 + 1.1574 + for (uint32_t i = 0; i < ArrayLength(gCSSSheetTypes); ++i) { 1.1575 + if (gCSSSheetTypes[i] == eScopedDocSheet) 1.1576 + continue; 1.1577 + nsCSSRuleProcessor *ruleProc = static_cast<nsCSSRuleProcessor*> 1.1578 + (mRuleProcessors[gCSSSheetTypes[i]].get()); 1.1579 + if (ruleProc && !ruleProc->AppendFontFaceRules(aPresContext, aArray)) 1.1580 + return false; 1.1581 + } 1.1582 + return true; 1.1583 +} 1.1584 + 1.1585 +nsCSSKeyframesRule* 1.1586 +nsStyleSet::KeyframesRuleForName(nsPresContext* aPresContext, 1.1587 + const nsString& aName) 1.1588 +{ 1.1589 + NS_ENSURE_FALSE(mInShutdown, nullptr); 1.1590 + 1.1591 + for (uint32_t i = ArrayLength(gCSSSheetTypes); i-- != 0; ) { 1.1592 + if (gCSSSheetTypes[i] == eScopedDocSheet) 1.1593 + continue; 1.1594 + nsCSSRuleProcessor *ruleProc = static_cast<nsCSSRuleProcessor*> 1.1595 + (mRuleProcessors[gCSSSheetTypes[i]].get()); 1.1596 + if (!ruleProc) 1.1597 + continue; 1.1598 + nsCSSKeyframesRule* result = 1.1599 + ruleProc->KeyframesRuleForName(aPresContext, aName); 1.1600 + if (result) 1.1601 + return result; 1.1602 + } 1.1603 + return nullptr; 1.1604 +} 1.1605 + 1.1606 +bool 1.1607 +nsStyleSet::AppendFontFeatureValuesRules(nsPresContext* aPresContext, 1.1608 + nsTArray<nsCSSFontFeatureValuesRule*>& aArray) 1.1609 +{ 1.1610 + NS_ENSURE_FALSE(mInShutdown, false); 1.1611 + 1.1612 + for (uint32_t i = 0; i < ArrayLength(gCSSSheetTypes); ++i) { 1.1613 + nsCSSRuleProcessor *ruleProc = static_cast<nsCSSRuleProcessor*> 1.1614 + (mRuleProcessors[gCSSSheetTypes[i]].get()); 1.1615 + if (ruleProc && 1.1616 + !ruleProc->AppendFontFeatureValuesRules(aPresContext, aArray)) 1.1617 + { 1.1618 + return false; 1.1619 + } 1.1620 + } 1.1621 + return true; 1.1622 +} 1.1623 + 1.1624 +already_AddRefed<gfxFontFeatureValueSet> 1.1625 +nsStyleSet::GetFontFeatureValuesLookup() 1.1626 +{ 1.1627 + if (mInitFontFeatureValuesLookup) { 1.1628 + mInitFontFeatureValuesLookup = false; 1.1629 + 1.1630 + nsTArray<nsCSSFontFeatureValuesRule*> rules; 1.1631 + AppendFontFeatureValuesRules(PresContext(), rules); 1.1632 + 1.1633 + mFontFeatureValuesLookup = new gfxFontFeatureValueSet(); 1.1634 + 1.1635 + uint32_t i, numRules = rules.Length(); 1.1636 + for (i = 0; i < numRules; i++) { 1.1637 + nsCSSFontFeatureValuesRule *rule = rules[i]; 1.1638 + 1.1639 + const nsTArray<nsString>& familyList = rule->GetFamilyList(); 1.1640 + const nsTArray<gfxFontFeatureValueSet::FeatureValues>& 1.1641 + featureValues = rule->GetFeatureValues(); 1.1642 + 1.1643 + // for each family 1.1644 + uint32_t f, numFam; 1.1645 + 1.1646 + numFam = familyList.Length(); 1.1647 + for (f = 0; f < numFam; f++) { 1.1648 + const nsString& family = familyList.ElementAt(f); 1.1649 + nsAutoString silly(family); 1.1650 + mFontFeatureValuesLookup->AddFontFeatureValues(silly, featureValues); 1.1651 + } 1.1652 + } 1.1653 + } 1.1654 + 1.1655 + nsRefPtr<gfxFontFeatureValueSet> lookup = mFontFeatureValuesLookup; 1.1656 + return lookup.forget(); 1.1657 +} 1.1658 + 1.1659 +bool 1.1660 +nsStyleSet::AppendPageRules(nsPresContext* aPresContext, 1.1661 + nsTArray<nsCSSPageRule*>& aArray) 1.1662 +{ 1.1663 + NS_ENSURE_FALSE(mInShutdown, false); 1.1664 + 1.1665 + for (uint32_t i = 0; i < ArrayLength(gCSSSheetTypes); ++i) { 1.1666 + if (gCSSSheetTypes[i] == eScopedDocSheet) 1.1667 + continue; 1.1668 + nsCSSRuleProcessor* ruleProc = static_cast<nsCSSRuleProcessor*> 1.1669 + (mRuleProcessors[gCSSSheetTypes[i]].get()); 1.1670 + if (ruleProc && !ruleProc->AppendPageRules(aPresContext, aArray)) 1.1671 + return false; 1.1672 + } 1.1673 + return true; 1.1674 +} 1.1675 + 1.1676 +void 1.1677 +nsStyleSet::BeginShutdown(nsPresContext* aPresContext) 1.1678 +{ 1.1679 + mInShutdown = 1; 1.1680 + mRoots.Clear(); // no longer valid, since we won't keep it up to date 1.1681 +} 1.1682 + 1.1683 +void 1.1684 +nsStyleSet::Shutdown(nsPresContext* aPresContext) 1.1685 +{ 1.1686 + mRuleTree->Destroy(); 1.1687 + mRuleTree = nullptr; 1.1688 + 1.1689 + // We can have old rule trees either because: 1.1690 + // (1) we failed the assertions in EndReconstruct, or 1.1691 + // (2) we're shutting down within a reconstruct (see bug 462392) 1.1692 + for (uint32_t i = mOldRuleTrees.Length(); i > 0; ) { 1.1693 + --i; 1.1694 + mOldRuleTrees[i]->Destroy(); 1.1695 + } 1.1696 + mOldRuleTrees.Clear(); 1.1697 +} 1.1698 + 1.1699 +static const uint32_t kGCInterval = 300; 1.1700 + 1.1701 +void 1.1702 +nsStyleSet::NotifyStyleContextDestroyed(nsPresContext* aPresContext, 1.1703 + nsStyleContext* aStyleContext) 1.1704 +{ 1.1705 + if (mInShutdown) 1.1706 + return; 1.1707 + 1.1708 + // Remove style contexts from mRoots even if mOldRuleTree is non-null. This 1.1709 + // could be a style context from the new ruletree! 1.1710 + if (!aStyleContext->GetParent()) { 1.1711 + mRoots.RemoveElement(aStyleContext); 1.1712 + } 1.1713 + 1.1714 + if (mInReconstruct) 1.1715 + return; 1.1716 + 1.1717 + if (mUnusedRuleNodeCount >= kGCInterval) { 1.1718 + GCRuleTrees(); 1.1719 + } 1.1720 +} 1.1721 + 1.1722 +void 1.1723 +nsStyleSet::GCRuleTrees() 1.1724 +{ 1.1725 + mUnusedRuleNodeCount = 0; 1.1726 + 1.1727 + // Mark the style context tree by marking all style contexts which 1.1728 + // have no parent, which will mark all descendants. This will reach 1.1729 + // style contexts in the undisplayed map and "additional style 1.1730 + // contexts" since they are descendants of the roots. 1.1731 + for (int32_t i = mRoots.Length() - 1; i >= 0; --i) { 1.1732 + mRoots[i]->Mark(); 1.1733 + } 1.1734 + 1.1735 + // Sweep the rule tree. 1.1736 +#ifdef DEBUG 1.1737 + bool deleted = 1.1738 +#endif 1.1739 + mRuleTree->Sweep(); 1.1740 + NS_ASSERTION(!deleted, "Root node must not be gc'd"); 1.1741 + 1.1742 + // Sweep the old rule trees. 1.1743 + for (uint32_t i = mOldRuleTrees.Length(); i > 0; ) { 1.1744 + --i; 1.1745 + if (mOldRuleTrees[i]->Sweep()) { 1.1746 + // It was deleted, as it should be. 1.1747 + mOldRuleTrees.RemoveElementAt(i); 1.1748 + } else { 1.1749 + NS_NOTREACHED("old rule tree still referenced"); 1.1750 + } 1.1751 + } 1.1752 +} 1.1753 + 1.1754 +/** 1.1755 + * Return an equivalent to aRuleNode with both animation and transition 1.1756 + * rules removed, and post a restyle if needed. 1.1757 + */ 1.1758 +static inline nsRuleNode* 1.1759 +SkipAnimationRules(nsRuleNode* aRuleNode, Element* aElement, bool isPseudo) 1.1760 +{ 1.1761 + nsRuleNode* ruleNode = aRuleNode; 1.1762 + // The transition rule must be at the top of the cascade. 1.1763 + if (!ruleNode->IsRoot() && 1.1764 + ruleNode->GetLevel() == nsStyleSet::eTransitionSheet) { 1.1765 + ruleNode = ruleNode->GetParent(); 1.1766 + } 1.1767 + NS_ABORT_IF_FALSE(ruleNode->IsRoot() || 1.1768 + ruleNode->GetLevel() != nsStyleSet::eTransitionSheet, 1.1769 + "can't have more than one transition rule"); 1.1770 + 1.1771 + // Use our existing ReplaceAnimationRule function to replace the 1.1772 + // animation rule, if present. 1.1773 + nsIStyleRule* animationRule = GetAnimationRule(ruleNode); 1.1774 + if (animationRule) { 1.1775 + ruleNode = ReplaceAnimationRule(ruleNode, animationRule, nullptr); 1.1776 + } 1.1777 + 1.1778 + if (ruleNode != aRuleNode) { 1.1779 + NS_ASSERTION(aElement, "How can we have transition rules but no element?"); 1.1780 + // Need to do an animation restyle, just like 1.1781 + // nsTransitionManager::WalkTransitionRule and 1.1782 + // nsAnimationManager::GetAnimationRule would. 1.1783 + nsRestyleHint hint = isPseudo ? eRestyle_Subtree : eRestyle_Self; 1.1784 + aRuleNode->PresContext()->PresShell()->RestyleForAnimation(aElement, hint); 1.1785 + } 1.1786 + return ruleNode; 1.1787 +} 1.1788 + 1.1789 +already_AddRefed<nsStyleContext> 1.1790 +nsStyleSet::ReparentStyleContext(nsStyleContext* aStyleContext, 1.1791 + nsStyleContext* aNewParentContext, 1.1792 + Element* aElement) 1.1793 +{ 1.1794 + MOZ_ASSERT(aStyleContext, "aStyleContext must not be null"); 1.1795 + 1.1796 + // This short-circuit is OK because we don't call TryStartingTransition 1.1797 + // during style reresolution if the style context pointer hasn't changed. 1.1798 + if (aStyleContext->GetParent() == aNewParentContext) { 1.1799 + nsRefPtr<nsStyleContext> ret = aStyleContext; 1.1800 + return ret.forget(); 1.1801 + } 1.1802 + 1.1803 + nsIAtom* pseudoTag = aStyleContext->GetPseudo(); 1.1804 + nsCSSPseudoElements::Type pseudoType = aStyleContext->GetPseudoType(); 1.1805 + nsRuleNode* ruleNode = aStyleContext->RuleNode(); 1.1806 + 1.1807 + // Skip transition rules as needed just like 1.1808 + // nsTransitionManager::WalkTransitionRule would. 1.1809 + bool skipAnimationRules = PresContext()->IsProcessingRestyles() && 1.1810 + !PresContext()->IsProcessingAnimationStyleChange(); 1.1811 + if (skipAnimationRules) { 1.1812 + // Make sure that we're not using transition rules or animation rules for 1.1813 + // our new style context. If we need them, an animation restyle will 1.1814 + // provide. 1.1815 + ruleNode = 1.1816 + SkipAnimationRules(ruleNode, aElement, 1.1817 + pseudoType != 1.1818 + nsCSSPseudoElements::ePseudo_NotPseudoElement); 1.1819 + } 1.1820 + 1.1821 + nsRuleNode* visitedRuleNode = nullptr; 1.1822 + nsStyleContext* visitedContext = aStyleContext->GetStyleIfVisited(); 1.1823 + // Reparenting a style context just changes where we inherit from, 1.1824 + // not what rules we match or what our DOM looks like. In 1.1825 + // particular, it doesn't change whether this is a style context for 1.1826 + // a link. 1.1827 + if (visitedContext) { 1.1828 + visitedRuleNode = visitedContext->RuleNode(); 1.1829 + // Again, skip transition rules as needed 1.1830 + if (skipAnimationRules) { 1.1831 + // FIXME do something here for animations? 1.1832 + visitedRuleNode = 1.1833 + SkipAnimationRules(visitedRuleNode, aElement, 1.1834 + pseudoType != 1.1835 + nsCSSPseudoElements::ePseudo_NotPseudoElement); 1.1836 + } 1.1837 + } 1.1838 + 1.1839 + uint32_t flags = eNoFlags; 1.1840 + if (aStyleContext->IsLinkContext()) { 1.1841 + flags |= eIsLink; 1.1842 + } 1.1843 + 1.1844 + // If we're a style context for a link, then we already know whether 1.1845 + // our relevant link is visited, since that does not depend on our 1.1846 + // parent. Otherwise, we need to match aNewParentContext. 1.1847 + bool relevantLinkVisited = aStyleContext->IsLinkContext() ? 1.1848 + aStyleContext->RelevantLinkVisited() : 1.1849 + aNewParentContext->RelevantLinkVisited(); 1.1850 + 1.1851 + if (relevantLinkVisited) { 1.1852 + flags |= eIsVisitedLink; 1.1853 + } 1.1854 + 1.1855 + if (pseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement || 1.1856 + pseudoType == nsCSSPseudoElements::ePseudo_before || 1.1857 + pseudoType == nsCSSPseudoElements::ePseudo_after) { 1.1858 + flags |= eDoAnimation; 1.1859 + } 1.1860 + 1.1861 + if (aElement && aElement->IsRootOfAnonymousSubtree()) { 1.1862 + // For anonymous subtree roots, don't tweak "display" value based on 1.1863 + // whether or not the parent is styled as a flex container. (If the parent 1.1864 + // has anonymous-subtree kids, then we know it's not actually going to get 1.1865 + // a flex container frame, anyway.) 1.1866 + flags |= eSkipFlexItemStyleFixup; 1.1867 + } 1.1868 + 1.1869 + return GetContext(aNewParentContext, ruleNode, visitedRuleNode, 1.1870 + pseudoTag, pseudoType, 1.1871 + aElement, flags); 1.1872 +} 1.1873 + 1.1874 +struct MOZ_STACK_CLASS StatefulData : public StateRuleProcessorData { 1.1875 + StatefulData(nsPresContext* aPresContext, Element* aElement, 1.1876 + EventStates aStateMask, TreeMatchContext& aTreeMatchContext) 1.1877 + : StateRuleProcessorData(aPresContext, aElement, aStateMask, 1.1878 + aTreeMatchContext), 1.1879 + mHint(nsRestyleHint(0)) 1.1880 + {} 1.1881 + nsRestyleHint mHint; 1.1882 +}; 1.1883 + 1.1884 +struct MOZ_STACK_CLASS StatefulPseudoElementData : public PseudoElementStateRuleProcessorData { 1.1885 + StatefulPseudoElementData(nsPresContext* aPresContext, Element* aElement, 1.1886 + EventStates aStateMask, nsCSSPseudoElements::Type aPseudoType, 1.1887 + TreeMatchContext& aTreeMatchContext, Element* aPseudoElement) 1.1888 + : PseudoElementStateRuleProcessorData(aPresContext, aElement, aStateMask, 1.1889 + aPseudoType, aTreeMatchContext, 1.1890 + aPseudoElement), 1.1891 + mHint(nsRestyleHint(0)) 1.1892 + {} 1.1893 + nsRestyleHint mHint; 1.1894 +}; 1.1895 + 1.1896 +static bool SheetHasDocumentStateStyle(nsIStyleRuleProcessor* aProcessor, 1.1897 + void *aData) 1.1898 +{ 1.1899 + StatefulData* data = (StatefulData*)aData; 1.1900 + if (aProcessor->HasDocumentStateDependentStyle(data)) { 1.1901 + data->mHint = eRestyle_Self; 1.1902 + return false; // don't continue 1.1903 + } 1.1904 + return true; // continue 1.1905 +} 1.1906 + 1.1907 +// Test if style is dependent on a document state. 1.1908 +bool 1.1909 +nsStyleSet::HasDocumentStateDependentStyle(nsPresContext* aPresContext, 1.1910 + nsIContent* aContent, 1.1911 + EventStates aStateMask) 1.1912 +{ 1.1913 + if (!aContent || !aContent->IsElement()) 1.1914 + return false; 1.1915 + 1.1916 + TreeMatchContext treeContext(false, nsRuleWalker::eLinksVisitedOrUnvisited, 1.1917 + aContent->OwnerDoc()); 1.1918 + InitStyleScopes(treeContext, aContent->AsElement()); 1.1919 + StatefulData data(aPresContext, aContent->AsElement(), aStateMask, 1.1920 + treeContext); 1.1921 + WalkRuleProcessors(SheetHasDocumentStateStyle, &data, true); 1.1922 + return data.mHint != 0; 1.1923 +} 1.1924 + 1.1925 +static bool SheetHasStatefulStyle(nsIStyleRuleProcessor* aProcessor, 1.1926 + void *aData) 1.1927 +{ 1.1928 + StatefulData* data = (StatefulData*)aData; 1.1929 + nsRestyleHint hint = aProcessor->HasStateDependentStyle(data); 1.1930 + data->mHint = nsRestyleHint(data->mHint | hint); 1.1931 + return true; // continue 1.1932 +} 1.1933 + 1.1934 +static bool SheetHasStatefulPseudoElementStyle(nsIStyleRuleProcessor* aProcessor, 1.1935 + void *aData) 1.1936 +{ 1.1937 + StatefulPseudoElementData* data = (StatefulPseudoElementData*)aData; 1.1938 + nsRestyleHint hint = aProcessor->HasStateDependentStyle(data); 1.1939 + data->mHint = nsRestyleHint(data->mHint | hint); 1.1940 + return true; // continue 1.1941 +} 1.1942 + 1.1943 +// Test if style is dependent on content state 1.1944 +nsRestyleHint 1.1945 +nsStyleSet::HasStateDependentStyle(nsPresContext* aPresContext, 1.1946 + Element* aElement, 1.1947 + EventStates aStateMask) 1.1948 +{ 1.1949 + TreeMatchContext treeContext(false, nsRuleWalker::eLinksVisitedOrUnvisited, 1.1950 + aElement->OwnerDoc()); 1.1951 + InitStyleScopes(treeContext, aElement); 1.1952 + StatefulData data(aPresContext, aElement, aStateMask, treeContext); 1.1953 + WalkRuleProcessors(SheetHasStatefulStyle, &data, false); 1.1954 + return data.mHint; 1.1955 +} 1.1956 + 1.1957 +nsRestyleHint 1.1958 +nsStyleSet::HasStateDependentStyle(nsPresContext* aPresContext, 1.1959 + Element* aElement, 1.1960 + nsCSSPseudoElements::Type aPseudoType, 1.1961 + Element* aPseudoElement, 1.1962 + EventStates aStateMask) 1.1963 +{ 1.1964 + TreeMatchContext treeContext(false, nsRuleWalker::eLinksVisitedOrUnvisited, 1.1965 + aElement->OwnerDoc()); 1.1966 + InitStyleScopes(treeContext, aElement); 1.1967 + StatefulPseudoElementData data(aPresContext, aElement, aStateMask, 1.1968 + aPseudoType, treeContext, aPseudoElement); 1.1969 + WalkRuleProcessors(SheetHasStatefulPseudoElementStyle, &data, false); 1.1970 + return data.mHint; 1.1971 +} 1.1972 + 1.1973 +struct MOZ_STACK_CLASS AttributeData : public AttributeRuleProcessorData { 1.1974 + AttributeData(nsPresContext* aPresContext, 1.1975 + Element* aElement, nsIAtom* aAttribute, int32_t aModType, 1.1976 + bool aAttrHasChanged, TreeMatchContext& aTreeMatchContext) 1.1977 + : AttributeRuleProcessorData(aPresContext, aElement, aAttribute, aModType, 1.1978 + aAttrHasChanged, aTreeMatchContext), 1.1979 + mHint(nsRestyleHint(0)) 1.1980 + {} 1.1981 + nsRestyleHint mHint; 1.1982 +}; 1.1983 + 1.1984 +static bool 1.1985 +SheetHasAttributeStyle(nsIStyleRuleProcessor* aProcessor, void *aData) 1.1986 +{ 1.1987 + AttributeData* data = (AttributeData*)aData; 1.1988 + nsRestyleHint hint = aProcessor->HasAttributeDependentStyle(data); 1.1989 + data->mHint = nsRestyleHint(data->mHint | hint); 1.1990 + return true; // continue 1.1991 +} 1.1992 + 1.1993 +// Test if style is dependent on content state 1.1994 +nsRestyleHint 1.1995 +nsStyleSet::HasAttributeDependentStyle(nsPresContext* aPresContext, 1.1996 + Element* aElement, 1.1997 + nsIAtom* aAttribute, 1.1998 + int32_t aModType, 1.1999 + bool aAttrHasChanged) 1.2000 +{ 1.2001 + TreeMatchContext treeContext(false, nsRuleWalker::eLinksVisitedOrUnvisited, 1.2002 + aElement->OwnerDoc()); 1.2003 + InitStyleScopes(treeContext, aElement); 1.2004 + AttributeData data(aPresContext, aElement, aAttribute, 1.2005 + aModType, aAttrHasChanged, treeContext); 1.2006 + WalkRuleProcessors(SheetHasAttributeStyle, &data, false); 1.2007 + return data.mHint; 1.2008 +} 1.2009 + 1.2010 +bool 1.2011 +nsStyleSet::MediumFeaturesChanged(nsPresContext* aPresContext) 1.2012 +{ 1.2013 + // We can't use WalkRuleProcessors without a content node. 1.2014 + bool stylesChanged = false; 1.2015 + for (uint32_t i = 0; i < ArrayLength(mRuleProcessors); ++i) { 1.2016 + nsIStyleRuleProcessor *processor = mRuleProcessors[i]; 1.2017 + if (!processor) { 1.2018 + continue; 1.2019 + } 1.2020 + bool thisChanged = processor->MediumFeaturesChanged(aPresContext); 1.2021 + stylesChanged = stylesChanged || thisChanged; 1.2022 + } 1.2023 + for (uint32_t i = 0; i < mScopedDocSheetRuleProcessors.Length(); ++i) { 1.2024 + nsIStyleRuleProcessor *processor = mScopedDocSheetRuleProcessors[i]; 1.2025 + bool thisChanged = processor->MediumFeaturesChanged(aPresContext); 1.2026 + stylesChanged = stylesChanged || thisChanged; 1.2027 + } 1.2028 + 1.2029 + if (mBindingManager) { 1.2030 + bool thisChanged = false; 1.2031 + mBindingManager->MediumFeaturesChanged(aPresContext, &thisChanged); 1.2032 + stylesChanged = stylesChanged || thisChanged; 1.2033 + } 1.2034 + 1.2035 + return stylesChanged; 1.2036 +} 1.2037 + 1.2038 +nsCSSStyleSheet::EnsureUniqueInnerResult 1.2039 +nsStyleSet::EnsureUniqueInnerOnCSSSheets() 1.2040 +{ 1.2041 + nsAutoTArray<nsCSSStyleSheet*, 32> queue; 1.2042 + for (uint32_t i = 0; i < ArrayLength(gCSSSheetTypes); ++i) { 1.2043 + nsCOMArray<nsIStyleSheet> &sheets = mSheets[gCSSSheetTypes[i]]; 1.2044 + for (uint32_t j = 0, j_end = sheets.Count(); j < j_end; ++j) { 1.2045 + nsCSSStyleSheet *sheet = static_cast<nsCSSStyleSheet*>(sheets[j]); 1.2046 + queue.AppendElement(sheet); 1.2047 + } 1.2048 + } 1.2049 + 1.2050 + if (mBindingManager) { 1.2051 + mBindingManager->AppendAllSheets(queue); 1.2052 + } 1.2053 + 1.2054 + nsCSSStyleSheet::EnsureUniqueInnerResult res = 1.2055 + nsCSSStyleSheet::eUniqueInner_AlreadyUnique; 1.2056 + while (!queue.IsEmpty()) { 1.2057 + uint32_t idx = queue.Length() - 1; 1.2058 + nsCSSStyleSheet *sheet = queue[idx]; 1.2059 + queue.RemoveElementAt(idx); 1.2060 + 1.2061 + nsCSSStyleSheet::EnsureUniqueInnerResult sheetRes = 1.2062 + sheet->EnsureUniqueInner(); 1.2063 + if (sheetRes == nsCSSStyleSheet::eUniqueInner_ClonedInner) { 1.2064 + res = sheetRes; 1.2065 + } 1.2066 + 1.2067 + // Enqueue all the sheet's children. 1.2068 + sheet->AppendAllChildSheets(queue); 1.2069 + } 1.2070 + return res; 1.2071 +} 1.2072 + 1.2073 +nsIStyleRule* 1.2074 +nsStyleSet::InitialStyleRule() 1.2075 +{ 1.2076 + if (!mInitialStyleRule) { 1.2077 + mInitialStyleRule = new nsInitialStyleRule; 1.2078 + } 1.2079 + return mInitialStyleRule; 1.2080 +}