Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : /*
7 : * the container for the style sheets that apply to a presentation, and
8 : * the internal API that the style system exposes for creating (and
9 : * potentially re-creating) style contexts
10 : */
11 :
12 : #ifndef nsStyleSet_h_
13 : #define nsStyleSet_h_
14 :
15 : #include "mozilla/Attributes.h"
16 : #include "mozilla/StyleSheetInlines.h"
17 : #include "mozilla/EnumeratedArray.h"
18 : #include "mozilla/LinkedList.h"
19 : #include "mozilla/MemoryReporting.h"
20 : #include "mozilla/ServoTypes.h"
21 : #include "mozilla/SheetType.h"
22 :
23 : #include "nsIStyleRuleProcessor.h"
24 : #include "nsBindingManager.h"
25 : #include "nsRuleNode.h"
26 : #include "nsTArray.h"
27 : #include "nsCOMArray.h"
28 : #include "nsIStyleRule.h"
29 : #include "nsCSSAnonBoxes.h"
30 :
31 : class gfxFontFeatureValueSet;
32 : class nsCSSKeyframesRule;
33 : class nsCSSFontFeatureValuesRule;
34 : class nsCSSPageRule;
35 : class nsCSSCounterStyleRule;
36 : class nsICSSPseudoComparator;
37 : class nsRuleWalker;
38 : struct ElementDependentRuleProcessorData;
39 : struct nsFontFaceRuleContainer;
40 : struct TreeMatchContext;
41 :
42 : namespace mozilla {
43 : class CSSStyleSheet;
44 : enum class CSSPseudoElementType : uint8_t;
45 : class EventStates;
46 : namespace dom {
47 : class ShadowRoot;
48 : } // namespace dom
49 : } // namespace mozilla
50 :
51 84 : class nsEmptyStyleRule final : public nsIStyleRule
52 : {
53 : private:
54 12 : ~nsEmptyStyleRule() {}
55 :
56 : public:
57 : NS_DECL_ISUPPORTS
58 : virtual void MapRuleInfoInto(nsRuleData* aRuleData) override;
59 : virtual bool MightMapInheritedStyleData() override;
60 : virtual bool GetDiscretelyAnimatedCSSValue(nsCSSPropertyID aProperty,
61 : nsCSSValue* aValue) override;
62 : #ifdef DEBUG
63 : virtual void List(FILE* out = stdout, int32_t aIndent = 0) const override;
64 : #endif
65 : };
66 :
67 0 : class nsInitialStyleRule final : public nsIStyleRule
68 : {
69 : private:
70 0 : ~nsInitialStyleRule() {}
71 :
72 : public:
73 : NS_DECL_ISUPPORTS
74 : virtual void MapRuleInfoInto(nsRuleData* aRuleData) override;
75 : virtual bool MightMapInheritedStyleData() override;
76 : virtual bool GetDiscretelyAnimatedCSSValue(nsCSSPropertyID aProperty,
77 : nsCSSValue* aValue) override;
78 : #ifdef DEBUG
79 : virtual void List(FILE* out = stdout, int32_t aIndent = 0) const override;
80 : #endif
81 : };
82 :
83 28 : class nsDisableTextZoomStyleRule final : public nsIStyleRule
84 : {
85 : private:
86 4 : ~nsDisableTextZoomStyleRule() {}
87 :
88 : public:
89 : NS_DECL_ISUPPORTS
90 : virtual void MapRuleInfoInto(nsRuleData* aRuleData) override;
91 : virtual bool MightMapInheritedStyleData() override;
92 : virtual bool GetDiscretelyAnimatedCSSValue(nsCSSPropertyID aProperty,
93 : nsCSSValue* aValue) override;
94 : #ifdef DEBUG
95 : virtual void List(FILE* out = stdout, int32_t aIndent = 0) const override;
96 : #endif
97 : };
98 :
99 : // The style set object is created by the document viewer and ownership is
100 : // then handed off to the PresShell. Only the PresShell should delete a
101 : // style set.
102 :
103 : class nsStyleSet final
104 : {
105 : public:
106 : nsStyleSet();
107 : ~nsStyleSet();
108 :
109 : size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
110 :
111 : void Init(nsPresContext* aPresContext, nsBindingManager* aBindingManager);
112 :
113 1618 : nsRuleNode* GetRuleTree() { return mRuleTree; }
114 :
115 : // get a style context for a non-pseudo frame.
116 : already_AddRefed<nsStyleContext>
117 : ResolveStyleFor(mozilla::dom::Element* aElement,
118 : nsStyleContext* aParentContext);
119 :
120 : already_AddRefed<nsStyleContext>
121 299 : ResolveStyleFor(mozilla::dom::Element* aElement,
122 : nsStyleContext* aParentContext,
123 : mozilla::LazyComputeBehavior)
124 : {
125 299 : return ResolveStyleFor(aElement, aParentContext);
126 : }
127 :
128 : already_AddRefed<nsStyleContext>
129 : ResolveStyleFor(mozilla::dom::Element* aElement,
130 : nsStyleContext* aParentContext,
131 : TreeMatchContext& aTreeMatchContext);
132 :
133 : already_AddRefed<nsStyleContext>
134 878 : ResolveStyleFor(mozilla::dom::Element* aElement,
135 : nsStyleContext* aParentContext,
136 : mozilla::LazyComputeBehavior aMayCompute,
137 : TreeMatchContext& aTreeMatchContext)
138 : {
139 878 : return ResolveStyleFor(aElement, aParentContext, aTreeMatchContext);
140 : }
141 :
142 : // Get a style context (with the given parent) for the
143 : // sequence of style rules in the |aRules| array.
144 : already_AddRefed<nsStyleContext>
145 : ResolveStyleForRules(nsStyleContext* aParentContext,
146 : const nsTArray< nsCOMPtr<nsIStyleRule> > &aRules);
147 :
148 : // Get a style context that represents aBaseContext, but as though
149 : // it additionally matched the rules in the aRules array (in that
150 : // order, as more specific than any other rules).
151 : //
152 : // One of the following must hold:
153 : // 1. The resulting style context must be used only on a temporary
154 : // basis, and it must never be put into the style context tree
155 : // (and, in particular, we must never call
156 : // ResolveStyleWithReplacement with it as the old context, which
157 : // might happen if it is put in the style context tree), or
158 : // 2. The additional rules must be appropriate for the transitions
159 : // level of the cascade, which is the highest level of the cascade.
160 : // (This is the case for one current caller, the cover rule used
161 : // for CSS transitions.)
162 : already_AddRefed<nsStyleContext>
163 : ResolveStyleByAddingRules(nsStyleContext* aBaseContext,
164 : const nsCOMArray<nsIStyleRule> &aRules);
165 :
166 : // Resolve style by making replacements in the list of style rules as
167 : // described by aReplacements, but otherwise maintaining the status
168 : // quo.
169 : // aPseudoElement must follow the same rules as for
170 : // ResolvePseudoElementStyle, and be null for non-pseudo-element cases
171 : enum { // flags for aFlags
172 : // Skip starting CSS animations that result from the style.
173 : eSkipStartingAnimations = (1<<0),
174 : };
175 : already_AddRefed<nsStyleContext>
176 : ResolveStyleWithReplacement(mozilla::dom::Element* aElement,
177 : mozilla::dom::Element* aPseudoElement,
178 : nsStyleContext* aNewParentContext,
179 : nsStyleContext* aOldStyleContext,
180 : nsRestyleHint aReplacements,
181 : uint32_t aFlags = 0);
182 :
183 : // Resolve style by returning a style context with the specified
184 : // animation data removed. It is allowable to remove all animation
185 : // data with eRestyle_AllHintsWithAnimations, or by using any other
186 : // hints that are allowed by ResolveStyleWithReplacement.
187 : already_AddRefed<nsStyleContext>
188 : ResolveStyleByRemovingAnimation(mozilla::dom::Element* aElement,
189 : nsStyleContext* aStyleContext,
190 : nsRestyleHint aWhichToRemove);
191 :
192 : // Similar to the above, but resolving style without all animation data in
193 : // the first place.
194 : already_AddRefed<nsStyleContext>
195 : ResolveStyleWithoutAnimation(mozilla::dom::Element* aTarget,
196 : nsStyleContext* aParentContext);
197 :
198 : // Pseudo-element version of the above, ResolveStyleWithoutAnimation.
199 : already_AddRefed<nsStyleContext>
200 : ResolvePseudoElementStyleWithoutAnimation(
201 : mozilla::dom::Element* aParentElement,
202 : mozilla::CSSPseudoElementType aType,
203 : nsStyleContext* aParentContext,
204 : mozilla::dom::Element* aPseudoElement);
205 :
206 : // Get a style context for a text node (which no rules will match).
207 : //
208 : // The returned style context will have nsCSSAnonBoxes::mozText as its pseudo.
209 : //
210 : // (Perhaps mozText should go away and we shouldn't even create style
211 : // contexts for such content nodes, when text-combine-upright is not
212 : // present. However, not doing any rule matching for them is a first step.)
213 : already_AddRefed<nsStyleContext>
214 : ResolveStyleForText(nsIContent* aTextNode, nsStyleContext* aParentContext);
215 :
216 : // Get a style context for a first-letter continuation (which no rules will
217 : // match).
218 : //
219 : // The returned style context will have
220 : // nsCSSAnonBoxes::firstLetterContinuation as its pseudo.
221 : //
222 : // (Perhaps nsCSSAnonBoxes::firstLetterContinuation should go away and we
223 : // shouldn't even create style contexts for such frames. However, not doing
224 : // any rule matching for them is a first step. And right now we do use this
225 : // style context for some things)
226 : already_AddRefed<nsStyleContext>
227 : ResolveStyleForFirstLetterContinuation(nsStyleContext* aParentContext);
228 :
229 : // Get a style context for a placeholder frame (which no rules will match).
230 : //
231 : // The returned style context will have nsCSSAnonBoxes::oofPlaceholder as
232 : // its pseudo.
233 : //
234 : // (Perhaps nsCSSAnonBoxes::oofPlaceholder should go away and we shouldn't
235 : // even create style contexts for placeholders. However, not doing any rule
236 : // matching for them is a first step.)
237 : already_AddRefed<nsStyleContext>
238 : ResolveStyleForPlaceholder();
239 :
240 : // Get a style context for a pseudo-element. aParentElement must be
241 : // non-null. aPseudoID is the CSSPseudoElementType for the
242 : // pseudo-element. aPseudoElement must be non-null if the pseudo-element
243 : // type is one that allows user action pseudo-classes after it or allows
244 : // style attributes; otherwise, it is ignored.
245 : already_AddRefed<nsStyleContext>
246 : ResolvePseudoElementStyle(mozilla::dom::Element* aParentElement,
247 : mozilla::CSSPseudoElementType aType,
248 : nsStyleContext* aParentContext,
249 : mozilla::dom::Element* aPseudoElement);
250 :
251 : // This functions just like ResolvePseudoElementStyle except that it will
252 : // return nullptr if there are no explicit style rules for that
253 : // pseudo element.
254 : already_AddRefed<nsStyleContext>
255 : ProbePseudoElementStyle(mozilla::dom::Element* aParentElement,
256 : mozilla::CSSPseudoElementType aType,
257 : nsStyleContext* aParentContext);
258 : already_AddRefed<nsStyleContext>
259 : ProbePseudoElementStyle(mozilla::dom::Element* aParentElement,
260 : mozilla::CSSPseudoElementType aType,
261 : nsStyleContext* aParentContext,
262 : TreeMatchContext& aTreeMatchContext);
263 :
264 : /**
265 : * Bit-flags that can be passed to GetContext in its parameter 'aFlags'.
266 : */
267 : enum {
268 : eNoFlags = 0,
269 : eIsLink = 1 << 0,
270 : eIsVisitedLink = 1 << 1,
271 : eDoAnimation = 1 << 2,
272 :
273 : // Indicates that we should skip the flex/grid item specific chunk of
274 : // ApplyStyleFixups(). This is useful if our parent has "display: flex"
275 : // or "display: grid" but we can tell we're not going to honor that (e.g. if
276 : // it's the outer frame of a button widget, and we're the inline frame for
277 : // the button's label).
278 : eSkipParentDisplayBasedStyleFixup = 1 << 3
279 : };
280 :
281 : // Get a style context for an anonymous box. aPseudoTag is the pseudo-tag to
282 : // use and must be non-null. It must be an anon box, and must be one that
283 : // inherits style from the given aParentContext.
284 : already_AddRefed<nsStyleContext>
285 : ResolveInheritingAnonymousBoxStyle(nsIAtom* aPseudoTag,
286 : nsStyleContext* aParentContext);
287 :
288 : // Get a style context for an anonymous box that does not inherit style from
289 : // anything. aPseudoTag is the pseudo-tag to use and must be non-null. It
290 : // must be an anon box, and must be a non-inheriting one.
291 : already_AddRefed<nsStyleContext>
292 : ResolveNonInheritingAnonymousBoxStyle(nsIAtom* aPseudoTag);
293 :
294 : #ifdef MOZ_XUL
295 : // Get a style context for a XUL tree pseudo. aPseudoTag is the
296 : // pseudo-tag to use and must be non-null. aParentContent must be
297 : // non-null. aComparator must be non-null.
298 : already_AddRefed<nsStyleContext>
299 : ResolveXULTreePseudoStyle(mozilla::dom::Element* aParentElement,
300 : nsICSSAnonBoxPseudo* aPseudoTag,
301 : nsStyleContext* aParentContext,
302 : nsICSSPseudoComparator* aComparator);
303 : #endif
304 :
305 : // Append all the currently-active font face rules to aArray. Return
306 : // true for success and false for failure.
307 : bool AppendFontFaceRules(nsTArray<nsFontFaceRuleContainer>& aArray);
308 :
309 : // Return the winning (in the cascade) @keyframes rule for the given name.
310 : nsCSSKeyframesRule* KeyframesRuleForName(const nsString& aName);
311 :
312 : // Return the winning (in the cascade) @counter-style rule for the given name.
313 : nsCSSCounterStyleRule* CounterStyleRuleForName(nsIAtom* aName);
314 :
315 : // Fetch object for looking up font feature values
316 : already_AddRefed<gfxFontFeatureValueSet> GetFontFeatureValuesLookup();
317 :
318 : // Append all the currently-active font feature values rules to aArray.
319 : // Return true for success and false for failure.
320 : bool AppendFontFeatureValuesRules(
321 : nsTArray<nsCSSFontFeatureValuesRule*>& aArray);
322 :
323 : // Append all the currently-active page rules to aArray. Return
324 : // true for success and false for failure.
325 : bool AppendPageRules(nsTArray<nsCSSPageRule*>& aArray);
326 :
327 : // Begin ignoring style context destruction, to avoid lots of unnecessary
328 : // work on document teardown.
329 : void BeginShutdown();
330 :
331 : // Free all of the data associated with this style set.
332 : void Shutdown();
333 :
334 : // Notes that a style sheet has changed.
335 : void RecordStyleSheetChange(mozilla::CSSStyleSheet* aStyleSheet,
336 : mozilla::StyleSheet::ChangeType);
337 :
338 : // Notes that style sheets have changed in a shadow root.
339 : void RecordShadowStyleChange(mozilla::dom::ShadowRoot* aShadowRoot);
340 :
341 62 : bool StyleSheetsHaveChanged() const
342 : {
343 62 : return mStylesHaveChanged || !mChangedScopeStyleRoots.IsEmpty();
344 : }
345 :
346 : void InvalidateStyleForCSSRuleChanges();
347 :
348 : // Get a new style context that lives in a different parent
349 : // The new context will be the same as the old if the new parent is the
350 : // same as the old parent.
351 : // aElement should be non-null if this is a style context for an
352 : // element or pseudo-element; in the latter case it should be the
353 : // real element the pseudo-element is for.
354 : already_AddRefed<nsStyleContext>
355 : ReparentStyleContext(nsStyleContext* aStyleContext,
356 : nsStyleContext* aNewParentContext,
357 : mozilla::dom::Element* aElement);
358 :
359 : // Test if style is dependent on a document state.
360 : bool HasDocumentStateDependentStyle(nsIContent* aContent,
361 : mozilla::EventStates aStateMask);
362 :
363 : // Test if style is dependent on content state
364 : nsRestyleHint HasStateDependentStyle(mozilla::dom::Element* aElement,
365 : mozilla::EventStates aStateMask);
366 : nsRestyleHint HasStateDependentStyle(mozilla::dom::Element* aElement,
367 : mozilla::CSSPseudoElementType aPseudoType,
368 : mozilla::dom::Element* aPseudoElement,
369 : mozilla::EventStates aStateMask);
370 :
371 : // Test if style is dependent on the presence of an attribute.
372 : nsRestyleHint HasAttributeDependentStyle(mozilla::dom::Element* aElement,
373 : int32_t aNameSpaceID,
374 : nsIAtom* aAttribute,
375 : int32_t aModType,
376 : bool aAttrHasChanged,
377 : const nsAttrValue* aOtherValue,
378 : mozilla::RestyleHintData&
379 : aRestyleHintDataResult);
380 :
381 : /*
382 : * Do any processing that needs to happen as a result of a change in
383 : * the characteristics of the medium, and return whether style rules
384 : * may have changed as a result.
385 : */
386 : bool MediumFeaturesChanged();
387 :
388 : // APIs to manipulate the style sheet lists. The sheets in each
389 : // list are stored with the most significant sheet last.
390 : nsresult AppendStyleSheet(mozilla::SheetType aType,
391 : mozilla::CSSStyleSheet* aSheet);
392 : nsresult PrependStyleSheet(mozilla::SheetType aType,
393 : mozilla::CSSStyleSheet* aSheet);
394 : nsresult RemoveStyleSheet(mozilla::SheetType aType,
395 : mozilla::CSSStyleSheet* aSheet);
396 : nsresult ReplaceSheets(mozilla::SheetType aType,
397 : const nsTArray<RefPtr<mozilla::CSSStyleSheet>>& aNewSheets);
398 : nsresult InsertStyleSheetBefore(mozilla::SheetType aType,
399 : mozilla::CSSStyleSheet* aNewSheet,
400 : mozilla::CSSStyleSheet* aReferenceSheet);
401 :
402 : // Enable/Disable entire author style level (Doc, ScopedDoc & PresHint levels)
403 : bool GetAuthorStyleDisabled() const;
404 : nsresult SetAuthorStyleDisabled(bool aStyleDisabled);
405 :
406 28 : int32_t SheetCount(mozilla::SheetType aType) const {
407 28 : return mSheets[aType].Length();
408 : }
409 :
410 0 : mozilla::CSSStyleSheet* StyleSheetAt(mozilla::SheetType aType,
411 : int32_t aIndex) const {
412 0 : return mSheets[aType][aIndex];
413 : }
414 :
415 : void AppendAllXBLStyleSheets(nsTArray<mozilla::StyleSheet*>& aArray) const;
416 :
417 : nsresult RemoveDocStyleSheet(mozilla::CSSStyleSheet* aSheet);
418 : nsresult AddDocStyleSheet(mozilla::CSSStyleSheet* aSheet,
419 : nsIDocument* aDocument);
420 :
421 : void BeginUpdate();
422 : nsresult EndUpdate();
423 :
424 : // Methods for reconstructing the tree; BeginReconstruct basically moves the
425 : // old rule tree root and style context roots out of the way,
426 : // and EndReconstruct destroys the old rule tree when we're done
427 : nsresult BeginReconstruct();
428 : // Note: EndReconstruct should not be called if BeginReconstruct fails
429 : void EndReconstruct();
430 :
431 655 : bool IsInRuleTreeReconstruct() const {
432 655 : return mInReconstruct;
433 : }
434 :
435 308 : void RootStyleContextAdded() {
436 308 : ++mRootStyleContextCount;
437 308 : }
438 : void RootStyleContextRemoved() {
439 : MOZ_ASSERT(mRootStyleContextCount > 0);
440 : --mRootStyleContextCount;
441 : }
442 :
443 : // Return whether the rule tree has cached data such that we need to
444 : // do dynamic change handling for changes that change the results of
445 : // media queries or require rebuilding all style data.
446 : // We don't care whether we have cached rule processors or whether
447 : // they have cached rule cascades; getting the rule cascades again in
448 : // order to do rule matching will get the correct rule cascade.
449 61 : bool HasCachedStyleData() const {
450 61 : return (mRuleTree && mRuleTree->TreeHasCachedData()) || mRootStyleContextCount > 0;
451 : }
452 :
453 : // Notify the style set that a rulenode is no longer in use, or was
454 : // just created and is not in use yet.
455 : static const uint32_t kGCInterval = 300;
456 3202 : void RuleNodeUnused(nsRuleNode* aNode, bool aMayGC) {
457 3202 : ++mUnusedRuleNodeCount;
458 3202 : mUnusedRuleNodeList.insertBack(aNode);
459 3202 : if (aMayGC && mUnusedRuleNodeCount >= kGCInterval && !mInGC && !mInReconstruct) {
460 0 : GCRuleTrees();
461 : }
462 3202 : }
463 :
464 : // Notify the style set that a rulenode that wasn't in use now is
465 2190 : void RuleNodeInUse(nsRuleNode* aNode) {
466 2190 : MOZ_ASSERT(mUnusedRuleNodeCount > 0);
467 2190 : --mUnusedRuleNodeCount;
468 2190 : aNode->removeFrom(mUnusedRuleNodeList);
469 2190 : }
470 :
471 : // Returns true if a restyle of the document is needed due to cloning
472 : // sheet inners.
473 : bool EnsureUniqueInnerOnCSSSheets();
474 :
475 : // Called by StyleSheet::EnsureUniqueInner to let us know it cloned
476 : // its inner.
477 0 : void SetNeedsRestyleAfterEnsureUniqueInner() {
478 0 : mNeedsRestyleAfterEnsureUniqueInner = true;
479 0 : }
480 :
481 : nsIStyleRule* InitialStyleRule();
482 :
483 : bool HasRuleProcessorUsedByMultipleStyleSets(mozilla::SheetType aSheetType);
484 :
485 : // Tells the RestyleManager for the document using this style set
486 : // to drop any nsCSSSelector pointers it has.
487 : void ClearSelectors();
488 :
489 : // Returns whether aSheetType represents a level of the cascade that uses
490 : // CSSStyleSheets. See gCSSSheetTypes in nsStyleSet.cpp for the list
491 : // of CSS sheet types.
492 : static bool IsCSSSheetType(mozilla::SheetType aSheetType);
493 :
494 : private:
495 : nsStyleSet(const nsStyleSet& aCopy) = delete;
496 : nsStyleSet& operator=(const nsStyleSet& aCopy) = delete;
497 :
498 : // Free all the rules with reference-count zero. This continues iterating
499 : // over the free list until it is empty, which allows immediate collection
500 : // of nodes whose reference-count drops to zero during the destruction of
501 : // a child node. This allows the collection of entire trees at once, since
502 : // children hold their parents alive.
503 : void GCRuleTrees();
504 :
505 : nsresult DirtyRuleProcessors(mozilla::SheetType aType);
506 :
507 : // Update the rule processor list after a change to the style sheet list.
508 : nsresult GatherRuleProcessors(mozilla::SheetType aType);
509 :
510 : void AddImportantRules(nsRuleNode* aCurrLevelNode,
511 : nsRuleNode* aLastPrevLevelNode,
512 : nsRuleWalker* aRuleWalker);
513 :
514 : // Move aRuleWalker forward by the appropriate rule if we need to add
515 : // a rule due to property restrictions on pseudo-elements.
516 : void WalkRestrictionRule(mozilla::CSSPseudoElementType aPseudoType,
517 : nsRuleWalker* aRuleWalker);
518 :
519 : void WalkDisableTextZoomRule(mozilla::dom::Element* aElement,
520 : nsRuleWalker* aRuleWalker);
521 :
522 : #ifdef DEBUG
523 : // Just like AddImportantRules except it doesn't actually add anything; it
524 : // just asserts that there are no important rules between aCurrLevelNode and
525 : // aLastPrevLevelNode.
526 : void AssertNoImportantRules(nsRuleNode* aCurrLevelNode,
527 : nsRuleNode* aLastPrevLevelNode);
528 :
529 : // Just like AddImportantRules except it doesn't actually add anything; it
530 : // just asserts that there are no CSS rules between aCurrLevelNode and
531 : // aLastPrevLevelNode. Mostly useful for the preshint level.
532 : void AssertNoCSSRules(nsRuleNode* aCurrLevelNode,
533 : nsRuleNode* aLastPrevLevelNode);
534 : #endif
535 :
536 : // Enumerate the rules in a way that cares about the order of the
537 : // rules.
538 : // aElement is the element the rules are for. It might be null. aData
539 : // is the closure to pass to aCollectorFunc. If aContent is not null,
540 : // aData must be a RuleProcessorData*
541 : void FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
542 : RuleProcessorData* aData, mozilla::dom::Element* aElement,
543 : nsRuleWalker* aRuleWalker);
544 :
545 : // Enumerate all the rules in a way that doesn't care about the order
546 : // of the rules and break out if the enumeration is halted.
547 : void WalkRuleProcessors(nsIStyleRuleProcessor::EnumFunc aFunc,
548 : ElementDependentRuleProcessorData* aData,
549 : bool aWalkAllXBLStylesheets);
550 :
551 : // Helper for ResolveStyleWithReplacement
552 : // aPseudoElement must follow the same rules as for
553 : // ResolvePseudoElementStyle, and be null for non-pseudo-element cases
554 : nsRuleNode* RuleNodeWithReplacement(mozilla::dom::Element* aElement,
555 : mozilla::dom::Element* aPseudoElement,
556 : nsRuleNode* aOldRuleNode,
557 : mozilla::CSSPseudoElementType aPseudoType,
558 : nsRestyleHint aReplacements);
559 :
560 : already_AddRefed<nsStyleContext>
561 : GetContext(nsStyleContext* aParentContext,
562 : nsRuleNode* aRuleNode,
563 : nsRuleNode* aVisitedRuleNode,
564 : nsIAtom* aPseudoTag,
565 : mozilla::CSSPseudoElementType aPseudoType,
566 : mozilla::dom::Element* aElementForAnimation,
567 : uint32_t aFlags);
568 :
569 : enum AnimationFlag {
570 : eWithAnimation,
571 : eWithoutAnimation,
572 : };
573 : already_AddRefed<nsStyleContext>
574 : ResolveStyleForInternal(mozilla::dom::Element* aElement,
575 : nsStyleContext* aParentContext,
576 : TreeMatchContext& aTreeMatchContext,
577 : AnimationFlag aAnimationFlag);
578 :
579 : already_AddRefed<nsStyleContext>
580 : ResolvePseudoElementStyleInternal(mozilla::dom::Element* aParentElement,
581 : mozilla::CSSPseudoElementType aType,
582 : nsStyleContext* aParentContext,
583 : mozilla::dom::Element* aPseudoElement,
584 : AnimationFlag aAnimationFlag);
585 :
586 16982 : nsPresContext* PresContext() { return mRuleTree->PresContext(); }
587 :
588 : // Clear our cached mNonInheritingStyleContexts. We do this when we want to
589 : // make sure those style contexts won't live too long (e.g. at ruletree
590 : // reconstruct or shutdown time).
591 : void ClearNonInheritingStyleContexts();
592 :
593 : // The sheets in each array in mSheets are stored with the most significant
594 : // sheet last.
595 : // The arrays for ePresHintSheet, eStyleAttrSheet, eTransitionSheet,
596 : // eAnimationSheet are always empty.
597 : // (FIXME: We should reduce the storage needed for them.)
598 : mozilla::EnumeratedArray<mozilla::SheetType, mozilla::SheetType::Count,
599 : nsTArray<RefPtr<mozilla::CSSStyleSheet>>> mSheets;
600 :
601 : // mRuleProcessors[eScopedDocSheet] is always null; rule processors
602 : // for scoped style sheets are stored in mScopedDocSheetRuleProcessors.
603 : mozilla::EnumeratedArray<mozilla::SheetType, mozilla::SheetType::Count,
604 : nsCOMPtr<nsIStyleRuleProcessor>> mRuleProcessors;
605 :
606 : // Rule processors for HTML5 scoped style sheets, one per scope.
607 : nsTArray<nsCOMPtr<nsIStyleRuleProcessor> > mScopedDocSheetRuleProcessors;
608 :
609 : RefPtr<nsBindingManager> mBindingManager;
610 :
611 : RefPtr<nsRuleNode> mRuleTree; // This is the root of our rule tree. It is a
612 : // lexicographic tree of matched rules that style
613 : // contexts use to look up properties.
614 :
615 : // List of subtrees rooted at style scope roots that need to be restyled.
616 : // When a change to a scoped style sheet is made, we add the style scope
617 : // root to this array rather than setting mStylesHaveChanged = true, since
618 : // we know we don't need to restyle the whole document. However, if in the
619 : // same update block we have already had other changes that require
620 : // the whole document to be restyled (i.e., mStylesHaveChanged is already
621 : // true), then we don't bother adding the scope root here.
622 : AutoTArray<RefPtr<mozilla::dom::Element>,1> mChangedScopeStyleRoots;
623 :
624 : uint16_t mBatching;
625 :
626 : // Indicates that the whole document must be restyled. Changes to scoped
627 : // style sheets are recorded in mChangedScopeStyleRoots rather than here
628 : // in mStylesHaveChanged.
629 : unsigned mStylesHaveChanged : 1;
630 : unsigned mInShutdown : 1;
631 : unsigned mInGC : 1;
632 : unsigned mAuthorStyleDisabled: 1;
633 : unsigned mInReconstruct : 1;
634 : unsigned mInitFontFeatureValuesLookup : 1;
635 : unsigned mNeedsRestyleAfterEnsureUniqueInner : 1;
636 : unsigned mDirty : int(mozilla::SheetType::Count); // one bit per sheet type
637 :
638 : uint32_t mRootStyleContextCount;
639 :
640 : #ifdef DEBUG
641 : // In debug builds, we stash a weak pointer here to the old root during
642 : // reconstruction. During GC, we check for this pointer, and null it out
643 : // when we encounter it. This allows us to assert that the old root (and
644 : // thus all of its subtree) was GCed after reconstruction, which implies
645 : // that there are no style contexts holding on to old rule nodes.
646 : nsRuleNode* mOldRootNode;
647 : #endif
648 :
649 : // Track our rule nodes with zero refcount. When this hits a threshold, we
650 : // sweep and free. Keeping unused rule nodes around for a bit allows us to
651 : // reuse them in many cases.
652 : mozilla::LinkedList<nsRuleNode> mUnusedRuleNodeList;
653 : uint32_t mUnusedRuleNodeCount;
654 :
655 : // Empty style rules to force things that restrict which properties
656 : // apply into different branches of the rule tree.
657 : RefPtr<nsEmptyStyleRule> mFirstLineRule, mFirstLetterRule, mPlaceholderRule;
658 :
659 : // Style rule which sets all properties to their initial values for
660 : // determining when context-sensitive values are in use.
661 : RefPtr<nsInitialStyleRule> mInitialStyleRule;
662 :
663 : // Style rule that sets the internal -x-text-zoom property on
664 : // <svg:text> elements to disable the effect of text zooming.
665 : RefPtr<nsDisableTextZoomStyleRule> mDisableTextZoomStyleRule;
666 :
667 : // whether font feature values lookup object needs initialization
668 : RefPtr<gfxFontFeatureValueSet> mFontFeatureValuesLookup;
669 :
670 : // Stores pointers to our cached style contexts for non-inheriting anonymous
671 : // boxes.
672 : mozilla::EnumeratedArray<nsCSSAnonBoxes::NonInheriting,
673 : nsCSSAnonBoxes::NonInheriting::_Count,
674 : RefPtr<nsStyleContext>> mNonInheritingStyleContexts;
675 : };
676 :
677 : #ifdef MOZILLA_INTERNAL_API
678 : inline
679 4225 : void nsRuleNode::AddRef()
680 : {
681 4225 : if (mRefCnt++ == 0) {
682 2190 : MOZ_ASSERT(mPresContext->StyleSet()->IsGecko(),
683 : "ServoStyleSets should not have rule nodes");
684 2190 : mPresContext->StyleSet()->AsGecko()->RuleNodeInUse(this);
685 : }
686 4225 : }
687 :
688 : inline
689 2564 : void nsRuleNode::Release()
690 : {
691 2564 : if (--mRefCnt == 0) {
692 1180 : MOZ_ASSERT(mPresContext->StyleSet()->IsGecko(),
693 : "ServoStyleSets should not have rule nodes");
694 1180 : mPresContext->StyleSet()->AsGecko()->RuleNodeUnused(this, /* aMayGC = */ true);
695 : }
696 2564 : }
697 : #endif
698 :
699 : #endif
|