summaryrefslogtreecommitdiff
path: root/Source/WebCore/dom/Element.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-03-12 14:11:15 +0100
committerSimon Hausmann <simon.hausmann@nokia.com>2012-03-12 14:11:15 +0100
commitdd91e772430dc294e3bf478c119ef8d43c0a3358 (patch)
tree6f33ce4d5872a5691e0291eb45bf6ab373a5f567 /Source/WebCore/dom/Element.cpp
parentad0d549d4cc13433f77c1ac8f0ab379c83d93f28 (diff)
downloadqtwebkit-dd91e772430dc294e3bf478c119ef8d43c0a3358.tar.gz
Imported WebKit commit 3db4eb1820ac8fb03065d7ea73a4d9db1e8fea1a (http://svn.webkit.org/repository/webkit/trunk@110422)
This includes build fixes for the latest qtbase/qtdeclarative as well as the final QML2 API.
Diffstat (limited to 'Source/WebCore/dom/Element.cpp')
-rw-r--r--Source/WebCore/dom/Element.cpp395
1 files changed, 194 insertions, 201 deletions
diff --git a/Source/WebCore/dom/Element.cpp b/Source/WebCore/dom/Element.cpp
index 1b4d839db..cdb17b6b4 100644
--- a/Source/WebCore/dom/Element.cpp
+++ b/Source/WebCore/dom/Element.cpp
@@ -52,6 +52,7 @@
#include "InspectorInstrumentation.h"
#include "MutationObserverInterestGroup.h"
#include "MutationRecord.h"
+#include "NamedNodeMap.h"
#include "NodeList.h"
#include "NodeRenderStyle.h"
#include "NodeRenderingContext.h"
@@ -60,6 +61,7 @@
#include "RenderRegion.h"
#include "RenderView.h"
#include "RenderWidget.h"
+#include "RuntimeEnabledFeatures.h"
#include "Settings.h"
#include "ShadowRoot.h"
#include "Text.h"
@@ -93,7 +95,7 @@ public:
if (m_pushedStyleSelector)
return;
m_pushedStyleSelector = m_parent->document()->styleSelector();
- m_pushedStyleSelector->pushParent(m_parent);
+ m_pushedStyleSelector->pushParentElement(m_parent);
}
~StyleSelectorParentPusher()
{
@@ -107,7 +109,7 @@ public:
if (m_pushedStyleSelector != m_parent->document()->styleSelector())
return;
- m_pushedStyleSelector->popParent(m_parent);
+ m_pushedStyleSelector->popParentElement(m_parent);
}
private:
@@ -122,9 +124,10 @@ PassRefPtr<Element> Element::create(const QualifiedName& tagName, Document* docu
Element::~Element()
{
- removeShadowRoot();
- if (m_attributeMap)
- m_attributeMap->detachFromElement();
+ if (shadowTree())
+ rareData()->m_shadowTree.clear();
+ if (m_attributeData)
+ m_attributeData->clearAttributes();
}
inline ElementRareData* Element::rareData() const
@@ -184,10 +187,9 @@ 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)
@@ -198,6 +200,17 @@ void Element::setBooleanAttribute(const QualifiedName& name, bool value)
removeAttribute(name);
}
+NamedNodeMap* Element::attributes() const
+{
+ ensureUpdatedAttributeData();
+ ElementRareData* rareData = const_cast<Element*>(this)->ensureRareData();
+ if (NamedNodeMap* attributeMap = rareData->m_attributeMap.get())
+ return attributeMap;
+
+ rareData->m_attributeMap = NamedNodeMap::create(const_cast<Element*>(this));
+ return rareData->m_attributeMap.get();
+}
+
Node::NodeType Element::nodeType() const
{
return ELEMENT_NODE;
@@ -218,8 +231,8 @@ const AtomicString& Element::getAttribute(const QualifiedName& name) const
updateAnimatedSVGAttribute(name);
#endif
- if (m_attributeMap) {
- if (Attribute* attribute = m_attributeMap->getAttributeItem(name))
+ if (m_attributeData) {
+ if (Attribute* attribute = getAttributeItem(name))
return attribute->value();
}
return nullAtom;
@@ -595,8 +608,8 @@ const AtomicString& Element::getAttribute(const String& name) const
}
#endif
- if (m_attributeMap) {
- if (Attribute* attribute = m_attributeMap->getAttributeItem(name, ignoreCase))
+ if (m_attributeData) {
+ if (Attribute* attribute = m_attributeData->getAttributeItem(name, ignoreCase))
return attribute->value();
}
@@ -622,38 +635,41 @@ void Element::setAttribute(const AtomicString& name, const AtomicString& value,
setAttributeInternal(index, qName, value);
}
-void Element::setAttribute(const QualifiedName& name, const AtomicString& value)
+void Element::setAttribute(const QualifiedName& name, const AtomicString& value, bool notifyChanged)
{
- setAttributeInternal(ensureUpdatedAttributeData()->getAttributeItemIndex(name), name, value);
+ setAttributeInternal(ensureUpdatedAttributeData()->getAttributeItemIndex(name), name, value, notifyChanged);
}
-inline void Element::setAttributeInternal(size_t index, const QualifiedName& name, const AtomicString& value)
+inline void Element::setAttributeInternal(size_t index, const QualifiedName& name, const AtomicString& value, bool notifyChanged)
{
- ElementAttributeData* attributeData = &m_attributeMap->m_attributeData;
- Attribute* old = index != notFound ? attributeData->attributeItem(index) : 0;
+ Attribute* old = index != notFound ? m_attributeData->attributeItem(index) : 0;
if (value.isNull()) {
if (old)
- attributeData->removeAttribute(index, this);
+ m_attributeData->removeAttribute(index, this);
return;
}
if (!old) {
- attributeData->addAttribute(Attribute::create(name, value), this);
+ m_attributeData->addAttribute(Attribute::create(name, value), this);
return;
}
- willModifyAttribute(name, old ? old->value() : nullAtom, value);
+ if (notifyChanged)
+ willModifyAttribute(name, old ? old->value() : nullAtom, value);
if (Attr* attrNode = old->attr())
attrNode->setValue(value);
else
old->setValue(value);
- didModifyAttribute(old);
+ if (notifyChanged)
+ didModifyAttribute(old);
}
void Element::attributeChanged(Attribute* attr)
{
+ document()->incDOMTreeVersion();
+
if (isIdAttributeName(attr->name()))
idAttributeChanged(attr);
else if (attr->name() == HTMLNames::nameAttr)
@@ -723,48 +739,59 @@ 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::parserSetAttributes(PassOwnPtr<AttributeVector> attributeVector, FragmentScriptingPermission scriptingPermission)
{
ASSERT(!inDocument());
ASSERT(!parentNode());
- document()->incDOMTreeVersion();
+ ASSERT(!m_attributeData);
+
+ if (!attributeVector)
+ return;
- ASSERT(!m_attributeMap);
- m_attributeMap = list;
-
- if (m_attributeMap) {
- ElementAttributeData* attributeData = &m_attributeMap->m_attributeData;
- 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 = 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++;
+ createAttributeData();
+ m_attributeData->m_attributes.swap(*attributeVector);
+
+ // 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_attributeData->length()) {
+ const QualifiedName& attributeName = m_attributeData->m_attributes[i]->name();
+ if (isEventHandlerAttribute(attributeName)) {
+ m_attributeData->m_attributes.remove(i);
+ continue;
}
+
+ if (isAttributeToRemove(attributeName, m_attributeData->m_attributes[i]->value()))
+ m_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;
- attributeData->copyAttributesToVector(attributes);
- for (Vector<RefPtr<Attribute> >::iterator iter = attributes.begin(); iter != attributes.end(); ++iter)
- attributeChanged(iter->get());
}
+
+ // Store the set of attributes that changed on the stack in case
+ // attributeChanged mutates m_attributeData.
+ Vector<RefPtr<Attribute> > attributes;
+ m_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 m_attributeData && m_attributeData->length();
+}
+
+bool Element::hasEquivalentAttributes(const Element* other) const
+{
+ ElementAttributeData* attributeData = updatedAttributeData();
+ ElementAttributeData* otherAttributeData = other->updatedAttributeData();
+ if (attributeData)
+ return attributeData->isEquivalent(otherAttributeData);
+ if (otherAttributeData)
+ return otherAttributeData->isEquivalent(attributeData);
+ return true;
}
String Element::nodeName() const
@@ -805,9 +832,9 @@ KURL Element::baseURI() const
return KURL(parentBase, baseAttribute);
}
-void Element::createAttributeMap() const
+void Element::createAttributeData() const
{
- m_attributeMap = NamedNodeMap::create(const_cast<Element*>(this));
+ m_attributeData = ElementAttributeData::create();
}
bool Element::isURLAttribute(Attribute*) const
@@ -847,8 +874,8 @@ void Element::willRemove()
if (containsFullScreenElement())
setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false);
#endif
- if (ShadowRootList* shadowRoots = shadowRootList())
- shadowRoots->willRemove();
+ if (ShadowTree* tree = shadowTree())
+ tree->willRemove();
ContainerNode::willRemove();
}
@@ -857,17 +884,17 @@ void Element::insertedIntoDocument()
// need to do superclass processing first so inDocument() is true
// by the time we reach updateId
ContainerNode::insertedIntoDocument();
- if (ShadowRootList* shadowRoots = shadowRootList())
- shadowRoots->insertedIntoDocument();
+ if (ShadowTree* tree = shadowTree())
+ tree->insertedIntoDocument();
- if (m_attributeMap) {
+ if (m_attributeData) {
if (hasID()) {
- Attribute* idItem = m_attributeMap->getAttributeItem(document()->idAttributeName());
+ Attribute* idItem = getAttributeItem(document()->idAttributeName());
if (idItem && !idItem->isNull())
updateId(nullAtom, idItem->value());
}
if (hasName()) {
- Attribute* nameItem = m_attributeMap->getAttributeItem(HTMLNames::nameAttr);
+ Attribute* nameItem = getAttributeItem(HTMLNames::nameAttr);
if (nameItem && !nameItem->isNull())
updateName(nullAtom, nameItem->value());
}
@@ -876,22 +903,22 @@ void Element::insertedIntoDocument()
void Element::removedFromDocument()
{
- if (m_attributeMap) {
+ if (m_attributeData) {
if (hasID()) {
- Attribute* idItem = m_attributeMap->getAttributeItem(document()->idAttributeName());
+ Attribute* idItem = getAttributeItem(document()->idAttributeName());
if (idItem && !idItem->isNull())
updateId(idItem->value(), nullAtom);
}
if (hasName()) {
- Attribute* nameItem = m_attributeMap->getAttributeItem(HTMLNames::nameAttr);
+ Attribute* nameItem = getAttributeItem(HTMLNames::nameAttr);
if (nameItem && !nameItem->isNull())
updateName(nameItem->value(), nullAtom);
}
}
ContainerNode::removedFromDocument();
- if (ShadowRootList* shadowRoots = shadowRootList())
- shadowRoots->removedFromDocument();
+ if (ShadowTree* tree = shadowTree())
+ tree->removedFromDocument();
}
void Element::insertedIntoTree(bool deep)
@@ -899,8 +926,8 @@ void Element::insertedIntoTree(bool deep)
ContainerNode::insertedIntoTree(deep);
if (!deep)
return;
- if (ShadowRootList* shadowRoots = shadowRootList())
- shadowRoots->insertedIntoTree(true);
+ if (ShadowTree* tree = shadowTree())
+ tree->insertedIntoTree(true);
#if ENABLE(FULLSCREEN_API)
if (containsFullScreenElement() && parentElement() && !parentElement()->containsFullScreenElement())
@@ -913,8 +940,8 @@ void Element::removedFromTree(bool deep)
ContainerNode::removedFromTree(deep);
if (!deep)
return;
- if (ShadowRootList* shadowRoots = shadowRootList())
- shadowRoots->removedFromTree(true);
+ if (ShadowTree* tree = shadowTree())
+ tree->removedFromTree(true);
}
void Element::attach()
@@ -926,18 +953,9 @@ void Element::attach()
StyleSelectorParentPusher parentPusher(this);
// When a shadow root exists, it does the work of attaching the children.
- if (hasShadowRoot()) {
+ if (ShadowTree* tree = shadowTree()) {
parentPusher.push();
- shadowRootList()->attach();
-
- // In a shadow tree, some of light children may be attached by 'content' element.
- // However, when there is no content element or content element does not select
- // all light children, we have to attach the rest of light children here.
- for (Node* child = firstChild(); child; child = child->nextSibling()) {
- if (!child->attached())
- child->attach();
- }
- Node::attach();
+ tree->attachHost(this);
} else {
if (firstChild())
parentPusher.push();
@@ -964,9 +982,11 @@ void Element::detach()
cancelFocusAppearanceUpdate();
if (hasRareData())
rareData()->resetComputedStyle();
- ContainerNode::detach();
- if (ShadowRootList* shadowRoots = shadowRootList())
- shadowRoots->detach();
+
+ if (ShadowTree* tree = shadowTree())
+ tree->detachHost(this);
+ else
+ ContainerNode::detach();
RenderWidget::resumeWidgetHierarchyUpdates();
}
@@ -1089,12 +1109,16 @@ void Element::recalcStyle(StyleChange change)
} else if (styleChangeType() == SyntheticStyleChange)
setRenderStyle(newStyle);
+ // If "rem" units are used anywhere in the document, and if the document element's font size changes, then go ahead and force font updating
+ // all the way down the tree. This is simpler than having to maintain a cache of objects (and such font size changes should be rare anyway).
+ if (document()->usesRemUnits() && document()->documentElement() == this && ch != NoChange && currentStyle && newStyle && currentStyle->fontSize() != newStyle->fontSize()) {
+ // Cached RenderStyles may depend on the rem units.
+ document()->styleSelector()->invalidateMatchedPropertiesCache();
+ change = Force;
+ }
+
if (change != Force) {
- // If "rem" units are used anywhere in the document, and if the document element's font size changes, then go ahead and force font updating
- // all the way down the tree. This is simpler than having to maintain a cache of objects (and such font size changes should be rare anyway).
- if (document()->usesRemUnits() && ch != NoChange && currentStyle && newStyle && currentStyle->fontSize() != newStyle->fontSize() && document()->documentElement() == this)
- change = Force;
- else if (styleChangeType() >= FullStyleChange)
+ if (styleChangeType() >= FullStyleChange)
change = Force;
else
change = ch;
@@ -1126,10 +1150,10 @@ void Element::recalcStyle(StyleChange change)
}
// FIXME: This does not care about sibling combinators. Will be necessary in XBL2 world.
if (hasShadowRoot()) {
- ShadowRootList* list = shadowRootList();
- if (change >= Inherit || list->childNeedsStyleRecalc() || list->needsStyleRecalc()) {
+ ShadowTree* tree = shadowTree();
+ if (change >= Inherit || tree->childNeedsStyleRecalc() || tree->needsStyleRecalc()) {
parentPusher.push();
- list->recalcShadowTreeStyle(change);
+ tree->recalcShadowTreeStyle(change);
}
}
@@ -1142,93 +1166,36 @@ void Element::recalcStyle(StyleChange change)
bool Element::hasShadowRoot() const
{
- if (ShadowRootList* list = shadowRootList())
- return list->hasShadowRoot();
+ if (ShadowTree* tree = shadowTree())
+ return tree->hasShadowRoot();
return false;
}
-ShadowRootList* Element::shadowRootList() const
+ShadowTree* Element::shadowTree() const
{
if (!hasRareData())
return 0;
- return &rareData()->m_shadowRootList;
+ return rareData()->m_shadowTree.get();
}
-static bool validateShadowRoot(Document* document, ShadowRoot* shadowRoot, ExceptionCode& ec)
+ShadowTree* Element::ensureShadowTree()
{
- if (!shadowRoot)
- return true;
-
- if (shadowRoot->shadowHost()) {
- ec = HIERARCHY_REQUEST_ERR;
- return false;
- }
-
- if (shadowRoot->document() != document) {
- ec = WRONG_DOCUMENT_ERR;
- return false;
- }
+ if (ShadowTree* tree = ensureRareData()->m_shadowTree.get())
+ return tree;
- return true;
-}
-
-void Element::setShadowRoot(PassRefPtr<ShadowRoot> shadowRoot, ExceptionCode& ec)
-{
- if (!validateShadowRoot(document(), shadowRoot.get(), ec))
- return;
-
- if (!hasRareData())
- ensureRareData();
-
- removeShadowRoot();
-
- shadowRoot->setShadowHost(this);
- shadowRootList()->pushShadowRoot(shadowRoot.get());
-
- if (inDocument())
- shadowRoot->insertedIntoDocument();
- if (attached()) {
- shadowRoot->lazyAttach();
- for (Node* child = firstChild(); child; child = child->nextSibling())
- child->detach();
- }
+ rareData()->m_shadowTree = adoptPtr(new ShadowTree());
+ return rareData()->m_shadowTree.get();
}
ShadowRoot* Element::ensureShadowRoot()
{
if (hasShadowRoot())
- return shadowRootList()->oldestShadowRoot();
+ return shadowTree()->oldestShadowRoot();
return ShadowRoot::create(this, ShadowRoot::CreatingUserAgentShadowRoot).get();
}
-void Element::removeShadowRoot()
-{
- if (!hasShadowRoot())
- return;
-
- while (RefPtr<ShadowRoot> oldRoot = shadowRootList()->popShadowRoot()) {
- document()->removeFocusedNodeOfSubtree(oldRoot.get());
-
- if (oldRoot->attached())
- oldRoot->detach();
-
- oldRoot->setShadowHost(0);
- document()->adoptIfNeeded(oldRoot.get());
- if (oldRoot->inDocument())
- oldRoot->removedFromDocument();
- else
- oldRoot->removedFromTree(true);
- if (attached()) {
- for (Node* child = firstChild(); child; child = child->nextSibling()) {
- if (!child->attached())
- child->lazyAttach();
- }
- }
- }
-}
-
const AtomicString& Element::shadowPseudoId() const
{
return hasRareData() ? rareData()->m_shadowPseudoId : nullAtom;
@@ -1275,6 +1242,9 @@ static void checkForEmptyStyleChange(Element* element, RenderStyle* style)
static void checkForSiblingStyleChanges(Element* e, RenderStyle* style, bool finishedParsingCallback,
Node* beforeChange, Node* afterChange, int childCountDelta)
{
+ // :empty selector.
+ checkForEmptyStyleChange(e, style);
+
if (!style || (e->needsStyleRecalc() && style->childrenAffectedByPositionalRules()))
return;
@@ -1346,9 +1316,6 @@ static void checkForSiblingStyleChanges(Element* e, RenderStyle* style, bool fin
if ((style->childrenAffectedByForwardPositionalRules() && afterChange) ||
(style->childrenAffectedByBackwardPositionalRules() && beforeChange))
e->setNeedsStyleRecalc();
-
- // :empty selector.
- checkForEmptyStyleChange(e, style);
}
void Element::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
@@ -1361,7 +1328,7 @@ void Element::childrenChanged(bool changedByParser, Node* beforeChange, Node* af
if (hasRareData()) {
if (hasShadowRoot())
- shadowRootList()->hostChildrenChanged();
+ shadowTree()->hostChildrenChanged();
}
}
@@ -1370,7 +1337,7 @@ void Element::beginParsingChildren()
clearIsParsingChildrenFinished();
CSSStyleSelector* styleSelector = document()->styleSelectorIfExists();
if (styleSelector && attached())
- styleSelector->pushParent(this);
+ styleSelector->pushParentElement(this);
}
void Element::finishParsingChildren()
@@ -1379,7 +1346,7 @@ void Element::finishParsingChildren()
setIsParsingChildrenFinished();
checkForSiblingStyleChanges(this, renderStyle(), true, lastChild(), 0, 0);
if (CSSStyleSelector* styleSelector = document()->styleSelectorIfExists())
- styleSelector->popParent(this);
+ styleSelector->popParentElement(this);
}
#ifndef NDEBUG
@@ -1419,16 +1386,34 @@ PassRefPtr<Attr> Element::setAttributeNode(Attr* attr, ExceptionCode& ec)
ec = TYPE_MISMATCH_ERR;
return 0;
}
- return static_pointer_cast<Attr>(ensureUpdatedAttributes()->setNamedItem(attr, ec));
+
+ ElementAttributeData* attributeData = ensureUpdatedAttributeData();
+ Attribute* attribute = attr->attr();
+ size_t index = attributeData->getAttributeItemIndex(attribute->name());
+ Attribute* oldAttribute = index != notFound ? attributeData->attributeItem(index) : 0;
+ if (oldAttribute == attribute)
+ return attr; // 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(this);
+ attributeData->replaceAttribute(index, attribute, this);
+ } else
+ attributeData->addAttribute(attribute, this);
+
+ return oldAttr.release();
}
PassRefPtr<Attr> Element::setAttributeNodeNS(Attr* attr, ExceptionCode& ec)
{
- if (!attr) {
- ec = TYPE_MISMATCH_ERR;
- return 0;
- }
- return static_pointer_cast<Attr>(ensureUpdatedAttributes()->setNamedItem(attr, ec));
+ return setAttributeNode(attr, ec);
}
PassRefPtr<Attr> Element::removeAttributeNode(Attr* attr, ExceptionCode& ec)
@@ -1444,11 +1429,17 @@ PassRefPtr<Attr> Element::removeAttributeNode(Attr* attr, ExceptionCode& ec)
ASSERT(document() == attr->document());
- NamedNodeMap* attrs = updatedAttributes();
- if (!attrs)
+ ElementAttributeData* attributeData = updatedAttributeData();
+ if (!attributeData)
return 0;
- return static_pointer_cast<Attr>(attrs->removeNamedItem(attr->qualifiedName(), ec));
+ size_t index = attributeData->getAttributeItemIndex(attr->qualifiedName());
+ if (index == notFound) {
+ ec = NOT_FOUND_ERR;
+ return 0;
+ }
+
+ return attributeData->takeAttribute(index, this);
}
void Element::setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode& ec, FragmentScriptingPermission scriptingPermission)
@@ -1491,19 +1482,18 @@ void Element::removeAttributeNS(const String& namespaceURI, const String& localN
PassRefPtr<Attr> Element::getAttributeNode(const String& name)
{
- NamedNodeMap* attrs = updatedAttributes();
- if (!attrs)
+ ElementAttributeData* attributeData = updatedAttributeData();
+ if (!attributeData)
return 0;
- String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
- return static_pointer_cast<Attr>(attrs->getNamedItem(localName));
+ return attributeData->getAttributeNode(name, shouldIgnoreAttributeCase(this), this);
}
PassRefPtr<Attr> Element::getAttributeNodeNS(const String& namespaceURI, const String& localName)
{
- NamedNodeMap* attrs = updatedAttributes();
- if (!attrs)
+ ElementAttributeData* attributeData = updatedAttributeData();
+ if (!attributeData)
return 0;
- return static_pointer_cast<Attr>(attrs->getNamedItem(QualifiedName(nullAtom, localName, namespaceURI)));
+ return attributeData->getAttributeNode(QualifiedName(nullAtom, localName, namespaceURI), this);
}
bool Element::hasAttribute(const String& name) const
@@ -1653,8 +1643,13 @@ RenderStyle* Element::computedStyle(PseudoId pseudoElementSpecifier)
// FIXME: Find and use the renderer from the pseudo element instead of the actual element so that the 'length'
// properties, which are only known by the renderer because it did the layout, will be correct and so that the
// values returned for the ":selection" pseudo-element will be correct.
- if (RenderStyle* usedStyle = renderStyle())
- return pseudoElementSpecifier ? usedStyle->getCachedPseudoStyle(pseudoElementSpecifier) : usedStyle;
+ if (RenderStyle* usedStyle = renderStyle()) {
+ if (pseudoElementSpecifier) {
+ RenderStyle* cachedPseudoStyle = usedStyle->getCachedPseudoStyle(pseudoElementSpecifier);
+ return cachedPseudoStyle ? cachedPseudoStyle : usedStyle;
+ } else
+ return usedStyle;
+ }
if (!attached())
// FIXME: Try to do better than this. Ensure that styleForElement() works for elements that are not in the
@@ -1807,8 +1802,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 (m_attributeData) {
+ if (Attribute* attribute = getAttributeItem(name))
ASSERT(isURLAttribute(attribute));
}
#endif
@@ -1818,8 +1813,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 (m_attributeData) {
+ if (Attribute* attribute = getAttributeItem(name))
ASSERT(isURLAttribute(attribute));
}
#endif
@@ -1986,25 +1981,27 @@ bool Element::fastAttributeLookupAllowed(const QualifiedName& name) const
}
#endif
-void Element::willModifyAttribute(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue)
+#ifdef DUMP_NODE_STATISTICS
+bool Element::hasNamedNodeMap() const
{
- document()->incDOMTreeVersion();
+ return hasRareData() && rareData()->m_attributeMap;
+}
+#endif
+void Element::willModifyAttribute(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue)
+{
if (isIdAttributeName(name))
updateId(oldValue, newValue);
else if (name == HTMLNames::nameAttr)
updateName(oldValue, newValue);
#if ENABLE(MUTATION_OBSERVERS)
- if (!isSynchronizingStyleAttribute()) {
- if (OwnPtr<MutationObserverInterestGroup> recipients = MutationObserverInterestGroup::createForAttributesMutation(this, name))
- recipients->enqueueMutationRecord(MutationRecord::createAttributes(this, name, oldValue));
- }
+ if (OwnPtr<MutationObserverInterestGroup> recipients = MutationObserverInterestGroup::createForAttributesMutation(this, name))
+ recipients->enqueueMutationRecord(MutationRecord::createAttributes(this, name, oldValue));
#endif
#if ENABLE(INSPECTOR)
- if (!isSynchronizingStyleAttribute())
- InspectorInstrumentation::willModifyDOMAttr(document(), this, oldValue, newValue);
+ InspectorInstrumentation::willModifyDOMAttr(document(), this, oldValue, newValue);
#endif
}
@@ -2012,10 +2009,8 @@ void Element::didModifyAttribute(Attribute* attr)
{
attributeChanged(attr);
- if (!isSynchronizingStyleAttribute()) {
- InspectorInstrumentation::didModifyDOMAttr(document(), this, attr->name().localName(), attr->value());
- dispatchSubtreeModifiedEvent();
- }
+ InspectorInstrumentation::didModifyDOMAttr(document(), this, attr->name().localName(), attr->value());
+ dispatchSubtreeModifiedEvent();
}
void Element::didRemoveAttribute(Attribute* attr)
@@ -2028,10 +2023,8 @@ void Element::didRemoveAttribute(Attribute* attr)
attributeChanged(attr);
attr->setValue(savedValue);
- if (!isSynchronizingStyleAttribute()) {
- InspectorInstrumentation::didRemoveDOMAttr(document(), this, attr->name().localName());
- dispatchSubtreeModifiedEvent();
- }
+ InspectorInstrumentation::didRemoveDOMAttr(document(), this, attr->name().localName());
+ dispatchSubtreeModifiedEvent();
}