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 "mozilla/dom/HTMLSharedListElement.h"
8 #include "mozilla/dom/HTMLDListElementBinding.h"
9 #include "mozilla/dom/HTMLOListElementBinding.h"
10 #include "mozilla/dom/HTMLUListElementBinding.h"
11 
12 #include "mozilla/MappedDeclarations.h"
13 #include "nsGenericHTMLElement.h"
14 #include "nsAttrValueInlines.h"
15 #include "nsGkAtoms.h"
16 #include "nsStyleConsts.h"
17 #include "nsMappedAttributes.h"
18 
19 NS_IMPL_NS_NEW_HTML_ELEMENT(SharedList)
20 
21 namespace mozilla::dom {
22 
23 HTMLSharedListElement::~HTMLSharedListElement() = default;
24 
25 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(HTMLSharedListElement,
26                                                nsGenericHTMLElement)
27 
28 NS_IMPL_ELEMENT_CLONE(HTMLSharedListElement)
29 
30 // Shared with nsHTMLSharedElement.cpp
31 nsAttrValue::EnumTable kListTypeTable[] = {
32     {"none", NS_STYLE_LIST_STYLE_NONE},
33     {"disc", NS_STYLE_LIST_STYLE_DISC},
34     {"circle", NS_STYLE_LIST_STYLE_CIRCLE},
35     {"round", NS_STYLE_LIST_STYLE_CIRCLE},
36     {"square", NS_STYLE_LIST_STYLE_SQUARE},
37     {"decimal", NS_STYLE_LIST_STYLE_DECIMAL},
38     {"lower-roman", NS_STYLE_LIST_STYLE_LOWER_ROMAN},
39     {"upper-roman", NS_STYLE_LIST_STYLE_UPPER_ROMAN},
40     {"lower-alpha", NS_STYLE_LIST_STYLE_LOWER_ALPHA},
41     {"upper-alpha", NS_STYLE_LIST_STYLE_UPPER_ALPHA},
42     {nullptr, 0}};
43 
44 static const nsAttrValue::EnumTable kOldListTypeTable[] = {
45     {"1", NS_STYLE_LIST_STYLE_DECIMAL},
46     {"A", NS_STYLE_LIST_STYLE_UPPER_ALPHA},
47     {"a", NS_STYLE_LIST_STYLE_LOWER_ALPHA},
48     {"I", NS_STYLE_LIST_STYLE_UPPER_ROMAN},
49     {"i", NS_STYLE_LIST_STYLE_LOWER_ROMAN},
50     {nullptr, 0}};
51 
ParseAttribute(int32_t aNamespaceID,nsAtom * aAttribute,const nsAString & aValue,nsIPrincipal * aMaybeScriptedPrincipal,nsAttrValue & aResult)52 bool HTMLSharedListElement::ParseAttribute(
53     int32_t aNamespaceID, nsAtom* aAttribute, const nsAString& aValue,
54     nsIPrincipal* aMaybeScriptedPrincipal, nsAttrValue& aResult) {
55   if (aNamespaceID == kNameSpaceID_None) {
56     if (mNodeInfo->Equals(nsGkAtoms::ol) || mNodeInfo->Equals(nsGkAtoms::ul)) {
57       if (aAttribute == nsGkAtoms::type) {
58         return aResult.ParseEnumValue(aValue, kListTypeTable, false) ||
59                aResult.ParseEnumValue(aValue, kOldListTypeTable, true);
60       }
61     }
62     if (mNodeInfo->Equals(nsGkAtoms::ol)) {
63       if (aAttribute == nsGkAtoms::start) {
64         return aResult.ParseIntValue(aValue);
65       }
66     }
67   }
68 
69   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
70                                               aMaybeScriptedPrincipal, aResult);
71 }
72 
MapAttributesIntoRule(const nsMappedAttributes * aAttributes,MappedDeclarations & aDecls)73 void HTMLSharedListElement::MapAttributesIntoRule(
74     const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
75   if (!aDecls.PropertyIsSet(eCSSProperty_list_style_type)) {
76     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::type);
77     if (value && value->Type() == nsAttrValue::eEnum) {
78       aDecls.SetKeywordValue(eCSSProperty_list_style_type,
79                              value->GetEnumValue());
80     }
81   }
82 
83   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
84 }
85 
MapOLAttributesIntoRule(const nsMappedAttributes * aAttributes,MappedDeclarations & aDecls)86 void HTMLSharedListElement::MapOLAttributesIntoRule(
87     const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
88   if (!aDecls.PropertyIsSet(eCSSProperty_counter_reset)) {
89     const nsAttrValue* startAttr = aAttributes->GetAttr(nsGkAtoms::start);
90     bool haveStart = startAttr && startAttr->Type() == nsAttrValue::eInteger;
91     int32_t start = 0;
92     if (haveStart) {
93       start = startAttr->GetIntegerValue() - 1;
94     }
95     bool haveReversed = !!aAttributes->GetAttr(nsGkAtoms::reversed);
96     if (haveReversed) {
97       if (haveStart) {
98         start += 2;  // i.e. the attr value + 1
99       } else {
100         start = std::numeric_limits<int32_t>::min();
101       }
102     }
103     if (haveStart || haveReversed) {
104       aDecls.SetCounterResetListItem(start, haveReversed);
105     }
106   }
107 
108   HTMLSharedListElement::MapAttributesIntoRule(aAttributes, aDecls);
109 }
110 
NS_IMETHODIMP_(bool)111 NS_IMETHODIMP_(bool)
112 HTMLSharedListElement::IsAttributeMapped(const nsAtom* aAttribute) const {
113   if (mNodeInfo->Equals(nsGkAtoms::ul)) {
114     static const MappedAttributeEntry attributes[] = {{nsGkAtoms::type},
115                                                       {nullptr}};
116 
117     static const MappedAttributeEntry* const map[] = {
118         attributes,
119         sCommonAttributeMap,
120     };
121 
122     return FindAttributeDependence(aAttribute, map);
123   }
124 
125   if (mNodeInfo->Equals(nsGkAtoms::ol)) {
126     static const MappedAttributeEntry attributes[] = {{nsGkAtoms::type},
127                                                       {nsGkAtoms::start},
128                                                       {nsGkAtoms::reversed},
129                                                       {nullptr}};
130 
131     static const MappedAttributeEntry* const map[] = {
132         attributes,
133         sCommonAttributeMap,
134     };
135 
136     return FindAttributeDependence(aAttribute, map);
137   }
138 
139   return nsGenericHTMLElement::IsAttributeMapped(aAttribute);
140 }
141 
GetAttributeMappingFunction() const142 nsMapRuleToAttributesFunc HTMLSharedListElement::GetAttributeMappingFunction()
143     const {
144   if (mNodeInfo->Equals(nsGkAtoms::ul)) {
145     return &MapAttributesIntoRule;
146   }
147   if (mNodeInfo->Equals(nsGkAtoms::ol)) {
148     return &MapOLAttributesIntoRule;
149   }
150 
151   return nsGenericHTMLElement::GetAttributeMappingFunction();
152 }
153 
WrapNode(JSContext * aCx,JS::Handle<JSObject * > aGivenProto)154 JSObject* HTMLSharedListElement::WrapNode(JSContext* aCx,
155                                           JS::Handle<JSObject*> aGivenProto) {
156   if (mNodeInfo->Equals(nsGkAtoms::ol)) {
157     return HTMLOListElement_Binding::Wrap(aCx, this, aGivenProto);
158   }
159   if (mNodeInfo->Equals(nsGkAtoms::dl)) {
160     return HTMLDListElement_Binding::Wrap(aCx, this, aGivenProto);
161   }
162   MOZ_ASSERT(mNodeInfo->Equals(nsGkAtoms::ul));
163   return HTMLUListElement_Binding::Wrap(aCx, this, aGivenProto);
164 }
165 
166 }  // namespace mozilla::dom
167