Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : /* atom list for CSS pseudo-elements */
7 :
8 : #include "nsCSSPseudoElements.h"
9 :
10 : #include "mozilla/ArrayUtils.h"
11 :
12 : #include "nsAtomListUtils.h"
13 : #include "nsStaticAtom.h"
14 : #include "nsCSSAnonBoxes.h"
15 : #include "nsDOMString.h"
16 :
17 : using namespace mozilla;
18 :
19 : // define storage for all atoms
20 : #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
21 : nsICSSPseudoElement* nsCSSPseudoElements::name_;
22 : #include "nsCSSPseudoElementList.h"
23 : #undef CSS_PSEUDO_ELEMENT
24 :
25 : #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
26 : NS_STATIC_ATOM_BUFFER(name_##_pseudo_element_buffer, value_)
27 : #include "nsCSSPseudoElementList.h"
28 : #undef CSS_PSEUDO_ELEMENT
29 :
30 : // Array of nsStaticAtom for each of the pseudo-elements.
31 : static const nsStaticAtom CSSPseudoElements_info[] = {
32 : #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
33 : NS_STATIC_ATOM(name_##_pseudo_element_buffer, (nsIAtom**)&nsCSSPseudoElements::name_),
34 : #include "nsCSSPseudoElementList.h"
35 : #undef CSS_PSEUDO_ELEMENT
36 : };
37 :
38 : // Flags data for each of the pseudo-elements, which must be separate
39 : // from the previous array since there's no place for it in
40 : // nsStaticAtom.
41 : /* static */ const uint32_t
42 : nsCSSPseudoElements::kPseudoElementFlags[] = {
43 : #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
44 : flags_,
45 : #include "nsCSSPseudoElementList.h"
46 : #undef CSS_PSEUDO_ELEMENT
47 : };
48 :
49 3 : void nsCSSPseudoElements::AddRefAtoms()
50 : {
51 3 : NS_RegisterStaticAtoms(CSSPseudoElements_info);
52 3 : }
53 :
54 12 : bool nsCSSPseudoElements::IsPseudoElement(nsIAtom *aAtom)
55 : {
56 12 : return nsAtomListUtils::IsMember(aAtom, CSSPseudoElements_info,
57 24 : ArrayLength(CSSPseudoElements_info));
58 : }
59 :
60 : /* static */ bool
61 12 : nsCSSPseudoElements::IsCSS2PseudoElement(nsIAtom *aAtom)
62 : {
63 : // We don't implement this using PseudoElementHasFlags because callers
64 : // want to pass things that could be anon boxes.
65 12 : NS_ASSERTION(nsCSSPseudoElements::IsPseudoElement(aAtom) ||
66 : nsCSSAnonBoxes::IsAnonBox(aAtom),
67 : "must be pseudo element or anon box");
68 22 : bool result = aAtom == nsCSSPseudoElements::after ||
69 10 : aAtom == nsCSSPseudoElements::before ||
70 12 : aAtom == nsCSSPseudoElements::firstLetter ||
71 12 : aAtom == nsCSSPseudoElements::firstLine;
72 12 : NS_ASSERTION(nsCSSAnonBoxes::IsAnonBox(aAtom) ||
73 : result == PseudoElementHasFlags(
74 : GetPseudoType(aAtom, EnabledState::eIgnoreEnabledState),
75 : CSS_PSEUDO_ELEMENT_IS_CSS2),
76 : "result doesn't match flags");
77 12 : return result;
78 : }
79 :
80 : /* static */ CSSPseudoElementType
81 3374 : nsCSSPseudoElements::GetPseudoType(nsIAtom *aAtom, EnabledState aEnabledState)
82 : {
83 165776 : for (CSSPseudoElementTypeBase i = 0;
84 82888 : i < ArrayLength(CSSPseudoElements_info);
85 : ++i) {
86 79773 : if (*CSSPseudoElements_info[i].mAtom == aAtom) {
87 259 : auto type = static_cast<Type>(i);
88 : // ::moz-placeholder is an alias for ::placeholder
89 259 : if (type == CSSPseudoElementType::mozPlaceholder) {
90 0 : type = CSSPseudoElementType::placeholder;
91 : }
92 259 : return IsEnabled(type, aEnabledState) ? type : Type::NotPseudo;
93 : }
94 : }
95 :
96 3115 : if (nsCSSAnonBoxes::IsAnonBox(aAtom)) {
97 : #ifdef MOZ_XUL
98 614 : if (nsCSSAnonBoxes::IsTreePseudoElement(aAtom)) {
99 70 : return Type::XULTree;
100 : }
101 : #endif
102 :
103 544 : if (nsCSSAnonBoxes::IsNonInheritingAnonBox(aAtom)) {
104 4 : return Type::NonInheritingAnonBox;
105 : }
106 :
107 540 : return Type::InheritingAnonBox;
108 : }
109 :
110 2501 : return Type::NotPseudo;
111 : }
112 :
113 : /* static */ nsIAtom*
114 1292 : nsCSSPseudoElements::GetPseudoAtom(Type aType)
115 : {
116 1292 : NS_ASSERTION(aType < Type::Count, "Unexpected type");
117 : return *CSSPseudoElements_info[
118 1292 : static_cast<CSSPseudoElementTypeBase>(aType)].mAtom;
119 : }
120 :
121 : /* static */ nsIAtom*
122 4 : nsCSSPseudoElements::GetPseudoAtom(const nsAString& aPseudoElement)
123 : {
124 4 : if (DOMStringIsNull(aPseudoElement) || aPseudoElement.IsEmpty() ||
125 0 : aPseudoElement.First() != char16_t(':')) {
126 4 : return nullptr;
127 : }
128 :
129 : // deal with two-colon forms of aPseudoElt
130 0 : nsAString::const_iterator start, end;
131 0 : aPseudoElement.BeginReading(start);
132 0 : aPseudoElement.EndReading(end);
133 0 : NS_ASSERTION(start != end, "aPseudoElement is not empty!");
134 0 : ++start;
135 0 : bool haveTwoColons = true;
136 0 : if (start == end || *start != char16_t(':')) {
137 0 : --start;
138 0 : haveTwoColons = false;
139 : }
140 0 : nsCOMPtr<nsIAtom> pseudo = NS_Atomize(Substring(start, end));
141 0 : MOZ_ASSERT(pseudo);
142 :
143 : // There aren't any non-CSS2 pseudo-elements with a single ':'
144 0 : if (!haveTwoColons &&
145 0 : (!IsPseudoElement(pseudo) || !IsCSS2PseudoElement(pseudo))) {
146 : // XXXbz I'd really rather we threw an exception or something, but
147 : // the DOM spec sucks.
148 0 : return nullptr;
149 : }
150 :
151 0 : return pseudo;
152 : }
153 :
154 : /* static */ bool
155 700 : nsCSSPseudoElements::PseudoElementSupportsUserActionState(const Type aType)
156 : {
157 : return PseudoElementHasFlags(aType,
158 700 : CSS_PSEUDO_ELEMENT_SUPPORTS_USER_ACTION_STATE);
159 : }
|