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