summaryrefslogtreecommitdiff
path: root/Source/WebCore/dom/Element.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-07-30 11:37:48 +0200
committerSimon Hausmann <simon.hausmann@nokia.com>2012-07-30 11:38:52 +0200
commit89e2486a48b739f8d771d69ede5a6a1b244a10fc (patch)
tree503b1a7812cf97d93704c32437eb5f62dc1a1ff9 /Source/WebCore/dom/Element.cpp
parent625f028249cb37c55bbbd153f3902afd0b0756d9 (diff)
downloadqtwebkit-89e2486a48b739f8d771d69ede5a6a1b244a10fc.tar.gz
Imported WebKit commit 0282df8ca7c11d8c8a66ea18543695c69f545a27 (http://svn.webkit.org/repository/webkit/trunk@124002)
New snapshot with prospective Mountain Lion build fix
Diffstat (limited to 'Source/WebCore/dom/Element.cpp')
-rw-r--r--Source/WebCore/dom/Element.cpp204
1 files changed, 140 insertions, 64 deletions
diff --git a/Source/WebCore/dom/Element.cpp b/Source/WebCore/dom/Element.cpp
index 3499447ed..c323fa10d 100644
--- a/Source/WebCore/dom/Element.cpp
+++ b/Source/WebCore/dom/Element.cpp
@@ -201,7 +201,7 @@ PassRefPtr<Attr> Element::detachAttribute(size_t index)
{
ASSERT(attributeData());
- Attribute* attribute = attributeData()->attributeItem(index);
+ const Attribute* attribute = attributeData()->attributeItem(index);
ASSERT(attribute);
RefPtr<Attr> attr = attrIfExists(attribute->name());
@@ -210,7 +210,7 @@ PassRefPtr<Attr> Element::detachAttribute(size_t index)
else
attr = Attr::create(document(), attribute->name(), attribute->value());
- attributeData()->removeAttribute(index, this);
+ mutableAttributeData()->removeAttribute(index, this);
return attr.release();
}
@@ -222,7 +222,11 @@ void Element::removeAttribute(const QualifiedName& name)
if (RefPtr<Attr> attr = attrIfExists(name))
attr->detachFromElementWithValue(attr->value());
- attributeData()->removeAttribute(name, this);
+ size_t index = attributeData()->getAttributeItemIndex(name);
+ if (index == notFound)
+ return;
+
+ mutableAttributeData()->removeAttribute(index, this);
}
void Element::setBooleanAttribute(const QualifiedName& name, bool value)
@@ -264,8 +268,8 @@ const AtomicString& Element::getAttribute(const QualifiedName& name) const
updateAnimatedSVGAttribute(name);
#endif
- if (m_attributeData) {
- if (Attribute* attribute = getAttributeItem(name))
+ if (attributeData()) {
+ if (const Attribute* attribute = getAttributeItem(name))
return attribute->value();
}
return nullAtom;
@@ -412,8 +416,12 @@ int Element::clientLeft()
{
document()->updateLayoutIgnorePendingStylesheets();
- if (RenderBox* renderer = renderBox())
- return adjustForAbsoluteZoom(roundToInt(renderer->clientLeft()), renderer);
+ if (RenderBox* renderer = renderBox()) {
+ LayoutUnit clientLeft = renderer->clientLeft();
+ if (renderer->style() && renderer->style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
+ clientLeft += renderer->verticalScrollbarWidth();
+ return adjustForAbsoluteZoom(roundToInt(clientLeft), renderer);
+ }
return 0;
}
@@ -624,15 +632,15 @@ const AtomicString& Element::getAttribute(const AtomicString& name) const
}
#endif
- if (m_attributeData) {
- if (Attribute* attribute = m_attributeData->getAttributeItem(name, ignoreCase))
+ if (attributeData()) {
+ if (const Attribute* attribute = attributeData()->getAttributeItem(name, ignoreCase))
return attribute->value();
}
return nullAtom;
}
-const AtomicString& Element::getAttributeNS(const String& namespaceURI, const String& localName) const
+const AtomicString& Element::getAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const
{
return getAttribute(QualifiedName(nullAtom, localName, namespaceURI));
}
@@ -658,15 +666,17 @@ void Element::setAttribute(const QualifiedName& name, const AtomicString& value,
inline void Element::setAttributeInternal(size_t index, const QualifiedName& name, const AtomicString& value, EInUpdateStyleAttribute inUpdateStyleAttribute)
{
- Attribute* old = index != notFound ? m_attributeData->attributeItem(index) : 0;
+ ElementAttributeData* attributeData = mutableAttributeData();
+
+ Attribute* old = index != notFound ? attributeData->attributeItem(index) : 0;
if (value.isNull()) {
if (old)
- m_attributeData->removeAttribute(index, this, inUpdateStyleAttribute);
+ attributeData->removeAttribute(index, this, inUpdateStyleAttribute);
return;
}
if (!old) {
- m_attributeData->addAttribute(Attribute(name, value), this, inUpdateStyleAttribute);
+ attributeData->addAttribute(Attribute(name, value), this, inUpdateStyleAttribute);
return;
}
@@ -760,44 +770,44 @@ void Element::parserSetAttributes(const Vector<Attribute>& attributeVector, Frag
if (attributeVector.isEmpty())
return;
- createAttributeData();
- m_attributeData->m_attributes = attributeVector;
- m_attributeData->m_attributes.shrinkToFit();
+ Vector<Attribute> filteredAttributes = 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 == DisallowScriptingContent) {
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);
+ while (i < filteredAttributes.size()) {
+ Attribute& attribute = filteredAttributes[i];
+ if (isEventHandlerAttribute(attribute.name())) {
+ filteredAttributes.remove(i);
continue;
}
- if (isAttributeToRemove(attributeName, m_attributeData->m_attributes[i].value()))
- m_attributeData->m_attributes[i].setValue(nullAtom);
+ if (isAttributeToRemove(attribute.name(), attribute.value()))
+ attribute.setValue(emptyAtom);
i++;
}
}
- // Store the set of attributes that changed on the stack in case
+ m_attributeData = ElementAttributeData::createImmutable(filteredAttributes);
+
+ // Iterate over the set of attributes we already have on the stack in case
// attributeChanged mutates m_attributeData.
- Vector<Attribute> clonedAttributes = m_attributeData->clonedAttributeVector();
- for (unsigned i = 0; i < clonedAttributes.size(); ++i)
- attributeChanged(clonedAttributes[i]);
+ // FIXME: Find a way so we don't have to do this.
+ for (unsigned i = 0; i < filteredAttributes.size(); ++i)
+ attributeChanged(filteredAttributes[i]);
}
bool Element::hasAttributes() const
{
updateInvalidAttributes();
- return m_attributeData && m_attributeData->length();
+ return attributeData() && attributeData()->length();
}
bool Element::hasEquivalentAttributes(const Element* other) const
{
- ElementAttributeData* attributeData = updatedAttributeData();
- ElementAttributeData* otherAttributeData = other->updatedAttributeData();
+ const ElementAttributeData* attributeData = updatedAttributeData();
+ const ElementAttributeData* otherAttributeData = other->updatedAttributeData();
if (attributeData)
return attributeData->isEquivalent(otherAttributeData);
if (otherAttributeData)
@@ -843,11 +853,6 @@ KURL Element::baseURI() const
return KURL(parentBase, baseAttribute);
}
-void Element::createAttributeData() const
-{
- m_attributeData = ElementAttributeData::create();
-}
-
const QualifiedName& Element::imageSourceAttributeName() const
{
return srcAttr;
@@ -1394,8 +1399,6 @@ PassRefPtr<Attr> Element::setAttributeNode(Attr* attr, ExceptionCode& ec)
return 0;
}
- ElementAttributeData* attributeData = ensureUpdatedAttributeData();
-
RefPtr<Attr> oldAttr = attrIfExists(attr->qualifiedName());
if (oldAttr.get() == attr)
return attr; // This Attr is already attached to the element.
@@ -1407,6 +1410,9 @@ PassRefPtr<Attr> Element::setAttributeNode(Attr* attr, ExceptionCode& ec)
return 0;
}
+ updateInvalidAttributes();
+ ElementAttributeData* attributeData = mutableAttributeData();
+
size_t index = attributeData->getAttributeItemIndex(attr->qualifiedName());
Attribute* oldAttribute = index != notFound ? attributeData->attributeItem(index) : 0;
@@ -1444,7 +1450,7 @@ PassRefPtr<Attr> Element::removeAttributeNode(Attr* attr, ExceptionCode& ec)
ASSERT(document() == attr->document());
- ElementAttributeData* attributeData = updatedAttributeData();
+ const ElementAttributeData* attributeData = updatedAttributeData();
ASSERT(attributeData);
size_t index = attributeData->getAttributeItemIndex(attr->qualifiedName());
@@ -1456,44 +1462,50 @@ PassRefPtr<Attr> Element::removeAttributeNode(Attr* attr, ExceptionCode& ec)
return detachAttribute(index);
}
-void Element::setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode& ec, FragmentScriptingPermission scriptingPermission)
+bool Element::parseAttributeName(QualifiedName& out, const AtomicString& namespaceURI, const AtomicString& qualifiedName, ExceptionCode& ec)
{
String prefix, localName;
if (!Document::parseQualifiedName(qualifiedName, prefix, localName, ec))
- return;
+ return false;
+ ASSERT(!ec);
QualifiedName qName(prefix, localName, namespaceURI);
if (!Document::hasValidNamespaceForAttributes(qName)) {
ec = NAMESPACE_ERR;
- return;
+ return false;
}
- if (scriptingPermission == DisallowScriptingContent && (isEventHandlerAttribute(qName) || isAttributeToRemove(qName, value)))
- return;
+ out = qName;
+ return true;
+}
- setAttribute(qName, value);
+void Element::setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode& ec)
+{
+ QualifiedName parsedName = anyName;
+ if (!parseAttributeName(parsedName, namespaceURI, qualifiedName, ec))
+ return;
+ setAttribute(parsedName, value);
}
void Element::removeAttribute(size_t index)
{
ASSERT(attributeData());
ASSERT(index <= attributeCount());
- attributeData()->removeAttribute(index, this);
+ mutableAttributeData()->removeAttribute(index, this);
}
void Element::removeAttribute(const String& name)
{
- ElementAttributeData* attributeData = this->attributeData();
- if (!attributeData)
+ if (!attributeData())
return;
String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
- size_t index = attributeData->getAttributeItemIndex(localName, false);
+ size_t index = attributeData()->getAttributeItemIndex(localName, false);
if (index == notFound)
return;
- attributeData->removeAttribute(index, this);
+ mutableAttributeData()->removeAttribute(index, this);
}
void Element::removeAttributeNS(const String& namespaceURI, const String& localName)
@@ -1503,7 +1515,7 @@ void Element::removeAttributeNS(const String& namespaceURI, const String& localN
PassRefPtr<Attr> Element::getAttributeNode(const String& name)
{
- ElementAttributeData* attributeData = updatedAttributeData();
+ const ElementAttributeData* attributeData = updatedAttributeData();
if (!attributeData)
return 0;
return attributeData->getAttributeNode(name, shouldIgnoreAttributeCase(this), this);
@@ -1511,7 +1523,7 @@ PassRefPtr<Attr> Element::getAttributeNode(const String& name)
PassRefPtr<Attr> Element::getAttributeNodeNS(const String& namespaceURI, const String& localName)
{
- ElementAttributeData* attributeData = updatedAttributeData();
+ const ElementAttributeData* attributeData = updatedAttributeData();
if (!attributeData)
return 0;
return attributeData->getAttributeNode(QualifiedName(nullAtom, localName, namespaceURI), this);
@@ -1519,19 +1531,18 @@ PassRefPtr<Attr> Element::getAttributeNodeNS(const String& namespaceURI, const S
bool Element::hasAttribute(const String& name) const
{
- ElementAttributeData* attributeData = updatedAttributeData();
- if (!attributeData)
+ if (!attributeData())
return false;
// This call to String::lower() seems to be required but
// there may be a way to remove it.
String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
- return attributeData->getAttributeItem(localName, false);
+ return updatedAttributeData()->getAttributeItem(localName, false);
}
bool Element::hasAttributeNS(const String& namespaceURI, const String& localName) const
{
- ElementAttributeData* attributeData = updatedAttributeData();
+ const ElementAttributeData* attributeData = updatedAttributeData();
if (!attributeData)
return false;
return attributeData->getAttributeItem(QualifiedName(nullAtom, localName, namespaceURI));
@@ -1738,12 +1749,11 @@ void Element::normalizeAttributes()
if (!hasAttrList())
return;
- ElementAttributeData* attributeData = updatedAttributeData();
+ const ElementAttributeData* attributeData = updatedAttributeData();
ASSERT(attributeData);
- const Vector<Attribute>& attributes = attributeData->attributeVector();
- for (size_t i = 0; i < attributes.size(); ++i) {
- if (RefPtr<Attr> attr = attrIfExists(attributes[i].name()))
+ for (size_t i = 0; i < attributeData->length(); ++i) {
+ if (RefPtr<Attr> attr = attrIfExists(attributeData->attributeItem(i)->name()))
attr->normalize();
}
}
@@ -1812,8 +1822,8 @@ DOMStringMap* Element::dataset()
KURL Element::getURLAttribute(const QualifiedName& name) const
{
#if !ASSERT_DISABLED
- if (m_attributeData) {
- if (Attribute* attribute = getAttributeItem(name))
+ if (attributeData()) {
+ if (const Attribute* attribute = getAttributeItem(name))
ASSERT(isURLAttribute(*attribute));
}
#endif
@@ -1823,8 +1833,8 @@ KURL Element::getURLAttribute(const QualifiedName& name) const
KURL Element::getNonEmptyURLAttribute(const QualifiedName& name) const
{
#if !ASSERT_DISABLED
- if (m_attributeData) {
- if (Attribute* attribute = getAttributeItem(name))
+ if (attributeData()) {
+ if (const Attribute* attribute = getAttributeItem(name))
ASSERT(isURLAttribute(*attribute));
}
#endif
@@ -2168,8 +2178,8 @@ PassRefPtr<RenderStyle> Element::customStyleForRenderer()
void Element::cloneAttributesFromElement(const Element& other)
{
- if (ElementAttributeData* attributeData = other.updatedAttributeData())
- ensureUpdatedAttributeData()->cloneDataFrom(*attributeData, other, *this);
+ if (const ElementAttributeData* attributeData = other.updatedAttributeData())
+ mutableAttributeData()->cloneDataFrom(*attributeData, other, *this);
else if (m_attributeData) {
m_attributeData->clearAttributes(this);
m_attributeData.clear();
@@ -2182,4 +2192,70 @@ void Element::cloneDataFromElement(const Element& other)
copyNonAttributePropertiesFromElement(other);
}
+void Element::createMutableAttributeData()
+{
+ if (!m_attributeData)
+ m_attributeData = ElementAttributeData::create();
+ else
+ m_attributeData = m_attributeData->makeMutable();
+}
+
+#if ENABLE(UNDO_MANAGER)
+bool Element::undoScope() const
+{
+ return hasRareData() && elementRareData()->m_undoScope;
+}
+
+void Element::setUndoScope(bool undoScope)
+{
+ ElementRareData* data = ensureElementRareData();
+ data->m_undoScope = undoScope;
+ if (!undoScope)
+ disconnectUndoManager();
+}
+
+PassRefPtr<UndoManager> Element::undoManager()
+{
+ if (!undoScope() || (isContentEditable() && !isRootEditableElement())) {
+ disconnectUndoManager();
+ return 0;
+ }
+ ElementRareData* data = ensureElementRareData();
+ if (!data->m_undoManager)
+ data->m_undoManager = UndoManager::create(this);
+ return data->m_undoManager;
+}
+
+void Element::disconnectUndoManager()
+{
+ if (!hasRareData())
+ return;
+ ElementRareData* data = elementRareData();
+ UndoManager* undoManager = data->m_undoManager.get();
+ if (!undoManager)
+ return;
+ undoManager->clearUndoRedo();
+ undoManager->disconnect();
+ data->m_undoManager.clear();
+}
+
+void Element::disconnectUndoManagersInSubtree()
+{
+ Node* node = firstChild();
+ while (node) {
+ if (node->isElementNode()) {
+ Element* element = toElement(node);
+ if (element->hasRareData() && element->elementRareData()->m_undoManager) {
+ if (!node->isContentEditable()) {
+ node = node->traverseNextSibling(this);
+ continue;
+ }
+ element->disconnectUndoManager();
+ }
+ }
+ node = node->traverseNextNode(this);
+ }
+}
+#endif
+
} // namespace WebCore