Diff
Modified: trunk/Source/WebCore/ChangeLog (117322 => 117323)
--- trunk/Source/WebCore/ChangeLog 2012-05-16 19:25:25 UTC (rev 117322)
+++ trunk/Source/WebCore/ChangeLog 2012-05-16 19:31:40 UTC (rev 117323)
@@ -1,3 +1,53 @@
+2012-05-16 Andreas Kling <kl...@webkit.org>
+
+ Avoid reparsing the style attribute when cloning elements.
+ <http://webkit.org/b/86574>
+
+ Reviewed by Antti Koivisto.
+
+ Refactor cloning of attributes a bit to dodge the styleAttr reparse previously
+ caused by ElementAttributeData::setAttributes().
+
+ Introduced Element::cloneDataFromElement() which takes care of cloning the
+ ElementAttributeData as well as "non-attribute properties" (which is currently
+ specific to HTMLInputElement.)
+
+ Also includes some additional dodging of attribute vector traversal to find
+ old/new 'id' and 'name' attributes.
+
+ I'm seeing a ~10% improvement on PerformanceTests/DOM/CloneNodes locally.
+
+ * dom/Document.cpp:
+ (WebCore::Document::importNode):
+ * dom/Element.cpp:
+ (WebCore::Element::cloneElementWithoutChildren):
+ (WebCore::Element::cloneAttributesFromElement):
+ (WebCore::Element::cloneDataFromElement):
+ * dom/Element.h:
+ (WebCore::Element::copyNonAttributePropertiesFromElement):
+ * dom/ElementAttributeData.cpp:
+ (WebCore::ElementAttributeData::cloneDataFrom):
+ * dom/ElementAttributeData.h:
+ (ElementAttributeData):
+ * dom/Node.h:
+ * dom/StyledElement.cpp:
+ (WebCore::StyledElement::styleAttributeChanged):
+ (WebCore::StyledElement::parseAttribute):
+ * dom/StyledElement.h:
+ * editing/ReplaceNodeWithSpanCommand.cpp:
+ (WebCore::swapInNodePreservingAttributesAndChildren):
+ * html/HTMLElement.cpp:
+ * html/HTMLInputElement.cpp:
+ (WebCore::HTMLInputElement::copyNonAttributePropertiesFromElement):
+ * html/HTMLInputElement.h:
+ * inspector/DOMPatchSupport.cpp:
+ (WebCore::DOMPatchSupport::innerPatchNode):
+ * inspector/InspectorDOMAgent.cpp:
+ (WebCore::InspectorDOMAgent::setNodeName):
+ * svg/SVGUseElement.cpp:
+ (WebCore::SVGUseElement::expandSymbolElementsInShadowTree):
+ (WebCore::SVGUseElement::transferUseAttributesToReplacedElement):
+
2012-05-16 Brent Fulgham <bfulg...@webkit.org>
[WinCairo] Unreviewed build change after r115385. Several Cairo
Modified: trunk/Source/WebCore/dom/Document.cpp (117322 => 117323)
--- trunk/Source/WebCore/dom/Document.cpp 2012-05-16 19:25:25 UTC (rev 117322)
+++ trunk/Source/WebCore/dom/Document.cpp 2012-05-16 19:31:40 UTC (rev 117323)
@@ -914,8 +914,7 @@
if (ec)
return 0;
- newElement->setAttributesFromElement(*oldElement);
- newElement->copyNonAttributeProperties(oldElement);
+ newElement->cloneDataFromElement(*oldElement);
if (deep) {
for (Node* oldChild = oldElement->firstChild(); oldChild; oldChild = oldChild->nextSibling()) {
Modified: trunk/Source/WebCore/dom/Element.cpp (117322 => 117323)
--- trunk/Source/WebCore/dom/Element.cpp 2012-05-16 19:25:25 UTC (rev 117322)
+++ trunk/Source/WebCore/dom/Element.cpp 2012-05-16 19:31:40 UTC (rev 117323)
@@ -178,9 +178,7 @@
// This is a sanity check as HTML overloads some of the DOM methods.
ASSERT(isHTMLElement() == clone->isHTMLElement());
- clone->setAttributesFromElement(*this);
- clone->copyNonAttributeProperties(this);
-
+ clone->cloneDataFromElement(*this);
return clone.release();
}
@@ -189,10 +187,6 @@
return document()->createElement(tagQName(), false);
}
-void Element::copyNonAttributeProperties(const Element*)
-{
-}
-
PassRefPtr<Attr> Element::detachAttribute(size_t index)
{
if (!attributeData())
@@ -2117,4 +2111,20 @@
}
+void Element::cloneAttributesFromElement(const Element& other)
+{
+ if (ElementAttributeData* attributeData = other.updatedAttributeData())
+ ensureUpdatedAttributeData()->cloneDataFrom(*attributeData, other, *this);
+ else if (m_attributeData) {
+ m_attributeData->clearAttributes(this);
+ m_attributeData.clear();
+ }
+}
+
+void Element::cloneDataFromElement(const Element& other)
+{
+ cloneAttributesFromElement(other);
+ copyNonAttributePropertiesFromElement(other);
+}
+
} // namespace WebCore
Modified: trunk/Source/WebCore/dom/Element.h (117322 => 117323)
--- trunk/Source/WebCore/dom/Element.h 2012-05-16 19:25:25 UTC (rev 117322)
+++ trunk/Source/WebCore/dom/Element.h 2012-05-16 19:31:40 UTC (rev 117323)
@@ -251,10 +251,15 @@
ElementAttributeData* updatedAttributeData() const;
ElementAttributeData* ensureUpdatedAttributeData() const;
- void setAttributesFromElement(const Element&);
+ // Clones attributes only.
+ void cloneAttributesFromElement(const Element&);
+
+ // Clones all attribute-derived data, including subclass specifics (through copyNonAttributeProperties.)
+ void cloneDataFromElement(const Element&);
+
bool hasEquivalentAttributes(const Element* other) const;
- virtual void copyNonAttributeProperties(const Element* source);
+ virtual void copyNonAttributePropertiesFromElement(const Element&) { }
virtual void attach();
virtual void detach();
@@ -562,12 +567,6 @@
return ensureAttributeData();
}
-inline void Element::setAttributesFromElement(const Element& other)
-{
- if (ElementAttributeData* attributeData = other.updatedAttributeData())
- ensureUpdatedAttributeData()->setAttributes(*attributeData, this);
-}
-
inline void Element::updateName(const AtomicString& oldName, const AtomicString& newName)
{
if (!inDocument())
Modified: trunk/Source/WebCore/dom/ElementAttributeData.cpp (117322 => 117323)
--- trunk/Source/WebCore/dom/ElementAttributeData.cpp 2012-05-16 19:25:25 UTC (rev 117322)
+++ trunk/Source/WebCore/dom/ElementAttributeData.cpp 2012-05-16 19:31:40 UTC (rev 117323)
@@ -252,28 +252,36 @@
return notFound;
}
-void ElementAttributeData::setAttributes(const ElementAttributeData& other, Element* element)
+void ElementAttributeData::cloneDataFrom(const ElementAttributeData& sourceData, const Element& sourceElement, Element& targetElement)
{
- ASSERT(element);
+ const AtomicString& oldID = targetElement.getIdAttribute();
+ const AtomicString& newID = sourceElement.getIdAttribute();
- // 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.isNull() || !newID.isNull())
+ targetElement.updateId(oldID, newID);
- if (oldId || newId)
- element->updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom);
+ const AtomicString& oldName = targetElement.getNameAttribute();
+ const AtomicString& newName = sourceElement.getNameAttribute();
- Attribute* oldName = getAttributeItem(HTMLNames::nameAttr);
- Attribute* newName = other.getAttributeItem(HTMLNames::nameAttr);
+ if (!oldName.isNull() || !newName.isNull())
+ targetElement.updateName(oldName, newName);
- if (oldName || newName)
- element->updateName(oldName ? oldName->value() : nullAtom, newName ? newName->value() : nullAtom);
+ clearAttributes(&targetElement);
+ m_attributes = sourceData.m_attributes;
+ for (unsigned i = 0; i < m_attributes.size(); ++i) {
+ if (targetElement.isStyledElement() && m_attributes[i].name() == HTMLNames::styleAttr) {
+ static_cast<StyledElement&>(targetElement).styleAttributeChanged(m_attributes[i].value(), StyledElement::DoNotReparseStyleAttribute);
+ continue;
+ }
+ targetElement.attributeChanged(m_attributes[i]);
+ }
- clearAttributes(element);
- m_attributes = other.m_attributes;
- for (unsigned i = 0; i < m_attributes.size(); ++i)
- element->attributeChanged(m_attributes[i]);
+ if (targetElement.isStyledElement() && sourceData.m_inlineStyleDecl) {
+ StylePropertySet* inlineStyle = ensureMutableInlineStyle(static_cast<StyledElement*>(&targetElement));
+ inlineStyle->copyPropertiesFrom(*sourceData.m_inlineStyleDecl);
+ inlineStyle->setCSSParserMode(sourceData.m_inlineStyleDecl->cssParserMode());
+ targetElement.setIsStyleAttributeValid(sourceElement.isStyleAttributeValid());
+ }
}
void ElementAttributeData::clearAttributes(Element* element)
Modified: trunk/Source/WebCore/dom/ElementAttributeData.h (117322 => 117323)
--- trunk/Source/WebCore/dom/ElementAttributeData.h 2012-05-16 19:25:25 UTC (rev 117322)
+++ trunk/Source/WebCore/dom/ElementAttributeData.h 2012-05-16 19:31:40 UTC (rev 117323)
@@ -113,7 +113,7 @@
void detachAttributesFromElement(Element*);
Attribute* getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const;
size_t getAttributeItemIndexSlowCase(const String& name, bool shouldIgnoreAttributeCase) const;
- void setAttributes(const ElementAttributeData& other, Element*);
+ void cloneDataFrom(const ElementAttributeData& sourceData, const Element& sourceElement, Element& targetElement);
void clearAttributes(Element*);
void replaceAttribute(size_t index, const Attribute&, Element*);
Modified: trunk/Source/WebCore/dom/Node.h (117322 => 117323)
--- trunk/Source/WebCore/dom/Node.h 2012-05-16 19:25:25 UTC (rev 117322)
+++ trunk/Source/WebCore/dom/Node.h 2012-05-16 19:31:40 UTC (rev 117323)
@@ -790,15 +790,17 @@
Node* m_next;
RenderObject* m_renderer;
-protected:
- bool isParsingChildrenFinished() const { return getFlag(IsParsingChildrenFinishedFlag); }
- void setIsParsingChildrenFinished() { setFlag(IsParsingChildrenFinishedFlag); }
- void clearIsParsingChildrenFinished() { clearFlag(IsParsingChildrenFinishedFlag); }
+public:
bool isStyleAttributeValid() const { return getFlag(IsStyleAttributeValidFlag); }
void setIsStyleAttributeValid(bool f) { setFlag(f, IsStyleAttributeValidFlag); }
void setIsStyleAttributeValid() const { setFlag(IsStyleAttributeValidFlag); }
void clearIsStyleAttributeValid() { clearFlag(IsStyleAttributeValidFlag); }
+protected:
+ bool isParsingChildrenFinished() const { return getFlag(IsParsingChildrenFinishedFlag); }
+ void setIsParsingChildrenFinished() { setFlag(IsParsingChildrenFinishedFlag); }
+ void clearIsParsingChildrenFinished() { clearFlag(IsParsingChildrenFinishedFlag); }
+
#if ENABLE(SVG)
bool areSVGAttributesValid() const { return getFlag(AreSVGAttributesValidFlag); }
void setAreSVGAttributesValid() const { setFlag(AreSVGAttributesValidFlag); }
Modified: trunk/Source/WebCore/dom/StyledElement.cpp (117322 => 117323)
--- trunk/Source/WebCore/dom/StyledElement.cpp 2012-05-16 19:25:25 UTC (rev 117322)
+++ trunk/Source/WebCore/dom/StyledElement.cpp 2012-05-16 19:31:40 UTC (rev 117323)
@@ -168,21 +168,27 @@
setNeedsStyleRecalc();
}
-void StyledElement::parseAttribute(const Attribute& attribute)
+void StyledElement::styleAttributeChanged(const AtomicString& newStyleString, ShouldReparseStyleAttribute shouldReparse)
{
- if (attribute.name() == classAttr)
- classAttributeChanged(attribute.value());
- else if (attribute.name() == styleAttr) {
- if (attribute.isNull())
+ if (shouldReparse) {
+ if (newStyleString.isNull())
destroyInlineStyle();
else if (document()->contentSecurityPolicy()->allowInlineStyle())
- ensureAttributeData()->updateInlineStyleAvoidingMutation(this, attribute.value());
+ ensureAttributeData()->updateInlineStyleAvoidingMutation(this, newStyleString);
setIsStyleAttributeValid();
- setNeedsStyleRecalc();
- InspectorInstrumentation::didInvalidateStyleAttr(document(), this);
}
+ setNeedsStyleRecalc();
+ InspectorInstrumentation::didInvalidateStyleAttr(document(), this);
}
+void StyledElement::parseAttribute(const Attribute& attribute)
+{
+ if (attribute.name() == classAttr)
+ classAttributeChanged(attribute.value());
+ else if (attribute.name() == styleAttr)
+ styleAttributeChanged(attribute.value());
+}
+
void StyledElement::inlineStyleChanged()
{
setNeedsStyleRecalc(InlineStyleChange);
Modified: trunk/Source/WebCore/dom/StyledElement.h (117322 => 117323)
--- trunk/Source/WebCore/dom/StyledElement.h 2012-05-16 19:25:25 UTC (rev 117322)
+++ trunk/Source/WebCore/dom/StyledElement.h 2012-05-16 19:31:40 UTC (rev 117323)
@@ -57,6 +57,10 @@
virtual void collectStyleForAttribute(const Attribute&, StylePropertySet*) { }
+ // May be called by ElementAttributeData::cloneDataFrom().
+ enum ShouldReparseStyleAttribute { DoNotReparseStyleAttribute = 0, ReparseStyleAttribute = 1 };
+ void styleAttributeChanged(const AtomicString& newStyleString, ShouldReparseStyleAttribute = ReparseStyleAttribute);
+
protected:
StyledElement(const QualifiedName& name, Document* document, ConstructionType type)
: Element(name, document, type)
@@ -65,7 +69,6 @@
virtual void attributeChanged(const Attribute&) OVERRIDE;
virtual void parseAttribute(const Attribute&);
- virtual void copyNonAttributeProperties(const Element*);
virtual bool isPresentationAttribute(const QualifiedName&) const { return false; }
Modified: trunk/Source/WebCore/editing/ReplaceNodeWithSpanCommand.cpp (117322 => 117323)
--- trunk/Source/WebCore/editing/ReplaceNodeWithSpanCommand.cpp 2012-05-16 19:25:25 UTC (rev 117322)
+++ trunk/Source/WebCore/editing/ReplaceNodeWithSpanCommand.cpp 2012-05-16 19:31:40 UTC (rev 117323)
@@ -64,7 +64,7 @@
}
// FIXME: Fix this to send the proper MutationRecords when MutationObservers are present.
- newNode->setAttributesFromElement(*nodeToReplace);
+ newNode->cloneDataFromElement(*nodeToReplace);
parentNode->removeChild(nodeToReplace, ec);
ASSERT(!ec);
Modified: trunk/Source/WebCore/html/HTMLElement.cpp (117322 => 117323)
--- trunk/Source/WebCore/html/HTMLElement.cpp 2012-05-16 19:25:25 UTC (rev 117322)
+++ trunk/Source/WebCore/html/HTMLElement.cpp 2012-05-16 19:31:40 UTC (rev 117323)
@@ -1108,25 +1108,6 @@
style->setProperty(propertyID, cssValuePool().createColorValue(parsedColor.rgb()));
}
-void StyledElement::copyNonAttributeProperties(const Element* sourceElement)
-{
- ASSERT(sourceElement);
- ASSERT(sourceElement->isStyledElement());
-
- const StyledElement* source = static_cast<const StyledElement*>(sourceElement);
- if (!source->inlineStyle())
- return;
-
- StylePropertySet* inlineStyle = ensureAttributeData()->ensureMutableInlineStyle(this);
- inlineStyle->copyPropertiesFrom(*source->inlineStyle());
- inlineStyle->setCSSParserMode(source->inlineStyle()->cssParserMode());
-
- setIsStyleAttributeValid(source->isStyleAttributeValid());
-
- Element::copyNonAttributeProperties(sourceElement);
-}
-
-
} // namespace WebCore
#ifndef NDEBUG
Modified: trunk/Source/WebCore/html/HTMLInputElement.cpp (117322 => 117323)
--- trunk/Source/WebCore/html/HTMLInputElement.cpp 2012-05-16 19:25:25 UTC (rev 117322)
+++ trunk/Source/WebCore/html/HTMLInputElement.cpp 2012-05-16 19:31:40 UTC (rev 117323)
@@ -825,17 +825,17 @@
return m_inputType->sizeShouldIncludeDecoration(defaultSize, preferredSize);
}
-void HTMLInputElement::copyNonAttributeProperties(const Element* source)
+void HTMLInputElement::copyNonAttributePropertiesFromElement(const Element& source)
{
- const HTMLInputElement* sourceElement = static_cast<const HTMLInputElement*>(source);
+ const HTMLInputElement& sourceElement = static_cast<const HTMLInputElement&>(source);
- m_valueIfDirty = sourceElement->m_valueIfDirty;
+ m_valueIfDirty = sourceElement.m_valueIfDirty;
m_wasModifiedByUser = false;
- setChecked(sourceElement->m_isChecked);
- m_reflectsCheckedAttribute = sourceElement->m_reflectsCheckedAttribute;
- m_isIndeterminate = sourceElement->m_isIndeterminate;
+ setChecked(sourceElement.m_isChecked);
+ m_reflectsCheckedAttribute = sourceElement.m_reflectsCheckedAttribute;
+ m_isIndeterminate = sourceElement.m_isIndeterminate;
- HTMLTextFormControlElement::copyNonAttributeProperties(source);
+ HTMLTextFormControlElement::copyNonAttributePropertiesFromElement(source);
setFormControlValueMatchesRenderer(false);
updateInnerTextValue();
Modified: trunk/Source/WebCore/html/HTMLInputElement.h (117322 => 117323)
--- trunk/Source/WebCore/html/HTMLInputElement.h 2012-05-16 19:25:25 UTC (rev 117322)
+++ trunk/Source/WebCore/html/HTMLInputElement.h 2012-05-16 19:31:40 UTC (rev 117323)
@@ -290,7 +290,7 @@
virtual void collectStyleForAttribute(const Attribute&, StylePropertySet*) OVERRIDE;
virtual void finishParsingChildren();
- virtual void copyNonAttributeProperties(const Element* source);
+ virtual void copyNonAttributePropertiesFromElement(const Element&);
virtual void attach();
Modified: trunk/Source/WebCore/inspector/DOMPatchSupport.cpp (117322 => 117323)
--- trunk/Source/WebCore/inspector/DOMPatchSupport.cpp 2012-05-16 19:25:25 UTC (rev 117322)
+++ trunk/Source/WebCore/inspector/DOMPatchSupport.cpp 2012-05-16 19:31:40 UTC (rev 117323)
@@ -180,7 +180,7 @@
}
}
- // FIXME: Create a function in Element for copying properties. setAttributesFromElement() is close but not enough for this case.
+ // FIXME: Create a function in Element for copying properties. cloneDataFromElement() is close but not enough for this case.
if (newElement->hasAttributesWithoutUpdate()) {
size_t numAttrs = newElement->attributeCount();
for (size_t i = 0; i < numAttrs; ++i) {
Modified: trunk/Source/WebCore/inspector/InspectorDOMAgent.cpp (117322 => 117323)
--- trunk/Source/WebCore/inspector/InspectorDOMAgent.cpp 2012-05-16 19:25:25 UTC (rev 117322)
+++ trunk/Source/WebCore/inspector/InspectorDOMAgent.cpp 2012-05-16 19:31:40 UTC (rev 117323)
@@ -653,7 +653,7 @@
return;
// Copy over the original node's attributes.
- newElem->setAttributesFromElement(*toElement(oldNode));
+ newElem->cloneAttributesFromElement(*toElement(oldNode));
// Copy over the original node's children.
Node* child;
Modified: trunk/Source/WebCore/svg/SVGUseElement.cpp (117322 => 117323)
--- trunk/Source/WebCore/svg/SVGUseElement.cpp 2012-05-16 19:25:25 UTC (rev 117322)
+++ trunk/Source/WebCore/svg/SVGUseElement.cpp 2012-05-16 19:31:40 UTC (rev 117323)
@@ -766,8 +766,8 @@
// 'svg' element will use values of 100% for these attributes.
RefPtr<SVGSVGElement> svgElement = SVGSVGElement::create(SVGNames::svgTag, referencedDocument());
- // Transfer all attributes from <symbol> to the new <svg> element
- svgElement->setAttributesFromElement(*toElement(element));
+ // Transfer all data (attributes, etc.) from <symbol> to the new <svg> element.
+ svgElement->cloneDataFromElement(*toElement(element));
// Only clone symbol children, and add them to the new <svg> element
for (Node* child = element->firstChild(); child; child = child->nextSibling()) {
@@ -898,7 +898,7 @@
ASSERT(from);
ASSERT(to);
- to->setAttributesFromElement(*from);
+ to->cloneDataFromElement(*from);
to->removeAttribute(SVGNames::xAttr);
to->removeAttribute(SVGNames::yAttr);