tor-browser

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

ShadowParts.cpp (3978B)


      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 "ShadowParts.h"
      8 
      9 #include "nsContentUtils.h"
     10 #include "nsString.h"
     11 
     12 namespace mozilla {
     13 
     14 static bool IsSpace(char16_t aChar) {
     15  return nsContentUtils::IsHTMLWhitespace(aChar);
     16 };
     17 
     18 using SingleMapping = std::pair<RefPtr<nsAtom>, RefPtr<nsAtom>>;
     19 
     20 // https://drafts.csswg.org/css-shadow-parts/#parsing-mapping
     21 //
     22 // Returns null on both tokens to signal an error.
     23 static SingleMapping ParseSingleMapping(const nsAString& aString) {
     24  const char16_t* c = aString.BeginReading();
     25  const char16_t* end = aString.EndReading();
     26 
     27  const auto CollectASequenceOfSpaces = [&c, end]() {
     28    while (c != end && IsSpace(*c)) {
     29      ++c;
     30    }
     31  };
     32 
     33  const auto CollectToken = [&c, end]() -> RefPtr<nsAtom> {
     34    const char16_t* t = c;
     35    while (c != end && !IsSpace(*c) && *c != ':') {
     36      ++c;
     37    }
     38    if (c == t) {
     39      return nullptr;
     40    }
     41    return NS_AtomizeMainThread(Substring(t, c));
     42  };
     43 
     44  // Steps 1 and 2 are variable declarations.
     45  //
     46  // 3. Collect a sequence of code points that are space characters.
     47  CollectASequenceOfSpaces();
     48 
     49  // 4. Collect a sequence of code points that are not space characters or
     50  // U+003A COLON characters, and call the result first token.
     51  RefPtr<nsAtom> firstToken = CollectToken();
     52 
     53  // 5. If first token is empty then return error.
     54  if (!firstToken) {
     55    return {nullptr, nullptr};
     56  }
     57 
     58  // 6. Collect a sequence of code points that are space characters.
     59  CollectASequenceOfSpaces();
     60 
     61  // 7. If the end of the input has been reached, return the pair first
     62  // token/first token.
     63  if (c == end) {
     64    return {firstToken, firstToken};
     65  }
     66 
     67  // 8. If character at position is not a U+003A COLON character, return error.
     68  if (*c != ':') {
     69    return {nullptr, nullptr};
     70  }
     71 
     72  // 9. Consume the U+003A COLON character.
     73  ++c;
     74 
     75  // 10. Collect a sequence of code points that are space characters.
     76  CollectASequenceOfSpaces();
     77 
     78  // 11. Collect a sequence of code points that are not space characters or
     79  // U+003A COLON characters. and let second token be the result.
     80  RefPtr<nsAtom> secondToken = CollectToken();
     81 
     82  // 12. If second token is empty then return error.
     83  if (!secondToken) {
     84    return {nullptr, nullptr};
     85  }
     86 
     87  // 13. Collect a sequence of code points that are space characters.
     88  CollectASequenceOfSpaces();
     89 
     90  // 14. If position is not past the end of input then return error.
     91  if (c != end) {
     92    return {nullptr, nullptr};
     93  }
     94 
     95  // 15. Return the pair first token/second token.
     96  return {std::move(firstToken), std::move(secondToken)};
     97 }
     98 
     99 // https://drafts.csswg.org/css-shadow-parts/#parsing-mapping-list
    100 ShadowParts ShadowParts::Parse(const nsAString& aString) {
    101  ShadowParts parts;
    102 
    103  for (const auto& substring : aString.Split(',')) {
    104    auto mapping = ParseSingleMapping(substring);
    105    if (!mapping.first) {
    106      MOZ_ASSERT(!mapping.second);
    107      continue;
    108    }
    109    nsAtom* second = mapping.second.get();
    110    parts.mMappings.GetOrInsertNew(mapping.first)
    111        ->AppendElement(std::move(mapping.second));
    112    parts.mReverseMappings.InsertOrUpdate(second, std::move(mapping.first));
    113  }
    114 
    115  return parts;
    116 }
    117 
    118 #ifdef DEBUG
    119 void ShadowParts::Dump() const {
    120  if (mMappings.IsEmpty()) {
    121    printf("  (empty)\n");
    122    return;
    123  }
    124  for (auto& entry : mMappings) {
    125    nsAutoCString key;
    126    entry.GetKey()->ToUTF8String(key);
    127    printf("  %s: ", key.get());
    128 
    129    bool first = true;
    130    for (nsAtom* part : *entry.GetData()) {
    131      if (!first) {
    132        printf(", ");
    133      }
    134      first = false;
    135      nsAutoCString value;
    136      part->ToUTF8String(value);
    137      printf("%s", value.get());
    138    }
    139    printf("\n");
    140  }
    141 }
    142 #endif
    143 }  // namespace mozilla