Bug 1839315: part 4) Link from `SheetLoadData::mWasAlternate` to spec. r=emilio DONTBUILD
[gecko.git] / layout / style / nsCSSPseudoElements.cpp
blob48b4d5c1a70d702b4f30ff540ab64a4e1cd1987e
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/. */
7 /* atom list for CSS pseudo-elements */
9 #include "nsCSSPseudoElements.h"
11 #include "mozilla/ArrayUtils.h"
13 #include "nsCSSAnonBoxes.h"
14 #include "nsDOMString.h"
15 #include "nsGkAtomConsts.h"
16 #include "nsStaticAtomUtils.h"
17 #include "nsStringFwd.h"
19 using namespace mozilla;
21 // Flags data for each of the pseudo-elements.
22 /* static */ const uint32_t nsCSSPseudoElements::kPseudoElementFlags[] = {
23 #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) flags_,
24 #include "nsCSSPseudoElementList.h"
25 #undef CSS_PSEUDO_ELEMENT
28 /* static */
29 nsStaticAtom* nsCSSPseudoElements::GetAtomBase() {
30 return const_cast<nsStaticAtom*>(
31 nsGkAtoms::GetAtomByIndex(kAtomIndex_PseudoElements));
34 /* static */
35 nsAtom* nsCSSPseudoElements::GetPseudoAtom(Type aType) {
36 MOZ_ASSERT(PseudoStyle::IsPseudoElement(aType), "Unexpected type");
37 size_t index = kAtomIndex_PseudoElements + static_cast<size_t>(aType);
38 return nsGkAtoms::GetAtomByIndex(index);
41 /* static */
42 std::tuple<mozilla::Maybe<PseudoStyleType>, RefPtr<nsAtom>>
43 nsCSSPseudoElements::ParsePseudoElement(const nsAString& aPseudoElement,
44 CSSEnabledState aEnabledState) {
45 if (DOMStringIsNull(aPseudoElement) || aPseudoElement.IsEmpty()) {
46 return {Some(PseudoStyleType::NotPseudo), nullptr};
49 if (aPseudoElement.First() != char16_t(':')) {
50 return {};
53 // deal with two-colon forms of aPseudoElt
54 const char16_t* start = aPseudoElement.BeginReading();
55 const char16_t* end = aPseudoElement.EndReading();
56 NS_ASSERTION(start != end, "aPseudoElement is not empty!");
57 ++start;
58 bool haveTwoColons = true;
59 if (start == end || *start != char16_t(':')) {
60 --start;
61 haveTwoColons = false;
64 // XXX jjaschke: this parsing algorithm should be replaced by the css parser
65 // for correct handling of all edge cases. See Bug 1845712.
66 const int32_t parameterPosition = aPseudoElement.FindChar('(');
67 const bool hasParameter = parameterPosition != kNotFound;
68 if (hasParameter) {
69 end = start + parameterPosition - 1;
71 RefPtr<nsAtom> pseudo = NS_Atomize(Substring(start, end));
72 MOZ_ASSERT(pseudo);
74 Maybe<uint32_t> index = nsStaticAtomUtils::Lookup(pseudo, GetAtomBase(),
75 kAtomCount_PseudoElements);
76 if (index.isNothing()) {
77 return {};
79 auto type = static_cast<Type>(*index);
80 RefPtr<nsAtom> functionalPseudoParameter;
81 if (hasParameter) {
82 if (type != PseudoStyleType::highlight) {
83 return {};
85 functionalPseudoParameter =
86 [&aPseudoElement, parameterPosition]() -> already_AddRefed<nsAtom> {
87 const char16_t* start = aPseudoElement.BeginReading();
88 const char16_t* end = aPseudoElement.EndReading();
89 start += parameterPosition + 1;
90 --end;
91 if (*end != ')') {
92 return nullptr;
94 return NS_Atomize(Substring(start, end));
95 }();
98 if (!haveTwoColons &&
99 !PseudoElementHasFlags(type, CSS_PSEUDO_ELEMENT_IS_CSS2)) {
100 return {};
102 if (IsEnabled(type, aEnabledState)) {
103 return {Some(type), functionalPseudoParameter};
105 return {};
108 /* static */
109 mozilla::Maybe<PseudoStyleType> nsCSSPseudoElements::GetPseudoType(
110 const nsAString& aPseudoElement, CSSEnabledState aEnabledState) {
111 auto [pseudoType, _] = ParsePseudoElement(aPseudoElement, aEnabledState);
112 return pseudoType;
115 /* static */
116 bool nsCSSPseudoElements::PseudoElementSupportsUserActionState(
117 const Type aType) {
118 return PseudoElementHasFlags(aType,
119 CSS_PSEUDO_ELEMENT_SUPPORTS_USER_ACTION_STATE);
122 /* static */
123 nsString nsCSSPseudoElements::PseudoTypeAsString(Type aPseudoType) {
124 switch (aPseudoType) {
125 case PseudoStyleType::before:
126 return u"::before"_ns;
127 case PseudoStyleType::after:
128 return u"::after"_ns;
129 case PseudoStyleType::marker:
130 return u"::marker"_ns;
131 default:
132 MOZ_ASSERT(aPseudoType == PseudoStyleType::NotPseudo,
133 "Unexpected pseudo type");
134 return u""_ns;
138 #ifdef DEBUG
139 /* static */
140 void nsCSSPseudoElements::AssertAtoms() {
141 nsStaticAtom* base = GetAtomBase();
142 # define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
144 RefPtr<nsAtom> atom = NS_Atomize(value_); \
145 size_t index = static_cast<size_t>(PseudoStyleType::name_); \
146 MOZ_ASSERT(atom == nsGkAtoms::PseudoElement_##name_, \
147 "Static atom for " #name_ " has incorrect value"); \
148 MOZ_ASSERT(atom == &base[index], \
149 "Static atom for " #name_ " not at expected index"); \
151 # include "nsCSSPseudoElementList.h"
152 # undef CSS_PSEUDO_ELEMENT
154 #endif