Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(198)

Side by Side Diff: Source/core/dom/Attr.cpp

Issue 1158433004: Remove Attr child nodes (making Attr a Node, not a ContainerNode) (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: address feedback Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/dom/Attr.h ('k') | Source/core/dom/Attr.idl » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Peter Kelly (pmk@post.com) 4 * (C) 2001 Peter Kelly (pmk@post.com)
5 * (C) 2001 Dirk Mueller (mueller@kde.org) 5 * (C) 2001 Dirk Mueller (mueller@kde.org)
6 * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2012 Apple Inc. All rights reserved. 6 * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2012 Apple Inc. All rights reserved.
7 * 7 *
8 * This library is free software; you can redistribute it and/or 8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public 9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either 10 * License as published by the Free Software Foundation; either
(...skipping 20 matching lines...) Expand all
31 #include "core/events/ScopedEventQueue.h" 31 #include "core/events/ScopedEventQueue.h"
32 #include "core/frame/UseCounter.h" 32 #include "core/frame/UseCounter.h"
33 #include "wtf/text/AtomicString.h" 33 #include "wtf/text/AtomicString.h"
34 #include "wtf/text/StringBuilder.h" 34 #include "wtf/text/StringBuilder.h"
35 35
36 namespace blink { 36 namespace blink {
37 37
38 using namespace HTMLNames; 38 using namespace HTMLNames;
39 39
40 Attr::Attr(Element& element, const QualifiedName& name) 40 Attr::Attr(Element& element, const QualifiedName& name)
41 : ContainerNode(&element.document()) 41 : Node(&element.document(), CreateOther)
42 , m_element(&element) 42 , m_element(&element)
43 , m_name(name) 43 , m_name(name)
44 , m_ignoreChildrenChanged(0)
45 { 44 {
46 } 45 }
47 46
48 Attr::Attr(Document& document, const QualifiedName& name, const AtomicString& st andaloneValue) 47 Attr::Attr(Document& document, const QualifiedName& name, const AtomicString& st andaloneValue)
49 : ContainerNode(&document) 48 : Node(&document, CreateOther)
50 , m_element(nullptr) 49 , m_element(nullptr)
51 , m_name(name) 50 , m_name(name)
52 , m_standaloneValueOrAttachedLocalName(standaloneValue) 51 , m_standaloneValueOrAttachedLocalName(standaloneValue)
53 , m_ignoreChildrenChanged(0)
54 { 52 {
55 } 53 }
56 54
57 PassRefPtrWillBeRawPtr<Attr> Attr::create(Element& element, const QualifiedName& name) 55 PassRefPtrWillBeRawPtr<Attr> Attr::create(Element& element, const QualifiedName& name)
58 { 56 {
59 RefPtrWillBeRawPtr<Attr> attr = adoptRefWillBeNoop(new Attr(element, name)); 57 return adoptRefWillBeNoop(new Attr(element, name));
60 attr->createTextChild();
61 return attr.release();
62 } 58 }
63 59
64 PassRefPtrWillBeRawPtr<Attr> Attr::create(Document& document, const QualifiedNam e& name, const AtomicString& value) 60 PassRefPtrWillBeRawPtr<Attr> Attr::create(Document& document, const QualifiedNam e& name, const AtomicString& value)
65 { 61 {
66 RefPtrWillBeRawPtr<Attr> attr = adoptRefWillBeNoop(new Attr(document, name, value)); 62 return adoptRefWillBeNoop(new Attr(document, name, value));
67 attr->createTextChild();
68 return attr.release();
69 } 63 }
70 64
71 Attr::~Attr() 65 Attr::~Attr()
72 { 66 {
73 } 67 }
74 68
75 const QualifiedName Attr::qualifiedName() const 69 const QualifiedName Attr::qualifiedName() const
76 { 70 {
77 if (m_element && !m_standaloneValueOrAttachedLocalName.isNull()) { 71 if (m_element && !m_standaloneValueOrAttachedLocalName.isNull()) {
78 // In the unlikely case the Element attribute has a local name 72 // In the unlikely case the Element attribute has a local name
79 // that differs by case, construct the qualified name based on 73 // that differs by case, construct the qualified name based on
80 // it. This is the qualified name that must be used when 74 // it. This is the qualified name that must be used when
81 // looking up the attribute on the element. 75 // looking up the attribute on the element.
82 return QualifiedName(m_name.prefix(), m_standaloneValueOrAttachedLocalNa me, m_name.namespaceURI()); 76 return QualifiedName(m_name.prefix(), m_standaloneValueOrAttachedLocalNa me, m_name.namespaceURI());
83 } 77 }
84 78
85 return m_name; 79 return m_name;
86 } 80 }
87 81
88 void Attr::createTextChild() 82 const AtomicString& Attr::value() const
89 { 83 {
90 #if !ENABLE(OILPAN) 84 if (m_element)
91 ASSERT(refCount()); 85 return m_element->getAttribute(qualifiedName());
92 #endif 86 return m_standaloneValueOrAttachedLocalName;
93 if (!value().isEmpty()) {
94 RefPtrWillBeRawPtr<Text> textNode = document().createTextNode(value().st ring());
95
96 // This does everything appendChild() would do in this situation (assumi ng m_ignoreChildrenChanged was set),
97 // but much more efficiently.
98 textNode->setParentOrShadowHostNode(this);
99 treeScope().adoptIfNeeded(*textNode);
100 setFirstChild(textNode.get());
101 setLastChild(textNode.get());
102 }
103 } 87 }
104 88
105 void Attr::setValue(const AtomicString& value) 89 void Attr::setValue(const AtomicString& value)
106 { 90 {
107 EventQueueScope scope;
108 m_ignoreChildrenChanged++;
109 // We don't fire the DOMSubtreeModified event for Attr Nodes. This matches t he behavior
110 // of IE and Firefox. This event is fired synchronously and is a source of t rouble for
111 // attributes as the JS callback could alter the attributes and leave us in a bad state.
112 removeChildren(OmitSubtreeModifiedEvent);
113 if (m_element) 91 if (m_element)
114 updateElementAttribute(value); 92 m_element->setAttribute(qualifiedName(), value);
tkent 2015/05/29 03:34:07 Does this cause infinite loop? Element::setAttri
davve 2015/05/29 06:29:14 Element::setAttributeInternal shouldn't call into
tkent 2015/05/29 07:49:15 Ah, I see. Attr doesn't need to update the value
115 else 93 else
116 m_standaloneValueOrAttachedLocalName = value; 94 m_standaloneValueOrAttachedLocalName = value;
117 createTextChild();
118 m_ignoreChildrenChanged--;
119
120 QualifiedName name = qualifiedName();
121 invalidateNodeListCachesInAncestors(&name, m_element);
tkent 2015/05/29 03:34:07 Is it safe to remove invalidateNodeListCachesInAnc
davve 2015/05/29 06:29:14 invalidateNodeListCachesInAncestors should still b
122 }
123
124 void Attr::setValueInternal(const AtomicString& value)
125 {
126 if (m_element)
127 m_element->willModifyAttribute(qualifiedName(), this->value(), value);
128
129 setValue(value);
130
131 if (m_element)
132 m_element->didModifyAttribute(qualifiedName(), value);
133 } 95 }
134 96
135 const AtomicString& Attr::valueForBindings() const 97 const AtomicString& Attr::valueForBindings() const
136 { 98 {
137 UseCounter::count(document(), UseCounter::AttrGetValue); 99 UseCounter::count(document(), UseCounter::AttrGetValue);
138 return value(); 100 return value();
139 } 101 }
140 102
141 void Attr::setValueForBindings(const AtomicString& value) 103 void Attr::setValueForBindings(const AtomicString& value)
142 { 104 {
143 UseCounter::count(document(), UseCounter::AttrSetValue); 105 UseCounter::count(document(), UseCounter::AttrSetValue);
144 if (m_element) 106 if (m_element)
145 UseCounter::count(document(), UseCounter::AttrSetValueWithElement); 107 UseCounter::count(document(), UseCounter::AttrSetValueWithElement);
146 setValueInternal(value); 108 setValue(value);
147 } 109 }
148 110
149 void Attr::setNodeValue(const String& v) 111 void Attr::setNodeValue(const String& v)
150 { 112 {
151 // Attr uses AtomicString type for its value to save memory as there 113 // Attr uses AtomicString type for its value to save memory as there
152 // is duplication among Elements' attributes values. 114 // is duplication among Elements' attributes values.
153 setValueInternal(AtomicString(v)); 115 setValue(AtomicString(v));
154 } 116 }
155 117
156 PassRefPtrWillBeRawPtr<Node> Attr::cloneNode(bool /*deep*/) 118 PassRefPtrWillBeRawPtr<Node> Attr::cloneNode(bool /*deep*/)
157 { 119 {
158 RefPtrWillBeRawPtr<Attr> clone = adoptRefWillBeNoop(new Attr(document(), m_n ame, value())); 120 return adoptRefWillBeNoop(new Attr(document(), m_name, value()));
159 cloneChildNodes(clone.get());
160 return clone.release();
161 }
162
163 // DOM Section 1.1.1
164 bool Attr::childTypeAllowed(NodeType type) const
165 {
166 return TEXT_NODE == type;
167 }
168
169 void Attr::childrenChanged(const ChildrenChange&)
170 {
171 if (m_ignoreChildrenChanged > 0)
172 return;
173
174 UseCounter::countDeprecation(document(), UseCounter::AttrChildChange);
175
176 QualifiedName name = qualifiedName();
177 invalidateNodeListCachesInAncestors(&name, m_element);
178
179 StringBuilder valueBuilder;
180 for (Node *n = firstChild(); n; n = n->nextSibling()) {
181 if (n->isTextNode())
182 valueBuilder.append(toText(n)->data());
183 }
184
185 AtomicString newValue = valueBuilder.toAtomicString();
186 if (m_element)
187 m_element->willModifyAttribute(qualifiedName(), value(), newValue);
188
189 if (m_element)
190 updateElementAttribute(newValue);
191 else
192 m_standaloneValueOrAttachedLocalName = newValue;
193
194 if (m_element)
195 m_element->attributeChanged(qualifiedName(), newValue);
196 }
197
198 const AtomicString& Attr::value() const
199 {
200 if (m_element)
201 return m_element->getAttribute(qualifiedName());
202 return m_standaloneValueOrAttachedLocalName;
203 }
204
205 void Attr::updateElementAttribute(const AtomicString& value)
206 {
207 ASSERT(m_element);
208 ASSERT(m_element->elementData());
209 MutableAttributeCollection attributes = m_element->ensureUniqueElementData() .attributes();
210 size_t index = attributes.findIndex(qualifiedName());
211 if (index == kNotFound) {
212 // Element attributes with null values are not stored.
213 if (!value.isNull())
214 attributes.append(qualifiedName(), value);
215 return;
216 }
217 return attributes[index].setValue(value);
218 } 121 }
219 122
220 void Attr::detachFromElementWithValue(const AtomicString& value) 123 void Attr::detachFromElementWithValue(const AtomicString& value)
221 { 124 {
222 ASSERT(m_element); 125 ASSERT(m_element);
223 m_standaloneValueOrAttachedLocalName = value; 126 m_standaloneValueOrAttachedLocalName = value;
224 m_element = nullptr; 127 m_element = nullptr;
225 } 128 }
226 129
227 void Attr::attachToElement(Element* element, const AtomicString& attachedLocalNa me) 130 void Attr::attachToElement(Element* element, const AtomicString& attachedLocalNa me)
228 { 131 {
229 ASSERT(!m_element); 132 ASSERT(!m_element);
230 m_element = element; 133 m_element = element;
231 m_standaloneValueOrAttachedLocalName = attachedLocalName; 134 m_standaloneValueOrAttachedLocalName = attachedLocalName;
232 } 135 }
233 136
234 DEFINE_TRACE(Attr) 137 DEFINE_TRACE(Attr)
235 { 138 {
236 visitor->trace(m_element); 139 visitor->trace(m_element);
237 ContainerNode::trace(visitor); 140 Node::trace(visitor);
238 } 141 }
239 142
240 } 143 }
OLDNEW
« no previous file with comments | « Source/core/dom/Attr.h ('k') | Source/core/dom/Attr.idl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698