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