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"
18 using namespace mozilla
;
20 // Flags data for each of the pseudo-elements.
21 /* static */ const uint32_t nsCSSPseudoElements::kPseudoElementFlags
[] = {
22 #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) flags_,
23 #include "nsCSSPseudoElementList.h"
24 #undef CSS_PSEUDO_ELEMENT
28 nsStaticAtom
* nsCSSPseudoElements::GetAtomBase() {
29 return const_cast<nsStaticAtom
*>(
30 nsGkAtoms::GetAtomByIndex(kAtomIndex_PseudoElements
));
33 bool nsCSSPseudoElements::IsPseudoElement(nsAtom
* aAtom
) {
34 return nsStaticAtomUtils::IsMember(aAtom
, GetAtomBase(),
35 kAtomCount_PseudoElements
);
39 bool nsCSSPseudoElements::IsCSS2PseudoElement(nsAtom
* aAtom
) {
40 // We don't implement this using PseudoElementHasFlags because callers
41 // want to pass things that could be anon boxes.
42 MOZ_ASSERT(IsPseudoElement(aAtom
), "must be pseudo element");
43 bool result
= aAtom
== nsCSSPseudoElements::after() ||
44 aAtom
== nsCSSPseudoElements::before() ||
45 aAtom
== nsCSSPseudoElements::firstLetter() ||
46 aAtom
== nsCSSPseudoElements::firstLine();
48 result
== PseudoElementHasFlags(
49 GetPseudoType(aAtom
, EnabledState::IgnoreEnabledState
),
50 CSS_PSEUDO_ELEMENT_IS_CSS2
),
51 "result doesn't match flags");
56 PseudoStyleType
nsCSSPseudoElements::GetPseudoType(nsAtom
* aAtom
,
57 EnabledState aEnabledState
) {
58 Maybe
<uint32_t> index
= nsStaticAtomUtils::Lookup(aAtom
, GetAtomBase(),
59 kAtomCount_PseudoElements
);
61 auto type
= static_cast<Type
>(*index
);
62 return IsEnabled(type
, aEnabledState
) ? type
: Type::NotPseudo
;
65 return Type::NotPseudo
;
69 nsAtom
* nsCSSPseudoElements::GetPseudoAtom(Type aType
) {
70 MOZ_ASSERT(PseudoStyle::IsPseudoElement(aType
), "Unexpected type");
71 size_t index
= kAtomIndex_PseudoElements
+ static_cast<size_t>(aType
);
72 return nsGkAtoms::GetAtomByIndex(index
);
76 already_AddRefed
<nsAtom
> nsCSSPseudoElements::GetPseudoAtom(
77 const nsAString
& aPseudoElement
) {
78 if (DOMStringIsNull(aPseudoElement
) || aPseudoElement
.IsEmpty() ||
79 aPseudoElement
.First() != char16_t(':')) {
83 // deal with two-colon forms of aPseudoElt
84 nsAString::const_iterator start
, end
;
85 aPseudoElement
.BeginReading(start
);
86 aPseudoElement
.EndReading(end
);
87 NS_ASSERTION(start
!= end
, "aPseudoElement is not empty!");
89 bool haveTwoColons
= true;
90 if (start
== end
|| *start
!= char16_t(':')) {
92 haveTwoColons
= false;
94 RefPtr
<nsAtom
> pseudo
= NS_Atomize(Substring(start
, end
));
97 // There aren't any non-CSS2 pseudo-elements with a single ':'
99 (!IsPseudoElement(pseudo
) || !IsCSS2PseudoElement(pseudo
))) {
100 // XXXbz I'd really rather we threw an exception or something, but
101 // the DOM spec sucks.
105 return pseudo
.forget();
109 bool nsCSSPseudoElements::PseudoElementSupportsUserActionState(
111 return PseudoElementHasFlags(aType
,
112 CSS_PSEUDO_ELEMENT_SUPPORTS_USER_ACTION_STATE
);
116 nsString
nsCSSPseudoElements::PseudoTypeAsString(Type aPseudoType
) {
117 switch (aPseudoType
) {
118 case PseudoStyleType::before
:
119 return u
"::before"_ns
;
120 case PseudoStyleType::after
:
121 return u
"::after"_ns
;
122 case PseudoStyleType::marker
:
123 return u
"::marker"_ns
;
125 MOZ_ASSERT(aPseudoType
== PseudoStyleType::NotPseudo
,
126 "Unexpected pseudo type");
133 void nsCSSPseudoElements::AssertAtoms() {
134 nsStaticAtom
* base
= GetAtomBase();
135 # define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
137 RefPtr<nsAtom> atom = NS_Atomize(value_); \
138 size_t index = static_cast<size_t>(PseudoStyleType::name_); \
139 MOZ_ASSERT(atom == nsGkAtoms::PseudoElement_##name_, \
140 "Static atom for " #name_ " has incorrect value"); \
141 MOZ_ASSERT(atom == &base[index], \
142 "Static atom for " #name_ " not at expected index"); \
144 # include "nsCSSPseudoElementList.h"
145 # undef CSS_PSEUDO_ELEMENT