WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
bug-77674-20120203113444.patch (text/plain), 120.46 KB, created by
Caio Marcelo de Oliveira Filho
on 2012-02-03 06:34:41 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Caio Marcelo de Oliveira Filho
Created:
2012-02-03 06:34:41 PST
Size:
120.46 KB
patch
obsolete
>Subversion Revision: 106655 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 04b94baecdeb969f8bcb10bc870a629e10d745aa..3382bab00b4e130fc6a6e5d5ebf2da346d5de1af 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,208 @@ >+2012-02-03 Caio Marcelo de Oliveira Filho <caio.oliveira@openbossa.org> >+ >+ Move attribute storage from NamedNodeMap to ElementAttributeData >+ https://bugs.webkit.org/show_bug.cgi?id=77674 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Moves m_attributes vector from NamedNodeMap to ElementAttributeData, and make >+ callsites interact directly with ElementAttributeData. The parser code was also >+ changed to create ElementAttributeData instead of NamedNodeMap, since it only >+ uses it as attribute storage. >+ >+ To unify the attribute storage getter functions, this commit also moves the >+ inline style declaration functions to ElementAttributeData (the data was there >+ already). >+ >+ This is another step towards https://bugs.webkit.org/show_bug.cgi?id=75069. The >+ next step will be decouple ElementAttributeData's lifetime from NamedNodeMap. >+ >+ * css/CSSStyleSelector.cpp: >+ (WebCore::CSSStyleSelector::matchAllRules): >+ (WebCore::mappedAttributesEquivalent): >+ (WebCore::CSSStyleSelector::canShareStyleWithElement): >+ * css/SelectorChecker.cpp: >+ (WebCore::anyAttributeMatches): >+ (WebCore::SelectorChecker::checkOneSelector): >+ * css/SelectorChecker.h: >+ (WebCore::SelectorChecker::checkExactAttribute): >+ * dom/Attr.h: >+ (Attr): >+ * dom/Attribute.h: >+ (WebCore): >+ * dom/DatasetDOMStringMap.cpp: >+ (WebCore::DatasetDOMStringMap::getNames): >+ (WebCore::DatasetDOMStringMap::item): >+ (WebCore::DatasetDOMStringMap::contains): >+ * dom/Document.cpp: >+ (WebCore::Document::importNode): >+ * dom/Element.cpp: >+ (WebCore::Element::removeAttribute): >+ (WebCore::Element::getAttribute): >+ (WebCore::Element::setAttribute): >+ (WebCore::Element::setAttributeInternal): >+ (WebCore::Element::parserSetAttributeData): >+ (WebCore::Element::hasAttributes): >+ (WebCore::Element::insertedIntoDocument): >+ (WebCore::Element::removedFromDocument): >+ (WebCore::Element::setAttributeNode): >+ (WebCore::Element::setAttributeNodeNS): >+ (WebCore::Element::removeAttributeNode): >+ (WebCore::Element::getAttributeNode): >+ (WebCore::Element::getAttributeNodeNS): >+ (WebCore::Element::hasAttribute): >+ (WebCore::Element::hasAttributeNS): >+ (WebCore::Element::normalizeAttributes): >+ (WebCore::Element::getURLAttribute): >+ (WebCore::Element::getNonEmptyURLAttribute): >+ * dom/Element.h: >+ (Element): >+ (WebCore::Element::attributes): >+ (WebCore): >+ (WebCore::Element::ensureAttributeData): >+ (WebCore::Element::updatedAttributeData): >+ (WebCore::Element::ensureUpdatedAttributeData): >+ (WebCore::Element::setAttributesFromElement): >+ (WebCore::Element::fastHasAttribute): >+ (WebCore::Element::fastGetAttribute): >+ (WebCore::shouldIgnoreAttributeCase): >+ * dom/ElementAttributeData.cpp: >+ (WebCore::ElementAttributeData::~ElementAttributeData): >+ (WebCore): >+ (WebCore::ElementAttributeData::ensureInlineStyleDecl): >+ (WebCore::ElementAttributeData::destroyInlineStyleDecl): >+ (WebCore::ElementAttributeData::getNamedItem): >+ (WebCore::ElementAttributeData::removeNamedItem): >+ (WebCore::ElementAttributeData::setNamedItem): >+ (WebCore::ElementAttributeData::item): >+ (WebCore::ElementAttributeData::equivalent): >+ (WebCore::ElementAttributeData::addAttribute): >+ (WebCore::ElementAttributeData::removeAttribute): >+ (WebCore::ElementAttributeData::copyAttributesToVector): >+ (WebCore::ElementAttributeData::detachAttributesFromElement): >+ (WebCore::ElementAttributeData::getAttributeItemIndexSlowCase): >+ (WebCore::ElementAttributeData::setAttributes): >+ (WebCore::ElementAttributeData::clearAttributes): >+ (WebCore::ElementAttributeData::replaceAttribute): >+ * dom/ElementAttributeData.h: >+ (WebCore::ElementAttributeData::create): >+ (ElementAttributeData): >+ (WebCore::ElementAttributeData::inlineStyleDecl): >+ (WebCore::ElementAttributeData::length): >+ (WebCore::ElementAttributeData::isEmpty): >+ (WebCore::ElementAttributeData::insertAttribute): >+ (WebCore::ElementAttributeData::attributeItem): >+ (WebCore::ElementAttributeData::reserveInitialCapacity): >+ (WebCore::ElementAttributeData::removeAttribute): >+ (WebCore): >+ (WebCore::ElementAttributeData::getAttributeItem): >+ (WebCore::ElementAttributeData::getAttributeItemIndex): >+ (WebCore::ElementAttributeData::mappedAttributeCount): >+ * dom/NamedNodeMap.cpp: >+ (WebCore::NamedNodeMap::detachFromElement): >+ * dom/NamedNodeMap.h: >+ (WebCore::NamedNodeMap::getNamedItem): >+ (WebCore::NamedNodeMap::removeNamedItem): >+ (WebCore::NamedNodeMap::setNamedItem): >+ (WebCore::NamedNodeMap::item): >+ (WebCore::NamedNodeMap::length): >+ (WebCore::NamedNodeMap::mapsEquivalent): >+ (NamedNodeMap): >+ * dom/Node.cpp: >+ (WebCore::Node::isEqualNode): >+ (WebCore::Node::isDefaultNamespace): >+ (WebCore::Node::lookupNamespaceURI): >+ (WebCore::Node::lookupNamespacePrefix): >+ (WebCore::Node::compareDocumentPosition): >+ * dom/Node.h: >+ (WebCore): >+ * dom/StyledElement.cpp: >+ (WebCore::StyledElement::classAttributeChanged): >+ * dom/StyledElement.h: >+ (WebCore::StyledElement::mappedAttributeCount): >+ (WebCore::StyledElement::inlineStyleDecl): >+ (WebCore::StyledElement::ensureInlineStyleDecl): >+ (WebCore::StyledElement::destroyInlineStyleDecl): >+ * editing/ApplyStyleCommand.cpp: >+ (WebCore::hasNoAttributeOrOnlyStyleAttribute): >+ (WebCore::isEmptyFontTag): >+ * editing/EditingStyle.cpp: >+ (WebCore::EditingStyle::elementIsStyledSpanOrHTMLEquivalent): >+ * editing/InsertParagraphSeparatorCommand.cpp: >+ (WebCore::highestVisuallyEquivalentDivBelowRoot): >+ * editing/MarkupAccumulator.cpp: >+ (WebCore::MarkupAccumulator::appendElement): >+ * editing/htmlediting.cpp: >+ (WebCore::areIdenticalElements): >+ * editing/markup.cpp: >+ (WebCore::completeURLs): Make use of continue to avoid indentation. >+ (WebCore::StyledMarkupAccumulator::appendElement): >+ * html/HTMLEmbedElement.cpp: >+ (WebCore::HTMLEmbedElement::parametersForPlugin): >+ * html/HTMLInputElement.cpp: >+ (WebCore::HTMLInputElement::updateType): >+ * html/HTMLObjectElement.cpp: >+ (WebCore::HTMLObjectElement::parametersForPlugin): >+ * html/HTMLParamElement.cpp: >+ (WebCore::HTMLParamElement::isURLAttribute): >+ * html/parser/HTMLConstructionSite.cpp: >+ (WebCore::HTMLConstructionSite::insertHTMLHtmlStartTagBeforeHTML): >+ (WebCore::HTMLConstructionSite::mergeAttributesFromTokenIntoElement): >+ (WebCore::HTMLConstructionSite::insertScriptElement): >+ (WebCore::HTMLConstructionSite::createElement): >+ (WebCore::HTMLConstructionSite::createHTMLElement): >+ (WebCore): >+ * html/parser/HTMLFormattingElementList.cpp: >+ (WebCore::attributeCount): >+ (WebCore::HTMLFormattingElementList::ensureNoahsArkCondition): >+ * html/parser/HTMLToken.h: >+ (WebCore::AtomicHTMLToken::AtomicHTMLToken): >+ * html/parser/HTMLTreeBuilder.cpp: >+ (WebCore::HTMLTreeBuilder::processFakeStartTag): >+ (WebCore::HTMLTreeBuilder::attributesForIsindexInput): >+ (WebCore): >+ * html/parser/HTMLTreeBuilder.h: >+ * html/parser/TextDocumentParser.cpp: >+ (WebCore::TextDocumentParser::insertFakePreElement): >+ * inspector/DOMEditor.cpp: >+ (WebCore::DOMEditor::innerPatchNode): >+ (WebCore::DOMEditor::createDigest): >+ * inspector/DOMEditor.h: >+ (WebCore): >+ * inspector/InspectorCSSAgent.cpp: >+ (WebCore::InspectorCSSAgent::buildArrayForAttributeStyles): >+ * inspector/InspectorDOMAgent.cpp: >+ (WebCore::InspectorDOMAgent::setAttributesAsText): >+ (WebCore::InspectorDOMAgent::performSearch): >+ (WebCore::InspectorDOMAgent::buildArrayForElementAttributes): >+ * page/PageSerializer.cpp: >+ (WebCore::isCharsetSpecifyingNode): >+ * svg/SVGElement.cpp: >+ (WebCore::SVGElement::attributeChanged): >+ * svg/SVGStyledElement.cpp: >+ (WebCore::SVGStyledElement::getPresentationAttribute): >+ * svg/properties/SVGAnimatedPropertySynchronizer.h: >+ * xml/XPathFunctions.cpp: >+ (WebCore::XPath::FunLang::evaluate): >+ * xml/XPathNodeSet.cpp: >+ (WebCore::XPath::NodeSet::traversalSort): >+ * xml/XPathStep.cpp: >+ (WebCore::XPath::Step::nodesInAxis): >+ * xml/parser/MarkupTokenBase.h: >+ (WebCore::AtomicMarkupTokenBase::AtomicMarkupTokenBase): >+ (WebCore::AtomicMarkupTokenBase::attributes): >+ (WebCore::AtomicMarkupTokenBase::takeAttributes): >+ (AtomicMarkupTokenBase): >+ (WebCore::::initializeAttributes): >+ * xml/parser/XMLDocumentParserLibxml2.cpp: >+ (WebCore::XMLDocumentParser::XMLDocumentParser): >+ * xml/parser/XMLDocumentParserQt.cpp: >+ (WebCore::XMLDocumentParser::XMLDocumentParser): >+ * xml/parser/XMLToken.h: >+ (WebCore::AtomicXMLToken::AtomicXMLToken): >+ * xml/parser/XMLTreeBuilder.cpp: >+ (WebCore::XMLTreeBuilder::XMLTreeBuilder): >+ > 2012-02-03 Rob Buis <rbuis@rim.com> > > Upstream targetType usage on ResourceRequest for BlackBerry port >diff --git a/Source/WebKit/chromium/ChangeLog b/Source/WebKit/chromium/ChangeLog >index bff3adf49b5c32f267e519f329f1c706f3c936b1..7d055a9a1119c3a6b64cbce08a202a6cc80cd8fc 100644 >--- a/Source/WebKit/chromium/ChangeLog >+++ b/Source/WebKit/chromium/ChangeLog >@@ -1,3 +1,16 @@ >+2012-02-03 Caio Marcelo de Oliveira Filho <caio.oliveira@openbossa.org> >+ >+ Move attribute storage from NamedNodeMap to ElementAttributeData >+ https://bugs.webkit.org/show_bug.cgi?id=77674 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * src/WebNamedNodeMap.cpp: >+ (WebKit::WebNamedNodeMap::attributeItem): attributeItem() is now a method of >+ ElementAttributeData. >+ * src/WebPageSerializerImpl.cpp: >+ (WebKit::WebPageSerializerImpl::openTagToString): use updatedAttributeData(). >+ > 2012-02-03 Yury Semikhatsky <yurys@chromium.org> > > Unreviewed. Update Chromium deps. >diff --git a/Source/WebKit/qt/ChangeLog b/Source/WebKit/qt/ChangeLog >index 1a046df462e952c46adb7959b99ea3c6ba0bd8bb..ca4ca0aba134e8fcdac308e88752e2d9b3bcd184 100644 >--- a/Source/WebKit/qt/ChangeLog >+++ b/Source/WebKit/qt/ChangeLog >@@ -1,3 +1,13 @@ >+2012-02-03 Caio Marcelo de Oliveira Filho <caio.oliveira@openbossa.org> >+ >+ Move attribute storage from NamedNodeMap to ElementAttributeData >+ https://bugs.webkit.org/show_bug.cgi?id=77674 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * Api/qwebelement.cpp: >+ (QWebElement::attributeNames): use updatedAttributeData(). >+ > 2012-02-02 Sheriff Bot <webkit.review.bot@gmail.com> > > Unreviewed, rolling out r106620. >diff --git a/Source/WebCore/css/CSSStyleSelector.cpp b/Source/WebCore/css/CSSStyleSelector.cpp >index 84c302ac0b73809eb2879dd9a976c3a8536f8622..98bb290d4643d6f3bf7bcce2f74fd727a6c0ea8e 100644 >--- a/Source/WebCore/css/CSSStyleSelector.cpp >+++ b/Source/WebCore/css/CSSStyleSelector.cpp >@@ -996,10 +996,10 @@ void CSSStyleSelector::matchAllRules(MatchResult& result) > > // Now check author rules, beginning first with presentational attributes mapped from HTML. > if (m_styledElement) { >- if (const NamedNodeMap* map = m_styledElement->attributeMap()) { >- // Walk the element's attribute map and add all mapped attribute declarations. >- for (unsigned i = 0; i < map->length(); ++i) { >- Attribute* attribute = map->attributeItem(i); >+ if (const ElementAttributeData* attributeData = m_styledElement->attributeData()) { >+ // Walk the element's attribute data and add all mapped attribute declarations. >+ for (unsigned i = 0; i < attributeData->length(); ++i) { >+ Attribute* attribute = attributeData->attributeItem(i); > if (!attribute->decl()) > continue; > ASSERT(attribute->isMappedAttribute()); >@@ -1198,7 +1198,7 @@ bool CSSStyleSelector::canShareStyleWithControl(StyledElement* element) const > return true; > } > >-static inline bool mappedAttributesEquivalent(NamedNodeMap* a, NamedNodeMap* b) >+static inline bool mappedAttributesEquivalent(ElementAttributeData* a, ElementAttributeData* b) > { > ASSERT(a->mappedAttributeCount() == b->mappedAttributeCount()); > >@@ -1295,7 +1295,7 @@ bool CSSStyleSelector::canShareStyleWithElement(StyledElement* element) const > if (element->hasClass() && m_element->getAttribute(classAttr) != element->getAttribute(classAttr)) > return false; > >- if (mappedAttributeCount && !mappedAttributesEquivalent(element->attributeMap(), m_styledElement->attributeMap())) >+ if (mappedAttributeCount && !mappedAttributesEquivalent(element->attributeData(), m_styledElement->attributeData())) > return false; > > if (element->isLink() && m_elementLinkState != style->insideLink()) >diff --git a/Source/WebCore/css/SelectorChecker.cpp b/Source/WebCore/css/SelectorChecker.cpp >index 586774647a087d3a0c2d7f282cb3bb0336f94405..4de66319a95024670a5bb8b9b2f06c9ad0a59cd1 100644 >--- a/Source/WebCore/css/SelectorChecker.cpp >+++ b/Source/WebCore/css/SelectorChecker.cpp >@@ -671,7 +671,7 @@ static bool attributeValueMatches(Attribute* attributeItem, CSSSelector::Match m > return true; > } > >-static bool anyAttributeMatches(NamedNodeMap* attributes, CSSSelector::Match match, const QualifiedName& selectorAttr, const AtomicString& selectorValue, bool caseSensitive) >+static bool anyAttributeMatches(ElementAttributeData* attributes, CSSSelector::Match match, const QualifiedName& selectorAttr, const AtomicString& selectorValue, bool caseSensitive) > { > for (size_t i = 0; i < attributes->length(); ++i) { > Attribute* attributeItem = attributes->attributeItem(i); >@@ -701,7 +701,7 @@ bool SelectorChecker::checkOneSelector(CSSSelector* sel, Element* e, PseudoId& d > if (sel->isAttributeSelector()) { > const QualifiedName& attr = sel->attribute(); > >- NamedNodeMap* attributes = e->updatedAttributes(); >+ ElementAttributeData* attributes = e->updatedAttributeData(); > if (!attributes) > return false; > >diff --git a/Source/WebCore/css/SelectorChecker.h b/Source/WebCore/css/SelectorChecker.h >index 3f9469e5d79b09c9ab842e742d85fad717b9471f..3f916d20a6a39e785fa52183ed145ac8717286bf 100644 >--- a/Source/WebCore/css/SelectorChecker.h >+++ b/Source/WebCore/css/SelectorChecker.h >@@ -185,12 +185,12 @@ inline bool SelectorChecker::attributeNameMatches(const Attribute* attribute, co > > inline bool SelectorChecker::checkExactAttribute(const Element* element, const QualifiedName& selectorAttributeName, const AtomicStringImpl* value) > { >- NamedNodeMap* attributeMap = element->attributeMap(); >- if (!attributeMap) >+ ElementAttributeData* attributeData = element->attributeData(); >+ if (!attributeData) > return false; >- unsigned size = attributeMap->length(); >+ unsigned size = attributeData->length(); > for (unsigned i = 0; i < size; ++i) { >- Attribute* attribute = attributeMap->attributeItem(i); >+ Attribute* attribute = attributeData->attributeItem(i); > if (attributeNameMatches(attribute, selectorAttributeName) && (!value || attribute->value().impl() == value)) > return true; > } >diff --git a/Source/WebCore/dom/Attr.h b/Source/WebCore/dom/Attr.h >index 7b6e332eeaab8263d86939e9eceb2bca073a5769..09ac796a1e948f087f600b051fe503bb7f337384 100644 >--- a/Source/WebCore/dom/Attr.h >+++ b/Source/WebCore/dom/Attr.h >@@ -37,7 +37,7 @@ namespace WebCore { > // destruction. however, this is not yet implemented. > > class Attr : public ContainerNode { >- friend class NamedNodeMap; >+ friend class ElementAttributeData; > public: > static PassRefPtr<Attr> create(Element*, Document*, PassRefPtr<Attribute>); > virtual ~Attr(); >diff --git a/Source/WebCore/dom/Attribute.h b/Source/WebCore/dom/Attribute.h >index 938e1922dcffd283371b824d61708688220d02c8..0c3e174d73a7617eb2e4804710ae23023b8ca1ea 100644 >--- a/Source/WebCore/dom/Attribute.h >+++ b/Source/WebCore/dom/Attribute.h >@@ -33,7 +33,6 @@ namespace WebCore { > class Attr; > class CSSStyleDeclaration; > class Element; >-class NamedNodeMap; > > // This has no counterpart in DOM. > // It is an internal representation of the node value of an Attr. >diff --git a/Source/WebCore/dom/DatasetDOMStringMap.cpp b/Source/WebCore/dom/DatasetDOMStringMap.cpp >index dff0ad75072067e556ce1e28614512427e130c03..2f54e48e514726e299cec81823de9f1eb7fdcea6 100644 >--- a/Source/WebCore/dom/DatasetDOMStringMap.cpp >+++ b/Source/WebCore/dom/DatasetDOMStringMap.cpp >@@ -29,7 +29,6 @@ > #include "Attribute.h" > #include "Element.h" > #include "ExceptionCode.h" >-#include "NamedNodeMap.h" > #include <wtf/ASCIICType.h> > #include <wtf/text/StringBuilder.h> > >@@ -142,11 +141,11 @@ void DatasetDOMStringMap::deref() > > void DatasetDOMStringMap::getNames(Vector<String>& names) > { >- NamedNodeMap* attributeMap = m_element->updatedAttributes(); >- if (attributeMap) { >- unsigned length = attributeMap->length(); >+ ElementAttributeData* attributeData = m_element->updatedAttributeData(); >+ if (attributeData) { >+ unsigned length = attributeData->length(); > for (unsigned i = 0; i < length; i++) { >- Attribute* attribute = attributeMap->attributeItem(i); >+ Attribute* attribute = attributeData->attributeItem(i); > if (isValidAttributeName(attribute->localName())) > names.append(convertAttributeNameToPropertyName(attribute->localName())); > } >@@ -155,11 +154,11 @@ void DatasetDOMStringMap::getNames(Vector<String>& names) > > String DatasetDOMStringMap::item(const String& name) > { >- NamedNodeMap* attributeMap = m_element->updatedAttributes(); >- if (attributeMap) { >- unsigned length = attributeMap->length(); >+ ElementAttributeData* attributeData = m_element->updatedAttributeData(); >+ if (attributeData) { >+ unsigned length = attributeData->length(); > for (unsigned i = 0; i < length; i++) { >- Attribute* attribute = attributeMap->attributeItem(i); >+ Attribute* attribute = attributeData->attributeItem(i); > if (propertyNameMatchesAttributeName(name, attribute->localName())) > return attribute->value(); > } >@@ -170,11 +169,11 @@ String DatasetDOMStringMap::item(const String& name) > > bool DatasetDOMStringMap::contains(const String& name) > { >- NamedNodeMap* attributeMap = m_element->updatedAttributes(); >- if (attributeMap) { >- unsigned length = attributeMap->length(); >+ ElementAttributeData* attributeData = m_element->updatedAttributeData(); >+ if (attributeData) { >+ unsigned length = attributeData->length(); > for (unsigned i = 0; i < length; i++) { >- Attribute* attribute = attributeMap->attributeItem(i); >+ Attribute* attribute = attributeData->attributeItem(i); > if (propertyNameMatchesAttributeName(name, attribute->localName())) > return true; > } >diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp >index 6ef4bc77096c27bd1d4af81ab3a6abbbdfe411a8..84160d27ed7812b97b65725dfdc5597c0d9e864e 100644 >--- a/Source/WebCore/dom/Document.cpp >+++ b/Source/WebCore/dom/Document.cpp >@@ -850,7 +850,7 @@ PassRefPtr<Node> Document::importNode(Node* importedNode, bool deep, ExceptionCo > if (ec) > return 0; > >- NamedNodeMap* attrs = oldElement->updatedAttributes(); >+ ElementAttributeData* attrs = oldElement->updatedAttributeData(); > if (attrs) { > unsigned length = attrs->length(); > for (unsigned i = 0; i < length; i++) { >diff --git a/Source/WebCore/dom/Element.cpp b/Source/WebCore/dom/Element.cpp >index 57caa4a00e38a7acc0993b310dcc921014a57ac1..628328b9157486091d6bcf06ebfebc9375821c71 100644 >--- a/Source/WebCore/dom/Element.cpp >+++ b/Source/WebCore/dom/Element.cpp >@@ -183,10 +183,10 @@ void Element::copyNonAttributeProperties(const Element*) > > void Element::removeAttribute(const QualifiedName& name) > { >- if (!m_attributeMap) >+ if (!attributeData()) > return; > >- m_attributeMap->removeAttribute(name); >+ attributeData()->removeAttribute(name, this); > } > > void Element::setBooleanAttribute(const QualifiedName& name, bool value) >@@ -217,8 +217,8 @@ const AtomicString& Element::getAttribute(const QualifiedName& name) const > updateAnimatedSVGAttribute(name); > #endif > >- if (m_attributeMap) { >- if (Attribute* attribute = m_attributeMap->getAttributeItem(name)) >+ if (attributeData()) { >+ if (Attribute* attribute = attributeData()->getAttributeItem(name)) > return attribute->value(); > } > return nullAtom; >@@ -574,11 +574,6 @@ LayoutRect Element::screenRect() const > return renderer()->view()->frameView()->contentsToScreen(renderer()->absoluteBoundingBoxRectIgnoringTransforms()); > } > >-static inline bool shouldIgnoreAttributeCase(const Element* e) >-{ >- return e && e->document()->isHTMLDocument() && e->isHTMLElement(); >-} >- > const AtomicString& Element::getAttribute(const String& name) const > { > bool ignoreCase = shouldIgnoreAttributeCase(this); >@@ -594,8 +589,8 @@ const AtomicString& Element::getAttribute(const String& name) const > } > #endif > >- if (m_attributeMap) { >- if (Attribute* attribute = m_attributeMap->getAttributeItem(name, ignoreCase)) >+ if (attributeData()) { >+ if (Attribute* attribute = attributeData()->getAttributeItem(name, ignoreCase)) > return attribute->value(); > } > >@@ -616,27 +611,27 @@ void Element::setAttribute(const AtomicString& name, const AtomicString& value, > > const AtomicString& localName = shouldIgnoreAttributeCase(this) ? name.lower() : name; > >- size_t index = ensureUpdatedAttributes()->getAttributeItemIndex(localName, false); >- const QualifiedName& qName = index != notFound ? m_attributeMap->attributeItem(index)->name() : QualifiedName(nullAtom, localName, nullAtom); >+ size_t index = ensureUpdatedAttributeData()->getAttributeItemIndex(localName, false); >+ const QualifiedName& qName = index != notFound ? attributeData()->attributeItem(index)->name() : QualifiedName(nullAtom, localName, nullAtom); > setAttributeInternal(index, qName, value); > } > > void Element::setAttribute(const QualifiedName& name, const AtomicString& value) > { >- setAttributeInternal(ensureUpdatedAttributes()->getAttributeItemIndex(name), name, value); >+ setAttributeInternal(ensureUpdatedAttributeData()->getAttributeItemIndex(name), name, value); > } > > inline void Element::setAttributeInternal(size_t index, const QualifiedName& name, const AtomicString& value) > { >- Attribute* old = index != notFound ? m_attributeMap->attributeItem(index) : 0; >+ Attribute* old = index != notFound ? attributeData()->attributeItem(index) : 0; > if (value.isNull()) { > if (old) >- m_attributeMap->removeAttribute(index); >+ attributeData()->removeAttribute(index, this); > return; > } > > if (!old) { >- m_attributeMap->addAttribute(createAttribute(name, value)); >+ attributeData()->addAttribute(createAttribute(name, value), this); > return; > } > >@@ -736,7 +731,7 @@ static bool isAttributeToRemove(const QualifiedName& name, const AtomicString& v > return (name.localName().endsWith(hrefAttr.localName()) || name == srcAttr || name == actionAttr) && protocolIsJavaScript(stripLeadingAndTrailingHTMLSpaces(value)); > } > >-void Element::parserSetAttributeMap(PassOwnPtr<NamedNodeMap> list, FragmentScriptingPermission scriptingPermission) >+void Element::parserSetAttributeData(PassOwnPtr<ElementAttributeData> attributeData, FragmentScriptingPermission scriptingPermission) > { > ASSERT(!inDocument()); > ASSERT(!parentNode()); >@@ -744,39 +739,45 @@ void Element::parserSetAttributeMap(PassOwnPtr<NamedNodeMap> list, FragmentScrip > document()->incDOMTreeVersion(); > > ASSERT(!m_attributeMap); >- m_attributeMap = list; >- >- if (m_attributeMap) { >- m_attributeMap->m_element = this; >- // If the element is created as result of a paste or drag-n-drop operation >- // we want to remove all the script and event handlers. >- if (scriptingPermission == FragmentScriptingNotAllowed) { >- unsigned i = 0; >- while (i < m_attributeMap->length()) { >- const QualifiedName& attributeName = m_attributeMap->m_attributes[i]->name(); >- if (isEventHandlerAttribute(attributeName)) { >- m_attributeMap->m_attributes.remove(i); >- continue; >- } >- >- if (isAttributeToRemove(attributeName, m_attributeMap->m_attributes[i]->value())) >- m_attributeMap->m_attributes[i]->setValue(nullAtom); >- i++; >+ >+ if (!attributeData) >+ return; >+ >+ createAttributeMap(); >+ >+ // If the element is created as result of a paste or drag-n-drop operation >+ // we want to remove all the script and event handlers. >+ if (scriptingPermission == FragmentScriptingNotAllowed) { >+ unsigned i = 0; >+ while (i < attributeData->length()) { >+ const QualifiedName& attributeName = attributeData->m_attributes[i]->name(); >+ if (isEventHandlerAttribute(attributeName)) { >+ attributeData->m_attributes.remove(i); >+ continue; > } >+ >+ if (isAttributeToRemove(attributeName, attributeData->m_attributes[i]->value())) >+ attributeData->m_attributes[i]->setValue(nullAtom); >+ i++; > } >- // Store the set of attributes that changed on the stack in case >- // attributeChanged mutates m_attributeMap. >- Vector<RefPtr<Attribute> > attributes; >- m_attributeMap->copyAttributesToVector(attributes); >- for (Vector<RefPtr<Attribute> >::iterator iter = attributes.begin(); iter != attributes.end(); ++iter) >- attributeChanged(iter->get()); > } >+ >+ // FIXME: this shouldn't be a copy, we should get ownership of attributeData. This will be >+ // fixed when we move ElementAttributeData out from NamedNodeMap. >+ m_attributeMap->m_attributeData = *attributeData; >+ >+ // Store the set of attributes that changed on the stack in case >+ // attributeChanged mutates m_attributeMap. >+ Vector<RefPtr<Attribute> > attributes; >+ attributeData->copyAttributesToVector(attributes); >+ for (Vector<RefPtr<Attribute> >::iterator iter = attributes.begin(); iter != attributes.end(); ++iter) >+ attributeChanged(iter->get()); > } > > bool Element::hasAttributes() const > { > updateInvalidAttributes(); >- return m_attributeMap && m_attributeMap->length(); >+ return attributeData() && attributeData()->length(); > } > > String Element::nodeName() const >@@ -870,14 +871,14 @@ void Element::insertedIntoDocument() > if (ShadowRoot* shadow = shadowRoot()) > shadow->insertedIntoDocument(); > >- if (m_attributeMap) { >+ if (attributeData()) { > if (hasID()) { >- Attribute* idItem = m_attributeMap->getAttributeItem(document()->idAttributeName()); >+ Attribute* idItem = attributeData()->getAttributeItem(document()->idAttributeName()); > if (idItem && !idItem->isNull()) > updateId(nullAtom, idItem->value()); > } > if (hasName()) { >- Attribute* nameItem = m_attributeMap->getAttributeItem(HTMLNames::nameAttr); >+ Attribute* nameItem = attributeData()->getAttributeItem(HTMLNames::nameAttr); > if (nameItem && !nameItem->isNull()) > updateName(nullAtom, nameItem->value()); > } >@@ -886,14 +887,14 @@ void Element::insertedIntoDocument() > > void Element::removedFromDocument() > { >- if (m_attributeMap) { >+ if (attributeData()) { > if (hasID()) { >- Attribute* idItem = m_attributeMap->getAttributeItem(document()->idAttributeName()); >+ Attribute* idItem = attributeData()->getAttributeItem(document()->idAttributeName()); > if (idItem && !idItem->isNull()) > updateId(idItem->value(), nullAtom); > } > if (hasName()) { >- Attribute* nameItem = m_attributeMap->getAttributeItem(HTMLNames::nameAttr); >+ Attribute* nameItem = attributeData()->getAttributeItem(HTMLNames::nameAttr); > if (nameItem && !nameItem->isNull()) > updateName(nameItem->value(), nullAtom); > } >@@ -1420,7 +1421,7 @@ PassRefPtr<Attr> Element::setAttributeNode(Attr* attr, ExceptionCode& ec) > ec = TYPE_MISMATCH_ERR; > return 0; > } >- return static_pointer_cast<Attr>(ensureUpdatedAttributes()->setNamedItem(attr, ec)); >+ return static_pointer_cast<Attr>(ensureUpdatedAttributeData()->setNamedItem(attr, ec, this)); > } > > PassRefPtr<Attr> Element::setAttributeNodeNS(Attr* attr, ExceptionCode& ec) >@@ -1429,7 +1430,7 @@ PassRefPtr<Attr> Element::setAttributeNodeNS(Attr* attr, ExceptionCode& ec) > ec = TYPE_MISMATCH_ERR; > return 0; > } >- return static_pointer_cast<Attr>(ensureUpdatedAttributes()->setNamedItem(attr, ec)); >+ return static_pointer_cast<Attr>(ensureUpdatedAttributeData()->setNamedItem(attr, ec, this)); > } > > PassRefPtr<Attr> Element::removeAttributeNode(Attr* attr, ExceptionCode& ec) >@@ -1445,11 +1446,11 @@ PassRefPtr<Attr> Element::removeAttributeNode(Attr* attr, ExceptionCode& ec) > > ASSERT(document() == attr->document()); > >- NamedNodeMap* attrs = updatedAttributes(); >+ ElementAttributeData* attrs = updatedAttributeData(); > if (!attrs) > return 0; > >- return static_pointer_cast<Attr>(attrs->removeNamedItem(attr->qualifiedName(), ec)); >+ return static_pointer_cast<Attr>(attrs->removeNamedItem(attr->qualifiedName(), ec, this)); > } > > void Element::setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode& ec, FragmentScriptingPermission scriptingPermission) >@@ -1473,15 +1474,15 @@ void Element::setAttributeNS(const AtomicString& namespaceURI, const AtomicStrin > > void Element::removeAttribute(const String& name) > { >- if (!m_attributeMap) >+ if (!attributeData()) > return; > > String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name; >- size_t index = m_attributeMap->getAttributeItemIndex(localName, false); >+ size_t index = attributeData()->getAttributeItemIndex(localName, false); > if (index == notFound) > return; > >- m_attributeMap->removeAttribute(index); >+ attributeData()->removeAttribute(index, this); > } > > void Element::removeAttributeNS(const String& namespaceURI, const String& localName) >@@ -1491,24 +1492,24 @@ void Element::removeAttributeNS(const String& namespaceURI, const String& localN > > PassRefPtr<Attr> Element::getAttributeNode(const String& name) > { >- NamedNodeMap* attrs = updatedAttributes(); >+ ElementAttributeData* attrs = updatedAttributeData(); > if (!attrs) > return 0; > String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name; >- return static_pointer_cast<Attr>(attrs->getNamedItem(localName)); >+ return static_pointer_cast<Attr>(attrs->getNamedItem(localName, this)); > } > > PassRefPtr<Attr> Element::getAttributeNodeNS(const String& namespaceURI, const String& localName) > { >- NamedNodeMap* attrs = updatedAttributes(); >+ ElementAttributeData* attrs = updatedAttributeData(); > if (!attrs) > return 0; >- return static_pointer_cast<Attr>(attrs->getNamedItem(QualifiedName(nullAtom, localName, namespaceURI))); >+ return static_pointer_cast<Attr>(attrs->getNamedItem(QualifiedName(nullAtom, localName, namespaceURI), this)); > } > > bool Element::hasAttribute(const String& name) const > { >- NamedNodeMap* attrs = updatedAttributes(); >+ ElementAttributeData* attrs = updatedAttributeData(); > if (!attrs) > return false; > >@@ -1520,7 +1521,7 @@ bool Element::hasAttribute(const String& name) const > > bool Element::hasAttributeNS(const String& namespaceURI, const String& localName) const > { >- NamedNodeMap* attrs = updatedAttributes(); >+ ElementAttributeData* attrs = updatedAttributeData(); > if (!attrs) > return false; > return attrs->getAttributeItem(QualifiedName(nullAtom, localName, namespaceURI)); >@@ -1710,7 +1711,7 @@ void Element::cancelFocusAppearanceUpdate() > > void Element::normalizeAttributes() > { >- NamedNodeMap* attrs = updatedAttributes(); >+ ElementAttributeData* attrs = updatedAttributeData(); > if (!attrs) > return; > >@@ -1834,8 +1835,8 @@ DOMStringMap* Element::dataset() > KURL Element::getURLAttribute(const QualifiedName& name) const > { > #if !ASSERT_DISABLED >- if (m_attributeMap) { >- if (Attribute* attribute = m_attributeMap->getAttributeItem(name)) >+ if (attributeData()) { >+ if (Attribute* attribute = attributeData()->getAttributeItem(name)) > ASSERT(isURLAttribute(attribute)); > } > #endif >@@ -1845,8 +1846,8 @@ KURL Element::getURLAttribute(const QualifiedName& name) const > KURL Element::getNonEmptyURLAttribute(const QualifiedName& name) const > { > #if !ASSERT_DISABLED >- if (m_attributeMap) { >- if (Attribute* attribute = m_attributeMap->getAttributeItem(name)) >+ if (attributeData()) { >+ if (Attribute* attribute = attributeData()->getAttributeItem(name)) > ASSERT(isURLAttribute(attribute)); > } > #endif >diff --git a/Source/WebCore/dom/Element.h b/Source/WebCore/dom/Element.h >index 3c2765965e22fe647ece1ebfee1cc36a64fda061..09fefcb2155f7c5f121ad1c11ec6443ef6c183af 100644 >--- a/Source/WebCore/dom/Element.h >+++ b/Source/WebCore/dom/Element.h >@@ -215,22 +215,18 @@ public: > void setBooleanAttribute(const QualifiedName& name, bool); > > // For exposing to DOM only. >- NamedNodeMap* attributes() const { return ensureUpdatedAttributes(); } >- >- NamedNodeMap* ensureUpdatedAttributes() const; >- NamedNodeMap* updatedAttributes() const; >+ NamedNodeMap* attributes() const; > > // This method is called whenever an attribute is added, changed or removed. > virtual void attributeChanged(Attribute*, bool preserveDecls = false); > > // Only called by the parser immediately after element construction. >- void parserSetAttributeMap(PassOwnPtr<NamedNodeMap>, FragmentScriptingPermission); >- >- NamedNodeMap* attributeMap() const { return m_attributeMap.get(); } >- NamedNodeMap* ensureAttributeMap() const; >+ void parserSetAttributeData(PassOwnPtr<ElementAttributeData>, FragmentScriptingPermission); > > ElementAttributeData* attributeData() const { return m_attributeMap ? m_attributeMap->attributeData() : 0; } >- ElementAttributeData* ensureAttributeData() const { return ensureUpdatedAttributes()->attributeData(); } >+ ElementAttributeData* ensureAttributeData() const; >+ ElementAttributeData* updatedAttributeData() const; >+ ElementAttributeData* ensureUpdatedAttributeData() const; > > void setAttributesFromElement(const Element&); > >@@ -522,22 +518,37 @@ inline Element* Element::nextElementSibling() const > return static_cast<Element*>(n); > } > >-inline NamedNodeMap* Element::ensureUpdatedAttributes() const >+inline NamedNodeMap* Element::attributes() const > { > updateInvalidAttributes(); >- return ensureAttributeMap(); >+ if (!m_attributeMap) >+ createAttributeMap(); >+ return m_attributeMap.get(); >+} >+ >+inline ElementAttributeData* Element::ensureAttributeData() const >+{ >+ if (!m_attributeMap) >+ createAttributeMap(); >+ return m_attributeMap->attributeData(); > } > >-inline NamedNodeMap* Element::updatedAttributes() const >+inline ElementAttributeData* Element::updatedAttributeData() const > { > updateInvalidAttributes(); >- return m_attributeMap.get(); >+ return attributeData(); >+} >+ >+inline ElementAttributeData* Element::ensureUpdatedAttributeData() const >+{ >+ updateInvalidAttributes(); >+ return ensureAttributeData(); > } > > inline void Element::setAttributesFromElement(const Element& other) > { >- if (NamedNodeMap* attributeMap = other.updatedAttributes()) >- ensureUpdatedAttributes()->setAttributes(*attributeMap); >+ if (ElementAttributeData* otherAttributes = other.updatedAttributeData()) >+ ensureUpdatedAttributeData()->setAttributes(*otherAttributes, this); > } > > inline void Element::updateName(const AtomicString& oldName, const AtomicString& newName) >@@ -579,14 +590,16 @@ inline void Element::willRemoveAttribute(const QualifiedName& name, const Atomic > inline bool Element::fastHasAttribute(const QualifiedName& name) const > { > ASSERT(fastAttributeLookupAllowed(name)); >- return m_attributeMap && m_attributeMap->getAttributeItem(name); >+ ElementAttributeData* attributes = attributeData(); >+ return attributes && attributes->getAttributeItem(name); > } > > inline const AtomicString& Element::fastGetAttribute(const QualifiedName& name) const > { > ASSERT(fastAttributeLookupAllowed(name)); >- if (m_attributeMap) { >- if (Attribute* attribute = m_attributeMap->getAttributeItem(name)) >+ ElementAttributeData* attributes = attributeData(); >+ if (attributes) { >+ if (Attribute* attribute = attributes->getAttributeItem(name)) > return attribute->value(); > } > return nullAtom; >@@ -617,13 +630,6 @@ inline void Element::setIdAttribute(const AtomicString& value) > setAttribute(document()->idAttributeName(), value); > } > >-inline NamedNodeMap* Element::ensureAttributeMap() const >-{ >- if (!m_attributeMap) >- createAttributeMap(); >- return m_attributeMap.get(); >-} >- > inline void Element::updateInvalidAttributes() const > { > if (!isStyleAttributeValid()) >@@ -644,6 +650,11 @@ inline Element* firstElementChild(const ContainerNode* container) > return static_cast<Element*>(child); > } > >+inline bool shouldIgnoreAttributeCase(const Element* e) >+{ >+ return e && e->document()->isHTMLDocument() && e->isHTMLElement(); >+} >+ > } // namespace > > #endif >diff --git a/Source/WebCore/dom/ElementAttributeData.cpp b/Source/WebCore/dom/ElementAttributeData.cpp >index 1283304bdc075ca4146a565bc167b613d52806a5..7cfa98d4682121749ade5394cfedfdedf67b2c25 100644 >--- a/Source/WebCore/dom/ElementAttributeData.cpp >+++ b/Source/WebCore/dom/ElementAttributeData.cpp >@@ -26,11 +26,273 @@ > #include "config.h" > #include "ElementAttributeData.h" > >+#include "Attr.h" >+#include "Document.h" >+#include "Element.h" >+#include "ExceptionCode.h" >+#include "StyledElement.h" >+ > namespace WebCore { > >+ElementAttributeData::~ElementAttributeData() >+{ >+ detachAttributesFromElement(); >+} >+ >+CSSMutableStyleDeclaration* ElementAttributeData::ensureInlineStyleDecl(Element* element) >+{ >+ if (!m_inlineStyleDecl) { >+ ASSERT(element->isStyledElement()); >+ m_inlineStyleDecl = CSSMutableStyleDeclaration::createInline(static_cast<StyledElement*>(element)); >+ m_inlineStyleDecl->setStrictParsing(element->isHTMLElement() && !element->document()->inQuirksMode()); >+ } >+ return m_inlineStyleDecl.get(); >+} >+ >+void ElementAttributeData::destroyInlineStyleDecl() >+{ >+ if (!m_inlineStyleDecl) >+ return; >+ m_inlineStyleDecl->clearParentElement(); >+ m_inlineStyleDecl = 0; >+} >+ >+PassRefPtr<Node> ElementAttributeData::getNamedItem(const String& name, Element* element) const >+{ >+ Attribute* a = getAttributeItem(name, shouldIgnoreAttributeCase(element)); >+ if (!a) >+ return 0; >+ return a->createAttrIfNeeded(element); >+} >+ >+PassRefPtr<Node> ElementAttributeData::removeNamedItem(const String& name, ExceptionCode& ec, Element* element) >+{ >+ Attribute* a = getAttributeItem(name, shouldIgnoreAttributeCase(element)); >+ if (!a) { >+ ec = NOT_FOUND_ERR; >+ return 0; >+ } >+ return removeNamedItem(a->name(), ec, element); >+} >+ >+PassRefPtr<Node> ElementAttributeData::getNamedItem(const QualifiedName& name, Element* element) const >+{ >+ Attribute* a = getAttributeItem(name); >+ if (!a) >+ return 0; >+ return a->createAttrIfNeeded(element); >+} >+ >+PassRefPtr<Node> ElementAttributeData::removeNamedItem(const QualifiedName& name, ExceptionCode& ec, Element* element) >+{ >+ ASSERT(element); >+ >+ size_t index = getAttributeItemIndex(name); >+ if (index == notFound) { >+ ec = NOT_FOUND_ERR; >+ return 0; >+ } >+ >+ RefPtr<Attr> attr = attributeItem(index)->createAttrIfNeeded(element); >+ >+ removeAttribute(index, element); >+ >+ return attr.release(); >+} >+ >+PassRefPtr<Node> ElementAttributeData::setNamedItem(Node* node, ExceptionCode& ec, Element* element) >+{ >+ if (!element || !node) { >+ ec = NOT_FOUND_ERR; >+ return 0; >+ } >+ >+ // Not mentioned in spec: throw a HIERARCHY_REQUEST_ERROR if the user passes in a non-attribute node. >+ if (!node->isAttributeNode()) { >+ ec = HIERARCHY_REQUEST_ERR; >+ return 0; >+ } >+ Attr* attr = static_cast<Attr*>(node); >+ >+ Attribute* attribute = attr->attr(); >+ size_t index = getAttributeItemIndex(attribute->name()); >+ Attribute* oldAttribute = index != notFound ? attributeItem(index) : 0; >+ if (oldAttribute == attribute) >+ return node; // we know about it already >+ >+ // INUSE_ATTRIBUTE_ERR: Raised if node is an Attr that is already an attribute of another Element object. >+ // The DOM user must explicitly clone Attr nodes to re-use them in other elements. >+ if (attr->ownerElement()) { >+ ec = INUSE_ATTRIBUTE_ERR; >+ return 0; >+ } >+ >+ RefPtr<Attr> oldAttr; >+ if (oldAttribute) { >+ oldAttr = oldAttribute->createAttrIfNeeded(element); >+ replaceAttribute(index, attribute, element); >+ } else >+ addAttribute(attribute, element); >+ >+ return oldAttr.release(); >+} >+ > void ElementAttributeData::setClass(const String& className, bool shouldFoldCase) > { > m_classNames.set(className, shouldFoldCase); > } > >+PassRefPtr<Node> ElementAttributeData::item(unsigned index, Element* element) const >+{ >+ if (index >= length()) >+ return 0; >+ return attributeItem(index)->createAttrIfNeeded(element); >+} >+ >+bool ElementAttributeData::equivalent(const ElementAttributeData* other) const >+{ >+ if (!other) >+ return isEmpty(); >+ >+ unsigned len = length(); >+ if (len != other->length()) >+ return false; >+ >+ for (unsigned i = 0; i < len; i++) { >+ Attribute* attr = attributeItem(i); >+ Attribute* otherAttr = other->getAttributeItem(attr->name()); >+ if (!otherAttr || attr->value() != otherAttr->value()) >+ return false; >+ } >+ >+ return true; >+} >+ >+void ElementAttributeData::addAttribute(PassRefPtr<Attribute> prpAttribute, Element* element) >+{ >+ RefPtr<Attribute> attribute = prpAttribute; >+ >+ if (element) >+ element->willModifyAttribute(attribute->name(), nullAtom, attribute->value()); >+ >+ m_attributes.append(attribute); >+ if (Attr* attr = attribute->attr()) >+ attr->m_element = element; >+ >+ if (element) >+ element->didModifyAttribute(attribute.get()); >+} >+ >+void ElementAttributeData::removeAttribute(size_t index, Element* element) >+{ >+ ASSERT(index < length()); >+ >+ RefPtr<Attribute> attribute = m_attributes[index]; >+ >+ if (element) >+ element->willRemoveAttribute(attribute->name(), attribute->value()); >+ >+ if (Attr* attr = attribute->attr()) >+ attr->m_element = 0; >+ m_attributes.remove(index); >+ >+ if (element) >+ element->didRemoveAttribute(attribute.get()); >+} >+ >+void ElementAttributeData::copyAttributesToVector(Vector<RefPtr<Attribute> >& copy) >+{ >+ copy = m_attributes; >+} >+ >+inline void ElementAttributeData::detachAttributesFromElement() >+{ >+ size_t size = m_attributes.size(); >+ for (size_t i = 0; i < size; i++) { >+ if (Attr* attr = m_attributes[i]->attr()) >+ attr->m_element = 0; >+ } >+} >+ >+size_t ElementAttributeData::getAttributeItemIndexSlowCase(const String& name, bool shouldIgnoreAttributeCase) const >+{ >+ unsigned len = length(); >+ >+ // Continue to checking case-insensitively and/or full namespaced names if necessary: >+ for (unsigned i = 0; i < len; ++i) { >+ const QualifiedName& attrName = m_attributes[i]->name(); >+ if (!attrName.hasPrefix()) { >+ if (shouldIgnoreAttributeCase && equalIgnoringCase(name, attrName.localName())) >+ return i; >+ } else { >+ // FIXME: Would be faster to do this comparison without calling toString, which >+ // generates a temporary string by concatenation. But this branch is only reached >+ // if the attribute name has a prefix, which is rare in HTML. >+ if (equalPossiblyIgnoringCase(name, attrName.toString(), shouldIgnoreAttributeCase)) >+ return i; >+ } >+ } >+ return notFound; >+} >+ >+void ElementAttributeData::setAttributes(const ElementAttributeData& other, Element* element) >+{ >+ // Clone all attributes in the other map, but attach to our element. >+ if (!element) >+ return; >+ >+ // If assigning the map changes the id attribute, we need to call updateId. >+ Attribute* oldId = getAttributeItem(element->document()->idAttributeName()); >+ Attribute* newId = other.getAttributeItem(element->document()->idAttributeName()); >+ >+ if (oldId || newId) >+ element->updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom); >+ >+ Attribute* oldName = getAttributeItem(HTMLNames::nameAttr); >+ Attribute* newName = other.getAttributeItem(HTMLNames::nameAttr); >+ >+ if (oldName || newName) >+ element->updateName(oldName ? oldName->value() : nullAtom, newName ? newName->value() : nullAtom); >+ >+ clearAttributes(); >+ unsigned newLength = other.length(); >+ m_attributes.resize(newLength); >+ for (unsigned i = 0; i < newLength; i++) >+ m_attributes[i] = other.m_attributes[i]->clone(); >+ >+ // FIXME: This is wasteful. The class list could be preserved on a copy, and we >+ // wouldn't have to waste time reparsing the attribute. >+ // The derived class, HTMLNamedNodeMap, which manages a parsed class list for the CLASS attribute, >+ // will update its member variable when parse attribute is called. >+ for (unsigned i = 0; i < newLength; i++) >+ element->attributeChanged(m_attributes[i].get(), true); >+} >+ >+void ElementAttributeData::clearAttributes() >+{ >+ clearClass(); >+ detachAttributesFromElement(); >+ m_attributes.clear(); >+} >+ >+void ElementAttributeData::replaceAttribute(size_t index, PassRefPtr<Attribute> prpAttribute, Element* element) >+{ >+ ASSERT(index < length()); >+ >+ RefPtr<Attribute> attribute = prpAttribute; >+ Attribute* old = m_attributes[index].get(); >+ >+ if (element) >+ element->willModifyAttribute(attribute->name(), old->value(), attribute->value()); >+ >+ if (Attr* attr = old->attr()) >+ attr->m_element = 0; >+ m_attributes[index] = attribute; >+ if (Attr* attr = attribute->attr()) >+ attr->m_element = element; >+ >+ if (element) >+ element->didModifyAttribute(attribute.get()); >+} >+ > } >diff --git a/Source/WebCore/dom/ElementAttributeData.h b/Source/WebCore/dom/ElementAttributeData.h >index 20116c62f0c9fa690acfbcced72cceda6b538909..b9ed24bd0c1dd39dbef0f74cf2781f7b48dc1296 100644 >--- a/Source/WebCore/dom/ElementAttributeData.h >+++ b/Source/WebCore/dom/ElementAttributeData.h >@@ -26,8 +26,10 @@ > #ifndef ElementAttributeData_h > #define ElementAttributeData_h > >+#include "Attribute.h" > #include "CSSMutableStyleDeclaration.h" > #include "SpaceSplitString.h" >+#include <wtf/NotFound.h> > > namespace WebCore { > >@@ -35,6 +37,17 @@ class Element; > > class ElementAttributeData { > public: >+ static PassOwnPtr<ElementAttributeData> create() >+ { >+ return adoptPtr(new ElementAttributeData()); >+ } >+ >+ ~ElementAttributeData(); >+ >+ CSSMutableStyleDeclaration* inlineStyleDecl() { return m_inlineStyleDecl.get(); } >+ CSSMutableStyleDeclaration* ensureInlineStyleDecl(Element*); >+ void destroyInlineStyleDecl(); >+ > void clearClass() { m_classNames.clear(); } > void setClass(const String& className, bool shouldFoldCase); > const SpaceSplitString& classNames() const { return m_classNames; } >@@ -42,18 +55,130 @@ public: > const AtomicString& idForStyleResolution() const { return m_idForStyleResolution; } > void setIdForStyleResolution(const AtomicString& newId) { m_idForStyleResolution = newId; } > >+ PassRefPtr<Node> getNamedItem(const String& name, Element*) const; >+ PassRefPtr<Node> removeNamedItem(const String& name, ExceptionCode&, Element*); >+ >+ PassRefPtr<Node> getNamedItem(const QualifiedName&, Element*) const; >+ PassRefPtr<Node> removeNamedItem(const QualifiedName&, ExceptionCode&, Element*); >+ PassRefPtr<Node> setNamedItem(Node*, ExceptionCode&, Element*); >+ >+ PassRefPtr<Node> item(unsigned index, Element*) const; >+ size_t length() const { return m_attributes.size(); } >+ bool isEmpty() const { return !length(); } >+ >+ // Used during parsing: only inserts if not already there. No error checking! >+ void insertAttribute(PassRefPtr<Attribute> newAttribute, bool allowDuplicates) >+ { >+ if (allowDuplicates || !getAttributeItem(newAttribute->name())) >+ addAttribute(newAttribute, 0); >+ } >+ >+ Attribute* attributeItem(unsigned index) const { return m_attributes[index].get(); } >+ Attribute* getAttributeItem(const QualifiedName&) const; >+ size_t getAttributeItemIndex(const QualifiedName&) const; >+ >+ void reserveInitialCapacity(unsigned capacity) { m_attributes.reserveInitialCapacity(capacity); } >+ >+ bool equivalent(const ElementAttributeData* other) const; >+ >+ // These functions do no error checking. >+ void addAttribute(PassRefPtr<Attribute>, Element*); >+ void removeAttribute(const QualifiedName&, Element*); >+ void removeAttribute(size_t index, Element*); >+ >+ size_t mappedAttributeCount() const; >+ > private: >+ friend class Element; > friend class NamedNodeMap; > > ElementAttributeData() > { > } > >+ void copyAttributesToVector(Vector<RefPtr<Attribute> >&); >+ >+ void detachAttributesFromElement(); >+ Attribute* getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const; >+ size_t getAttributeItemIndex(const String& name, bool shouldIgnoreAttributeCase) const; >+ size_t getAttributeItemIndexSlowCase(const String& name, bool shouldIgnoreAttributeCase) const; >+ void setAttributes(const ElementAttributeData&, Element*); >+ void clearAttributes(); >+ void replaceAttribute(size_t index, PassRefPtr<Attribute>, Element*); >+ > RefPtr<CSSMutableStyleDeclaration> m_inlineStyleDecl; > SpaceSplitString m_classNames; > AtomicString m_idForStyleResolution; >+ Vector<RefPtr<Attribute>, 4> m_attributes; > }; > >+inline void ElementAttributeData::removeAttribute(const QualifiedName& name, Element* element) >+{ >+ size_t index = getAttributeItemIndex(name); >+ if (index == notFound) >+ return; >+ >+ removeAttribute(index, element); >+} >+ >+inline Attribute* ElementAttributeData::getAttributeItem(const QualifiedName& name) const >+{ >+ size_t index = getAttributeItemIndex(name); >+ if (index != notFound) >+ return m_attributes[index].get(); >+ return 0; >+} >+ >+inline size_t ElementAttributeData::getAttributeItemIndex(const QualifiedName& name) const >+{ >+ size_t len = length(); >+ for (unsigned i = 0; i < len; ++i) { >+ if (m_attributes[i]->name().matches(name)) >+ return i; >+ } >+ return notFound; >+} >+ >+inline size_t ElementAttributeData::mappedAttributeCount() const >+{ >+ size_t count = 0; >+ for (size_t i = 0; i < m_attributes.size(); ++i) { >+ if (m_attributes[i]->decl()) >+ ++count; >+ } >+ return count; >+} >+ >+inline Attribute* ElementAttributeData::getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const >+{ >+ size_t index = getAttributeItemIndex(name, shouldIgnoreAttributeCase); >+ if (index != notFound) >+ return m_attributes[index].get(); >+ return 0; >+} >+ >+// We use a boolean parameter instead of calling shouldIgnoreAttributeCase so that the caller >+// can tune the behavior (hasAttribute is case sensitive whereas getAttribute is not). >+inline size_t ElementAttributeData::getAttributeItemIndex(const String& name, bool shouldIgnoreAttributeCase) const >+{ >+ unsigned len = length(); >+ bool doSlowCheck = shouldIgnoreAttributeCase; >+ >+ // Optimize for the case where the attribute exists and its name exactly matches. >+ for (unsigned i = 0; i < len; ++i) { >+ const QualifiedName& attrName = m_attributes[i]->name(); >+ if (!attrName.hasPrefix()) { >+ if (name == attrName.localName()) >+ return i; >+ } else >+ doSlowCheck = true; >+ } >+ >+ if (doSlowCheck) >+ return getAttributeItemIndexSlowCase(name, shouldIgnoreAttributeCase); >+ return notFound; >+} >+ > } > > #endif // ElementAttributeData_h >diff --git a/Source/WebCore/dom/NamedNodeMap.cpp b/Source/WebCore/dom/NamedNodeMap.cpp >index 7f622977536a78538cd4be5a133891e28ef03c33..bc023e2e487fd96db3f48e8149da108396dd980f 100644 >--- a/Source/WebCore/dom/NamedNodeMap.cpp >+++ b/Source/WebCore/dom/NamedNodeMap.cpp >@@ -25,31 +25,11 @@ > #include "config.h" > #include "NamedNodeMap.h" > >-#include "Attr.h" >-#include "Document.h" > #include "Element.h" > #include "ExceptionCode.h" >-#include "HTMLNames.h" >-#include "StyledElement.h" > > namespace WebCore { > >-using namespace HTMLNames; >- >-static inline bool shouldIgnoreAttributeCase(const Element* e) >-{ >- return e && e->document()->isHTMLDocument() && e->isHTMLElement(); >-} >- >-inline void NamedNodeMap::detachAttributesFromElement() >-{ >- size_t size = m_attributes.size(); >- for (size_t i = 0; i < size; i++) { >- if (Attr* attr = m_attributes[i]->attr()) >- attr->m_element = 0; >- } >-} >- > void NamedNodeMap::ref() > { > ASSERT(m_element); >@@ -62,150 +42,21 @@ void NamedNodeMap::deref() > m_element->deref(); > } > >-NamedNodeMap::~NamedNodeMap() >-{ >- detachAttributesFromElement(); >-} >- >-PassRefPtr<Node> NamedNodeMap::getNamedItem(const String& name) const >-{ >- Attribute* a = getAttributeItem(name, shouldIgnoreAttributeCase(m_element)); >- if (!a) >- return 0; >- >- return a->createAttrIfNeeded(m_element); >-} >- > PassRefPtr<Node> NamedNodeMap::getNamedItemNS(const String& namespaceURI, const String& localName) const > { > return getNamedItem(QualifiedName(nullAtom, localName, namespaceURI)); > } > >-PassRefPtr<Node> NamedNodeMap::removeNamedItem(const String& name, ExceptionCode& ec) >-{ >- Attribute* a = getAttributeItem(name, shouldIgnoreAttributeCase(m_element)); >- if (!a) { >- ec = NOT_FOUND_ERR; >- return 0; >- } >- >- return removeNamedItem(a->name(), ec); >-} >- > PassRefPtr<Node> NamedNodeMap::removeNamedItemNS(const String& namespaceURI, const String& localName, ExceptionCode& ec) > { > return removeNamedItem(QualifiedName(nullAtom, localName, namespaceURI), ec); > } > >-PassRefPtr<Node> NamedNodeMap::getNamedItem(const QualifiedName& name) const >-{ >- Attribute* a = getAttributeItem(name); >- if (!a) >- return 0; >- >- return a->createAttrIfNeeded(m_element); >-} >- >-PassRefPtr<Node> NamedNodeMap::setNamedItem(Node* node, ExceptionCode& ec) >-{ >- if (!m_element || !node) { >- ec = NOT_FOUND_ERR; >- return 0; >- } >- >- // Not mentioned in spec: throw a HIERARCHY_REQUEST_ERROR if the user passes in a non-attribute node >- if (!node->isAttributeNode()) { >- ec = HIERARCHY_REQUEST_ERR; >- return 0; >- } >- Attr* attr = static_cast<Attr*>(node); >- >- Attribute* attribute = attr->attr(); >- size_t index = getAttributeItemIndex(attribute->name()); >- Attribute* oldAttribute = index != notFound ? attributeItem(index) : 0; >- if (oldAttribute == attribute) >- return node; // we know about it already >- >- // INUSE_ATTRIBUTE_ERR: Raised if node is an Attr that is already an attribute of another Element object. >- // The DOM user must explicitly clone Attr nodes to re-use them in other elements. >- if (attr->ownerElement()) { >- ec = INUSE_ATTRIBUTE_ERR; >- return 0; >- } >- >- RefPtr<Attr> oldAttr; >- if (oldAttribute) { >- oldAttr = oldAttribute->createAttrIfNeeded(m_element); >- replaceAttribute(index, attribute); >- } else >- addAttribute(attribute); >- >- return oldAttr.release(); >-} >- > PassRefPtr<Node> NamedNodeMap::setNamedItemNS(Node* node, ExceptionCode& ec) > { > return setNamedItem(node, ec); > } > >-PassRefPtr<Node> NamedNodeMap::removeNamedItem(const QualifiedName& name, ExceptionCode& ec) >-{ >- ASSERT(m_element); >- >- size_t index = getAttributeItemIndex(name); >- if (index == notFound) { >- ec = NOT_FOUND_ERR; >- return 0; >- } >- >- RefPtr<Attr> attr = m_attributes[index]->createAttrIfNeeded(m_element); >- >- removeAttribute(index); >- >- return attr.release(); >-} >- >-PassRefPtr<Node> NamedNodeMap::item(unsigned index) const >-{ >- if (index >= length()) >- return 0; >- >- return m_attributes[index]->createAttrIfNeeded(m_element); >-} >- >-void NamedNodeMap::copyAttributesToVector(Vector<RefPtr<Attribute> >& copy) >-{ >- copy = m_attributes; >-} >- >-size_t NamedNodeMap::getAttributeItemIndexSlowCase(const String& name, bool shouldIgnoreAttributeCase) const >-{ >- unsigned len = length(); >- >- // Continue to checking case-insensitively and/or full namespaced names if necessary: >- for (unsigned i = 0; i < len; ++i) { >- const QualifiedName& attrName = m_attributes[i]->name(); >- if (!attrName.hasPrefix()) { >- if (shouldIgnoreAttributeCase && equalIgnoringCase(name, attrName.localName())) >- return i; >- } else { >- // FIXME: Would be faster to do this comparison without calling toString, which >- // generates a temporary string by concatenation. But this branch is only reached >- // if the attribute name has a prefix, which is rare in HTML. >- if (equalPossiblyIgnoringCase(name, attrName.toString(), shouldIgnoreAttributeCase)) >- return i; >- } >- } >- return notFound; >-} >- >-void NamedNodeMap::clearAttributes() >-{ >- attributeData()->clearClass(); >- detachAttributesFromElement(); >- m_attributes.clear(); >-} >- > void NamedNodeMap::detachFromElement() > { > // This can't happen if the holder of the map is JavaScript, because we mark the >@@ -213,130 +64,7 @@ void NamedNodeMap::detachFromElement() > // of that, we can simply clear all the attributes to avoid accessing stale > // pointers to do things like create Attr objects. > m_element = 0; >- clearAttributes(); >-} >- >-void NamedNodeMap::setAttributes(const NamedNodeMap& other) >-{ >- // clone all attributes in the other map, but attach to our element >- if (!m_element) >- return; >- >- // If assigning the map changes the id attribute, we need to call >- // updateId. >- Attribute* oldId = getAttributeItem(m_element->document()->idAttributeName()); >- Attribute* newId = other.getAttributeItem(m_element->document()->idAttributeName()); >- >- if (oldId || newId) >- m_element->updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom); >- >- Attribute* oldName = getAttributeItem(HTMLNames::nameAttr); >- Attribute* newName = other.getAttributeItem(HTMLNames::nameAttr); >- >- if (oldName || newName) >- m_element->updateName(oldName ? oldName->value() : nullAtom, newName ? newName->value() : nullAtom); >- >- clearAttributes(); >- unsigned newLength = other.length(); >- m_attributes.resize(newLength); >- for (unsigned i = 0; i < newLength; i++) >- m_attributes[i] = other.m_attributes[i]->clone(); >- >- // FIXME: This is wasteful. The class list could be preserved on a copy, and we >- // wouldn't have to waste time reparsing the attribute. >- // The derived class, HTMLNamedNodeMap, which manages a parsed class list for the CLASS attribute, >- // will update its member variable when parse attribute is called. >- for (unsigned i = 0; i < newLength; i++) >- m_element->attributeChanged(m_attributes[i].get(), true); >-} >- >-void NamedNodeMap::addAttribute(PassRefPtr<Attribute> prpAttribute) >-{ >- RefPtr<Attribute> attribute = prpAttribute; >- >- if (m_element) >- m_element->willModifyAttribute(attribute->name(), nullAtom, attribute->value()); >- >- m_attributes.append(attribute); >- if (Attr* attr = attribute->attr()) >- attr->m_element = m_element; >- >- if (m_element) >- m_element->didModifyAttribute(attribute.get()); >-} >- >-void NamedNodeMap::removeAttribute(size_t index) >-{ >- ASSERT(index < length()); >- >- RefPtr<Attribute> attribute = m_attributes[index]; >- >- if (m_element) >- m_element->willRemoveAttribute(attribute->name(), attribute->value()); >- >- if (Attr* attr = attribute->attr()) >- attr->m_element = 0; >- m_attributes.remove(index); >- >- if (m_element) >- m_element->didRemoveAttribute(attribute.get()); >-} >- >-void NamedNodeMap::replaceAttribute(size_t index, PassRefPtr<Attribute> prpAttribute) >-{ >- ASSERT(index < length()); >- >- RefPtr<Attribute> attribute = prpAttribute; >- Attribute* old = m_attributes[index].get(); >- >- if (m_element) >- m_element->willModifyAttribute(attribute->name(), old->value(), attribute->value()); >- >- if (Attr* attr = old->attr()) >- attr->m_element = 0; >- m_attributes[index] = attribute; >- if (Attr* attr = attribute->attr()) >- attr->m_element = m_element; >- >- if (m_element) >- m_element->didModifyAttribute(attribute.get()); >-} >- >-bool NamedNodeMap::mapsEquivalent(const NamedNodeMap* otherMap) const >-{ >- if (!otherMap) >- return isEmpty(); >- >- unsigned len = length(); >- if (len != otherMap->length()) >- return false; >- >- for (unsigned i = 0; i < len; i++) { >- Attribute* attr = attributeItem(i); >- Attribute* otherAttr = otherMap->getAttributeItem(attr->name()); >- if (!otherAttr || attr->value() != otherAttr->value()) >- return false; >- } >- >- return true; >-} >- >-CSSMutableStyleDeclaration* NamedNodeMap::ensureInlineStyleDecl() >-{ >- if (!attributeData()->m_inlineStyleDecl) { >- ASSERT(m_element->isStyledElement()); >- attributeData()->m_inlineStyleDecl = CSSMutableStyleDeclaration::createInline(static_cast<StyledElement*>(m_element)); >- attributeData()->m_inlineStyleDecl->setStrictParsing(m_element->isHTMLElement() && !m_element->document()->inQuirksMode()); >- } >- return attributeData()->m_inlineStyleDecl.get(); >-} >- >-void NamedNodeMap::destroyInlineStyleDecl() >-{ >- if (!attributeData()->m_inlineStyleDecl) >- return; >- attributeData()->m_inlineStyleDecl->clearParentElement(); >- attributeData()->m_inlineStyleDecl = 0; >+ attributeData()->clearAttributes(); > } > > } // namespace WebCore >diff --git a/Source/WebCore/dom/NamedNodeMap.h b/Source/WebCore/dom/NamedNodeMap.h >index f53047c300156d26a569d2307d41dff35415fc9f..6a6176527fa7a09ec97c1aaa71e89311889c6a5f 100644 >--- a/Source/WebCore/dom/NamedNodeMap.h >+++ b/Source/WebCore/dom/NamedNodeMap.h >@@ -25,10 +25,7 @@ > #ifndef NamedNodeMap_h > #define NamedNodeMap_h > >-#include "Attribute.h" > #include "ElementAttributeData.h" >-#include "SpaceSplitString.h" >-#include <wtf/NotFound.h> > > namespace WebCore { > >@@ -44,79 +41,37 @@ public: > return adoptPtr(new NamedNodeMap(element)); > } > >- ~NamedNodeMap(); >- > void ref(); > void deref(); > >- // Public DOM interface. >- >- PassRefPtr<Node> getNamedItem(const String& name) const; >- PassRefPtr<Node> removeNamedItem(const String& name, ExceptionCode&); >+ PassRefPtr<Node> getNamedItem(const String& name) const { return attributeData()->getNamedItem(name, m_element); } >+ PassRefPtr<Node> removeNamedItem(const String& name, ExceptionCode& ec) { return attributeData()->removeNamedItem(name, ec, m_element); } > > PassRefPtr<Node> getNamedItemNS(const String& namespaceURI, const String& localName) const; > PassRefPtr<Node> removeNamedItemNS(const String& namespaceURI, const String& localName, ExceptionCode&); > >- PassRefPtr<Node> getNamedItem(const QualifiedName& name) const; >- PassRefPtr<Node> removeNamedItem(const QualifiedName& name, ExceptionCode&); >- PassRefPtr<Node> setNamedItem(Node*, ExceptionCode&); >+ PassRefPtr<Node> getNamedItem(const QualifiedName& name) const { return attributeData()->getNamedItem(name, m_element); } >+ PassRefPtr<Node> removeNamedItem(const QualifiedName& name, ExceptionCode& ec) { return attributeData()->removeNamedItem(name, ec, m_element); } >+ PassRefPtr<Node> setNamedItem(Node* node, ExceptionCode& ec) { return attributeData()->setNamedItem(node, ec, m_element); } > PassRefPtr<Node> setNamedItemNS(Node*, ExceptionCode&); > >- PassRefPtr<Node> item(unsigned index) const; >- size_t length() const { return m_attributes.size(); } >- bool isEmpty() const { return !length(); } >- >- // Internal interface. >- >- Attribute* attributeItem(unsigned index) const { return m_attributes[index].get(); } >- Attribute* getAttributeItem(const QualifiedName&) const; >- size_t getAttributeItemIndex(const QualifiedName&) const; >- >- void copyAttributesToVector(Vector<RefPtr<Attribute> >&); >- >- void shrinkToLength() { m_attributes.shrinkCapacity(length()); } >- void reserveInitialCapacity(unsigned capacity) { m_attributes.reserveInitialCapacity(capacity); } >- >- // Used during parsing: only inserts if not already there. No error checking! >- void insertAttribute(PassRefPtr<Attribute> newAttribute, bool allowDuplicates) >- { >- ASSERT(!m_element); >- if (allowDuplicates || !getAttributeItem(newAttribute->name())) >- addAttribute(newAttribute); >- } >- >- bool mapsEquivalent(const NamedNodeMap* otherMap) const; >- >- // These functions do no error checking. >- void addAttribute(PassRefPtr<Attribute>); >- void removeAttribute(const QualifiedName&); >- void removeAttribute(size_t index); >+ PassRefPtr<Node> item(unsigned index) const { return attributeData()->item(index, m_element); } >+ size_t length() const { return attributeData()->length(); } > > Element* element() const { return m_element; } > >- size_t mappedAttributeCount() const; >+ bool mapsEquivalent(const NamedNodeMap* otherMap) const { return attributeData()->equivalent(otherMap->attributeData()); } > > ElementAttributeData* attributeData() { return &m_attributeData; } > const ElementAttributeData* attributeData() const { return &m_attributeData; } > >- CSSMutableStyleDeclaration* inlineStyleDecl() { return attributeData()->m_inlineStyleDecl.get(); } >- CSSMutableStyleDeclaration* ensureInlineStyleDecl(); >- void destroyInlineStyleDecl(); >- > private: > NamedNodeMap(Element* element) > : m_element(element) > { > } > >- void detachAttributesFromElement(); > void detachFromElement(); >- Attribute* getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const; >- size_t getAttributeItemIndex(const String& name, bool shouldIgnoreAttributeCase) const; >- size_t getAttributeItemIndexSlowCase(const String& name, bool shouldIgnoreAttributeCase) const; >- void setAttributes(const NamedNodeMap&); >- void clearAttributes(); >- void replaceAttribute(size_t index, PassRefPtr<Attribute>); > > // FIXME: NamedNodeMap is being broken up into two classes, one containing data > // for elements with attributes, and one for exposure to the DOM. >@@ -124,76 +79,8 @@ private: > ElementAttributeData m_attributeData; > > Element* m_element; >- Vector<RefPtr<Attribute>, 4> m_attributes; > }; > >-inline Attribute* NamedNodeMap::getAttributeItem(const QualifiedName& name) const >-{ >- size_t index = getAttributeItemIndex(name); >- if (index != notFound) >- return m_attributes[index].get(); >- return 0; >-} >- >-inline size_t NamedNodeMap::getAttributeItemIndex(const QualifiedName& name) const >-{ >- size_t len = length(); >- for (unsigned i = 0; i < len; ++i) { >- if (m_attributes[i]->name().matches(name)) >- return i; >- } >- return notFound; >-} >- >-inline Attribute* NamedNodeMap::getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const >-{ >- size_t index = getAttributeItemIndex(name, shouldIgnoreAttributeCase); >- if (index != notFound) >- return m_attributes[index].get(); >- return 0; >-} >- >-// We use a boolean parameter instead of calling shouldIgnoreAttributeCase so that the caller >-// can tune the behavior (hasAttribute is case sensitive whereas getAttribute is not). >-inline size_t NamedNodeMap::getAttributeItemIndex(const String& name, bool shouldIgnoreAttributeCase) const >-{ >- unsigned len = length(); >- bool doSlowCheck = shouldIgnoreAttributeCase; >- >- // Optimize for the case where the attribute exists and its name exactly matches. >- for (unsigned i = 0; i < len; ++i) { >- const QualifiedName& attrName = m_attributes[i]->name(); >- if (!attrName.hasPrefix()) { >- if (name == attrName.localName()) >- return i; >- } else >- doSlowCheck = true; >- } >- >- if (doSlowCheck) >- return getAttributeItemIndexSlowCase(name, shouldIgnoreAttributeCase); >- return notFound; >-} >- >-inline void NamedNodeMap::removeAttribute(const QualifiedName& name) >-{ >- size_t index = getAttributeItemIndex(name); >- if (index == notFound) >- return; >- >- removeAttribute(index); >-} >- >-inline size_t NamedNodeMap::mappedAttributeCount() const >-{ >- size_t count = 0; >- for (size_t i = 0; i < m_attributes.size(); ++i) { >- if (m_attributes[i]->decl()) >- ++count; >- } >- return count; >-} >- > } // namespace WebCore > > #endif // NamedNodeMap_h >diff --git a/Source/WebCore/dom/Node.cpp b/Source/WebCore/dom/Node.cpp >index 738000fecd314ae0dcbef7a2a9cd811f5825353f..22af831cf9008f5c38272adfab292516f480fa04 100644 >--- a/Source/WebCore/dom/Node.cpp >+++ b/Source/WebCore/dom/Node.cpp >@@ -1765,13 +1765,13 @@ bool Node::isEqualNode(Node* other) const > return false; > > if (isElementNode()) { >- NamedNodeMap* attributes = toElement(this)->updatedAttributes(); >- NamedNodeMap* otherAttributes = toElement(other)->updatedAttributes(); >+ ElementAttributeData* attributes = toElement(this)->updatedAttributeData(); >+ ElementAttributeData* otherAttributes = toElement(other)->updatedAttributeData(); > >- if (attributes && !attributes->mapsEquivalent(otherAttributes)) >+ if (attributes && !attributes->equivalent(otherAttributes)) > return false; > >- if (otherAttributes && !otherAttributes->mapsEquivalent(attributes)) >+ if (otherAttributes && !otherAttributes->equivalent(attributes)) > return false; > } > >@@ -1831,7 +1831,7 @@ bool Node::isDefaultNamespace(const AtomicString& namespaceURIMaybeEmpty) const > if (elem->prefix().isNull()) > return elem->namespaceURI() == namespaceURI; > >- if (NamedNodeMap* attrs = elem->updatedAttributes()) { >+ if (ElementAttributeData* attrs = elem->updatedAttributeData()) { > for (unsigned i = 0; i < attrs->length(); i++) { > Attribute* attr = attrs->attributeItem(i); > >@@ -1917,7 +1917,7 @@ String Node::lookupNamespaceURI(const String &prefix) const > if (!elem->namespaceURI().isNull() && elem->prefix() == prefix) > return elem->namespaceURI(); > >- if (NamedNodeMap* attrs = elem->updatedAttributes()) { >+ if (ElementAttributeData* attrs = elem->updatedAttributeData()) { > for (unsigned i = 0; i < attrs->length(); i++) { > Attribute *attr = attrs->attributeItem(i); > >@@ -1971,7 +1971,7 @@ String Node::lookupNamespacePrefix(const AtomicString &_namespaceURI, const Elem > if (originalElement->lookupNamespaceURI(prefix()) == _namespaceURI) > return prefix(); > >- if (NamedNodeMap* attrs = toElement(this)->updatedAttributes()) { >+ if (ElementAttributeData* attrs = toElement(this)->updatedAttributeData()) { > for (unsigned i = 0; i < attrs->length(); i++) { > Attribute* attr = attrs->attributeItem(i); > >@@ -2114,17 +2114,17 @@ unsigned short Node::compareDocumentPosition(Node* otherNode) > chain2.append(attr2); > > if (attr1 && attr2 && start1 == start2 && start1) { >- // We are comparing two attributes on the same node. Crawl our attribute map >+ // We are comparing two attributes on the same node. Crawl our attribute data > // and see which one we hit first. >- NamedNodeMap* map = attr1->ownerElement()->updatedAttributes(); >- unsigned length = map->length(); >+ ElementAttributeData* attributeData = attr1->ownerElement()->updatedAttributeData(); >+ unsigned length = attributeData->length(); > for (unsigned i = 0; i < length; ++i) { > // If neither of the two determining nodes is a child node and nodeType is the same for both determining nodes, then an > // implementation-dependent order between the determining nodes is returned. This order is stable as long as no nodes of > // the same nodeType are inserted into or removed from the direct container. This would be the case, for example, > // when comparing two attributes of the same element, and inserting or removing additional attributes might change > // the order between existing attributes. >- Attribute* attr = map->attributeItem(i); >+ Attribute* attr = attributeData->attributeItem(i); > if (attr1->attr() == attr) > return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_FOLLOWING; > if (attr2->attr() == attr) >diff --git a/Source/WebCore/dom/Node.h b/Source/WebCore/dom/Node.h >index 311bd4117cff9e740af60bffcb796bf00c389060..42a570456df40e74151933aac9a511f6195a8d24 100644 >--- a/Source/WebCore/dom/Node.h >+++ b/Source/WebCore/dom/Node.h >@@ -53,6 +53,7 @@ class DOMSettableTokenList; > class Document; > class DynamicSubtreeNodeList; > class Element; >+class ElementAttributeData; > class Event; > class EventContext; > class EventDispatchMediator; >diff --git a/Source/WebCore/dom/StyledElement.cpp b/Source/WebCore/dom/StyledElement.cpp >index 25f2cd807db0d10f2608378649606497ba0b3e97..d75fbf78c94b541aeab3a5ac8374619099a3c8ff 100644 >--- a/Source/WebCore/dom/StyledElement.cpp >+++ b/Source/WebCore/dom/StyledElement.cpp >@@ -201,7 +201,7 @@ void StyledElement::classAttributeChanged(const AtomicString& newClassString) > setHasClass(hasClass); > if (hasClass) { > const bool shouldFoldCase = document()->inQuirksMode(); >- ensureAttributeData()->setClass(newClassString, shouldFoldCase); >+ ensureUpdatedAttributeData()->setClass(newClassString, shouldFoldCase); > if (DOMTokenList* classList = optionalClassList()) > static_cast<ClassList*>(classList)->reset(newClassString); > } else if (attributeData()) >diff --git a/Source/WebCore/dom/StyledElement.h b/Source/WebCore/dom/StyledElement.h >index d61f0afaf4eb2bf8104d302967b0fd4665dbdb01..ce6a3cafce7759cb2907cfd37d270f0c42566037 100644 >--- a/Source/WebCore/dom/StyledElement.h >+++ b/Source/WebCore/dom/StyledElement.h >@@ -38,7 +38,7 @@ class StyledElement : public Element { > public: > virtual ~StyledElement(); > >- size_t mappedAttributeCount() const { return attributeMap() ? attributeMap()->mappedAttributeCount() : 0; } >+ size_t mappedAttributeCount() const { return attributeData() ? attributeData()->mappedAttributeCount() : 0; } > bool isMappedAttribute(const QualifiedName& name) const { MappedAttributeEntry res = eNone; mapToEntry(name, res); return res != eNone; } > > void addCSSLength(Attribute*, int id, const String& value); >@@ -58,8 +58,8 @@ public: > virtual PassRefPtr<CSSMutableStyleDeclaration> additionalAttributeStyle() { return 0; } > void invalidateStyleAttribute(); > >- CSSMutableStyleDeclaration* inlineStyleDecl() const { return attributeMap() ? attributeMap()->inlineStyleDecl() : 0; } >- CSSMutableStyleDeclaration* ensureInlineStyleDecl() { return ensureAttributeMap()->ensureInlineStyleDecl(); } >+ CSSMutableStyleDeclaration* inlineStyleDecl() const { return attributeData() ? attributeData()->inlineStyleDecl() : 0; } >+ CSSMutableStyleDeclaration* ensureInlineStyleDecl() { return ensureAttributeData()->ensureInlineStyleDecl(this); } > virtual CSSStyleDeclaration* style() OVERRIDE { return ensureInlineStyleDecl(); } > > const SpaceSplitString& classNames() const; >@@ -92,8 +92,8 @@ private: > > void destroyInlineStyleDecl() > { >- if (attributeMap()) >- attributeMap()->destroyInlineStyleDecl(); >+ if (attributeData()) >+ attributeData()->destroyInlineStyleDecl(); > } > }; > >diff --git a/Source/WebCore/editing/ApplyStyleCommand.cpp b/Source/WebCore/editing/ApplyStyleCommand.cpp >index 43820c4c2d9e85448c5d7e46293f0c19bbcb279c..352b452cf19996b7ee19fb5553a78449f361a2a5 100644 >--- a/Source/WebCore/editing/ApplyStyleCommand.cpp >+++ b/Source/WebCore/editing/ApplyStyleCommand.cpp >@@ -73,8 +73,8 @@ bool isLegacyAppleStyleSpan(const Node *node) > enum ShouldStyleAttributeBeEmpty { AllowNonEmptyStyleAttribute, StyleAttributeShouldBeEmpty }; > static bool hasNoAttributeOrOnlyStyleAttribute(const StyledElement* element, ShouldStyleAttributeBeEmpty shouldStyleAttributeBeEmpty) > { >- NamedNodeMap* map = element->updatedAttributes(); >- if (!map || map->isEmpty()) >+ ElementAttributeData* attributes = element->updatedAttributeData(); >+ if (!attributes || attributes->isEmpty()) > return true; > > unsigned matchedAttributes = 0; >@@ -84,8 +84,8 @@ static bool hasNoAttributeOrOnlyStyleAttribute(const StyledElement* element, Sho > || !element->inlineStyleDecl() || element->inlineStyleDecl()->isEmpty())) > matchedAttributes++; > >- ASSERT(matchedAttributes <= map->length()); >- return matchedAttributes == map->length(); >+ ASSERT(matchedAttributes <= attributes->length()); >+ return matchedAttributes == attributes->length(); > } > > bool isStyleSpanOrSpanWithOnlyStyleAttribute(const Element* element) >@@ -108,10 +108,10 @@ static bool isEmptyFontTag(const Node *node) > return false; > > const Element *elem = static_cast<const Element *>(node); >- NamedNodeMap* map = elem->updatedAttributes(); >- if (!map) >+ ElementAttributeData* attributes = elem->updatedAttributeData(); >+ if (!attributes) > return true; >- return map->isEmpty() || (map->length() == 1 && elem->getAttribute(classAttr) == styleSpanClassString()); >+ return attributes->isEmpty() || (attributes->length() == 1 && elem->getAttribute(classAttr) == styleSpanClassString()); > } > > static PassRefPtr<Element> createFontElement(Document* document) >diff --git a/Source/WebCore/editing/EditingStyle.cpp b/Source/WebCore/editing/EditingStyle.cpp >index 7e5441d3b58b078fe5621c9ca3f52d263c5dbcd2..e3ce47f3b7242c73edd55aa0dd1c131c6f67f97f 100644 >--- a/Source/WebCore/editing/EditingStyle.cpp >+++ b/Source/WebCore/editing/EditingStyle.cpp >@@ -817,8 +817,8 @@ bool EditingStyle::elementIsStyledSpanOrHTMLEquivalent(const HTMLElement* elemen > } > } > >- const NamedNodeMap* attributeMap = element->attributeMap(); >- if (!attributeMap || attributeMap->isEmpty()) >+ const ElementAttributeData* attributes = element->attributeData(); >+ if (!attributes || attributes->isEmpty()) > return elementIsSpanOrElementEquivalent; // span, b, etc... without any attributes > > unsigned matchedAttributes = 0; >@@ -846,8 +846,8 @@ bool EditingStyle::elementIsStyledSpanOrHTMLEquivalent(const HTMLElement* elemen > } > > // font with color attribute, span with style attribute, etc... >- ASSERT(matchedAttributes <= attributeMap->length()); >- return matchedAttributes >= attributeMap->length(); >+ ASSERT(matchedAttributes <= attributes->length()); >+ return matchedAttributes >= attributes->length(); > } > > void EditingStyle::prepareToApplyAt(const Position& position, ShouldPreserveWritingDirection shouldPreserveWritingDirection) >diff --git a/Source/WebCore/editing/InsertParagraphSeparatorCommand.cpp b/Source/WebCore/editing/InsertParagraphSeparatorCommand.cpp >index e646b51f22aaea81d7cf07d373e988bd69135669..219381a24738519cdd9dbb9c2b195ff73cb36074 100644 >--- a/Source/WebCore/editing/InsertParagraphSeparatorCommand.cpp >+++ b/Source/WebCore/editing/InsertParagraphSeparatorCommand.cpp >@@ -51,7 +51,7 @@ static Element* highestVisuallyEquivalentDivBelowRoot(Element* startBlock) > // We don't want to return a root node (if it happens to be a div, e.g., in a document fragment) because there are no > // siblings for us to append to. > while (!curBlock->nextSibling() && curBlock->parentElement()->hasTagName(divTag) && curBlock->parentElement()->parentElement()) { >- NamedNodeMap* attributes = curBlock->parentElement()->updatedAttributes(); >+ ElementAttributeData* attributes = curBlock->parentElement()->updatedAttributeData(); > if (attributes && !attributes->isEmpty()) > break; > curBlock = curBlock->parentElement(); >diff --git a/Source/WebCore/editing/MarkupAccumulator.cpp b/Source/WebCore/editing/MarkupAccumulator.cpp >index 5226b214c25811760935c566964e7630f02f9d18..645ad7da9007b5f45465869590d224da7b7e6eb2 100644 >--- a/Source/WebCore/editing/MarkupAccumulator.cpp >+++ b/Source/WebCore/editing/MarkupAccumulator.cpp >@@ -349,7 +349,7 @@ void MarkupAccumulator::appendElement(StringBuilder& out, Element* element, Name > { > appendOpenTag(out, element, namespaces); > >- NamedNodeMap* attributes = element->updatedAttributes(); >+ ElementAttributeData* attributes = element->updatedAttributeData(); > if (attributes) { > unsigned length = attributes->length(); > for (unsigned int i = 0; i < length; i++) >diff --git a/Source/WebCore/editing/htmlediting.cpp b/Source/WebCore/editing/htmlediting.cpp >index 28cc029d01b059902485f106a940522d0e2b4718..24ecc6c30c426bf7f04c3256313deda94fd9ba0b 100644 >--- a/Source/WebCore/editing/htmlediting.cpp >+++ b/Source/WebCore/editing/htmlediting.cpp >@@ -1149,21 +1149,19 @@ bool isRenderedAsNonInlineTableImageOrHR(const Node* node) > > bool areIdenticalElements(const Node* first, const Node* second) > { >- // check that tag name and all attribute names and values are identical >- > if (!first->isElementNode() || !second->isElementNode()) > return false; > > if (!toElement(first)->tagQName().matches(toElement(second)->tagQName())) > return false; > >- NamedNodeMap* firstMap = toElement(first)->updatedAttributes(); >- NamedNodeMap* secondMap = toElement(second)->updatedAttributes(); >+ ElementAttributeData* firstAttributes = toElement(first)->updatedAttributeData(); >+ ElementAttributeData* secondAttributes = toElement(second)->updatedAttributeData(); > >- if (firstMap) >- return firstMap->mapsEquivalent(secondMap); >- if (secondMap) >- return secondMap->mapsEquivalent(firstMap); >+ if (firstAttributes) >+ return firstAttributes->equivalent(secondAttributes); >+ if (secondAttributes) >+ return secondAttributes->equivalent(firstAttributes); > return true; > } > >diff --git a/Source/WebCore/editing/markup.cpp b/Source/WebCore/editing/markup.cpp >index a5482af234b64bf302dda9c1b27198954c907b1e..3ad9f6fde510c3008d1c1d3daca0cd6778cfe419 100644 >--- a/Source/WebCore/editing/markup.cpp >+++ b/Source/WebCore/editing/markup.cpp >@@ -102,17 +102,17 @@ static void completeURLs(Node* node, const String& baseURL) > > Node* end = node->traverseNextSibling(); > for (Node* n = node; n != end; n = n->traverseNextNode()) { >- if (n->isElementNode()) { >- Element* e = static_cast<Element*>(n); >- NamedNodeMap* attributes = e->updatedAttributes(); >- if (!attributes) >- continue; >- unsigned length = attributes->length(); >- for (unsigned i = 0; i < length; i++) { >- Attribute* attribute = attributes->attributeItem(i); >- if (e->isURLAttribute(attribute)) >- changes.append(AttributeChange(e, attribute->name(), KURL(parsedBaseURL, attribute->value()).string())); >- } >+ if (!n->isElementNode()) >+ continue; >+ Element* e = static_cast<Element*>(n); >+ ElementAttributeData* attributes = e->updatedAttributeData(); >+ if (!attributes) >+ continue; >+ unsigned length = attributes->length(); >+ for (unsigned i = 0; i < length; i++) { >+ Attribute* attribute = attributes->attributeItem(i); >+ if (e->isURLAttribute(attribute)) >+ changes.append(AttributeChange(e, attribute->name(), KURL(parsedBaseURL, attribute->value()).string())); > } > } > >@@ -289,7 +289,7 @@ void StyledMarkupAccumulator::appendElement(StringBuilder& out, Element* element > const bool documentIsHTML = element->document()->isHTMLDocument(); > appendOpenTag(out, element, 0); > >- NamedNodeMap* attributes = element->updatedAttributes(); >+ ElementAttributeData* attributes = element->updatedAttributeData(); > const unsigned length = attributes ? attributes->length() : 0; > const bool shouldAnnotateOrForceInline = element->isHTMLElement() && (shouldAnnotate() || addDisplayInline); > const bool shouldOverrideStyleAttr = shouldAnnotateOrForceInline || shouldApplyWrappingStyle(element); >diff --git a/Source/WebCore/html/HTMLEmbedElement.cpp b/Source/WebCore/html/HTMLEmbedElement.cpp >index 309aafe055a3a1bf4f45b15ef92b12745188f04e..33edf604364e4b2109c176311211bb32ed99bbc0 100644 >--- a/Source/WebCore/html/HTMLEmbedElement.cpp >+++ b/Source/WebCore/html/HTMLEmbedElement.cpp >@@ -117,7 +117,7 @@ void HTMLEmbedElement::parseMappedAttribute(Attribute* attr) > > void HTMLEmbedElement::parametersForPlugin(Vector<String>& paramNames, Vector<String>& paramValues) > { >- NamedNodeMap* attributes = updatedAttributes(); >+ ElementAttributeData* attributes = updatedAttributeData(); > if (!attributes) > return; > >diff --git a/Source/WebCore/html/HTMLInputElement.cpp b/Source/WebCore/html/HTMLInputElement.cpp >index 413c1277cc113893442ada5b6c98116cf180fe7d..3a1fbfe78134187ab8767b7a5a3d99751fa925c5 100644 >--- a/Source/WebCore/html/HTMLInputElement.cpp >+++ b/Source/WebCore/html/HTMLInputElement.cpp >@@ -545,13 +545,13 @@ void HTMLInputElement::updateType() > registerForSuspensionCallbackIfNeeded(); > > if (didRespectHeightAndWidth != m_inputType->shouldRespectHeightAndWidthAttributes()) { >- NamedNodeMap* map = attributeMap(); >- ASSERT(map); >- if (Attribute* height = map->getAttributeItem(heightAttr)) >+ ElementAttributeData* attributes = attributeData(); >+ ASSERT(attributes); >+ if (Attribute* height = attributes->getAttributeItem(heightAttr)) > attributeChanged(height, false); >- if (Attribute* width = map->getAttributeItem(widthAttr)) >+ if (Attribute* width = attributes->getAttributeItem(widthAttr)) > attributeChanged(width, false); >- if (Attribute* align = map->getAttributeItem(alignAttr)) >+ if (Attribute* align = attributes->getAttributeItem(alignAttr)) > attributeChanged(align, false); > } > >diff --git a/Source/WebCore/html/HTMLObjectElement.cpp b/Source/WebCore/html/HTMLObjectElement.cpp >index 590d69b98b24c96b707411cb5d87023a3e989c23..7e0bd0b94d9237b686ef62e4b81d454583d62f45 100644 >--- a/Source/WebCore/html/HTMLObjectElement.cpp >+++ b/Source/WebCore/html/HTMLObjectElement.cpp >@@ -177,7 +177,7 @@ void HTMLObjectElement::parametersForPlugin(Vector<String>& paramNames, Vector<S > } > > // Turn the attributes of the <object> element into arrays, but don't override <param> values. >- NamedNodeMap* attributes = updatedAttributes(); >+ ElementAttributeData* attributes = updatedAttributeData(); > if (attributes) { > for (unsigned i = 0; i < attributes->length(); ++i) { > Attribute* it = attributes->attributeItem(i); >diff --git a/Source/WebCore/html/HTMLParamElement.cpp b/Source/WebCore/html/HTMLParamElement.cpp >index aa228bc31663ab082a32022b84e1ce3eb09bfac1..30a979c2c6bedbce5ba8ba6ead27d46e1e45c286 100644 >--- a/Source/WebCore/html/HTMLParamElement.cpp >+++ b/Source/WebCore/html/HTMLParamElement.cpp >@@ -66,7 +66,7 @@ void HTMLParamElement::parseMappedAttribute(Attribute* attr) > bool HTMLParamElement::isURLAttribute(Attribute* attr) const > { > if (attr->name() == valueAttr && hasAttributes()) { >- Attribute* nameAttribute = attributeMap()->getAttributeItem(nameAttr); >+ Attribute* nameAttribute = attributeData()->getAttributeItem(nameAttr); > if (nameAttribute) { > const AtomicString& value = nameAttribute->value(); > if (isURLParameter(value)) >diff --git a/Source/WebCore/html/parser/HTMLConstructionSite.cpp b/Source/WebCore/html/parser/HTMLConstructionSite.cpp >index 0ee89f15250328123c7f0418652c18e349832031..48c584b6ad401f7f39eea1037381c05abe3ed07c 100644 >--- a/Source/WebCore/html/parser/HTMLConstructionSite.cpp >+++ b/Source/WebCore/html/parser/HTMLConstructionSite.cpp >@@ -194,7 +194,7 @@ void HTMLConstructionSite::dispatchDocumentElementAvailableIfNeeded() > void HTMLConstructionSite::insertHTMLHtmlStartTagBeforeHTML(AtomicHTMLToken& token) > { > RefPtr<HTMLHtmlElement> element = HTMLHtmlElement::create(m_document); >- element->parserSetAttributeMap(token.takeAttributes(), m_fragmentScriptingPermission); >+ element->parserSetAttributeData(token.takeAttributes(), m_fragmentScriptingPermission); > attachLater(m_attachmentRoot, element); > m_openElements.pushHTMLHtmlElement(element); > >@@ -208,7 +208,7 @@ void HTMLConstructionSite::mergeAttributesFromTokenIntoElement(AtomicHTMLToken& > if (!token.attributes()) > return; > >- NamedNodeMap* attributes = element->ensureUpdatedAttributes(); >+ ElementAttributeData* attributes = element->ensureUpdatedAttributeData(); > for (unsigned i = 0; i < token.attributes()->length(); ++i) { > Attribute* attribute = token.attributes()->attributeItem(i); > if (!attributes->getAttributeItem(attribute->name())) >@@ -336,7 +336,7 @@ void HTMLConstructionSite::insertScriptElement(AtomicHTMLToken& token) > { > RefPtr<HTMLScriptElement> element = HTMLScriptElement::create(scriptTag, currentNode()->document(), true); > if (m_fragmentScriptingPermission == FragmentScriptingAllowed) >- element->parserSetAttributeMap(token.takeAttributes(), m_fragmentScriptingPermission); >+ element->parserSetAttributeData(token.takeAttributes(), m_fragmentScriptingPermission); > attachLater(currentNode(), element); > m_openElements.push(element.release()); > } >@@ -399,7 +399,7 @@ PassRefPtr<Element> HTMLConstructionSite::createElement(AtomicHTMLToken& token, > { > QualifiedName tagName(nullAtom, token.name(), namespaceURI); > RefPtr<Element> element = currentNode()->document()->createElement(tagName, true); >- element->parserSetAttributeMap(token.takeAttributes(), m_fragmentScriptingPermission); >+ element->parserSetAttributeData(token.takeAttributes(), m_fragmentScriptingPermission); > return element.release(); > } > >@@ -410,7 +410,7 @@ PassRefPtr<Element> HTMLConstructionSite::createHTMLElement(AtomicHTMLToken& tok > // have to pass the current form element. We should rework form association > // to occur after construction to allow better code sharing here. > RefPtr<Element> element = HTMLElementFactory::createHTMLElement(tagName, currentNode()->document(), form(), true); >- element->parserSetAttributeMap(token.takeAttributes(), m_fragmentScriptingPermission); >+ element->parserSetAttributeData(token.takeAttributes(), m_fragmentScriptingPermission); > ASSERT(element->isHTMLElement()); > return element.release(); > } >@@ -423,17 +423,17 @@ PassRefPtr<Element> HTMLConstructionSite::createHTMLElementFromElementRecord(HTM > namespace { > > // FIXME: Move this function to the top of the file. >-inline PassOwnPtr<NamedNodeMap> cloneAttributes(Element* element) >+inline PassOwnPtr<ElementAttributeData> cloneAttributes(Element* element) > { >- NamedNodeMap* attributes = element->updatedAttributes(); >+ ElementAttributeData* attributes = element->updatedAttributeData(); > if (!attributes) > return nullptr; > >- OwnPtr<NamedNodeMap> newAttributes = NamedNodeMap::create(); >+ OwnPtr<ElementAttributeData> newAttributes = ElementAttributeData::create(); > for (size_t i = 0; i < attributes->length(); ++i) { > Attribute* attribute = attributes->attributeItem(i); > RefPtr<Attribute> clone = Attribute::createMapped(attribute->name(), attribute->value()); >- newAttributes->addAttribute(clone); >+ newAttributes->addAttribute(clone, 0); > } > return newAttributes.release(); > } >diff --git a/Source/WebCore/html/parser/HTMLFormattingElementList.cpp b/Source/WebCore/html/parser/HTMLFormattingElementList.cpp >index f331af7e70b6b5dc5d19a8147be7a284b3e629de..21e2b34774314010330e25c7c1b94cef964e5c08 100644 >--- a/Source/WebCore/html/parser/HTMLFormattingElementList.cpp >+++ b/Source/WebCore/html/parser/HTMLFormattingElementList.cpp >@@ -42,7 +42,7 @@ static const size_t kNoahsArkCapacity = 3; > > static inline size_t attributeCount(Element* element) > { >- return element->attributeMap() ? element->attributeMap()->length() : 0; >+ return element->attributeData() ? element->attributeData()->length() : 0; > } > > HTMLFormattingElementList::HTMLFormattingElementList() >@@ -178,18 +178,18 @@ void HTMLFormattingElementList::ensureNoahsArkCondition(Element* newElement) > Vector<Element*> remainingCandidates; > remainingCandidates.reserveInitialCapacity(candidates.size()); > >- NamedNodeMap* attributeMap = newElement->attributeMap(); >+ ElementAttributeData* attributes = newElement->attributeData(); > size_t newElementAttributeCount = attributeCount(newElement); > > for (size_t i = 0; i < newElementAttributeCount; ++i) { >- QualifiedName attributeName = attributeMap->attributeItem(i)->name(); >+ QualifiedName attributeName = attributes->attributeItem(i)->name(); > AtomicString attributeValue = newElement->fastGetAttribute(attributeName); > > for (size_t j = 0; j < candidates.size(); ++j) { > Element* candidate = candidates[j]; > > // These properties should already have been checked by tryToEnsureNoahsArkConditionQuickly. >- ASSERT(newElement->attributeMap()->length() == candidate->attributeMap()->length()); >+ ASSERT(newElement->attributeData()->length() == candidate->attributeData()->length()); > ASSERT(newElement->tagQName() == candidate->tagQName()); > > // FIXME: Technically we shouldn't read this information back from >diff --git a/Source/WebCore/html/parser/HTMLToken.h b/Source/WebCore/html/parser/HTMLToken.h >index c1782843460c6c07989fbbbd67cb20462868d57d..e8fdd125f849bdb7e5ec1d1fbbd86513c8700033 100644 >--- a/Source/WebCore/html/parser/HTMLToken.h >+++ b/Source/WebCore/html/parser/HTMLToken.h >@@ -86,7 +86,7 @@ class AtomicHTMLToken : public AtomicMarkupTokenBase<HTMLToken> { > public: > AtomicHTMLToken(HTMLToken& token) : AtomicMarkupTokenBase<HTMLToken>(&token) { } > >- AtomicHTMLToken(HTMLTokenTypes::Type type, AtomicString name, PassOwnPtr<NamedNodeMap> attributes = nullptr) >+ AtomicHTMLToken(HTMLTokenTypes::Type type, AtomicString name, PassOwnPtr<ElementAttributeData> attributes = nullptr) > : AtomicMarkupTokenBase<HTMLToken>(type, name, attributes) > { > } >diff --git a/Source/WebCore/html/parser/HTMLTreeBuilder.cpp b/Source/WebCore/html/parser/HTMLTreeBuilder.cpp >index 09e0a8e10ed79fd829d265d0b0ad9ab1d22df6b2..5fc3df49f7e1e2c37176ad12ddcb4e77fd5095e7 100644 >--- a/Source/WebCore/html/parser/HTMLTreeBuilder.cpp >+++ b/Source/WebCore/html/parser/HTMLTreeBuilder.cpp >@@ -531,7 +531,7 @@ void HTMLTreeBuilder::processDoctypeToken(AtomicHTMLToken& token) > parseError(token); > } > >-void HTMLTreeBuilder::processFakeStartTag(const QualifiedName& tagName, PassOwnPtr<NamedNodeMap> attributes) >+void HTMLTreeBuilder::processFakeStartTag(const QualifiedName& tagName, PassOwnPtr<ElementAttributeData> attributes) > { > // FIXME: We'll need a fancier conversion than just "localName" for SVG/MathML tags. > AtomicHTMLToken fakeToken(HTMLTokenTypes::StartTag, tagName.localName(), attributes); >@@ -560,15 +560,15 @@ void HTMLTreeBuilder::processFakePEndTagIfPInButtonScope() > processEndTag(endP); > } > >-PassOwnPtr<NamedNodeMap> HTMLTreeBuilder::attributesForIsindexInput(AtomicHTMLToken& token) >+PassOwnPtr<ElementAttributeData> HTMLTreeBuilder::attributesForIsindexInput(AtomicHTMLToken& token) > { >- OwnPtr<NamedNodeMap> attributes = token.takeAttributes(); >+ OwnPtr<ElementAttributeData> attributes = token.takeAttributes(); > if (!attributes) >- attributes = NamedNodeMap::create(); >+ attributes = ElementAttributeData::create(); > else { >- attributes->removeAttribute(nameAttr); >- attributes->removeAttribute(actionAttr); >- attributes->removeAttribute(promptAttr); >+ attributes->removeAttribute(nameAttr, 0); >+ attributes->removeAttribute(actionAttr, 0); >+ attributes->removeAttribute(promptAttr, 0); > } > > RefPtr<Attribute> mappedAttribute = Attribute::createMapped(nameAttr, isindexTag.localName()); >@@ -681,7 +681,7 @@ void adjustAttributes(AtomicHTMLToken& token) > mapLoweredLocalNameToName(caseMap, attrs, length); > } > >- NamedNodeMap* attributes = token.attributes(); >+ ElementAttributeData* attributes = token.attributes(); > if (!attributes) > return; > >@@ -730,7 +730,7 @@ void adjustForeignAttributes(AtomicHTMLToken& token) > map->add("xmlns:xlink", QualifiedName("xmlns", "xlink", XMLNSNames::xmlnsNamespaceURI)); > } > >- NamedNodeMap* attributes = token.attributes(); >+ ElementAttributeData* attributes = token.attributes(); > if (!attributes) > return; > >diff --git a/Source/WebCore/html/parser/HTMLTreeBuilder.h b/Source/WebCore/html/parser/HTMLTreeBuilder.h >index 0183d20cae1cea279dfa9ff4734e88bc4f6d65bb..f13ba7a01ed619ad44bfcbe7f423b34190e1b94b 100644 >--- a/Source/WebCore/html/parser/HTMLTreeBuilder.h >+++ b/Source/WebCore/html/parser/HTMLTreeBuilder.h >@@ -151,7 +151,7 @@ private: > void processCharacterBuffer(ExternalCharacterTokenBuffer&); > inline void processCharacterBufferForInBody(ExternalCharacterTokenBuffer&); > >- void processFakeStartTag(const QualifiedName&, PassOwnPtr<NamedNodeMap> attributes = nullptr); >+ void processFakeStartTag(const QualifiedName&, PassOwnPtr<ElementAttributeData> attributes = nullptr); > void processFakeEndTag(const QualifiedName&); > void processFakeCharacters(const String&); > void processFakePEndTagIfPInButtonScope(); >@@ -172,7 +172,7 @@ private: > inline bool shouldProcessTokenInForeignContent(AtomicHTMLToken&); > void processTokenInForeignContent(AtomicHTMLToken&); > >- PassOwnPtr<NamedNodeMap> attributesForIsindexInput(AtomicHTMLToken&); >+ PassOwnPtr<ElementAttributeData> attributesForIsindexInput(AtomicHTMLToken&); > > HTMLElementStack::ElementRecord* furthestBlockForFormattingElement(Element*); > void callTheAdoptionAgency(AtomicHTMLToken&); >diff --git a/Source/WebCore/html/parser/TextDocumentParser.cpp b/Source/WebCore/html/parser/TextDocumentParser.cpp >index 1c55fc2546e4b6c5a24161586e4e7e0f1ff70a42..190472c430ebb20f39d4d967b53c0e8fc17dce77 100644 >--- a/Source/WebCore/html/parser/TextDocumentParser.cpp >+++ b/Source/WebCore/html/parser/TextDocumentParser.cpp >@@ -61,7 +61,7 @@ void TextDocumentParser::insertFakePreElement() > // distrubing the line/column number calculations. > > RefPtr<Attribute> styleAttribute = Attribute::createMapped("style", "word-wrap: break-word; white-space: pre-wrap;"); >- OwnPtr<NamedNodeMap> attributes = NamedNodeMap::create(); >+ OwnPtr<ElementAttributeData> attributes = ElementAttributeData::create(); > attributes->insertAttribute(styleAttribute.release(), false); > AtomicHTMLToken fakePre(HTMLTokenTypes::StartTag, preTag.localName(), attributes.release()); > >diff --git a/Source/WebCore/inspector/DOMEditor.cpp b/Source/WebCore/inspector/DOMEditor.cpp >index 3c9d89b5dd1cfba3ab42e02594c15b4702403f54..1c8c0d9ab1f0191bd2b5915ac0e520fde63322bf 100644 >--- a/Source/WebCore/inspector/DOMEditor.cpp >+++ b/Source/WebCore/inspector/DOMEditor.cpp >@@ -160,16 +160,16 @@ void DOMEditor::innerPatchNode(Digest* oldDigest, Digest* newDigest, ExceptionCo > Element* oldElement = static_cast<Element*>(oldNode); > Element* newElement = static_cast<Element*>(newNode); > if (oldDigest->m_attrsSHA1 != newDigest->m_attrsSHA1) { >- NamedNodeMap* oldAttributeMap = oldElement->attributeMap(); >+ ElementAttributeData* oldAttributes = oldElement->attributeData(); > >- while (oldAttributeMap && oldAttributeMap->length()) >- oldAttributeMap->removeAttribute(0); >+ while (oldAttributes && oldAttributes->length()) >+ oldAttributes->removeAttribute(0, oldElement); > >- NamedNodeMap* newAttributeMap = newElement->attributeMap(); >- if (newAttributeMap) { >- size_t numAttrs = newAttributeMap->length(); >+ ElementAttributeData* newAttributes = newElement->attributeData(); >+ if (newAttributes) { >+ size_t numAttrs = newAttributes->length(); > for (size_t i = 0; i < numAttrs; ++i) { >- const Attribute* attribute = newAttributeMap->attributeItem(i); >+ const Attribute* attribute = newAttributes->attributeItem(i); > oldElement->setAttribute(attribute->name(), attribute->value()); > } > } >@@ -384,12 +384,12 @@ PassOwnPtr<DOMEditor::Digest> DOMEditor::createDigest(Node* node, UnusedNodesMap > } > Element* element = static_cast<Element*>(node); > >- NamedNodeMap* attrMap = element->attributeMap(); >- if (attrMap && attrMap->length()) { >- size_t numAttrs = attrMap->length(); >+ ElementAttributeData* attributes = element->attributeData(); >+ if (attributes && attributes->length()) { >+ size_t numAttrs = attributes->length(); > SHA1 attrsSHA1; > for (size_t i = 0; i < numAttrs; ++i) { >- const Attribute* attribute = attrMap->attributeItem(i); >+ const Attribute* attribute = attributes->attributeItem(i); > addStringToSHA1(attrsSHA1, attribute->name().toString()); > addStringToSHA1(attrsSHA1, attribute->value()); > } >diff --git a/Source/WebCore/inspector/DOMEditor.h b/Source/WebCore/inspector/DOMEditor.h >index 4affb00b1a69910546e9dd4566a12499d4758c90..f56a306cbc93a87f4dfc6743f968eae35f721432 100644 >--- a/Source/WebCore/inspector/DOMEditor.h >+++ b/Source/WebCore/inspector/DOMEditor.h >@@ -43,7 +43,6 @@ namespace WebCore { > > class ContainerNode; > class Document; >-class NamedNodeMap; > class Node; > > #if ENABLE(INSPECTOR) >diff --git a/Source/WebCore/inspector/InspectorCSSAgent.cpp b/Source/WebCore/inspector/InspectorCSSAgent.cpp >index 06635f52336c9fd404b3418e8294f5bb75d9d3ca..24cf0eec4bb931e3c1aa917e5982395c6fd725c8 100644 >--- a/Source/WebCore/inspector/InspectorCSSAgent.cpp >+++ b/Source/WebCore/inspector/InspectorCSSAgent.cpp >@@ -717,7 +717,7 @@ PassRefPtr<InspectorArray> InspectorCSSAgent::buildArrayForRuleList(CSSRuleList* > PassRefPtr<InspectorArray> InspectorCSSAgent::buildArrayForAttributeStyles(Element* element) > { > RefPtr<InspectorArray> attrStyles = InspectorArray::create(); >- NamedNodeMap* attributes = element->updatedAttributes(); >+ ElementAttributeData* attributes = element->updatedAttributeData(); > if (!attributes) > return attrStyles.release(); > >diff --git a/Source/WebCore/inspector/InspectorDOMAgent.cpp b/Source/WebCore/inspector/InspectorDOMAgent.cpp >index b50025bb00977a56bfbcb6e2c3fa0162c926e453..b17639d0d246e1be60009dc08b4cb47683aba5bd 100644 >--- a/Source/WebCore/inspector/InspectorDOMAgent.cpp >+++ b/Source/WebCore/inspector/InspectorDOMAgent.cpp >@@ -530,17 +530,17 @@ void InspectorDOMAgent::setAttributesAsText(ErrorString* errorString, int elemen > return; > } > >- const NamedNodeMap* attrMap = toHTMLElement(child)->updatedAttributes(); >- if (!attrMap && name) { >+ const ElementAttributeData* attributes = toHTMLElement(child)->updatedAttributeData(); >+ if (!attributes && name) { > element->removeAttribute(*name); > return; > } > > bool foundOriginalAttribute = false; >- unsigned numAttrs = attrMap->length(); >+ unsigned numAttrs = attributes->length(); > for (unsigned i = 0; i < numAttrs; ++i) { > // Add attribute pair >- const Attribute* attribute = attrMap->attributeItem(i); >+ const Attribute* attribute = attributes->attributeItem(i); > foundOriginalAttribute = foundOriginalAttribute || (name && attribute->name().toString() == *name); > element->setAttribute(attribute->name(), attribute->value()); > } >@@ -781,14 +781,14 @@ void InspectorDOMAgent::performSearch(ErrorString*, const String& whitespaceTrim > break; > } > // Go through all attributes and serialize them. >- const NamedNodeMap* attrMap = static_cast<Element*>(node)->updatedAttributes(); >- if (!attrMap) >+ const ElementAttributeData* attributes = static_cast<Element*>(node)->updatedAttributeData(); >+ if (!attributes) > break; > >- unsigned numAttrs = attrMap->length(); >+ unsigned numAttrs = attributes->length(); > for (unsigned i = 0; i < numAttrs; ++i) { > // Add attribute pair >- const Attribute* attribute = attrMap->attributeItem(i); >+ const Attribute* attribute = attributes->attributeItem(i); > if (attribute->localName().find(whitespaceTrimmedQuery) != notFound) { > resultCollector.add(node); > break; >@@ -1159,13 +1159,13 @@ PassRefPtr<InspectorArray> InspectorDOMAgent::buildArrayForElementAttributes(Ele > { > RefPtr<InspectorArray> attributesValue = InspectorArray::create(); > // Go through all attributes and serialize them. >- const NamedNodeMap* attrMap = element->updatedAttributes(); >- if (!attrMap) >+ const ElementAttributeData* attributes = element->updatedAttributeData(); >+ if (!attributes) > return attributesValue.release(); >- unsigned numAttrs = attrMap->length(); >+ unsigned numAttrs = attributes->length(); > for (unsigned i = 0; i < numAttrs; ++i) { > // Add attribute pair >- const Attribute* attribute = attrMap->attributeItem(i); >+ const Attribute* attribute = attributes->attributeItem(i); > attributesValue->pushString(attribute->name().toString()); > attributesValue->pushString(attribute->value()); > } >diff --git a/Source/WebCore/page/PageSerializer.cpp b/Source/WebCore/page/PageSerializer.cpp >index 2ea0fbe216abcb055f59041290d73ada25605144..b429b69cbd30b36d0af35b973355104d5d6d7d7c 100644 >--- a/Source/WebCore/page/PageSerializer.cpp >+++ b/Source/WebCore/page/PageSerializer.cpp >@@ -69,9 +69,9 @@ static bool isCharsetSpecifyingNode(Node* node) > if (!element->hasTagName(HTMLNames::metaTag)) > return false; > HTMLMetaCharsetParser::AttributeList attributes; >- if (const NamedNodeMap* attributesMap = element->updatedAttributes()) { >- for (unsigned i = 0; i < attributesMap->length(); ++i) { >- Attribute* item = attributesMap->attributeItem(i); >+ if (const ElementAttributeData* attributeData = element->updatedAttributeData()) { >+ for (unsigned i = 0; i < attributeData->length(); ++i) { >+ Attribute* item = attributeData->attributeItem(i); > // FIXME: We should deal appropriately with the attribute if they have a namespace. > attributes.append(make_pair(item->name().toString(), item->value().string())); > } >diff --git a/Source/WebCore/svg/SVGElement.cpp b/Source/WebCore/svg/SVGElement.cpp >index 6e160f0763f6770188094e458b5a18445b47d2c7..180ced0998ed5bd5b0f6fbe9212fff00ee28581c 100644 >--- a/Source/WebCore/svg/SVGElement.cpp >+++ b/Source/WebCore/svg/SVGElement.cpp >@@ -369,7 +369,7 @@ void SVGElement::attributeChanged(Attribute* attr, bool preserveDecls) > > // When an animated SVG property changes through SVG DOM, svgAttributeChanged() is called, not attributeChanged(). > // Next time someone tries to access the XML attributes, the synchronization code starts. During that synchronization >- // SVGAnimatedPropertySynchronizer may call NamedNodeMap::removeAttribute(), which in turn calls attributeChanged(). >+ // SVGAnimatedPropertySynchronizer may call ElementAttributeData::removeAttribute(), which in turn calls attributeChanged(). > // At this point we're not allowed to call svgAttributeChanged() again - it may lead to extra work being done, or crashes > // see bug https://bugs.webkit.org/show_bug.cgi?id=40994. > if (isSynchronizingSVGAttributes()) >diff --git a/Source/WebCore/svg/SVGStyledElement.cpp b/Source/WebCore/svg/SVGStyledElement.cpp >index 62669c8ba198bbfa54e543041ef2e393113a23d5..613d12b45f87f200cda6890cf6f999a268aa3596 100644 >--- a/Source/WebCore/svg/SVGStyledElement.cpp >+++ b/Source/WebCore/svg/SVGStyledElement.cpp >@@ -417,11 +417,11 @@ void SVGStyledElement::childrenChanged(bool changedByParser, Node* beforeChange, > > PassRefPtr<CSSValue> SVGStyledElement::getPresentationAttribute(const String& name) > { >- if (!attributeMap()) >+ if (!attributeData()) > return 0; > > QualifiedName attributeName(nullAtom, name, nullAtom); >- Attribute* attr = attributeMap()->getAttributeItem(attributeName); >+ Attribute* attr = attributeData()->getAttributeItem(attributeName); > if (!attr || !attr->isMappedAttribute() || !attr->mappedAttributeDeclaration()) > return 0; > >diff --git a/Source/WebCore/svg/properties/SVGAnimatedPropertySynchronizer.h b/Source/WebCore/svg/properties/SVGAnimatedPropertySynchronizer.h >index e6bd013ebf8fe06de24df8a668ce113f2beca938..d6e571085e5f3c9493a785c8ba10c50c83755b74 100644 >--- a/Source/WebCore/svg/properties/SVGAnimatedPropertySynchronizer.h >+++ b/Source/WebCore/svg/properties/SVGAnimatedPropertySynchronizer.h >@@ -37,15 +37,14 @@ struct SVGAnimatedPropertySynchronizer<true> { > // Attribute directly to avoid a call to Element::attributeChanged > // that could cause the SVGElement to erroneously reset its properties. > // svg/dom/SVGStringList-basics.xhtml exercises this behavior. >- NamedNodeMap* namedAttrMap = ownerElement->ensureUpdatedAttributes(); >- Attribute* old = namedAttrMap->getAttributeItem(attrName); >+ ElementAttributeData* attributeData = ownerElement->ensureUpdatedAttributeData(); >+ Attribute* old = attributeData->getAttributeItem(attrName); > if (old && value.isNull()) >- namedAttrMap->removeAttribute(old->name()); >+ attributeData->removeAttribute(old->name(), ownerElement); > else if (!old && !value.isNull()) >- namedAttrMap->addAttribute(ownerElement->createAttribute(attrName, value)); >+ attributeData->addAttribute(ownerElement->createAttribute(attrName, value), ownerElement); > else if (old && !value.isNull()) > old->setValue(value); >- > } > }; > >diff --git a/Source/WebCore/xml/XPathFunctions.cpp b/Source/WebCore/xml/XPathFunctions.cpp >index 283583d783afa6ef10ea7792cb209cd5134335cf..1dc3af331dd7c88a7e7c2dadac35f36d99df74fc 100644 >--- a/Source/WebCore/xml/XPathFunctions.cpp >+++ b/Source/WebCore/xml/XPathFunctions.cpp >@@ -29,7 +29,6 @@ > #include "XPathFunctions.h" > > #include "Element.h" >-#include "NamedNodeMap.h" > #include "ProcessingInstruction.h" > #include "TreeScope.h" > #include "XMLNames.h" >@@ -592,7 +591,7 @@ Value FunLang::evaluate() const > Node* node = evaluationContext().node.get(); > while (node) { > if (node->isElementNode()) { >- if (NamedNodeMap* attributes = toElement(node)->updatedAttributes()) >+ if (ElementAttributeData* attributes = toElement(node)->updatedAttributeData()) > languageAttribute = attributes->getAttributeItem(XMLNames::langAttr); > } > if (languageAttribute) >diff --git a/Source/WebCore/xml/XPathNodeSet.cpp b/Source/WebCore/xml/XPathNodeSet.cpp >index 8eefc573ff447942521fbd077adf1521d2a39af7..d75a847b47110959fb8110911aa27dbebeeefb2c 100644 >--- a/Source/WebCore/xml/XPathNodeSet.cpp >+++ b/Source/WebCore/xml/XPathNodeSet.cpp >@@ -213,7 +213,7 @@ void NodeSet::traversalSort() const > if (!containsAttributeNodes || !n->isElementNode()) > continue; > >- NamedNodeMap* attributes = toElement(n)->updatedAttributes(); >+ ElementAttributeData* attributes = toElement(n)->updatedAttributeData(); > if (!attributes) > continue; > >diff --git a/Source/WebCore/xml/XPathStep.cpp b/Source/WebCore/xml/XPathStep.cpp >index 12f394f2ca0b4456a81d108983b7924d5c4d875d..b4553ed835b63bb66f2af848446087caa6ad7e4e 100644 >--- a/Source/WebCore/xml/XPathStep.cpp >+++ b/Source/WebCore/xml/XPathStep.cpp >@@ -31,7 +31,6 @@ > #include "Attr.h" > #include "Document.h" > #include "Element.h" >-#include "NamedNodeMap.h" > #include "XMLNSNames.h" > #include "XPathParser.h" > #include "XPathUtil.h" >@@ -343,7 +342,7 @@ void Step::nodesInAxis(Node* context, NodeSet& nodes) const > return; > } > >- NamedNodeMap* attrs = contextElement->updatedAttributes(); >+ ElementAttributeData* attrs = contextElement->updatedAttributeData(); > if (!attrs) > return; > >diff --git a/Source/WebCore/xml/parser/MarkupTokenBase.h b/Source/WebCore/xml/parser/MarkupTokenBase.h >index 0e91913a604c00bf115e98ff31566f1adf89f436..8e3a0ed88ad622b9f672fb52553497ac1daef804 100644 >--- a/Source/WebCore/xml/parser/MarkupTokenBase.h >+++ b/Source/WebCore/xml/parser/MarkupTokenBase.h >@@ -27,7 +27,7 @@ > #ifndef MarkupTokenBase_h > #define MarkupTokenBase_h > >-#include "NamedNodeMap.h" >+#include "ElementAttributeData.h" > #include <wtf/PassOwnPtr.h> > #include <wtf/Vector.h> > >@@ -410,7 +410,7 @@ public: > } > } > >- AtomicMarkupTokenBase(typename Token::Type::Type type, AtomicString name, PassOwnPtr<NamedNodeMap> attributes = nullptr) >+ AtomicMarkupTokenBase(typename Token::Type::Type type, AtomicString name, PassOwnPtr<ElementAttributeData> attributes = nullptr) > : m_type(type) > , m_name(name) > , m_attributes(attributes) >@@ -446,13 +446,13 @@ public: > return m_attributes->getAttributeItem(attributeName); > } > >- NamedNodeMap* attributes() const >+ ElementAttributeData* attributes() const > { > ASSERT(usesAttributes()); > return m_attributes.get(); > } > >- PassOwnPtr<NamedNodeMap> takeAttributes() >+ PassOwnPtr<ElementAttributeData> takeAttributes() > { > ASSERT(usesAttributes()); > return m_attributes.release(); >@@ -516,7 +516,7 @@ protected: > // For StartTag and EndTag > bool m_selfClosing; > >- OwnPtr<NamedNodeMap> m_attributes; >+ OwnPtr<ElementAttributeData> m_attributes; > }; > > template<typename Token> >@@ -526,7 +526,7 @@ inline void AtomicMarkupTokenBase<Token>::initializeAttributes(const typename To > if (!size) > return; > >- m_attributes = NamedNodeMap::create(); >+ m_attributes = ElementAttributeData::create(); > m_attributes->reserveInitialCapacity(size); > for (size_t i = 0; i < size; ++i) { > const typename Token::Attribute& attribute = attributes[i]; >diff --git a/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp b/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp >index 4e1d49eefd04bfef686e0a2c5ce2b60c1d8d87c0..5c89f88bfbda0dae2bcf4e8a635f1292a673b576 100644 >--- a/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp >+++ b/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp >@@ -599,7 +599,7 @@ XMLDocumentParser::XMLDocumentParser(DocumentFragment* fragment, Element* parent > > for (; !elemStack.isEmpty(); elemStack.removeLast()) { > Element* element = elemStack.last(); >- if (NamedNodeMap* attrs = element->updatedAttributes()) { >+ if (ElementAttributeData* attrs = element->updatedAttributeData()) { > for (unsigned i = 0; i < attrs->length(); i++) { > Attribute* attr = attrs->attributeItem(i); > if (attr->localName() == xmlnsAtom) >diff --git a/Source/WebCore/xml/parser/XMLDocumentParserQt.cpp b/Source/WebCore/xml/parser/XMLDocumentParserQt.cpp >index cd6ea1494f512610258c682392b1a54f8ab4392c..75b319ffeeab62f76a0476fa229f505d58863b60 100644 >--- a/Source/WebCore/xml/parser/XMLDocumentParserQt.cpp >+++ b/Source/WebCore/xml/parser/XMLDocumentParserQt.cpp >@@ -138,7 +138,7 @@ XMLDocumentParser::XMLDocumentParser(DocumentFragment* fragment, Element* parent > > QXmlStreamNamespaceDeclarations namespaces; > for (Element* element = elemStack.last(); !elemStack.isEmpty(); elemStack.removeLast()) { >- if (NamedNodeMap* attrs = element->updatedAttributes()) { >+ if (ElementAttributeData* attrs = element->updatedAttributeData()) { > for (unsigned i = 0; i < attrs->length(); i++) { > Attribute* attr = attrs->attributeItem(i); > if (attr->localName() == "xmlns") >diff --git a/Source/WebCore/xml/parser/XMLToken.h b/Source/WebCore/xml/parser/XMLToken.h >index d1bdc0e6b9913cce83dd1ee4deef7f73a4d2c447..002582d9ed4bd9c2f9555e2bec83a315c2ae1a17 100644 >--- a/Source/WebCore/xml/parser/XMLToken.h >+++ b/Source/WebCore/xml/parser/XMLToken.h >@@ -431,7 +431,7 @@ public: > } > } > >- AtomicXMLToken(XMLTokenTypes::Type type, AtomicString name, PassOwnPtr<NamedNodeMap> attributes = nullptr) >+ AtomicXMLToken(XMLTokenTypes::Type type, AtomicString name, PassOwnPtr<ElementAttributeData> attributes = nullptr) > : AtomicMarkupTokenBase<XMLToken>(type, name, attributes) > { > } >diff --git a/Source/WebCore/xml/parser/XMLTreeBuilder.cpp b/Source/WebCore/xml/parser/XMLTreeBuilder.cpp >index 8de1a0817a4e4df1ba8a808ac939675a7aea0335..a7551ce6e3e95062ea18982de058f3b6c55a52ca 100644 >--- a/Source/WebCore/xml/parser/XMLTreeBuilder.cpp >+++ b/Source/WebCore/xml/parser/XMLTreeBuilder.cpp >@@ -80,7 +80,7 @@ XMLTreeBuilder::XMLTreeBuilder(NewXMLDocumentParser* parser, DocumentFragment* f > > for (Element* element; !nodeStack.isEmpty(); nodeStack.removeLast()) { > element = nodeStack.last(); >- if (NamedNodeMap* attrs = element->updatedAttributes()) { >+ if (ElementAttributeData* attrs = element->updatedAttributeData()) { > for (size_t i = 0; i < attrs->length(); ++i) { > Attribute* attr = attrs->attributeItem(i); > if (attr->localName() == xmlnsAtom) >diff --git a/Source/WebKit/chromium/src/WebNamedNodeMap.cpp b/Source/WebKit/chromium/src/WebNamedNodeMap.cpp >index e2455e6b9f7e12789cdb0c17dfe528ddcfd51b5f..30f0b6870dff53fea609aeaeb05d4e6b21a07218 100644 >--- a/Source/WebKit/chromium/src/WebNamedNodeMap.cpp >+++ b/Source/WebKit/chromium/src/WebNamedNodeMap.cpp >@@ -63,7 +63,7 @@ unsigned WebNamedNodeMap::length() const > > WebAttribute WebNamedNodeMap::attributeItem(unsigned index) const > { >- return WebAttribute(m_private->attributeItem(index)); >+ return WebAttribute(m_private->attributeData()->attributeItem(index)); > } > > } // namespace WebKit >diff --git a/Source/WebKit/chromium/src/WebPageSerializerImpl.cpp b/Source/WebKit/chromium/src/WebPageSerializerImpl.cpp >index da0e32555ec7cb8438ab8023a98bb62ceeeb53b5..d071413e64dbe4e3850de3a7b536b495889a432d 100644 >--- a/Source/WebKit/chromium/src/WebPageSerializerImpl.cpp >+++ b/Source/WebKit/chromium/src/WebPageSerializerImpl.cpp >@@ -307,13 +307,13 @@ void WebPageSerializerImpl::openTagToString(Element* element, > // Add open tag > result += "<" + element->nodeName().lower(); > // Go through all attributes and serialize them. >- const NamedNodeMap *attrMap = element->updatedAttributes(); >- if (attrMap) { >- unsigned numAttrs = attrMap->length(); >+ const ElementAttributeData *attrData = element->updatedAttributeData(); >+ if (attrData) { >+ unsigned numAttrs = attrData->length(); > for (unsigned i = 0; i < numAttrs; i++) { > result += " "; > // Add attribute pair >- const Attribute *attribute = attrMap->attributeItem(i); >+ const Attribute *attribute = attrData->attributeItem(i); > result += attribute->name().toString(); > result += "=\""; > if (!attribute->value().isEmpty()) { >diff --git a/Source/WebKit/qt/Api/qwebelement.cpp b/Source/WebKit/qt/Api/qwebelement.cpp >index 771ad56fb1b56718f3b5ee309656793c6ea7426a..efac6d436fd095622e9b1c5fd78ccceca041f0c7 100644 >--- a/Source/WebKit/qt/Api/qwebelement.cpp >+++ b/Source/WebKit/qt/Api/qwebelement.cpp >@@ -503,7 +503,7 @@ QStringList QWebElement::attributeNames(const QString& namespaceUri) const > return QStringList(); > > QStringList attributeNameList; >- const NamedNodeMap* const attrs = m_element->updatedAttributes(); >+ const ElementAttributeData* const attrs = m_element->updatedAttributeData(); > if (attrs) { > const String namespaceUriString(namespaceUri); // convert QString -> String once > const unsigned attrsCount = attrs->length();
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 77674
:
125170
|
125316
|
126495