tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Rule.cpp (5197B)


      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 /* base class for all rule types in a CSS style sheet */
      8 
      9 #include "Rule.h"
     10 
     11 #include "mozilla/HoldDropJSObjects.h"
     12 #include "mozilla/ServoBindings.h"
     13 #include "mozilla/css/GroupRule.h"
     14 #include "mozilla/dom/CSSImportRule.h"
     15 #include "mozilla/dom/Document.h"
     16 #include "mozilla/dom/DocumentOrShadowRoot.h"
     17 #include "nsCCUncollectableMarker.h"
     18 #include "nsWrapperCacheInlines.h"
     19 
     20 using namespace mozilla;
     21 using namespace mozilla::dom;
     22 
     23 namespace mozilla::css {
     24 
     25 NS_IMPL_CYCLE_COLLECTING_ADDREF(Rule)
     26 NS_IMPL_CYCLE_COLLECTING_RELEASE(Rule)
     27 
     28 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Rule)
     29  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
     30  NS_INTERFACE_MAP_ENTRY(nsISupports)
     31 NS_INTERFACE_MAP_END
     32 
     33 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(Rule)
     34 
     35 bool Rule::IsCCLeaf() const { return !PreservingWrapper(); }
     36 
     37 bool Rule::IsKnownLive() const {
     38  if (HasKnownLiveWrapper()) {
     39    return true;
     40  }
     41 
     42  StyleSheet* sheet = GetStyleSheet();
     43  if (!sheet) {
     44    return false;
     45  }
     46 
     47  Document* doc = sheet->GetKeptAliveByDocument();
     48  return doc &&
     49         nsCCUncollectableMarker::InGeneration(doc->GetMarkedCCGeneration());
     50 }
     51 
     52 void Rule::UnlinkDeclarationWrapper(nsWrapperCache& aDecl) {
     53  // We have to be a bit careful here. We have two separate nsWrapperCache
     54  // instances, aDecl and this, that both correspond to the same CC participant:
     55  // this. If we just used ReleaseWrapper() on one of them, that would
     56  // unpreserve that one wrapper, then trace us with a tracer that clears JS
     57  // things, and we would clear the wrapper on the cache that has not
     58  // unpreserved the wrapper yet. That would violate the invariant that the
     59  // cache keeps caching the wrapper until the wrapper dies.
     60  //
     61  // So instead we use a special case version of ReleaseWrapper to unpreserve
     62  // both wrappers before doing any clearing.
     63  bool needDrop = PreservingWrapper() || aDecl.PreservingWrapper();
     64  ReleaseWrapperWithoutDrop();
     65  aDecl.ReleaseWrapperWithoutDrop();
     66  if (needDrop) {
     67    DropJSObjects(this);
     68  }
     69 }
     70 
     71 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(Rule)
     72  return tmp->IsCCLeaf() || tmp->IsKnownLive();
     73 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
     74 
     75 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(Rule)
     76  // Please see documentation for nsCycleCollectionParticipant::CanSkip* for why
     77  // we need to check HasNothingToTrace here but not in the other two CanSkip
     78  // methods.
     79  return tmp->IsCCLeaf() || (tmp->IsKnownLive() && tmp->HasNothingToTrace(tmp));
     80 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
     81 
     82 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(Rule)
     83  return tmp->IsCCLeaf() || tmp->IsKnownLive();
     84 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
     85 
     86 /* virtual */
     87 void Rule::DropSheetReference() { mSheet = nullptr; }
     88 
     89 void Rule::SetCssText(const nsACString& aCssText) {
     90  // We used to throw for some rule types, but not all.  Specifically, we did
     91  // not throw for StyleRule.  Let's just always not throw.
     92 }
     93 
     94 Rule* Rule::GetParentRule() const { return mParentRule; }
     95 
     96 #ifdef DEBUG
     97 void Rule::AssertParentRuleType() {
     98  // Would be nice to check that this->Type() is StyleCssRuleType::Keyframe
     99  // when mParentRule->Tye() is StyleCssRuleType::Keyframes, but we can't call
    100  // this->Type() here since it's virtual.
    101  // Same for StyleCssRuleType::Margin and StyleCssRuleType::Page.
    102  if (mParentRule) {
    103    auto type = mParentRule->Type();
    104    MOZ_ASSERT(type == StyleCssRuleType::Media ||
    105               type == StyleCssRuleType::Style ||
    106               type == StyleCssRuleType::Document ||
    107               type == StyleCssRuleType::Supports ||
    108               type == StyleCssRuleType::Keyframes ||
    109               type == StyleCssRuleType::LayerBlock ||
    110               type == StyleCssRuleType::Container ||
    111               type == StyleCssRuleType::Scope ||
    112               type == StyleCssRuleType::StartingStyle ||
    113               type == StyleCssRuleType::Page);
    114  }
    115 }
    116 #endif
    117 
    118 bool Rule::IsReadOnly() const {
    119  MOZ_ASSERT(!mSheet || !mParentRule ||
    120                 mSheet->IsReadOnly() == mParentRule->IsReadOnly(),
    121             "a parent rule should be read only iff the owning sheet is "
    122             "read only");
    123  return mSheet && mSheet->IsReadOnly();
    124 }
    125 
    126 bool Rule::IsIncompleteImportRule() const {
    127  if (Type() != StyleCssRuleType::Import) {
    128    return false;
    129  }
    130  auto* sheet = static_cast<const dom::CSSImportRule*>(this)->GetStyleSheet();
    131  return !sheet || !sheet->IsComplete();
    132 }
    133 
    134 auto Rule::GetContainingRuleStateForParsing() const -> ContainingRuleState {
    135  ContainingRuleState result;
    136  for (const auto* rule = this; rule; rule = rule->GetParentRule()) {
    137    auto type = rule->Type();
    138    result.mContainingTypes |= (1 << UnderlyingValue(type));
    139    if (result.mParseRelativeType.isNothing() &&
    140        (type == StyleCssRuleType::Style || type == StyleCssRuleType::Scope)) {
    141      result.mParseRelativeType.emplace(type);
    142    }
    143  }
    144  return result;
    145 }
    146 
    147 }  // namespace mozilla::css