LCOV - code coverage report
Current view: top level - layout/style - DeclarationBlock.h (source / functions) Hit Total Coverage
Test: output.info Lines: 18 56 32.1 %
Date: 2018-08-07 16:42:27 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : /*
       8             :  * representation of a declaration block in a CSS stylesheet, or of
       9             :  * a style attribute
      10             :  */
      11             : 
      12             : #ifndef mozilla_DeclarationBlock_h
      13             : #define mozilla_DeclarationBlock_h
      14             : 
      15             : #include "mozilla/Atomics.h"
      16             : #include "mozilla/ServoBindings.h"
      17             : 
      18             : #include "nsCSSPropertyID.h"
      19             : 
      20             : class nsHTMLCSSStyleSheet;
      21             : 
      22             : namespace mozilla {
      23             : 
      24             : namespace css {
      25             : class Declaration;
      26             : class Rule;
      27             : } // namespace css
      28             : 
      29             : class DeclarationBlock final
      30             : {
      31          11 :   DeclarationBlock(const DeclarationBlock& aCopy)
      32           0 :     : mRaw(Servo_DeclarationBlock_Clone(aCopy.mRaw).Consume())
      33             :     , mImmutable(false)
      34           0 :     , mIsDirty(false)
      35             :   {
      36           0 :     mContainer.mRaw = 0;
      37          11 :   }
      38             : 
      39             : public:
      40          32 :   explicit DeclarationBlock(already_AddRefed<RawServoDeclarationBlock> aRaw)
      41           0 :     : mRaw(aRaw)
      42             :     , mImmutable(false)
      43         128 :     , mIsDirty(false)
      44             :   {
      45           0 :     mContainer.mRaw = 0;
      46          32 :   }
      47             : 
      48          26 :   DeclarationBlock()
      49           0 :     : DeclarationBlock(Servo_DeclarationBlock_CreateEmpty().Consume())
      50           0 :   { }
      51             : 
      52           0 :   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DeclarationBlock)
      53             : 
      54           0 :   already_AddRefed<DeclarationBlock> Clone() const
      55             :   {
      56           0 :     return do_AddRef(new DeclarationBlock(*this));
      57             :   }
      58             : 
      59             :   /**
      60             :    * Return whether |this| may be modified.
      61             :    */
      62             :   bool IsMutable() const { return !mImmutable; }
      63             : 
      64             :   /**
      65             :    * Crash in debug builds if |this| cannot be modified.
      66             :    */
      67           3 :   void AssertMutable() const
      68             :   {
      69           0 :     MOZ_ASSERT(IsMutable(), "someone forgot to call EnsureMutable");
      70           0 :   }
      71             : 
      72             :   /**
      73             :    * Mark this declaration as unmodifiable.
      74             :    */
      75           0 :   void SetImmutable() { mImmutable = true; }
      76             : 
      77             :   /**
      78             :    * Return whether |this| has been restyled after modified.
      79             :    */
      80           4 :   bool IsDirty() const { return mIsDirty; }
      81             : 
      82             :   /**
      83             :    * Mark this declaration as dirty.
      84             :    */
      85           2 :   void SetDirty() { mIsDirty = true; }
      86             : 
      87             :   /**
      88             :    * Mark this declaration as not dirty.
      89             :    */
      90          16 :   void UnsetDirty() { mIsDirty = false; }
      91             : 
      92             :   /**
      93             :    * Copy |this|, if necessary to ensure that it can be modified.
      94             :    */
      95           4 :   already_AddRefed<DeclarationBlock> EnsureMutable()
      96             :   {
      97           4 :     if (!IsDirty()) {
      98             :       // In stylo, the old DeclarationBlock is stored in element's rule node tree
      99             :       // directly, to avoid new values replacing the DeclarationBlock in the tree
     100             :       // directly, we need to copy the old one here if we haven't yet copied.
     101             :       // As a result the new value does not replace rule node tree until traversal
     102             :       // happens.
     103             :       //
     104             :       // FIXME(emilio): This is a hack for ::first-line and transitions starting
     105             :       // due to CSSOM changes when other transitions are already running. Try
     106             :       // to simplify this setup.
     107           2 :       return Clone();
     108             :     }
     109             : 
     110           0 :     if (!IsMutable()) {
     111           0 :       return Clone();
     112             :     }
     113             : 
     114           2 :     return do_AddRef(this);
     115             :   }
     116             : 
     117           0 :   void SetOwningRule(css::Rule* aRule)
     118             :   {
     119           0 :     MOZ_ASSERT(!mContainer.mOwningRule || !aRule,
     120             :                "should never overwrite one rule with another");
     121           0 :     mContainer.mOwningRule = aRule;
     122           0 :   }
     123             : 
     124             :   css::Rule* GetOwningRule() const
     125             :   {
     126             :     if (mContainer.mRaw & 0x1) {
     127             :       return nullptr;
     128             :     }
     129             :     return mContainer.mOwningRule;
     130             :   }
     131             : 
     132           0 :   void SetHTMLCSSStyleSheet(nsHTMLCSSStyleSheet* aHTMLCSSStyleSheet)
     133             :   {
     134           0 :     MOZ_ASSERT(!mContainer.mHTMLCSSStyleSheet || !aHTMLCSSStyleSheet,
     135             :                "should never overwrite one sheet with another");
     136           0 :     mContainer.mHTMLCSSStyleSheet = aHTMLCSSStyleSheet;
     137           0 :     if (aHTMLCSSStyleSheet) {
     138           0 :       mContainer.mRaw |= uintptr_t(1);
     139             :     }
     140           0 :   }
     141             : 
     142           0 :   nsHTMLCSSStyleSheet* GetHTMLCSSStyleSheet() const
     143             :   {
     144           0 :     if (!(mContainer.mRaw & 0x1)) {
     145             :       return nullptr;
     146             :     }
     147           0 :     auto c = mContainer;
     148           0 :     c.mRaw &= ~uintptr_t(1);
     149           0 :     return c.mHTMLCSSStyleSheet;
     150             :   }
     151             : 
     152             :   static already_AddRefed<DeclarationBlock>
     153             :   FromCssText(const nsAString& aCssText, URLExtraData* aExtraData,
     154             :               nsCompatibility aMode, css::Loader* aLoader);
     155             : 
     156         110 :   RawServoDeclarationBlock* Raw() const { return mRaw; }
     157             :   RawServoDeclarationBlock* const* RefRaw() const
     158             :   {
     159             :     static_assert(sizeof(RefPtr<RawServoDeclarationBlock>) ==
     160             :                   sizeof(RawServoDeclarationBlock*),
     161             :                   "RefPtr should just be a pointer");
     162             :     return reinterpret_cast<RawServoDeclarationBlock* const*>(&mRaw);
     163             :   }
     164             : 
     165             :   const RawServoDeclarationBlockStrong* RefRawStrong() const
     166             :   {
     167             :     static_assert(sizeof(RefPtr<RawServoDeclarationBlock>) ==
     168             :                   sizeof(RawServoDeclarationBlock*),
     169             :                   "RefPtr should just be a pointer");
     170             :     static_assert(sizeof(RefPtr<RawServoDeclarationBlock>) ==
     171             :                   sizeof(RawServoDeclarationBlockStrong),
     172             :                   "RawServoDeclarationBlockStrong should be the same as RefPtr");
     173          46 :     return reinterpret_cast<const RawServoDeclarationBlockStrong*>(&mRaw);
     174             :   }
     175             : 
     176           1 :   void ToString(nsAString& aResult) const
     177             :   {
     178           0 :     Servo_DeclarationBlock_GetCssText(mRaw, &aResult);
     179           0 :   }
     180             : 
     181           0 :   uint32_t Count() const
     182             :   {
     183           0 :     return Servo_DeclarationBlock_Count(mRaw);
     184             :   }
     185             : 
     186           0 :   bool GetNthProperty(uint32_t aIndex, nsAString& aReturn) const
     187             :   {
     188           0 :     aReturn.Truncate();
     189           0 :     return Servo_DeclarationBlock_GetNthProperty(mRaw, aIndex, &aReturn);
     190             :   }
     191             : 
     192           2 :   void GetPropertyValue(const nsAString& aProperty, nsAString& aValue) const
     193             :   {
     194           0 :     NS_ConvertUTF16toUTF8 property(aProperty);
     195             :     Servo_DeclarationBlock_GetPropertyValue(mRaw, &property, &aValue);
     196             :   }
     197             : 
     198             :   void GetPropertyValueByID(nsCSSPropertyID aPropID, nsAString& aValue) const
     199             :   {
     200             :     Servo_DeclarationBlock_GetPropertyValueById(mRaw, aPropID, &aValue);
     201             :   }
     202             : 
     203             :   bool GetPropertyIsImportant(const nsAString& aProperty) const
     204             :   {
     205             :     NS_ConvertUTF16toUTF8 property(aProperty);
     206             :     return Servo_DeclarationBlock_GetPropertyIsImportant(mRaw, &property);
     207             :   }
     208             : 
     209             :   // Returns whether the property was removed.
     210             :   bool RemoveProperty(const nsAString& aProperty,
     211             :                       DeclarationBlockMutationClosure aClosure = { })
     212             :   {
     213             :     AssertMutable();
     214             :     NS_ConvertUTF16toUTF8 property(aProperty);
     215             :     return Servo_DeclarationBlock_RemoveProperty(mRaw, &property, aClosure);
     216             :   }
     217             : 
     218             :   // Returns whether the property was removed.
     219             :   bool RemovePropertyByID(nsCSSPropertyID aProperty,
     220             :                           DeclarationBlockMutationClosure aClosure = { })
     221             :   {
     222             :     AssertMutable();
     223             :     return Servo_DeclarationBlock_RemovePropertyById(mRaw, aProperty, aClosure);
     224             :   }
     225             : 
     226             : private:
     227             :   ~DeclarationBlock() = default;
     228             :   union {
     229             :     // We only ever have one of these since we have an
     230             :     // nsHTMLCSSStyleSheet only for style attributes, and style
     231             :     // attributes never have an owning rule.
     232             : 
     233             :     // It's an nsHTMLCSSStyleSheet if the low bit is set.
     234             : 
     235             :     uintptr_t mRaw;
     236             : 
     237             :     // The style rule that owns this declaration.  May be null.
     238             :     css::Rule* mOwningRule;
     239             : 
     240             :     // The nsHTMLCSSStyleSheet that is responsible for this declaration.
     241             :     // Only non-null for style attributes.
     242             :     nsHTMLCSSStyleSheet* mHTMLCSSStyleSheet;
     243             :   } mContainer;
     244             : 
     245             :   RefPtr<RawServoDeclarationBlock> mRaw;
     246             : 
     247             :   // set when declaration put in the rule tree;
     248             :   bool mImmutable;
     249             : 
     250             :   // True if this declaration has not been restyled after modified.
     251             :   //
     252             :   // Since we can clear this flag from style worker threads, we use an Atomic.
     253             :   //
     254             :   // Note that although a single DeclarationBlock can be shared between
     255             :   // different rule nodes (due to the style="" attribute cache), whenever a
     256             :   // DeclarationBlock has its mIsDirty flag set to true, we always clone it to
     257             :   // a unique object first. So when we clear this flag during Servo traversal,
     258             :   // we know that we are clearing it on a DeclarationBlock that has a single
     259             :   // reference, and there is no problem with another user of the same
     260             :   // DeclarationBlock thinking that it is not dirty.
     261             :   Atomic<bool, MemoryOrdering::Relaxed> mIsDirty;
     262             : };
     263             : 
     264             : } // namespace mozilla
     265             : 
     266             : #endif // mozilla_DeclarationBlock_h

Generated by: LCOV version 1.13-14-ga5dd952