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
29 nsStaticAtom
* nsCSSPseudoElements::GetAtomBase() {
30 return const_cast<nsStaticAtom
*>(
31 nsGkAtoms::GetAtomByIndex(kAtomIndex_PseudoElements
));
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
);
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(':')) {
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!");
58 bool haveTwoColons
= true;
59 if (start
== end
|| *start
!= char16_t(':')) {
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
;
69 end
= start
+ parameterPosition
- 1;
71 RefPtr
<nsAtom
> pseudo
= NS_Atomize(Substring(start
, end
));
74 Maybe
<uint32_t> index
= nsStaticAtomUtils::Lookup(pseudo
, GetAtomBase(),
75 kAtomCount_PseudoElements
);
76 if (index
.isNothing()) {
79 auto type
= static_cast<Type
>(*index
);
80 RefPtr
<nsAtom
> functionalPseudoParameter
;
82 if (type
!= PseudoStyleType::highlight
) {
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;
94 return NS_Atomize(Substring(start
, end
));
99 !PseudoElementHasFlags(type
, CSS_PSEUDO_ELEMENT_IS_CSS2
)) {
102 if (IsEnabled(type
, aEnabledState
)) {
103 return {Some(type
), functionalPseudoParameter
};
109 mozilla::Maybe
<PseudoStyleType
> nsCSSPseudoElements::GetPseudoType(
110 const nsAString
& aPseudoElement
, CSSEnabledState aEnabledState
) {
111 auto [pseudoType
, _
] = ParsePseudoElement(aPseudoElement
, aEnabledState
);
116 bool nsCSSPseudoElements::PseudoElementSupportsUserActionState(
118 return PseudoElementHasFlags(aType
,
119 CSS_PSEUDO_ELEMENT_SUPPORTS_USER_ACTION_STATE
);
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
;
132 MOZ_ASSERT(aPseudoType
== PseudoStyleType::NotPseudo
,
133 "Unexpected pseudo type");
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