LCOV - code coverage report
Current view: top level - dom/base - nsMappedAttributes.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 84 163 51.5 %
Date: 2017-07-14 16:53:18 Functions: 16 27 59.3 %
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             :  * A unique per-element set of attributes that is used as an
       9             :  * nsIStyleRule; used to implement presentational attributes.
      10             :  */
      11             : 
      12             : #include "nsMappedAttributes.h"
      13             : #include "nsHTMLStyleSheet.h"
      14             : #include "nsRuleData.h"
      15             : #include "nsRuleWalker.h"
      16             : #include "mozilla/GenericSpecifiedValues.h"
      17             : #include "mozilla/HashFunctions.h"
      18             : #include "mozilla/MemoryReporting.h"
      19             : #include "mozilla/ServoDeclarationBlock.h"
      20             : #include "mozilla/ServoSpecifiedValues.h"
      21             : 
      22             : using namespace mozilla;
      23             : 
      24             : bool
      25             : nsMappedAttributes::sShuttingDown = false;
      26             : nsTArray<void*>*
      27             : nsMappedAttributes::sCachedMappedAttributeAllocations = nullptr;
      28             : 
      29             : void
      30           0 : nsMappedAttributes::Shutdown()
      31             : {
      32           0 :   sShuttingDown = true;
      33           0 :   if (sCachedMappedAttributeAllocations) {
      34           0 :     for (uint32_t i = 0; i < sCachedMappedAttributeAllocations->Length(); ++i) {
      35           0 :       void* cachedValue = (*sCachedMappedAttributeAllocations)[i];
      36             :       ::operator delete(cachedValue);
      37             :     }
      38             :   }
      39             : 
      40           0 :   delete sCachedMappedAttributeAllocations;
      41           0 :   sCachedMappedAttributeAllocations = nullptr;
      42           0 : }
      43             : 
      44          33 : nsMappedAttributes::nsMappedAttributes(nsHTMLStyleSheet* aSheet,
      45          33 :                                        nsMapRuleToAttributesFunc aMapRuleFunc)
      46             :   : mAttrCount(0),
      47             :     mSheet(aSheet),
      48             :     mRuleMapper(aMapRuleFunc),
      49          33 :     mServoStyle(nullptr)
      50             : {
      51          33 :   MOZ_ASSERT(mRefCnt == 0); // Ensure caching works as expected.
      52          33 : }
      53             : 
      54           0 : nsMappedAttributes::nsMappedAttributes(const nsMappedAttributes& aCopy)
      55           0 :   : mAttrCount(aCopy.mAttrCount),
      56           0 :     mSheet(aCopy.mSheet),
      57           0 :     mRuleMapper(aCopy.mRuleMapper),
      58             :     // This is only called by ::Clone, which is used to create independent
      59             :     // nsMappedAttributes objects which should not share a ServoDeclarationBlock
      60           0 :     mServoStyle(nullptr)
      61             : {
      62           0 :   NS_ASSERTION(mBufferSize >= aCopy.mAttrCount, "can't fit attributes");
      63           0 :   MOZ_ASSERT(mRefCnt == 0); // Ensure caching works as expected.
      64             : 
      65             :   uint32_t i;
      66           0 :   for (i = 0; i < mAttrCount; ++i) {
      67           0 :     new (&Attrs()[i]) InternalAttr(aCopy.Attrs()[i]);
      68             :   }
      69           0 : }
      70             : 
      71           2 : nsMappedAttributes::~nsMappedAttributes()
      72             : {
      73           1 :   if (mSheet) {
      74           0 :     mSheet->DropMappedAttributes(this);
      75             :   }
      76             : 
      77             :   uint32_t i;
      78           2 :   for (i = 0; i < mAttrCount; ++i) {
      79           1 :     Attrs()[i].~InternalAttr();
      80             :   }
      81           1 : }
      82             : 
      83             : 
      84             : nsMappedAttributes*
      85           0 : nsMappedAttributes::Clone(bool aWillAddAttr)
      86             : {
      87           0 :   uint32_t extra = aWillAddAttr ? 1 : 0;
      88             : 
      89             :   // This will call the overridden operator new
      90           0 :   return new (mAttrCount + extra) nsMappedAttributes(*this);
      91             : }
      92             : 
      93          33 : void* nsMappedAttributes::operator new(size_t aSize, uint32_t aAttrCount) CPP_THROW_NEW
      94             : {
      95             : 
      96          33 :   size_t size = aSize + aAttrCount * sizeof(InternalAttr);
      97             : 
      98             :   // aSize will include the mAttrs buffer so subtract that.
      99             :   // We don't want to under-allocate, however, so do not subtract
     100             :   // if we have zero attributes. The zero attribute case only happens
     101             :   // for <body>'s mapped attributes
     102          33 :   if (aAttrCount != 0) {
     103          26 :     size -= sizeof(void*[1]);
     104             :   }
     105             : 
     106          33 :   if (sCachedMappedAttributeAllocations) {
     107             :     void* cached =
     108          26 :       sCachedMappedAttributeAllocations->SafeElementAt(aAttrCount);
     109          26 :     if (cached) {
     110           1 :       (*sCachedMappedAttributeAllocations)[aAttrCount] = nullptr;
     111           1 :       return cached;
     112             :     }
     113             :   }
     114             : 
     115          32 :   void* newAttrs = ::operator new(size);
     116             : 
     117             : #ifdef DEBUG
     118          32 :   static_cast<nsMappedAttributes*>(newAttrs)->mBufferSize = aAttrCount;
     119             : #endif
     120          32 :   return newAttrs;
     121             : }
     122             : 
     123             : void
     124           1 : nsMappedAttributes::LastRelease()
     125             : {
     126           1 :   if (!sShuttingDown) {
     127           1 :     if (!sCachedMappedAttributeAllocations) {
     128           1 :       sCachedMappedAttributeAllocations = new nsTArray<void*>();
     129             :     }
     130             : 
     131             :     // Ensure the cache array is at least mAttrCount + 1 long and
     132             :     // that each item is either null or pointing to a cached item.
     133             :     // The size of the array is capped because mapped attributes are defined
     134             :     // statically in element implementations.
     135           1 :     sCachedMappedAttributeAllocations->SetCapacity(mAttrCount + 1);
     136           3 :     for (uint32_t i = sCachedMappedAttributeAllocations->Length();
     137           3 :          i < (uint32_t(mAttrCount) + 1); ++i) {
     138           2 :       sCachedMappedAttributeAllocations->AppendElement(nullptr);
     139             :     }
     140             : 
     141           1 :     if (!(*sCachedMappedAttributeAllocations)[mAttrCount]) {
     142           1 :       void* memoryToCache = this;
     143           1 :       this->~nsMappedAttributes();
     144           1 :       (*sCachedMappedAttributeAllocations)[mAttrCount] = memoryToCache;
     145           1 :       return;
     146             :     }
     147             :   }
     148             : 
     149           0 :   delete this;
     150             : }
     151             : 
     152         132 : NS_IMPL_ADDREF(nsMappedAttributes)
     153          70 : NS_IMPL_RELEASE_WITH_DESTROY(nsMappedAttributes, LastRelease())
     154             : 
     155         173 : NS_IMPL_QUERY_INTERFACE(nsMappedAttributes,
     156             :                         nsIStyleRule)
     157             : 
     158             : void
     159          26 : nsMappedAttributes::SetAndSwapAttr(nsIAtom* aAttrName, nsAttrValue& aValue,
     160             :                                    bool* aValueWasSet)
     161             : {
     162          26 :   NS_PRECONDITION(aAttrName, "null name");
     163          26 :   *aValueWasSet = false;
     164             :   uint32_t i;
     165          26 :   for (i = 0; i < mAttrCount && !Attrs()[i].mName.IsSmaller(aAttrName); ++i) {
     166           0 :     if (Attrs()[i].mName.Equals(aAttrName)) {
     167           0 :       Attrs()[i].mValue.SwapValueWith(aValue);
     168           0 :       *aValueWasSet = true;
     169           0 :       return;
     170             :     }
     171             :   }
     172             : 
     173          26 :   NS_ASSERTION(mBufferSize >= mAttrCount + 1, "can't fit attributes");
     174             : 
     175          26 :   if (mAttrCount != i) {
     176           0 :     memmove(&Attrs()[i + 1], &Attrs()[i], (mAttrCount - i) * sizeof(InternalAttr));
     177             :   }
     178             : 
     179          26 :   new (&Attrs()[i].mName) nsAttrName(aAttrName);
     180          26 :   new (&Attrs()[i].mValue) nsAttrValue();
     181          26 :   Attrs()[i].mValue.SwapValueWith(aValue);
     182          26 :   ++mAttrCount;
     183             : }
     184             : 
     185             : const nsAttrValue*
     186         402 : nsMappedAttributes::GetAttr(nsIAtom* aAttrName) const
     187             : {
     188         402 :   NS_PRECONDITION(aAttrName, "null name");
     189             : 
     190         634 :   for (uint32_t i = 0; i < mAttrCount; ++i) {
     191         357 :     if (Attrs()[i].mName.Equals(aAttrName)) {
     192         125 :       return &Attrs()[i].mValue;
     193             :     }
     194             :   }
     195             : 
     196         277 :   return nullptr;
     197             : }
     198             : 
     199             : const nsAttrValue*
     200           0 : nsMappedAttributes::GetAttr(const nsAString& aAttrName) const
     201             : {
     202           0 :   for (uint32_t i = 0; i < mAttrCount; ++i) {
     203           0 :     if (Attrs()[i].mName.Atom()->Equals(aAttrName)) {
     204           0 :       return &Attrs()[i].mValue;
     205             :     }
     206             :   }
     207             : 
     208           0 :   return nullptr;
     209             : }
     210             : 
     211             : bool
     212           1 : nsMappedAttributes::Equals(const nsMappedAttributes* aOther) const
     213             : {
     214           1 :   if (this == aOther) {
     215           0 :     return true;
     216             :   }
     217             : 
     218           1 :   if (mRuleMapper != aOther->mRuleMapper || mAttrCount != aOther->mAttrCount) {
     219           0 :     return false;
     220             :   }
     221             : 
     222             :   uint32_t i;
     223           2 :   for (i = 0; i < mAttrCount; ++i) {
     224           2 :     if (!Attrs()[i].mName.Equals(aOther->Attrs()[i].mName) ||
     225           1 :         !Attrs()[i].mValue.Equals(aOther->Attrs()[i].mValue)) {
     226           0 :       return false;
     227             :     }
     228             :   }
     229             : 
     230           1 :   return true;
     231             : }
     232             : 
     233             : PLDHashNumber
     234          33 : nsMappedAttributes::HashValue() const
     235             : {
     236          33 :   PLDHashNumber hash = HashGeneric(mRuleMapper);
     237             : 
     238             :   uint32_t i;
     239          59 :   for (i = 0; i < mAttrCount; ++i) {
     240          52 :     hash = AddToHash(hash,
     241          26 :                      Attrs()[i].mName.HashValue(),
     242          26 :                      Attrs()[i].mValue.HashValue());
     243             :   }
     244             : 
     245          33 :   return hash;
     246             : }
     247             : 
     248             : void
     249           0 : nsMappedAttributes::SetStyleSheet(nsHTMLStyleSheet* aSheet)
     250             : {
     251           0 :   if (mSheet) {
     252           0 :     mSheet->DropMappedAttributes(this);
     253             :   }
     254           0 :   mSheet = aSheet;  // not ref counted
     255           0 : }
     256             : 
     257             : /* virtual */ void
     258         172 : nsMappedAttributes::MapRuleInfoInto(nsRuleData* aRuleData)
     259             : {
     260         172 :   if (mRuleMapper) {
     261         172 :     (*mRuleMapper)(this, aRuleData);
     262             :   }
     263         172 : }
     264             : 
     265             : /* virtual */ bool
     266           0 : nsMappedAttributes::MightMapInheritedStyleData()
     267             : {
     268             :   // Just assume that we do, rather than adding checks to all of the different
     269             :   // kinds of attribute mapping functions we have.
     270           0 :   return true;
     271             : }
     272             : 
     273             : /* virtual */ bool
     274           0 : nsMappedAttributes::GetDiscretelyAnimatedCSSValue(nsCSSPropertyID aProperty,
     275             :                                                   nsCSSValue* aValue)
     276             : {
     277           0 :   MOZ_ASSERT(false, "GetDiscretelyAnimatedCSSValue is not implemented yet");
     278             :   return false;
     279             : }
     280             : 
     281             : #ifdef DEBUG
     282             : /* virtual */ void
     283           0 : nsMappedAttributes::List(FILE* out, int32_t aIndent) const
     284             : {
     285           0 :   nsAutoCString str;
     286           0 :   nsAutoString tmp;
     287             :   uint32_t i;
     288             : 
     289           0 :   for (i = 0; i < mAttrCount; ++i) {
     290             :     int32_t indent;
     291           0 :     for (indent = aIndent; indent > 0; --indent) {
     292           0 :       str.AppendLiteral("  ");
     293             :     }
     294             : 
     295           0 :     Attrs()[i].mName.GetQualifiedName(tmp);
     296           0 :     LossyAppendUTF16toASCII(tmp, str);
     297             : 
     298           0 :     Attrs()[i].mValue.ToString(tmp);
     299           0 :     LossyAppendUTF16toASCII(tmp, str);
     300           0 :     str.Append('\n');
     301           0 :     fprintf_stderr(out, "%s", str.get());
     302             :   }
     303           0 : }
     304             : #endif
     305             : 
     306             : void
     307           0 : nsMappedAttributes::RemoveAttrAt(uint32_t aPos, nsAttrValue& aValue)
     308             : {
     309           0 :   Attrs()[aPos].mValue.SwapValueWith(aValue);
     310           0 :   Attrs()[aPos].~InternalAttr();
     311           0 :   memmove(&Attrs()[aPos], &Attrs()[aPos + 1],
     312           0 :           (mAttrCount - aPos - 1) * sizeof(InternalAttr));
     313           0 :   mAttrCount--;
     314           0 : }
     315             : 
     316             : const nsAttrName*
     317           0 : nsMappedAttributes::GetExistingAttrNameFromQName(const nsAString& aName) const
     318             : {
     319             :   uint32_t i;
     320           0 :   for (i = 0; i < mAttrCount; ++i) {
     321           0 :     if (Attrs()[i].mName.IsAtom()) {
     322           0 :       if (Attrs()[i].mName.Atom()->Equals(aName)) {
     323           0 :         return &Attrs()[i].mName;
     324             :       }
     325             :     }
     326             :     else {
     327           0 :       if (Attrs()[i].mName.NodeInfo()->QualifiedNameEquals(aName)) {
     328           0 :         return &Attrs()[i].mName;
     329             :       }
     330             :     }
     331             :   }
     332             : 
     333           0 :   return nullptr;
     334             : }
     335             : 
     336             : int32_t
     337         135 : nsMappedAttributes::IndexOfAttr(nsIAtom* aLocalName) const
     338             : {
     339             :   uint32_t i;
     340         231 :   for (i = 0; i < mAttrCount; ++i) {
     341         132 :     if (Attrs()[i].mName.Equals(aLocalName)) {
     342          36 :       return i;
     343             :     }
     344             :   }
     345             : 
     346          99 :   return -1;
     347             : }
     348             : 
     349             : size_t
     350          21 : nsMappedAttributes::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
     351             : {
     352          21 :   NS_ASSERTION(mAttrCount == mBufferSize,
     353             :                "mBufferSize and mAttrCount are expected to be the same.");
     354             : 
     355          21 :   size_t n = aMallocSizeOf(this);
     356          42 :   for (uint16_t i = 0; i < mAttrCount; ++i) {
     357          21 :     n += Attrs()[i].mValue.SizeOfExcludingThis(aMallocSizeOf);
     358             :   }
     359          21 :   return n;
     360             : }
     361             : 
     362             : void
     363           0 : nsMappedAttributes::LazilyResolveServoDeclaration(nsPresContext* aContext)
     364             : {
     365             : 
     366           0 :   MOZ_ASSERT(!mServoStyle,
     367             :              "LazilyResolveServoDeclaration should not be called if mServoStyle is already set");
     368           0 :   if (mRuleMapper) {
     369           0 :     mServoStyle = Servo_DeclarationBlock_CreateEmpty().Consume();
     370           0 :     ServoSpecifiedValues servo = ServoSpecifiedValues(aContext, mServoStyle.get());
     371           0 :     (*mRuleMapper)(this, &servo);
     372             :   }
     373           9 : }

Generated by: LCOV version 1.13