tor-browser

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

StylePropertyMapReadOnly.cpp (10378B)


      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 #include "mozilla/dom/StylePropertyMapReadOnly.h"
      8 
      9 #include "CSSUnsupportedValue.h"
     10 #include "mozilla/Assertions.h"
     11 #include "mozilla/ComputedStyle.h"
     12 #include "mozilla/DeclarationBlock.h"
     13 #include "mozilla/ErrorResult.h"
     14 #include "mozilla/RefPtr.h"
     15 #include "mozilla/ServoStyleConsts.h"
     16 #include "mozilla/dom/CSSKeywordValue.h"
     17 #include "mozilla/dom/CSSMathSum.h"
     18 #include "mozilla/dom/CSSNumericArray.h"
     19 #include "mozilla/dom/CSSStyleRule.h"
     20 #include "mozilla/dom/CSSStyleValue.h"
     21 #include "mozilla/dom/CSSUnitValue.h"
     22 #include "mozilla/dom/Element.h"
     23 #include "mozilla/dom/StylePropertyMapReadOnlyBinding.h"
     24 #include "nsCSSProps.h"
     25 #include "nsComputedDOMStyle.h"
     26 #include "nsCycleCollectionParticipant.h"
     27 #include "nsReadableUtils.h"
     28 
     29 namespace mozilla::dom {
     30 
     31 namespace {
     32 
     33 template <typename Source>
     34 struct DeclarationTraits;
     35 
     36 // Specialization for inline style (specified values)
     37 struct InlineStyleDeclarations {};
     38 
     39 template <>
     40 struct DeclarationTraits<InlineStyleDeclarations> {
     41  static StylePropertyTypedValueResult Get(Element* aElement,
     42                                           const nsACString& aProperty,
     43                                           ErrorResult& aRv) {
     44    MOZ_ASSERT(aElement);
     45 
     46    auto result = StylePropertyTypedValueResult::None();
     47 
     48    RefPtr<DeclarationBlock> block = aElement->GetInlineStyleDeclaration();
     49    if (!block) {
     50      return result;
     51    }
     52 
     53    if (!block->GetPropertyTypedValue(aProperty, result)) {
     54      return result;
     55    }
     56 
     57    return result;
     58  }
     59 };
     60 
     61 // Specialization for computed style (computed values)
     62 struct ComputedStyleDeclarations {};
     63 
     64 template <>
     65 struct DeclarationTraits<ComputedStyleDeclarations> {
     66  static StylePropertyTypedValueResult Get(Element* aElement,
     67                                           const nsACString& aProperty,
     68                                           ErrorResult& aRv) {
     69    MOZ_ASSERT(aElement);
     70 
     71    auto result = StylePropertyTypedValueResult::None();
     72 
     73    RefPtr<const ComputedStyle> style =
     74        nsComputedDOMStyle::GetComputedStyle(aElement);
     75    if (!style) {
     76      return result;
     77    }
     78 
     79    if (!style->GetPropertyTypedValue(aProperty, result)) {
     80      return result;
     81    }
     82 
     83    return result;
     84  }
     85 };
     86 
     87 // Specialization for style rule
     88 struct StyleRuleDeclarations {};
     89 template <>
     90 struct DeclarationTraits<StyleRuleDeclarations> {
     91  static StylePropertyTypedValueResult Get(const CSSStyleRule* aRule,
     92                                           const nsACString& aProperty,
     93                                           ErrorResult& aRv) {
     94    MOZ_ASSERT(aRule);
     95 
     96    auto result = StylePropertyTypedValueResult::None();
     97 
     98    if (!aRule->GetDeclarationBlock().GetPropertyTypedValue(aProperty,
     99                                                            result)) {
    100      return result;
    101    }
    102 
    103    return result;
    104  }
    105 };
    106 
    107 }  // namespace
    108 
    109 StylePropertyMapReadOnly::StylePropertyMapReadOnly(Element* aElement,
    110                                                   bool aComputed)
    111    : mParent(aElement), mDeclarations(aElement, aComputed) {
    112  MOZ_ASSERT(mParent);
    113 }
    114 
    115 StylePropertyMapReadOnly::StylePropertyMapReadOnly(CSSStyleRule* aRule)
    116    : mParent(aRule), mDeclarations(aRule) {
    117  MOZ_ASSERT(mParent);
    118 }
    119 
    120 NS_IMPL_CYCLE_COLLECTING_ADDREF(StylePropertyMapReadOnly)
    121 NS_IMPL_CYCLE_COLLECTING_RELEASE(StylePropertyMapReadOnly)
    122 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(StylePropertyMapReadOnly)
    123  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
    124  NS_INTERFACE_MAP_ENTRY(nsISupports)
    125 NS_INTERFACE_MAP_END
    126 
    127 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(StylePropertyMapReadOnly)
    128 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(StylePropertyMapReadOnly)
    129  // Clear out our weak pointers.
    130  tmp->mDeclarations.Unlink();
    131 
    132  NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
    133  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
    134 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    135 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(StylePropertyMapReadOnly)
    136  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
    137 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    138 
    139 nsISupports* StylePropertyMapReadOnly::GetParentObject() const {
    140  return mParent;
    141 }
    142 
    143 JSObject* StylePropertyMapReadOnly::WrapObject(
    144    JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
    145  return StylePropertyMapReadOnly_Binding::Wrap(aCx, this, aGivenProto);
    146 }
    147 
    148 // start of StylePropertyMapReadOnly Web IDL implementation
    149 
    150 // https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymapreadonly-get
    151 //
    152 // XXX This is not yet fully implemented and optimized!
    153 void StylePropertyMapReadOnly::Get(const nsACString& aProperty,
    154                                   OwningUndefinedOrCSSStyleValue& aRetVal,
    155                                   ErrorResult& aRv) const {
    156  if (!mParent) {
    157    aRv.Throw(NS_ERROR_UNEXPECTED);
    158    return;
    159  }
    160  // Step 2.
    161 
    162  NonCustomCSSPropertyId id = nsCSSProps::LookupProperty(aProperty);
    163  if (id == eCSSProperty_UNKNOWN) {
    164    aRv.ThrowTypeError("Invalid property: "_ns + aProperty);
    165    return;
    166  }
    167 
    168  // Step 3.
    169 
    170  const Declarations& declarations = mDeclarations;
    171 
    172  // Step 4.
    173 
    174  auto result = declarations.Get(aProperty, aRv);
    175  if (aRv.Failed()) {
    176    return;
    177  }
    178 
    179  // XXX Move the creation of CSSStyleValue to a dedicated class for example
    180  // CSSStyleValueFactory and eventually split the handling of tags into
    181  // separate methods to make the code more readable and accessible for
    182  // CSSStyleValue::Parse. See bug 2004057
    183 
    184  RefPtr<CSSStyleValue> styleValue;
    185 
    186  switch (result.tag) {
    187    case StylePropertyTypedValueResult::Tag::Typed: {
    188      const auto& typedValue = result.AsTyped();
    189 
    190      switch (typedValue.tag) {
    191        case StyleTypedValue::Tag::Keyword:
    192          styleValue =
    193              MakeRefPtr<CSSKeywordValue>(mParent, typedValue.AsKeyword());
    194          break;
    195 
    196        case StyleTypedValue::Tag::Numeric: {
    197          auto numericValue = typedValue.AsNumeric();
    198 
    199          switch (numericValue.tag) {
    200            case StyleNumericValue::Tag::Unit: {
    201              auto unitValue = numericValue.AsUnit();
    202 
    203              styleValue = MakeRefPtr<CSSUnitValue>(mParent, unitValue.value,
    204                                                    unitValue.unit);
    205              break;
    206            }
    207 
    208            case StyleNumericValue::Tag::Sum: {
    209              auto mathSum = numericValue.AsSum();
    210 
    211              nsTArray<RefPtr<CSSNumericValue>> values;
    212 
    213              for (const auto& value : mathSum.values) {
    214                // XXX Only supporting units for now
    215                if (value.IsUnit()) {
    216                  auto unitValue = value.AsUnit();
    217 
    218                  values.AppendElement(MakeRefPtr<CSSUnitValue>(
    219                      mParent, unitValue.value, unitValue.unit));
    220                }
    221              }
    222 
    223              auto array =
    224                  MakeRefPtr<CSSNumericArray>(mParent, std::move(values));
    225 
    226              styleValue = MakeAndAddRef<CSSMathSum>(mParent, std::move(array));
    227              break;
    228            }
    229          }
    230 
    231          break;
    232        }
    233      }
    234      break;
    235    }
    236 
    237    case StylePropertyTypedValueResult::Tag::Unsupported: {
    238      auto propertyId = CSSPropertyId::FromIdOrCustomProperty(id, aProperty);
    239      auto rawBlock = result.AsUnsupported();
    240      auto block = MakeRefPtr<DeclarationBlock>(rawBlock.Consume());
    241      styleValue = MakeRefPtr<CSSUnsupportedValue>(mParent, propertyId,
    242                                                   std::move(block));
    243      break;
    244    }
    245 
    246    case StylePropertyTypedValueResult::Tag::None:
    247      break;
    248  }
    249 
    250  if (styleValue) {
    251    aRetVal.SetAsCSSStyleValue() = std::move(styleValue);
    252  } else {
    253    aRetVal.SetUndefined();
    254  }
    255 }
    256 
    257 // https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymapreadonly-getall
    258 //
    259 // XXX This is not yet fully implemented and optimized!
    260 void StylePropertyMapReadOnly::GetAll(const nsACString& aProperty,
    261                                      nsTArray<RefPtr<CSSStyleValue>>& aRetVal,
    262                                      ErrorResult& aRv) const {
    263  OwningUndefinedOrCSSStyleValue retVal;
    264 
    265  Get(aProperty, retVal, aRv);
    266  if (aRv.Failed()) {
    267    return;
    268  }
    269 
    270  if (retVal.IsCSSStyleValue()) {
    271    auto styleValue = retVal.GetAsCSSStyleValue();
    272    aRetVal.AppendElement(styleValue);
    273  }
    274 }
    275 
    276 bool StylePropertyMapReadOnly::Has(const nsACString& aProperty,
    277                                   ErrorResult& aRv) const {
    278  aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
    279  return false;
    280 }
    281 
    282 uint32_t StylePropertyMapReadOnly::Size() const { return 0; }
    283 
    284 uint32_t StylePropertyMapReadOnly::GetIterableLength() const { return 0; }
    285 
    286 const nsACString& StylePropertyMapReadOnly::GetKeyAtIndex(
    287    uint32_t aIndex) const {
    288  return EmptyCString();
    289 }
    290 
    291 nsTArray<RefPtr<CSSStyleValue>> StylePropertyMapReadOnly::GetValueAtIndex(
    292    uint32_t aIndex) const {
    293  return nsTArray<RefPtr<CSSStyleValue>>();
    294 }
    295 
    296 // end of StylePropertyMapReadOnly Web IDL implementation
    297 
    298 size_t StylePropertyMapReadOnly::SizeOfExcludingThis(
    299    MallocSizeOf aMallocSizeOf) const {
    300  return 0;
    301 }
    302 
    303 size_t StylePropertyMapReadOnly::SizeOfIncludingThis(
    304    MallocSizeOf aMallocSizeOf) const {
    305  return SizeOfExcludingThis(aMallocSizeOf) + aMallocSizeOf(this);
    306 }
    307 
    308 StylePropertyTypedValueResult StylePropertyMapReadOnly::Declarations::Get(
    309    const nsACString& aProperty, ErrorResult& aRv) const {
    310  switch (mKind) {
    311    case Kind::Inline:
    312      return DeclarationTraits<InlineStyleDeclarations>::Get(mElement,
    313                                                             aProperty, aRv);
    314 
    315    case Kind::Computed:
    316      return DeclarationTraits<ComputedStyleDeclarations>::Get(mElement,
    317                                                               aProperty, aRv);
    318 
    319    case Kind::Rule:
    320      return DeclarationTraits<StyleRuleDeclarations>::Get(mRule, aProperty,
    321                                                           aRv);
    322  }
    323  MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Bad kind value!");
    324 }
    325 
    326 void StylePropertyMapReadOnly::Declarations::Unlink() {
    327  switch (mKind) {
    328    case Kind::Inline:
    329    case Kind::Computed:
    330      mElement = nullptr;
    331      break;
    332 
    333    case Kind::Rule:
    334      mRule = nullptr;
    335      break;
    336  }
    337 }
    338 
    339 }  // namespace mozilla::dom