diff options
Diffstat (limited to 'Source/WebCore/dom/ElementAttributeData.cpp')
-rw-r--r-- | Source/WebCore/dom/ElementAttributeData.cpp | 183 |
1 files changed, 98 insertions, 85 deletions
diff --git a/Source/WebCore/dom/ElementAttributeData.cpp b/Source/WebCore/dom/ElementAttributeData.cpp index 601c34b9b..cb8917a45 100644 --- a/Source/WebCore/dom/ElementAttributeData.cpp +++ b/Source/WebCore/dom/ElementAttributeData.cpp @@ -3,7 +3,7 @@ * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Peter Kelly (pmk@post.com) * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2010, 2012 Apple Inc. All rights reserved. * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). * * This library is free software; you can redistribute it and/or @@ -26,25 +26,53 @@ #include "config.h" #include "ElementAttributeData.h" +#include "Attr.h" +#include "CSSStyleSheet.h" #include "StyledElement.h" namespace WebCore { -void AttributeVector::removeAttribute(const QualifiedName& name) +typedef HashMap<pair<Element*, QualifiedName>, RefPtr<Attr> > AttrMap; +static AttrMap& attrMap() { - size_t index = getAttributeItemIndex(name); - if (index == notFound) - return; + DEFINE_STATIC_LOCAL(AttrMap, map, ()); + return map; +} + +PassRefPtr<Attr> ElementAttributeData::attrIfExists(Element* element, const QualifiedName& name) +{ + if (!m_attrCount) + return 0; + return attrMap().get(std::make_pair(element, name)).get(); +} + +PassRefPtr<Attr> ElementAttributeData::ensureAttr(Element* element, const QualifiedName& name) +{ + AttrMap::AddResult result = attrMap().add(std::make_pair(element, name), 0); + if (result.isNewEntry) { + result.iterator->second = Attr::create(element, name); + ++m_attrCount; + } + return result.iterator->second.get(); +} + +void ElementAttributeData::setAttr(Element* element, const QualifiedName& name, Attr* attr) +{ + ASSERT(!attrMap().contains(std::make_pair(element, name))); + attrMap().add(std::make_pair(element, name), attr); + attr->attachToElement(element); + ++m_attrCount; +} - RefPtr<Attribute> attribute = at(index); - if (Attr* attr = attribute->attr()) - attr->m_element = 0; - remove(index); +void ElementAttributeData::removeAttr(Element* element, const QualifiedName& name) +{ + ASSERT(attrMap().contains(std::make_pair(element, name))); + attrMap().remove(std::make_pair(element, name)); + --m_attrCount; } ElementAttributeData::~ElementAttributeData() { - detachAttributesFromElement(); } void ElementAttributeData::setClass(const String& className, bool shouldFoldCase) @@ -57,16 +85,15 @@ StylePropertySet* ElementAttributeData::ensureInlineStyle(StyledElement* element if (!m_inlineStyleDecl) { ASSERT(element->isStyledElement()); m_inlineStyleDecl = StylePropertySet::create(); - m_inlineStyleDecl->setStrictParsing(element->isHTMLElement() && !element->document()->inQuirksMode()); + m_inlineStyleDecl->setCSSParserMode(strictToCSSParserMode(element->isHTMLElement() && !element->document()->inQuirksMode())); } return m_inlineStyleDecl.get(); } StylePropertySet* ElementAttributeData::ensureMutableInlineStyle(StyledElement* element) { - if (m_inlineStyleDecl && !m_inlineStyleDecl->hasCSSOMWrapper()) { + if (m_inlineStyleDecl && !m_inlineStyleDecl->isMutable()) { m_inlineStyleDecl = m_inlineStyleDecl->copy(); - m_inlineStyleDecl->setStrictParsing(element->isHTMLElement() && !element->document()->inQuirksMode()); return m_inlineStyleDecl.get(); } return ensureInlineStyle(element); @@ -76,13 +103,13 @@ void ElementAttributeData::updateInlineStyleAvoidingMutation(StyledElement* elem { // We reconstruct the property set instead of mutating if there is no CSSOM wrapper. // This makes wrapperless property sets immutable and so cacheable. - if (m_inlineStyleDecl && !m_inlineStyleDecl->hasCSSOMWrapper()) + if (m_inlineStyleDecl && !m_inlineStyleDecl->isMutable()) m_inlineStyleDecl.clear(); if (!m_inlineStyleDecl) { m_inlineStyleDecl = StylePropertySet::create(); - m_inlineStyleDecl->setStrictParsing(element->isHTMLElement() && !element->document()->inQuirksMode()); + m_inlineStyleDecl->setCSSParserMode(strictToCSSParserMode(element->isHTMLElement() && !element->document()->inQuirksMode())); } - m_inlineStyleDecl->parseDeclaration(text, element->document()->elementSheet()); + m_inlineStyleDecl->parseDeclaration(text, element->document()->elementSheet()->internal()); } void ElementAttributeData::destroyInlineStyle(StyledElement* element) @@ -93,46 +120,34 @@ void ElementAttributeData::destroyInlineStyle(StyledElement* element) m_inlineStyleDecl = 0; } -void ElementAttributeData::addAttribute(PassRefPtr<Attribute> prpAttribute, Element* element) +void ElementAttributeData::addAttribute(const Attribute& attribute, Element* element, EInUpdateStyleAttribute inUpdateStyleAttribute) { - RefPtr<Attribute> attribute = prpAttribute; - - if (element) - element->willModifyAttribute(attribute->name(), nullAtom, attribute->value()); + if (element && inUpdateStyleAttribute == NotInUpdateStyleAttribute) + 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()); + if (element && inUpdateStyleAttribute == NotInUpdateStyleAttribute) + element->didAddAttribute(const_cast<Attribute*>(&attribute)); } -void ElementAttributeData::removeAttribute(size_t index, Element* element) +void ElementAttributeData::removeAttribute(size_t index, Element* element, EInUpdateStyleAttribute inUpdateStyleAttribute) { ASSERT(index < length()); - RefPtr<Attribute> attribute = m_attributes[index]; - - if (element) - element->willRemoveAttribute(attribute->name(), attribute->value()); + Attribute& attribute = m_attributes[index]; + QualifiedName name = attribute.name(); - if (Attr* attr = attribute->attr()) - attr->m_element = 0; - m_attributes.remove(index); + if (element && inUpdateStyleAttribute == NotInUpdateStyleAttribute) + element->willRemoveAttribute(name, attribute.value()); - if (element) - element->didRemoveAttribute(attribute.get()); -} + if (RefPtr<Attr> attr = attrIfExists(element, name)) + attr->detachFromElementWithValue(attribute.value()); -PassRefPtr<Attr> ElementAttributeData::takeAttribute(size_t index, Element* element) -{ - ASSERT(index < length()); - ASSERT(element); + m_attributes.remove(index); - RefPtr<Attr> attr = m_attributes[index]->createAttrIfNeeded(element); - removeAttribute(index, element); - return attr.release(); + if (element && inUpdateStyleAttribute == NotInUpdateStyleAttribute) + element->didRemoveAttribute(name); } bool ElementAttributeData::isEquivalent(const ElementAttributeData* other) const @@ -145,44 +160,37 @@ bool ElementAttributeData::isEquivalent(const ElementAttributeData* other) const 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()) + Attribute* otherAttr = other->getAttributeItem(m_attributes[i].name()); + if (!otherAttr || m_attributes[i].value() != otherAttr->value()) return false; } return true; } -void ElementAttributeData::detachAttributesFromElement() +void ElementAttributeData::detachAttributesFromElement(Element* element) { - 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; - } -} + if (!m_attrCount) + return; -void ElementAttributeData::copyAttributesToVector(Vector<RefPtr<Attribute> >& copy) -{ - copy = m_attributes; + for (unsigned i = 0; i < m_attributes.size(); ++i) { + if (RefPtr<Attr> attr = attrIfExists(element, m_attributes[i].name())) + attr->detachFromElementWithValue(m_attributes[i].value()); + } } 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())) + for (unsigned i = 0; i < m_attributes.size(); ++i) { + if (!m_attributes[i].name().hasPrefix()) { + if (shouldIgnoreAttributeCase && equalIgnoringCase(name, m_attributes[i].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)) + if (equalPossiblyIgnoringCase(name, m_attributes[i].name().toString(), shouldIgnoreAttributeCase)) return i; } } @@ -207,41 +215,46 @@ void ElementAttributeData::setAttributes(const ElementAttributeData& other, Elem if (oldName || newName) element->updateName(oldName ? oldName->value() : nullAtom, newName ? newName->value() : nullAtom); - clearAttributes(); - unsigned newLength = other.length(); - m_attributes.resize(newLength); - - // FIXME: These loops can probably be combined. - for (unsigned i = 0; i < newLength; i++) - m_attributes[i] = other.m_attributes[i]->clone(); - for (unsigned i = 0; i < newLength; i++) - element->attributeChanged(m_attributes[i].get()); + clearAttributes(element); + m_attributes = other.m_attributes; + for (unsigned i = 0; i < m_attributes.size(); ++i) + element->attributeChanged(&m_attributes[i]); } -void ElementAttributeData::clearAttributes() +void ElementAttributeData::clearAttributes(Element* element) { clearClass(); - detachAttributesFromElement(); + detachAttributesFromElement(element); m_attributes.clear(); } -void ElementAttributeData::replaceAttribute(size_t index, PassRefPtr<Attribute> prpAttribute, Element* element) +void ElementAttributeData::replaceAttribute(size_t index, const Attribute& attribute, Element* element) { ASSERT(element); ASSERT(index < length()); - RefPtr<Attribute> attribute = prpAttribute; - Attribute* old = m_attributes[index].get(); - - element->willModifyAttribute(attribute->name(), old->value(), attribute->value()); - - if (Attr* attr = old->attr()) - attr->m_element = 0; + element->willModifyAttribute(attribute.name(), m_attributes[index].value(), attribute.value()); m_attributes[index] = attribute; - if (Attr* attr = attribute->attr()) - attr->m_element = element; + element->didModifyAttribute(const_cast<Attribute*>(&attribute)); +} - element->didModifyAttribute(attribute.get()); +PassRefPtr<Attr> ElementAttributeData::getAttributeNode(const String& name, bool shouldIgnoreAttributeCase, Element* element) const +{ + ASSERT(element); + Attribute* attribute = getAttributeItem(name, shouldIgnoreAttributeCase); + if (!attribute) + return 0; + return const_cast<ElementAttributeData*>(this)->ensureAttr(element, attribute->name()); } +PassRefPtr<Attr> ElementAttributeData::getAttributeNode(const QualifiedName& name, Element* element) const +{ + ASSERT(element); + Attribute* attribute = getAttributeItem(name); + if (!attribute) + return 0; + return const_cast<ElementAttributeData*>(this)->ensureAttr(element, attribute->name()); +} + + } |