nsStyleContext.h 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854
  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. /* the interface (to internal code) for retrieving computed style data */
  6. #ifndef _nsStyleContext_h_
  7. #define _nsStyleContext_h_
  8. #include "mozilla/Assertions.h"
  9. #include "mozilla/RestyleLogging.h"
  10. #include "mozilla/StyleContextSource.h"
  11. #include "nsCSSAnonBoxes.h"
  12. #include "nsStyleSet.h"
  13. class nsIAtom;
  14. class nsPresContext;
  15. namespace mozilla {
  16. enum class CSSPseudoElementType : uint8_t;
  17. } // namespace mozilla
  18. extern "C" {
  19. #define STYLE_STRUCT(name_, checkdata_cb_) \
  20. struct nsStyle##name_; \
  21. const nsStyle##name_* Servo_GetStyle##name_( \
  22. ServoComputedValuesBorrowedOrNull computed_values);
  23. #include "nsStyleStructList.h"
  24. #undef STYLE_STRUCT
  25. }
  26. /**
  27. * An nsStyleContext represents the computed style data for an element.
  28. * The computed style data are stored in a set of structs (see
  29. * nsStyleStruct.h) that are cached either on the style context or in
  30. * the rule tree (see nsRuleNode.h for a description of this caching and
  31. * how the cached structs are shared).
  32. *
  33. * Since the data in |nsIStyleRule|s and |nsRuleNode|s are immutable
  34. * (with a few exceptions, like system color changes), the data in an
  35. * nsStyleContext are also immutable (with the additional exception of
  36. * GetUniqueStyleData). When style data change,
  37. * ElementRestyler::Restyle creates a new style context.
  38. *
  39. * Style contexts are reference counted. References are generally held
  40. * by:
  41. * 1. the |nsIFrame|s that are using the style context and
  42. * 2. any *child* style contexts (this might be the reverse of
  43. * expectation, but it makes sense in this case)
  44. */
  45. class nsStyleContext final
  46. {
  47. public:
  48. /**
  49. * Create a new style context.
  50. * @param aParent The parent of a style context is used for CSS
  51. * inheritance. When the element or pseudo-element
  52. * this style context represents the style data of
  53. * inherits a CSS property, the value comes from the
  54. * parent style context. This means style context
  55. * parentage must match the definitions of inheritance
  56. * in the CSS specification.
  57. * @param aPseudoTag The pseudo-element or anonymous box for which
  58. * this style context represents style. Null if
  59. * this style context is for a normal DOM element.
  60. * @param aPseudoType Must match aPseudoTag.
  61. * @param aRuleNode A rule node representing the ordered sequence of
  62. * rules that any element, pseudo-element, or
  63. * anonymous box that this style context is for
  64. * matches. See |nsRuleNode| and |nsIStyleRule|.
  65. * @param aSkipParentDisplayBasedStyleFixup
  66. * If set, this flag indicates that we should skip
  67. * the chunk of ApplyStyleFixups() that applies to
  68. * special cases where a child element's style may
  69. * need to be modified based on its parent's display
  70. * value.
  71. */
  72. nsStyleContext(nsStyleContext* aParent, nsIAtom* aPseudoTag,
  73. mozilla::CSSPseudoElementType aPseudoType,
  74. already_AddRefed<nsRuleNode> aRuleNode,
  75. bool aSkipParentDisplayBasedStyleFixup);
  76. // Version of the above that takes a ServoComputedValues instead of a Gecko
  77. // nsRuleNode.
  78. nsStyleContext(nsStyleContext* aParent,
  79. nsPresContext* aPresContext,
  80. nsIAtom* aPseudoTag,
  81. mozilla::CSSPseudoElementType aPseudoType,
  82. already_AddRefed<ServoComputedValues> aComputedValues,
  83. bool aSkipParentDisplayBasedStyleFixup);
  84. void* operator new(size_t sz, nsPresContext* aPresContext);
  85. void Destroy();
  86. // These two methods are for use by ArenaRefPtr.
  87. static mozilla::ArenaObjectID ArenaObjectID()
  88. {
  89. return mozilla::eArenaObjectID_nsStyleContext;
  90. }
  91. nsIPresShell* Arena();
  92. #ifdef DEBUG
  93. /**
  94. * Initializes a cached pref, which is only used in DEBUG code.
  95. */
  96. static void Initialize();
  97. #endif
  98. nsrefcnt AddRef() {
  99. if (mRefCnt == UINT32_MAX) {
  100. NS_WARNING("refcount overflow, leaking object");
  101. return mRefCnt;
  102. }
  103. ++mRefCnt;
  104. NS_LOG_ADDREF(this, mRefCnt, "nsStyleContext", sizeof(nsStyleContext));
  105. return mRefCnt;
  106. }
  107. nsrefcnt Release() {
  108. if (mRefCnt == UINT32_MAX) {
  109. NS_WARNING("refcount overflow, leaking object");
  110. return mRefCnt;
  111. }
  112. --mRefCnt;
  113. NS_LOG_RELEASE(this, mRefCnt, "nsStyleContext");
  114. if (mRefCnt == 0) {
  115. Destroy();
  116. return 0;
  117. }
  118. return mRefCnt;
  119. }
  120. #ifdef DEBUG
  121. void FrameAddRef() {
  122. ++mFrameRefCnt;
  123. }
  124. void FrameRelease() {
  125. --mFrameRefCnt;
  126. }
  127. uint32_t FrameRefCnt() const {
  128. return mFrameRefCnt;
  129. }
  130. #endif
  131. bool HasSingleReference() const {
  132. NS_ASSERTION(mRefCnt != 0,
  133. "do not call HasSingleReference on a newly created "
  134. "nsStyleContext with no references yet");
  135. return mRefCnt == 1;
  136. }
  137. nsPresContext* PresContext() const {
  138. #ifdef MOZ_STYLO
  139. return mPresContext;
  140. #else
  141. return mSource.AsGeckoRuleNode()->PresContext();
  142. #endif
  143. }
  144. nsStyleContext* GetParent() const { return mParent; }
  145. nsIAtom* GetPseudo() const { return mPseudoTag; }
  146. mozilla::CSSPseudoElementType GetPseudoType() const {
  147. return static_cast<mozilla::CSSPseudoElementType>(
  148. mBits >> NS_STYLE_CONTEXT_TYPE_SHIFT);
  149. }
  150. bool IsAnonBox() const {
  151. return GetPseudoType() == mozilla::CSSPseudoElementType::AnonBox;
  152. }
  153. bool IsPseudoElement() const { return mPseudoTag && !IsAnonBox(); }
  154. // Find, if it already exists *and is easily findable* (i.e., near the
  155. // start of the child list), a style context whose:
  156. // * GetPseudo() matches aPseudoTag
  157. // * mSource matches aSource
  158. // * !!GetStyleIfVisited() == !!aSourceIfVisited, and, if they're
  159. // non-null, GetStyleIfVisited()->mSource == aSourceIfVisited
  160. // * RelevantLinkVisited() == aRelevantLinkVisited
  161. already_AddRefed<nsStyleContext>
  162. FindChildWithRules(const nsIAtom* aPseudoTag,
  163. mozilla::NonOwningStyleContextSource aSource,
  164. mozilla::NonOwningStyleContextSource aSourceIfVisited,
  165. bool aRelevantLinkVisited);
  166. // Does this style context or any of its ancestors have text
  167. // decoration lines?
  168. // Differs from nsStyleTextReset::HasTextDecorationLines, which tests
  169. // only the data for a single context.
  170. bool HasTextDecorationLines() const
  171. { return !!(mBits & NS_STYLE_HAS_TEXT_DECORATION_LINES); }
  172. // Whether any line break inside should be suppressed? If this returns
  173. // true, the line should not be broken inside, which means inlines act
  174. // as if nowrap is set, <br> is suppressed, and blocks are inlinized.
  175. // This bit is propogated to all children of line partitipants. It is
  176. // currently used by ruby to make its content frames unbreakable.
  177. // NOTE: for nsTextFrame, use nsTextFrame::ShouldSuppressLineBreak()
  178. // instead of this method.
  179. bool ShouldSuppressLineBreak() const
  180. { return !!(mBits & NS_STYLE_SUPPRESS_LINEBREAK); }
  181. // Does this style context or any of its ancestors have display:none set?
  182. bool IsInDisplayNoneSubtree() const
  183. { return !!(mBits & NS_STYLE_IN_DISPLAY_NONE_SUBTREE); }
  184. // Is this horizontal-in-vertical (tate-chu-yoko) text? This flag is
  185. // only set on style contexts whose pseudo is nsCSSAnonBoxes::mozText.
  186. bool IsTextCombined() const
  187. { return !!(mBits & NS_STYLE_IS_TEXT_COMBINED); }
  188. // Does this style context represent the style for a pseudo-element or
  189. // inherit data from such a style context? Whether this returns true
  190. // is equivalent to whether it or any of its ancestors returns
  191. // non-null for IsPseudoElement().
  192. bool HasPseudoElementData() const
  193. { return !!(mBits & NS_STYLE_HAS_PSEUDO_ELEMENT_DATA); }
  194. bool HasChildThatUsesResetStyle() const
  195. { return mBits & NS_STYLE_HAS_CHILD_THAT_USES_RESET_STYLE; }
  196. // Is the only link whose visitedness is allowed to influence the
  197. // style of the node this style context is for (which is that element
  198. // or its nearest ancestor that is a link) visited?
  199. bool RelevantLinkVisited() const
  200. { return !!(mBits & NS_STYLE_RELEVANT_LINK_VISITED); }
  201. // Is this a style context for a link?
  202. bool IsLinkContext() const {
  203. return
  204. GetStyleIfVisited() && GetStyleIfVisited()->GetParent() == GetParent();
  205. }
  206. // Is this style context the GetStyleIfVisited() for some other style
  207. // context?
  208. bool IsStyleIfVisited() const
  209. { return !!(mBits & NS_STYLE_IS_STYLE_IF_VISITED); }
  210. // Tells this style context that it should return true from
  211. // IsStyleIfVisited.
  212. void SetIsStyleIfVisited()
  213. { mBits |= NS_STYLE_IS_STYLE_IF_VISITED; }
  214. // Return the style context whose style data should be used for the R,
  215. // G, and B components of color, background-color, and border-*-color
  216. // if RelevantLinkIsVisited().
  217. //
  218. // GetPseudo() and GetPseudoType() on this style context return the
  219. // same as on |this|, and its depth in the tree (number of GetParent()
  220. // calls until null is returned) is the same as |this|, since its
  221. // parent is either |this|'s parent or |this|'s parent's
  222. // style-if-visited.
  223. //
  224. // Structs on this context should never be examined without also
  225. // examining the corresponding struct on |this|. Doing so will likely
  226. // both (1) lead to a privacy leak and (2) lead to dynamic change bugs
  227. // related to the Peek code in nsStyleContext::CalcStyleDifference.
  228. nsStyleContext* GetStyleIfVisited() const
  229. { return mStyleIfVisited; }
  230. // To be called only from nsStyleSet.
  231. void SetStyleIfVisited(already_AddRefed<nsStyleContext> aStyleIfVisited)
  232. {
  233. MOZ_ASSERT(!IsStyleIfVisited(), "this context is not visited data");
  234. NS_ASSERTION(!mStyleIfVisited, "should only be set once");
  235. mStyleIfVisited = aStyleIfVisited;
  236. MOZ_ASSERT(mStyleIfVisited->IsStyleIfVisited(),
  237. "other context is visited data");
  238. MOZ_ASSERT(!mStyleIfVisited->GetStyleIfVisited(),
  239. "other context does not have visited data");
  240. NS_ASSERTION(GetStyleIfVisited()->GetPseudo() == GetPseudo(),
  241. "pseudo tag mismatch");
  242. if (GetParent() && GetParent()->GetStyleIfVisited()) {
  243. NS_ASSERTION(GetStyleIfVisited()->GetParent() ==
  244. GetParent()->GetStyleIfVisited() ||
  245. GetStyleIfVisited()->GetParent() == GetParent(),
  246. "parent mismatch");
  247. } else {
  248. NS_ASSERTION(GetStyleIfVisited()->GetParent() == GetParent(),
  249. "parent mismatch");
  250. }
  251. }
  252. // Does any descendant of this style context have any style values
  253. // that were computed based on this style context's ancestors?
  254. bool HasChildThatUsesGrandancestorStyle() const
  255. { return !!(mBits & NS_STYLE_CHILD_USES_GRANDANCESTOR_STYLE); }
  256. // Is this style context shared with a sibling or cousin?
  257. // (See nsStyleSet::GetContext.)
  258. bool IsShared() const
  259. { return !!(mBits & NS_STYLE_IS_SHARED); }
  260. // Tell this style context to cache aStruct as the struct for aSID
  261. void SetStyle(nsStyleStructID aSID, void* aStruct);
  262. /**
  263. * Returns whether this style context has cached style data for a
  264. * given style struct and it does NOT own that struct. This can
  265. * happen because it was inherited from the parent style context, or
  266. * because it was stored conditionally on the rule node.
  267. */
  268. bool HasCachedDependentStyleData(nsStyleStructID aSID) {
  269. return mBits & nsCachedStyleData::GetBitForSID(aSID);
  270. }
  271. nsRuleNode* RuleNode() {
  272. MOZ_RELEASE_ASSERT(mSource.IsGeckoRuleNode());
  273. return mSource.AsGeckoRuleNode();
  274. }
  275. void AddStyleBit(const uint64_t& aBit) { mBits |= aBit; }
  276. /*
  277. * Get the style data for a style struct. This is the most important
  278. * member function of nsStyleContext. It fills in a const pointer
  279. * to a style data struct that is appropriate for the style context's
  280. * frame. This struct may be shared with other contexts (either in
  281. * the rule tree or the style context tree), so it should not be
  282. * modified.
  283. *
  284. * This function will NOT return null (even when out of memory) when
  285. * given a valid style struct ID, so the result does not need to be
  286. * null-checked.
  287. *
  288. * The typesafe functions below are preferred to the use of this
  289. * function, both because they're easier to read and because they're
  290. * faster.
  291. */
  292. const void* NS_FASTCALL StyleData(nsStyleStructID aSID);
  293. /**
  294. * Define typesafe getter functions for each style struct by
  295. * preprocessing the list of style structs. These functions are the
  296. * preferred way to get style data. The macro creates functions like:
  297. * const nsStyleBorder* StyleBorder();
  298. * const nsStyleColor* StyleColor();
  299. */
  300. #define STYLE_STRUCT(name_, checkdata_cb_) \
  301. const nsStyle##name_ * Style##name_() { \
  302. return DoGetStyle##name_<true>(); \
  303. }
  304. #include "nsStyleStructList.h"
  305. #undef STYLE_STRUCT
  306. /**
  307. * PeekStyle* is like Style* but doesn't trigger style
  308. * computation if the data is not cached on either the style context
  309. * or the rule node.
  310. *
  311. * Perhaps this shouldn't be a public nsStyleContext API.
  312. */
  313. #define STYLE_STRUCT(name_, checkdata_cb_) \
  314. const nsStyle##name_ * PeekStyle##name_() { \
  315. return DoGetStyle##name_<false>(); \
  316. }
  317. #include "nsStyleStructList.h"
  318. #undef STYLE_STRUCT
  319. /**
  320. * Compute the style changes needed during restyling when this style
  321. * context is being replaced by aNewContext. (This is nonsymmetric since
  322. * we optimize by skipping comparison for styles that have never been
  323. * requested.)
  324. *
  325. * This method returns a change hint (see nsChangeHint.h). All change
  326. * hints apply to the frame and its later continuations or ib-split
  327. * siblings. Most (all of those except the "NotHandledForDescendants"
  328. * hints) also apply to all descendants. The caller must pass in any
  329. * non-inherited hints that resulted from the parent style context's
  330. * style change. The caller *may* pass more hints than needed, but
  331. * must not pass less than needed; therefore if the caller doesn't
  332. * know, the caller should pass
  333. * nsChangeHint_Hints_NotHandledForDescendants.
  334. *
  335. * aEqualStructs must not be null. Into it will be stored a bitfield
  336. * representing which structs were compared to be non-equal.
  337. */
  338. nsChangeHint CalcStyleDifference(nsStyleContext* aNewContext,
  339. nsChangeHint aParentHintsNotHandledForDescendants,
  340. uint32_t* aEqualStructs,
  341. uint32_t* aSamePointerStructs);
  342. /**
  343. * Like the above, but allows comparing ServoComputedValues instead of needing
  344. * a full-fledged style context.
  345. */
  346. nsChangeHint CalcStyleDifference(const ServoComputedValues* aNewComputedValues,
  347. nsChangeHint aParentHintsNotHandledForDescendants,
  348. uint32_t* aEqualStructs,
  349. uint32_t* aSamePointerStructs);
  350. private:
  351. template<class StyleContextLike>
  352. nsChangeHint CalcStyleDifferenceInternal(StyleContextLike* aNewContext,
  353. nsChangeHint aParentHintsNotHandledForDescendants,
  354. uint32_t* aEqualStructs,
  355. uint32_t* aSamePointerStructs);
  356. public:
  357. /**
  358. * Get a color that depends on link-visitedness using this and
  359. * this->GetStyleIfVisited().
  360. *
  361. * aProperty must be a color-valued property that StyleAnimationValue
  362. * knows how to extract. It must also be a property that we know to
  363. * do change handling for in nsStyleContext::CalcDifference.
  364. */
  365. nscolor GetVisitedDependentColor(nsCSSPropertyID aProperty);
  366. /**
  367. * aColors should be a two element array of nscolor in which the first
  368. * color is the unvisited color and the second is the visited color.
  369. *
  370. * Combine the R, G, and B components of whichever of aColors should
  371. * be used based on aLinkIsVisited with the A component of aColors[0].
  372. */
  373. static nscolor CombineVisitedColors(nscolor *aColors,
  374. bool aLinkIsVisited);
  375. /**
  376. * Start the background image loads for this style context.
  377. */
  378. void StartBackgroundImageLoads() {
  379. // Just get our background struct; that should do the trick
  380. StyleBackground();
  381. }
  382. /**
  383. * Moves this style context to a new parent.
  384. *
  385. * This function violates style context tree immutability, and
  386. * is a very low-level function and should only be used after verifying
  387. * many conditions that make it safe to call.
  388. */
  389. void MoveTo(nsStyleContext* aNewParent);
  390. /**
  391. * Swaps owned style struct pointers between this and aNewContext, on
  392. * the assumption that aNewContext is the new style context for a frame
  393. * and this is the old one. aStructs indicates which structs to consider
  394. * swapping; only those which are owned in both this and aNewContext
  395. * will be swapped.
  396. *
  397. * Additionally, if there are identical struct pointers for one of the
  398. * structs indicated by aStructs, and it is not an owned struct on this,
  399. * then the cached struct slot on this will be set to null. If the struct
  400. * has been swapped on an ancestor, this style context (being the old one)
  401. * will be left caching the struct pointer on the new ancestor, despite
  402. * inheriting from the old ancestor. This is not normally a problem, as
  403. * this style context will usually be destroyed by being released at the
  404. * end of ElementRestyler::Restyle; but for style contexts held on to outside
  405. * of the frame, we need to clear out the cached pointer so that if we need
  406. * it again we'll re-fetch it from the new ancestor.
  407. */
  408. void SwapStyleData(nsStyleContext* aNewContext, uint32_t aStructs);
  409. /**
  410. * On each descendant of this style context, clears out any cached inherited
  411. * structs indicated in aStructs.
  412. */
  413. void ClearCachedInheritedStyleDataOnDescendants(uint32_t aStructs);
  414. /**
  415. * Sets the NS_STYLE_INELIGIBLE_FOR_SHARING bit on this style context
  416. * and its descendants. If it finds a descendant that has the bit
  417. * already set, assumes that it can skip that subtree.
  418. */
  419. void SetIneligibleForSharing();
  420. #ifdef DEBUG
  421. void List(FILE* out, int32_t aIndent, bool aListDescendants = true);
  422. static void AssertStyleStructMaxDifferenceValid();
  423. static const char* StructName(nsStyleStructID aSID);
  424. static bool LookupStruct(const nsACString& aName, nsStyleStructID& aResult);
  425. #endif
  426. #ifdef RESTYLE_LOGGING
  427. nsCString GetCachedStyleDataAsString(uint32_t aStructs);
  428. void LogStyleContextTree(int32_t aLoggingDepth, uint32_t aStructs);
  429. int32_t& LoggingDepth();
  430. #endif
  431. /**
  432. * Return style data that is currently cached on the style context.
  433. * Only returns the structs we cache ourselves; never consults the
  434. * rule tree.
  435. *
  436. * For "internal" use only in nsStyleContext and nsRuleNode.
  437. */
  438. const void* GetCachedStyleData(nsStyleStructID aSID)
  439. {
  440. const void* cachedData;
  441. if (nsCachedStyleData::IsReset(aSID)) {
  442. if (mCachedResetData) {
  443. cachedData = mCachedResetData->mStyleStructs[aSID];
  444. } else {
  445. cachedData = nullptr;
  446. }
  447. } else {
  448. cachedData = mCachedInheritedData.mStyleStructs[aSID];
  449. }
  450. return cachedData;
  451. }
  452. mozilla::NonOwningStyleContextSource StyleSource() const { return mSource.AsRaw(); }
  453. #ifdef MOZ_STYLO
  454. // NOTE: It'd be great to assert here that the previous change hint is always
  455. // consumed.
  456. //
  457. // This is not the case right now, since the changes of childs of frames that
  458. // go through frame construction are not consumed.
  459. void StoreChangeHint(nsChangeHint aHint)
  460. {
  461. MOZ_ASSERT(!IsShared());
  462. mStoredChangeHint = aHint;
  463. #ifdef DEBUG
  464. mConsumedChangeHint = false;
  465. #endif
  466. }
  467. nsChangeHint ConsumeStoredChangeHint()
  468. {
  469. MOZ_ASSERT(!mConsumedChangeHint, "Re-consuming the same change hint!");
  470. nsChangeHint result = mStoredChangeHint;
  471. mStoredChangeHint = nsChangeHint(0);
  472. #ifdef DEBUG
  473. mConsumedChangeHint = true;
  474. #endif
  475. return result;
  476. }
  477. #else
  478. void StoreChangeHint(nsChangeHint aHint)
  479. {
  480. MOZ_CRASH("stylo: Called nsStyleContext::StoreChangeHint in a non MOZ_STYLO "
  481. "build.");
  482. }
  483. nsChangeHint ConsumeStoredChangeHint()
  484. {
  485. MOZ_CRASH("stylo: Called nsStyleContext::ComsumeStoredChangeHint in a non "
  486. "MOZ_STYLO build.");
  487. }
  488. #endif
  489. private:
  490. // Private destructor, to discourage deletion outside of Release():
  491. ~nsStyleContext();
  492. // Delegated Helper constructor.
  493. nsStyleContext(nsStyleContext* aParent,
  494. mozilla::OwningStyleContextSource&& aSource,
  495. nsIAtom* aPseudoTag,
  496. mozilla::CSSPseudoElementType aPseudoType);
  497. // Helper post-contruct hook.
  498. void FinishConstruction(bool aSkipParentDisplayBasedStyleFixup);
  499. void AddChild(nsStyleContext* aChild);
  500. void RemoveChild(nsStyleContext* aChild);
  501. void* GetUniqueStyleData(const nsStyleStructID& aSID);
  502. void* CreateEmptyStyleData(const nsStyleStructID& aSID);
  503. void SetStyleBits();
  504. void ApplyStyleFixups(bool aSkipParentDisplayBasedStyleFixup);
  505. const void* StyleStructFromServoComputedValues(nsStyleStructID aSID) {
  506. switch (aSID) {
  507. #define STYLE_STRUCT(name_, checkdata_cb_) \
  508. case eStyleStruct_##name_: \
  509. return Servo_GetStyle##name_(mSource.AsServoComputedValues());
  510. #include "nsStyleStructList.h"
  511. #undef STYLE_STRUCT
  512. default:
  513. MOZ_ASSERT_UNREACHABLE("unexpected nsStyleStructID value");
  514. return nullptr;
  515. }
  516. }
  517. #ifdef DEBUG
  518. struct AutoCheckDependency {
  519. nsStyleContext* mStyleContext;
  520. nsStyleStructID mOuterSID;
  521. AutoCheckDependency(nsStyleContext* aContext, nsStyleStructID aInnerSID)
  522. : mStyleContext(aContext)
  523. {
  524. mOuterSID = aContext->mComputingStruct;
  525. MOZ_ASSERT(mOuterSID == nsStyleStructID_None ||
  526. DependencyAllowed(mOuterSID, aInnerSID),
  527. "Undeclared dependency, see generate-stylestructlist.py");
  528. aContext->mComputingStruct = aInnerSID;
  529. }
  530. ~AutoCheckDependency()
  531. {
  532. mStyleContext->mComputingStruct = mOuterSID;
  533. }
  534. };
  535. #define AUTO_CHECK_DEPENDENCY(sid_) \
  536. AutoCheckDependency checkNesting_(this, sid_)
  537. #else
  538. #define AUTO_CHECK_DEPENDENCY(sid_)
  539. #endif
  540. // Helper functions for GetStyle* and PeekStyle*
  541. #define STYLE_STRUCT_INHERITED(name_, checkdata_cb_) \
  542. template<bool aComputeData> \
  543. const nsStyle##name_ * DoGetStyle##name_() { \
  544. const nsStyle##name_ * cachedData = \
  545. static_cast<nsStyle##name_*>( \
  546. mCachedInheritedData.mStyleStructs[eStyleStruct_##name_]); \
  547. if (cachedData) /* Have it cached already, yay */ \
  548. return cachedData; \
  549. if (!aComputeData) { \
  550. /* We always cache inherited structs on the context when we */ \
  551. /* compute them. */ \
  552. return nullptr; \
  553. } \
  554. /* Have the rulenode deal */ \
  555. AUTO_CHECK_DEPENDENCY(eStyleStruct_##name_); \
  556. const nsStyle##name_ * newData; \
  557. if (mSource.IsGeckoRuleNode()) { \
  558. newData = mSource.AsGeckoRuleNode()-> \
  559. GetStyle##name_<aComputeData>(this, mBits); \
  560. } else { \
  561. /** \
  562. * Reach the parent to grab the inherited style struct if \
  563. * we're a text node. \
  564. * \
  565. * This causes the parent element's style context to cache any \
  566. * inherited structs we request for a text node, which means we \
  567. * don't have to compute change hints for the text node, as \
  568. * handling the change on the parent element is sufficient. \
  569. * \
  570. * Note that adding the inherit bit is ok, because the struct \
  571. * pointer returned by the parent and the child is owned by \
  572. * Servo. This is fine if the pointers are the same (as it \
  573. * should, read below), because both style context sources will \
  574. * hold it. \
  575. * \
  576. * In the case of a mishandled frame, we could end up with the \
  577. * pointer to and old parent style, but that's fine too, since \
  578. * the parent style context will remain alive until we reframe, \
  579. * in which case we'll discard both style contexts. Also, we \
  580. * hold a strong reference to the parent style context, which \
  581. * makes it a non-issue. \
  582. * \
  583. * Also, note that the assertion below should be true, except \
  584. * for those frames we still don't handle correctly, like \
  585. * anonymous table wrappers, in which case the pointers will \
  586. * differ. \
  587. * \
  588. * That means we're not going to restyle correctly text frames \
  589. * of anonymous table wrappers, for example. It's kind of \
  590. * embarrassing, but I think it's not worth it to add more \
  591. * logic here unconditionally, given that's going to be fixed. \
  592. * \
  593. * TODO(emilio): Convert to a strong assertion once we support \
  594. * all kinds of random frames. In fact, this can be a great \
  595. * assertion to debug them. \
  596. */ \
  597. if (mPseudoTag == nsCSSAnonBoxes::mozText) { \
  598. MOZ_ASSERT(mParent); \
  599. newData = mParent->DoGetStyle##name_<true>(); \
  600. NS_WARNING_ASSERTION( \
  601. newData == Servo_GetStyle##name_(mSource.AsServoComputedValues()), \
  602. "bad newData"); \
  603. } else { \
  604. newData = \
  605. Servo_GetStyle##name_(mSource.AsServoComputedValues()); \
  606. } \
  607. /* perform any remaining main thread work on the struct */ \
  608. const_cast<nsStyle##name_*>(newData)->FinishStyle(PresContext());\
  609. /* the Servo-backed StyleContextSource owns the struct */ \
  610. AddStyleBit(NS_STYLE_INHERIT_BIT(name_)); \
  611. } \
  612. /* always cache inherited data on the style context; the rule */ \
  613. /* node set the bit in mBits for us if needed. */ \
  614. mCachedInheritedData.mStyleStructs[eStyleStruct_##name_] = \
  615. const_cast<nsStyle##name_ *>(newData); \
  616. return newData; \
  617. }
  618. #define STYLE_STRUCT_RESET(name_, checkdata_cb_) \
  619. template<bool aComputeData> \
  620. const nsStyle##name_ * DoGetStyle##name_() { \
  621. if (mCachedResetData) { \
  622. const nsStyle##name_ * cachedData = \
  623. static_cast<nsStyle##name_*>( \
  624. mCachedResetData->mStyleStructs[eStyleStruct_##name_]); \
  625. if (cachedData) /* Have it cached already, yay */ \
  626. return cachedData; \
  627. } \
  628. /* Have the rulenode deal */ \
  629. AUTO_CHECK_DEPENDENCY(eStyleStruct_##name_); \
  630. const nsStyle##name_ * newData; \
  631. if (mSource.IsGeckoRuleNode()) { \
  632. newData = mSource.AsGeckoRuleNode()-> \
  633. GetStyle##name_<aComputeData>(this); \
  634. } else { \
  635. newData = \
  636. Servo_GetStyle##name_(mSource.AsServoComputedValues()); \
  637. /* perform any remaining main thread work on the struct */ \
  638. const_cast<nsStyle##name_*>(newData)->FinishStyle(PresContext());\
  639. /* The Servo-backed StyleContextSource owns the struct. \
  640. * \
  641. * XXXbholley: Unconditionally caching reset structs here \
  642. * defeats the memory optimization where we lazily allocate \
  643. * mCachedResetData, so that we can avoid performing an FFI \
  644. * call each time we want to get the style structs. We should \
  645. * measure the tradeoffs at some point. If the FFI overhead is \
  646. * low and the memory win significant, we should consider \
  647. * _always_ grabbing the struct over FFI, and potentially \
  648. * giving mCachedInheritedData the same treatment. \
  649. * \
  650. * Note that there is a similar comment in StyleData(). \
  651. */ \
  652. AddStyleBit(NS_STYLE_INHERIT_BIT(name_)); \
  653. SetStyle(eStyleStruct_##name_, \
  654. const_cast<nsStyle##name_*>(newData)); \
  655. } \
  656. return newData; \
  657. }
  658. #include "nsStyleStructList.h"
  659. #undef STYLE_STRUCT_RESET
  660. #undef STYLE_STRUCT_INHERITED
  661. // Helper for ClearCachedInheritedStyleDataOnDescendants.
  662. void DoClearCachedInheritedStyleDataOnDescendants(uint32_t aStructs);
  663. #ifdef DEBUG
  664. void AssertStructsNotUsedElsewhere(nsStyleContext* aDestroyingContext,
  665. int32_t aLevels) const;
  666. #endif
  667. #ifdef RESTYLE_LOGGING
  668. void LogStyleContextTree(bool aFirst, uint32_t aStructs);
  669. // This only gets called under call trees where we've already checked
  670. // that PresContext()->RestyleManager()->ShouldLogRestyle() returned true.
  671. // It exists here just to satisfy LOG_RESTYLE's expectations.
  672. bool ShouldLogRestyle() { return true; }
  673. #endif
  674. RefPtr<nsStyleContext> mParent;
  675. // Children are kept in two circularly-linked lists. The list anchor
  676. // is not part of the list (null for empty), and we point to the first
  677. // child.
  678. // mEmptyChild for children whose rule node is the root rule node, and
  679. // mChild for other children. The order of children is not
  680. // meaningful.
  681. nsStyleContext* mChild;
  682. nsStyleContext* mEmptyChild;
  683. nsStyleContext* mPrevSibling;
  684. nsStyleContext* mNextSibling;
  685. // Style to be used instead for the R, G, and B components of color,
  686. // background-color, and border-*-color if the nearest ancestor link
  687. // element is visited (see RelevantLinkVisited()).
  688. RefPtr<nsStyleContext> mStyleIfVisited;
  689. // If this style context is for a pseudo-element or anonymous box,
  690. // the relevant atom.
  691. nsCOMPtr<nsIAtom> mPseudoTag;
  692. // The source for our style data, either a Gecko nsRuleNode or a Servo
  693. // ComputedValues struct. This never changes after construction, except
  694. // when it's released and nulled out during teardown.
  695. const mozilla::OwningStyleContextSource mSource;
  696. #ifdef MOZ_STYLO
  697. // In Gecko, we can get this off the rule node. We make this conditional
  698. // on stylo builds to avoid the memory bloat on release.
  699. nsPresContext* mPresContext;
  700. #endif
  701. // mCachedInheritedData and mCachedResetData point to both structs that
  702. // are owned by this style context and structs that are owned by one of
  703. // this style context's ancestors (which are indirectly owned since this
  704. // style context owns a reference to its parent). If the bit in |mBits|
  705. // is set for a struct, that means that the pointer for that struct is
  706. // owned by an ancestor or by the rule node rather than by this style context.
  707. // Since style contexts typically have some inherited data but only sometimes
  708. // have reset data, we always allocate the mCachedInheritedData, but only
  709. // sometimes allocate the mCachedResetData.
  710. nsResetStyleData* mCachedResetData; // Cached reset style data.
  711. nsInheritedStyleData mCachedInheritedData; // Cached inherited style data
  712. // mBits stores a number of things:
  713. // - It records (using the style struct bits) which structs are
  714. // inherited from the parent context or owned by the rule node (i.e.,
  715. // not owned by the style context).
  716. // - It also stores the additional bits listed at the top of
  717. // nsStyleStruct.h.
  718. uint64_t mBits;
  719. uint32_t mRefCnt;
  720. // For now we store change hints on the style context during parallel traversal.
  721. // We should improve this - see bug 1289861.
  722. #ifdef MOZ_STYLO
  723. nsChangeHint mStoredChangeHint;
  724. #ifdef DEBUG
  725. bool mConsumedChangeHint;
  726. #endif
  727. #endif
  728. #ifdef DEBUG
  729. uint32_t mFrameRefCnt; // number of frames that use this
  730. // as their style context
  731. nsStyleStructID mComputingStruct;
  732. static bool DependencyAllowed(nsStyleStructID aOuterSID,
  733. nsStyleStructID aInnerSID)
  734. {
  735. return !!(sDependencyTable[aOuterSID] &
  736. nsCachedStyleData::GetBitForSID(aInnerSID));
  737. }
  738. static const uint32_t sDependencyTable[];
  739. #endif
  740. };
  741. already_AddRefed<nsStyleContext>
  742. NS_NewStyleContext(nsStyleContext* aParentContext,
  743. nsIAtom* aPseudoTag,
  744. mozilla::CSSPseudoElementType aPseudoType,
  745. nsRuleNode* aRuleNode,
  746. bool aSkipParentDisplayBasedStyleFixup);
  747. already_AddRefed<nsStyleContext>
  748. NS_NewStyleContext(nsStyleContext* aParentContext,
  749. nsPresContext* aPresContext,
  750. nsIAtom* aPseudoTag,
  751. mozilla::CSSPseudoElementType aPseudoType,
  752. already_AddRefed<ServoComputedValues> aComputedValues,
  753. bool aSkipParentDisplayBasedStyleFixup);
  754. #endif