18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (C) 1999 Antti Koivisto (koivisto@kde.org) 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (C) 2001 Peter Kelly (pmk@post.com) 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (C) 2001 Dirk Mueller (mueller@kde.org) 68f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (C) 2007 Eric Seidel (eric@webkit.org) 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is free software; you can redistribute it and/or 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modify it under the terms of the GNU Library General Public 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * License as published by the Free Software Foundation; either 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * version 2 of the License, or (at your option) any later version. 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is distributed in the hope that it will be useful, 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Library General Public License for more details. 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * You should have received a copy of the GNU Library General Public License 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * along with this library; see the file COPYING.LIB. If not, write to 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Boston, MA 02110-1301, USA. 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 265f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include "NamedNodeMap.h" 278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include "Attr.h" 298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Document.h" 308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Element.h" 318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ExceptionCode.h" 328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLNames.h" 338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore { 358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace HTMLNames; 378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool shouldIgnoreAttributeCase(const Element* e) 398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return e && e->document()->isHTMLDocument() && e->isHTMLElement(); 418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 435f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianinline void NamedNodeMap::detachAttributesFromElement() 448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian size_t size = m_attributes.size(); 468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian for (size_t i = 0; i < size; i++) { 478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian if (Attr* attr = m_attributes[i]->attr()) 488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian attr->m_element = 0; 498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian } 508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 525f1ab04193ad0130ca8204aadaceae083aca9881Feng QianNamedNodeMap::~NamedNodeMap() 538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian detachAttributesFromElement(); 558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 575f1ab04193ad0130ca8204aadaceae083aca9881Feng QianPassRefPtr<Node> NamedNodeMap::getNamedItem(const String& name) const 588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Attribute* a = getAttributeItem(name, shouldIgnoreAttributeCase(m_element)); 608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!a) 618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return a->createAttrIfNeeded(m_element); 648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 665f1ab04193ad0130ca8204aadaceae083aca9881Feng QianPassRefPtr<Node> NamedNodeMap::getNamedItemNS(const String& namespaceURI, const String& localName) const 678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return getNamedItem(QualifiedName(nullAtom, localName, namespaceURI)); 698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 715f1ab04193ad0130ca8204aadaceae083aca9881Feng QianPassRefPtr<Node> NamedNodeMap::removeNamedItem(const String& name, ExceptionCode& ec) 728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Attribute* a = getAttributeItem(name, shouldIgnoreAttributeCase(m_element)); 748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!a) { 758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ec = NOT_FOUND_ERR; 768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return removeNamedItem(a->name(), ec); 808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 825f1ab04193ad0130ca8204aadaceae083aca9881Feng QianPassRefPtr<Node> NamedNodeMap::removeNamedItemNS(const String& namespaceURI, const String& localName, ExceptionCode& ec) 838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return removeNamedItem(QualifiedName(nullAtom, localName, namespaceURI), ec); 858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 875f1ab04193ad0130ca8204aadaceae083aca9881Feng QianPassRefPtr<Node> NamedNodeMap::getNamedItem(const QualifiedName& name) const 888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Attribute* a = getAttributeItem(name); 908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!a) 918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return a->createAttrIfNeeded(m_element); 948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 965f1ab04193ad0130ca8204aadaceae083aca9881Feng QianPassRefPtr<Node> NamedNodeMap::setNamedItem(Node* arg, ExceptionCode& ec) 978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_element || !arg) { 998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ec = NOT_FOUND_ERR; 1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Not mentioned in spec: throw a HIERARCHY_REQUEST_ERROR if the user passes in a non-attribute node 1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!arg->isAttributeNode()) { 1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ec = HIERARCHY_REQUEST_ERR; 1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Attr *attr = static_cast<Attr*>(arg); 1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Attribute* a = attr->attr(); 1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Attribute* old = getAttributeItem(a->name()); 1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (old == a) 1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return RefPtr<Node>(arg); // we know about it already 1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // INUSE_ATTRIBUTE_ERR: Raised if arg is an Attr that is already an attribute of another Element object. 1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // The DOM user must explicitly clone Attr nodes to re-use them in other elements. 1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (attr->ownerElement()) { 1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ec = INUSE_ATTRIBUTE_ERR; 1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 122d0825bca7fe65beaee391d30da42e937db621564Steve Block if (attr->isId()) 1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_element->updateId(old ? old->value() : nullAtom, a->value()); 1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // ### slightly inefficient - resizes attribute array twice. 1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RefPtr<Node> r; 1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (old) { 1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project r = old->createAttrIfNeeded(m_element); 1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project removeAttribute(a->name()); 1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project addAttribute(a); 1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return r.release(); 1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 136e78cbe89e6f337f2f1fe40315be88f742b547151Steve BlockPassRefPtr<Node> NamedNodeMap::setNamedItemNS(Node* node, ExceptionCode& ec) 137e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block{ 138e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block return setNamedItem(node, ec); 139e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block} 140e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block 1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// The DOM2 spec doesn't say that removeAttribute[NS] throws NOT_FOUND_ERR 1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// if the attribute is not found, but at this level we have to throw NOT_FOUND_ERR 1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// because of removeNamedItem, removeNamedItemNS, and removeAttributeNode. 1445f1ab04193ad0130ca8204aadaceae083aca9881Feng QianPassRefPtr<Node> NamedNodeMap::removeNamedItem(const QualifiedName& name, ExceptionCode& ec) 1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Attribute* a = getAttributeItem(name); 1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!a) { 1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ec = NOT_FOUND_ERR; 1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 152d0825bca7fe65beaee391d30da42e937db621564Steve Block RefPtr<Attr> r = a->createAttrIfNeeded(m_element); 1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 154d0825bca7fe65beaee391d30da42e937db621564Steve Block if (r->isId()) 1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_element->updateId(a->value(), nullAtom); 1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project removeAttribute(name); 1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return r.release(); 1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochPassRefPtr<Node> NamedNodeMap::item(unsigned index) const 1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (index >= length()) 1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_attributes[index]->createAttrIfNeeded(m_element); 1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1696c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsenvoid NamedNodeMap::copyAttributesToVector(Vector<RefPtr<Attribute> >& copy) 1706c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen{ 1716c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen copy = m_attributes; 1726c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen} 1736c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 174d0825bca7fe65beaee391d30da42e937db621564Steve BlockAttribute* NamedNodeMap::getAttributeItemSlowCase(const String& name, bool shouldIgnoreAttributeCase) const 1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned len = length(); 177d0825bca7fe65beaee391d30da42e937db621564Steve Block 178d0825bca7fe65beaee391d30da42e937db621564Steve Block // Continue to checking case-insensitively and/or full namespaced names if necessary: 1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (unsigned i = 0; i < len; ++i) { 180643ca7872b450ea4efacab6188849e5aac2ba161Steve Block const QualifiedName& attrName = m_attributes[i]->name(); 181643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (!attrName.hasPrefix()) { 182d0825bca7fe65beaee391d30da42e937db621564Steve Block if (shouldIgnoreAttributeCase && equalIgnoringCase(name, attrName.localName())) 183d0825bca7fe65beaee391d30da42e937db621564Steve Block return m_attributes[i].get(); 184d0825bca7fe65beaee391d30da42e937db621564Steve Block } else { 185d0825bca7fe65beaee391d30da42e937db621564Steve Block // FIXME: Would be faster to do this comparison without calling toString, which 186d0825bca7fe65beaee391d30da42e937db621564Steve Block // generates a temporary string by concatenation. But this branch is only reached 187d0825bca7fe65beaee391d30da42e937db621564Steve Block // if the attribute name has a prefix, which is rare in HTML. 188d0825bca7fe65beaee391d30da42e937db621564Steve Block if (equalPossiblyIgnoringCase(name, attrName.toString(), shouldIgnoreAttributeCase)) 189643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return m_attributes[i].get(); 190643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } 1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianvoid NamedNodeMap::clearAttributes() 1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 197e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block m_classNames.clear(); 198e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block m_mappedAttributeCount = 0; 199e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block 2008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian detachAttributesFromElement(); 2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_attributes.clear(); 2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianvoid NamedNodeMap::detachFromElement() 2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 206231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // This can't happen if the holder of the map is JavaScript, because we mark the 207231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // element if the map is alive. So it has no impact on web page behavior. Because 208231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // of that, we can simply clear all the attributes to avoid accessing stale 209231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // pointers to do things like create Attr objects. 2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_element = 0; 211231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block clearAttributes(); 2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianvoid NamedNodeMap::setAttributes(const NamedNodeMap& other) 2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // clone all attributes in the other map, but attach to our element 2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_element) 2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If assigning the map changes the id attribute, we need to call 2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // updateId. 222545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch Attribute* oldId = getAttributeItem(m_element->document()->idAttributeName()); 223545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch Attribute* newId = other.getAttributeItem(m_element->document()->idAttributeName()); 2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (oldId || newId) 2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_element->updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom); 2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project clearAttributes(); 2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned newLength = other.length(); 2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_attributes.resize(newLength); 2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (unsigned i = 0; i < newLength; i++) 2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_attributes[i] = other.m_attributes[i]->clone(); 2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: This is wasteful. The class list could be preserved on a copy, and we 2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // wouldn't have to waste time reparsing the attribute. 2365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // The derived class, HTMLNamedNodeMap, which manages a parsed class list for the CLASS attribute, 2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // will update its member variable when parse attribute is called. 2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (unsigned i = 0; i < newLength; i++) 2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_element->attributeChanged(m_attributes[i].get(), true); 2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2425f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianvoid NamedNodeMap::addAttribute(PassRefPtr<Attribute> prpAttribute) 2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RefPtr<Attribute> attribute = prpAttribute; 2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Add the attribute to the list 2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_attributes.append(attribute); 2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (Attr* attr = attribute->attr()) 2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project attr->m_element = m_element; 2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Notify the element that the attribute has been added, and dispatch appropriate mutation events 253231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // Note that element may be null here if we are called from insertAttribute() during parsing 2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_element) { 2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_element->attributeChanged(attribute.get()); 2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Because of our updateStyleAttribute() style modification events are never sent at the right time, so don't bother sending them. 2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (attribute->name() != styleAttr) { 2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_element->dispatchAttrAdditionEvent(attribute.get()); 2598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_element->dispatchSubtreeModifiedEvent(); 2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2645f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianvoid NamedNodeMap::removeAttribute(const QualifiedName& name) 2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned len = length(); 267231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block unsigned index = len; 268231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block for (unsigned i = 0; i < len; ++i) { 2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_attributes[i]->name().matches(name)) { 2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project index = i; 2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 273231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (index >= len) 2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Remove the attribute from the list 2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RefPtr<Attribute> attr = m_attributes[index].get(); 2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (Attr* a = m_attributes[index]->attr()) 2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project a->m_element = 0; 2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_attributes.remove(index); 2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Notify the element that the attribute has been removed 2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // dispatch appropriate mutation events 2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_element && !attr->m_value.isNull()) { 2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project AtomicString value = attr->m_value; 2898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project attr->m_value = nullAtom; 2908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_element->attributeChanged(attr.get()); 2918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project attr->m_value = value; 2928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_element) { 2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_element->dispatchAttrRemovalEvent(attr.get()); 2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_element->dispatchSubtreeModifiedEvent(); 2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 299e78cbe89e6f337f2f1fe40315be88f742b547151Steve Blockvoid NamedNodeMap::setClass(const String& classStr) 300e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block{ 301e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block if (!element()->hasClass()) { 302e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block m_classNames.clear(); 303e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block return; 304e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block } 305e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block 3065ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen m_classNames.set(classStr, element()->document()->inQuirksMode()); 307e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block} 308e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block 309e78cbe89e6f337f2f1fe40315be88f742b547151Steve Blockint NamedNodeMap::declCount() const 310e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block{ 311e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block int result = 0; 312e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block for (unsigned i = 0; i < length(); i++) { 313e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block Attribute* attr = attributeItem(i); 314e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block if (attr->decl()) { 315e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block ASSERT(attr->isMappedAttribute()); 316e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block result++; 317e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block } 318e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block } 319e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block return result; 320e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block} 321e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block 3225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianbool NamedNodeMap::mapsEquivalent(const NamedNodeMap* otherMap) const 3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!otherMap) 3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned len = length(); 3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (len != otherMap->length()) 3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (unsigned i = 0; i < len; i++) { 332e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block Attribute* attr = attributeItem(i); 333e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block Attribute* otherAttr = otherMap->getAttributeItem(attr->name()); 3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!otherAttr || attr->value() != otherAttr->value()) 3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 341e78cbe89e6f337f2f1fe40315be88f742b547151Steve Blockbool NamedNodeMap::mappedMapsEquivalent(const NamedNodeMap* otherMap) const 342e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block{ 343e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block // The # of decls must match. 344e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block if (declCount() != otherMap->declCount()) 345e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block return false; 346e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block 347e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block // The values for each decl must match. 348e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block for (unsigned i = 0; i < length(); i++) { 349e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block Attribute* attr = attributeItem(i); 350e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block if (attr->decl()) { 351e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block ASSERT(attr->isMappedAttribute()); 352e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block 353e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block Attribute* otherAttr = otherMap->getAttributeItem(attr->name()); 3542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (!otherAttr || !otherAttr->decl() || attr->value() != otherAttr->value()) 355e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block return false; 356ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch if (!attr->decl()->propertiesEqual(otherAttr->decl())) 357ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch return false; 358e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block } 359e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block } 360e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block return true; 3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 362e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block 363e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block} // namespace WebCore 364