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

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

Issue 316583002: Correctly handle accessing a replaced Attr object's attribute value. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Add setAttributeNode() FIXME Created 6 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
« no previous file with comments | « Source/core/dom/Attr.h ('k') | Source/core/dom/Element.cpp » ('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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 , m_name(name) 42 , m_name(name)
43 , m_ignoreChildrenChanged(0) 43 , m_ignoreChildrenChanged(0)
44 { 44 {
45 ScriptWrappable::init(this); 45 ScriptWrappable::init(this);
46 } 46 }
47 47
48 Attr::Attr(Document& document, const QualifiedName& name, const AtomicString& st andaloneValue) 48 Attr::Attr(Document& document, const QualifiedName& name, const AtomicString& st andaloneValue)
49 : ContainerNode(&document) 49 : ContainerNode(&document)
50 , m_element(nullptr) 50 , m_element(nullptr)
51 , m_name(name) 51 , m_name(name)
52 , m_standaloneValue(standaloneValue) 52 , m_standaloneValueOrAttachedLocalName(standaloneValue)
53 , m_ignoreChildrenChanged(0) 53 , m_ignoreChildrenChanged(0)
54 { 54 {
55 ScriptWrappable::init(this); 55 ScriptWrappable::init(this);
56 } 56 }
57 57
58 PassRefPtrWillBeRawPtr<Attr> Attr::create(Element& element, const QualifiedName& name) 58 PassRefPtrWillBeRawPtr<Attr> Attr::create(Element& element, const QualifiedName& name)
59 { 59 {
60 RefPtrWillBeRawPtr<Attr> attr = adoptRefWillBeRefCountedGarbageCollected(new Attr(element, name)); 60 RefPtrWillBeRawPtr<Attr> attr = adoptRefWillBeRefCountedGarbageCollected(new Attr(element, name));
61 attr->createTextChild(); 61 attr->createTextChild();
62 return attr.release(); 62 return attr.release();
63 } 63 }
64 64
65 PassRefPtrWillBeRawPtr<Attr> Attr::create(Document& document, const QualifiedNam e& name, const AtomicString& value) 65 PassRefPtrWillBeRawPtr<Attr> Attr::create(Document& document, const QualifiedNam e& name, const AtomicString& value)
66 { 66 {
67 RefPtrWillBeRawPtr<Attr> attr = adoptRefWillBeRefCountedGarbageCollected(new Attr(document, name, value)); 67 RefPtrWillBeRawPtr<Attr> attr = adoptRefWillBeRefCountedGarbageCollected(new Attr(document, name, value));
68 attr->createTextChild(); 68 attr->createTextChild();
69 return attr.release(); 69 return attr.release();
70 } 70 }
71 71
72 Attr::~Attr() 72 Attr::~Attr()
73 { 73 {
74 } 74 }
75 75
76 const QualifiedName Attr::qualifiedName() const
77 {
78 if (m_element && !m_standaloneValueOrAttachedLocalName.isNull()) {
79 // In the unlikely case the Element attribute has a local name
80 // that differs by case, construct the qualified name based on
81 // it. This is the qualified name that must be used when
82 // looking up the attribute on the element.
83 return QualifiedName(m_name.prefix(), m_standaloneValueOrAttachedLocalNa me, m_name.namespaceURI());
84 }
85
86 return m_name;
87 }
88
76 void Attr::createTextChild() 89 void Attr::createTextChild()
77 { 90 {
78 #if !ENABLE(OILPAN) 91 #if !ENABLE(OILPAN)
79 ASSERT(refCount()); 92 ASSERT(refCount());
80 #endif 93 #endif
81 if (!value().isEmpty()) { 94 if (!value().isEmpty()) {
82 RefPtrWillBeRawPtr<Text> textNode = document().createTextNode(value().st ring()); 95 RefPtrWillBeRawPtr<Text> textNode = document().createTextNode(value().st ring());
83 96
84 // This does everything appendChild() would do in this situation (assumi ng m_ignoreChildrenChanged was set), 97 // This does everything appendChild() would do in this situation (assumi ng m_ignoreChildrenChanged was set),
85 // but much more efficiently. 98 // but much more efficiently.
86 textNode->setParentOrShadowHostNode(this); 99 textNode->setParentOrShadowHostNode(this);
87 treeScope().adoptIfNeeded(*textNode); 100 treeScope().adoptIfNeeded(*textNode);
88 setFirstChild(textNode.get()); 101 setFirstChild(textNode.get());
89 setLastChild(textNode.get()); 102 setLastChild(textNode.get());
90 } 103 }
91 } 104 }
92 105
93 void Attr::setValue(const AtomicString& value) 106 void Attr::setValue(const AtomicString& value)
94 { 107 {
95 EventQueueScope scope; 108 EventQueueScope scope;
96 m_ignoreChildrenChanged++; 109 m_ignoreChildrenChanged++;
97 removeChildren(); 110 removeChildren();
98 if (m_element) 111 if (m_element)
99 elementAttribute().setValue(value); 112 elementAttribute().setValue(value);
100 else 113 else
101 m_standaloneValue = value; 114 m_standaloneValueOrAttachedLocalName = value;
102 createTextChild(); 115 createTextChild();
103 m_ignoreChildrenChanged--; 116 m_ignoreChildrenChanged--;
104 117
105 invalidateNodeListCachesInAncestors(&m_name, m_element); 118 QualifiedName name = qualifiedName();
119 invalidateNodeListCachesInAncestors(&name, m_element);
106 } 120 }
107 121
108 void Attr::setValueInternal(const AtomicString& value) 122 void Attr::setValueInternal(const AtomicString& value)
109 { 123 {
110 if (m_element) 124 if (m_element)
111 m_element->willModifyAttribute(qualifiedName(), this->value(), value); 125 m_element->willModifyAttribute(qualifiedName(), this->value(), value);
112 126
113 setValue(value); 127 setValue(value);
114 128
115 if (m_element) 129 if (m_element)
(...skipping 16 matching lines...) Expand all
132 146
133 void Attr::setNodeValue(const String& v) 147 void Attr::setNodeValue(const String& v)
134 { 148 {
135 // Attr uses AtomicString type for its value to save memory as there 149 // Attr uses AtomicString type for its value to save memory as there
136 // is duplication among Elements' attributes values. 150 // is duplication among Elements' attributes values.
137 setValueInternal(AtomicString(v)); 151 setValueInternal(AtomicString(v));
138 } 152 }
139 153
140 PassRefPtrWillBeRawPtr<Node> Attr::cloneNode(bool /*deep*/) 154 PassRefPtrWillBeRawPtr<Node> Attr::cloneNode(bool /*deep*/)
141 { 155 {
142 RefPtrWillBeRawPtr<Attr> clone = adoptRefWillBeRefCountedGarbageCollected(ne w Attr(document(), qualifiedName(), value())); 156 RefPtrWillBeRawPtr<Attr> clone = adoptRefWillBeRefCountedGarbageCollected(ne w Attr(document(), m_name, value()));
143 cloneChildNodes(clone.get()); 157 cloneChildNodes(clone.get());
144 return clone.release(); 158 return clone.release();
145 } 159 }
146 160
147 // DOM Section 1.1.1 161 // DOM Section 1.1.1
148 bool Attr::childTypeAllowed(NodeType type) const 162 bool Attr::childTypeAllowed(NodeType type) const
149 { 163 {
150 return TEXT_NODE == type; 164 return TEXT_NODE == type;
151 } 165 }
152 166
153 void Attr::childrenChanged(bool, Node*, Node*, int) 167 void Attr::childrenChanged(bool, Node*, Node*, int)
154 { 168 {
155 if (m_ignoreChildrenChanged > 0) 169 if (m_ignoreChildrenChanged > 0)
156 return; 170 return;
157 171
158 invalidateNodeListCachesInAncestors(&qualifiedName(), m_element); 172 QualifiedName name = qualifiedName();
173 invalidateNodeListCachesInAncestors(&name, m_element);
159 174
160 StringBuilder valueBuilder; 175 StringBuilder valueBuilder;
161 for (Node *n = firstChild(); n; n = n->nextSibling()) { 176 for (Node *n = firstChild(); n; n = n->nextSibling()) {
162 if (n->isTextNode()) 177 if (n->isTextNode())
163 valueBuilder.append(toText(n)->data()); 178 valueBuilder.append(toText(n)->data());
164 } 179 }
165 180
166 AtomicString newValue = valueBuilder.toAtomicString(); 181 AtomicString newValue = valueBuilder.toAtomicString();
167 if (m_element) 182 if (m_element)
168 m_element->willModifyAttribute(qualifiedName(), value(), newValue); 183 m_element->willModifyAttribute(qualifiedName(), value(), newValue);
169 184
170 if (m_element) 185 if (m_element)
171 elementAttribute().setValue(newValue); 186 elementAttribute().setValue(newValue);
172 else 187 else
173 m_standaloneValue = newValue; 188 m_standaloneValueOrAttachedLocalName = newValue;
174 189
175 if (m_element) 190 if (m_element)
176 m_element->attributeChanged(qualifiedName(), newValue); 191 m_element->attributeChanged(qualifiedName(), newValue);
177 } 192 }
178 193
179 const AtomicString& Attr::value() const 194 const AtomicString& Attr::value() const
180 { 195 {
181 if (m_element) 196 if (m_element)
182 return m_element->getAttribute(qualifiedName()); 197 return m_element->getAttribute(qualifiedName());
183 return m_standaloneValue; 198 return m_standaloneValueOrAttachedLocalName;
184 } 199 }
185 200
186 Attribute& Attr::elementAttribute() 201 Attribute& Attr::elementAttribute()
187 { 202 {
188 ASSERT(m_element); 203 ASSERT(m_element);
189 ASSERT(m_element->elementData()); 204 ASSERT(m_element->elementData());
190 return *m_element->ensureUniqueElementData().getAttributeItem(qualifiedName( )); 205 return *m_element->ensureUniqueElementData().getAttributeItem(qualifiedName( ));
191 } 206 }
192 207
193 void Attr::detachFromElementWithValue(const AtomicString& value) 208 void Attr::detachFromElementWithValue(const AtomicString& value)
194 { 209 {
195 ASSERT(m_element); 210 ASSERT(m_element);
196 ASSERT(m_standaloneValue.isNull()); 211 m_standaloneValueOrAttachedLocalName = value;
197 m_standaloneValue = value;
198 m_element = nullptr; 212 m_element = nullptr;
199 } 213 }
200 214
201 void Attr::attachToElement(Element* element) 215 void Attr::attachToElement(Element* element, const AtomicString& attachedLocalNa me)
202 { 216 {
203 ASSERT(!m_element); 217 ASSERT(!m_element);
204 m_element = element; 218 m_element = element;
205 m_standaloneValue = nullAtom; 219 m_standaloneValueOrAttachedLocalName = attachedLocalName;
206 } 220 }
207 221
208 void Attr::trace(Visitor* visitor) 222 void Attr::trace(Visitor* visitor)
209 { 223 {
210 visitor->trace(m_element); 224 visitor->trace(m_element);
211 ContainerNode::trace(visitor); 225 ContainerNode::trace(visitor);
212 } 226 }
213 227
214 } 228 }
OLDNEW
« no previous file with comments | « Source/core/dom/Attr.h ('k') | Source/core/dom/Element.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698