https://bugs.webkit.org/show_bug.cgi?id=129467
Reviewed by Geoffrey Garen.
Exit early in childrenChanged when the attribute value didn't change.
* dom/Attr.cpp:
(WebCore::Attr::setValue):
(WebCore::Attr::childrenChanged):
* dom/Element.cpp:
(WebCore::Element::setAttributeInternal):
(WebCore::Element::attributeChanged):
(WebCore::Element::parserSetAttributes):
(WebCore::Element::removeAttributeInternal):
(WebCore::Element::didAddAttribute):
(WebCore::Element::didModifyAttribute):
(WebCore::Element::didRemoveAttribute):
(WebCore::Element::cloneAttributesFromElement):
* dom/Element.h:
* dom/StyledElement.cpp:
(WebCore::StyledElement::attributeChanged):
* dom/StyledElement.h:
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::updateType):
* mathml/MathMLElement.cpp:
(WebCore::MathMLElement::attributeChanged):
* mathml/MathMLElement.h:
* mathml/MathMLSelectElement.cpp:
(WebCore::MathMLSelectElement::attributeChanged):
* mathml/MathMLSelectElement.h:
* svg/SVGElement.cpp:
(WebCore::SVGElement::attributeChanged):
* svg/SVGElement.h:
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@164856
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2014-02-27 Ryosuke Niwa <rniwa@webkit.org>
+
+ Element::attributeChanged shouldn't do any work when attribute value didn't change
+ https://bugs.webkit.org/show_bug.cgi?id=129467
+
+ Reviewed by Geoffrey Garen.
+
+ Exit early in childrenChanged when the attribute value didn't change.
+
+ * dom/Attr.cpp:
+ (WebCore::Attr::setValue):
+ (WebCore::Attr::childrenChanged):
+ * dom/Element.cpp:
+ (WebCore::Element::setAttributeInternal):
+ (WebCore::Element::attributeChanged):
+ (WebCore::Element::parserSetAttributes):
+ (WebCore::Element::removeAttributeInternal):
+ (WebCore::Element::didAddAttribute):
+ (WebCore::Element::didModifyAttribute):
+ (WebCore::Element::didRemoveAttribute):
+ (WebCore::Element::cloneAttributesFromElement):
+ * dom/Element.h:
+ * dom/StyledElement.cpp:
+ (WebCore::StyledElement::attributeChanged):
+ * dom/StyledElement.h:
+ * html/HTMLInputElement.cpp:
+ (WebCore::HTMLInputElement::updateType):
+ * mathml/MathMLElement.cpp:
+ (WebCore::MathMLElement::attributeChanged):
+ * mathml/MathMLElement.h:
+ * mathml/MathMLSelectElement.cpp:
+ (WebCore::MathMLSelectElement::attributeChanged):
+ * mathml/MathMLSelectElement.h:
+ * svg/SVGElement.cpp:
+ (WebCore::SVGElement::attributeChanged):
+ * svg/SVGElement.h:
+
2014-02-27 Jinwoo Song <jinwoo7.song@samsung.com>
[EFL] Remove duplicated keyboard string key from keyMap
void Attr::setValue(const AtomicString& value, ExceptionCode&)
{
+ AtomicString oldValue = this->value();
if (m_element)
- m_element->willModifyAttribute(qualifiedName(), this->value(), value);
+ m_element->willModifyAttribute(qualifiedName(), oldValue, value);
setValue(value);
if (m_element)
- m_element->didModifyAttribute(qualifiedName(), value);
+ m_element->didModifyAttribute(qualifiedName(), oldValue, value);
}
void Attr::setNodeValue(const String& v, ExceptionCode& ec)
StringBuilder valueBuilder;
TextNodeTraversal::appendContents(this, valueBuilder);
+ AtomicString oldValue = value();
AtomicString newValue = valueBuilder.toAtomicString();
if (m_element)
- m_element->willModifyAttribute(qualifiedName(), value(), newValue);
+ m_element->willModifyAttribute(qualifiedName(), oldValue, newValue);
if (m_element)
elementAttribute().setValue(newValue);
m_standaloneValue = newValue;
if (m_element)
- m_element->attributeChanged(qualifiedName(), newValue);
+ m_element->attributeChanged(qualifiedName(), oldValue, newValue);
}
bool Attr::isId() const
return;
}
- bool valueChanged = newValue != attributeAt(index).value();
- QualifiedName attributeName = (!inSynchronizationOfLazyAttribute || valueChanged) ? attributeAt(index).name() : name;
+ const Attribute& attribute = attributeAt(index);
+ AtomicString oldValue = attribute.value();
+ bool valueChanged = newValue != oldValue;
+ const QualifiedName& attributeName = (!inSynchronizationOfLazyAttribute || valueChanged) ? attribute.name() : name;
if (!inSynchronizationOfLazyAttribute)
- willModifyAttribute(attributeName, attributeAt(index).value(), newValue);
+ willModifyAttribute(attributeName, oldValue, newValue);
if (valueChanged) {
// If there is an Attr node hooked to this attribute, the Attr::setValue() call below
}
if (!inSynchronizationOfLazyAttribute)
- didModifyAttribute(attributeName, newValue);
+ didModifyAttribute(attributeName, oldValue, newValue);
}
static inline AtomicString makeIdForStyleResolution(const AtomicString& value, bool inQuirksMode)
return false;
}
-void Element::attributeChanged(const QualifiedName& name, const AtomicString& newValue, AttributeModificationReason)
+void Element::attributeChanged(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue, AttributeModificationReason)
{
parseAttribute(name, newValue);
document().incDOMTreeVersion();
+ if (oldValue == newValue)
+ return;
+
StyleResolver* styleResolver = document().styleResolverIfExists();
bool testShouldInvalidateStyle = inRenderedDocument() && styleResolver && styleChangeType() < FullStyleChange;
bool shouldInvalidateStyle = false;
// Use attributeVector instead of m_elementData because attributeChanged might modify m_elementData.
for (unsigned i = 0; i < attributeVector.size(); ++i)
- attributeChanged(attributeVector[i].name(), attributeVector[i].value(), ModifiedDirectly);
+ attributeChanged(attributeVector[i].name(), nullAtom, attributeVector[i].value(), ModifiedDirectly);
}
bool Element::hasAttributes() const
elementData.removeAttribute(index);
if (!inSynchronizationOfLazyAttribute)
- didRemoveAttribute(name);
+ didRemoveAttribute(name, valueBeingRemoved);
}
void Element::addAttributeInternal(const QualifiedName& name, const AtomicString& value, SynchronizationOfLazyAttribute inSynchronizationOfLazyAttribute)
void Element::didAddAttribute(const QualifiedName& name, const AtomicString& value)
{
- attributeChanged(name, value);
+ attributeChanged(name, nullAtom, value);
InspectorInstrumentation::didModifyDOMAttr(&document(), this, name.localName(), value);
dispatchSubtreeModifiedEvent();
}
-void Element::didModifyAttribute(const QualifiedName& name, const AtomicString& value)
+void Element::didModifyAttribute(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue)
{
- attributeChanged(name, value);
- InspectorInstrumentation::didModifyDOMAttr(&document(), this, name.localName(), value);
+ attributeChanged(name, oldValue, newValue);
+ InspectorInstrumentation::didModifyDOMAttr(&document(), this, name.localName(), newValue);
// Do not dispatch a DOMSubtreeModified event here; see bug 81141.
}
-void Element::didRemoveAttribute(const QualifiedName& name)
+void Element::didRemoveAttribute(const QualifiedName& name, const AtomicString& oldValue)
{
- attributeChanged(name, nullAtom);
+ attributeChanged(name, oldValue, nullAtom);
InspectorInstrumentation::didRemoveDOMAttr(&document(), this, name.localName());
dispatchSubtreeModifiedEvent();
}
else
m_elementData = other.m_elementData->makeUniqueCopy();
- for (const Attribute& attribute : attributesIterator()) {
- attributeChanged(attribute.name(), attribute.value(), ModifiedByCloning);
- }
+ for (const Attribute& attribute : attributesIterator())
+ attributeChanged(attribute.name(), nullAtom, attribute.value(), ModifiedByCloning);
}
void Element::cloneDataFromElement(const Element& other)
};
// This method is called whenever an attribute is added, changed or removed.
- virtual void attributeChanged(const QualifiedName&, const AtomicString&, AttributeModificationReason = ModifiedDirectly);
+ virtual void attributeChanged(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue, AttributeModificationReason = ModifiedDirectly);
virtual void parseAttribute(const QualifiedName&, const AtomicString&) { }
// Only called by the parser immediately after element construction.
void didAddAttribute(const QualifiedName&, const AtomicString&);
void willModifyAttribute(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue);
- void didModifyAttribute(const QualifiedName&, const AtomicString&);
- void didRemoveAttribute(const QualifiedName&);
+ void didModifyAttribute(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue);
+ void didRemoveAttribute(const QualifiedName&, const AtomicString& oldValue);
void synchronizeAttribute(const QualifiedName&) const;
void synchronizeAttribute(const AtomicString& localName) const;
return static_cast<MutableStyleProperties&>(*inlineStyle);
}
-void StyledElement::attributeChanged(const QualifiedName& name, const AtomicString& newValue, AttributeModificationReason reason)
+void StyledElement::attributeChanged(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue, AttributeModificationReason reason)
{
if (name == styleAttr)
styleAttributeChanged(newValue, reason);
setNeedsStyleRecalc(InlineStyleChange);
}
- Element::attributeChanged(name, newValue, reason);
+ Element::attributeChanged(name, oldValue, newValue, reason);
}
PropertySetCSSStyleDeclaration* StyledElement::inlineStyleCSSOMWrapper()
{
}
- virtual void attributeChanged(const QualifiedName&, const AtomicString&, AttributeModificationReason = ModifiedDirectly) override;
+ virtual void attributeChanged(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue, AttributeModificationReason = ModifiedDirectly) override;
virtual bool isPresentationAttribute(const QualifiedName&) const { return false; }
if (didRespectHeightAndWidth != m_inputType->shouldRespectHeightAndWidthAttributes()) {
ASSERT(elementData());
+ // FIXME: We don't have the old attribute values so we pretend that we didn't have the old values.
if (const Attribute* height = findAttributeByName(heightAttr))
- attributeChanged(heightAttr, height->value());
+ attributeChanged(heightAttr, nullAtom, height->value());
if (const Attribute* width = findAttributeByName(widthAttr))
- attributeChanged(widthAttr, width->value());
+ attributeChanged(widthAttr, nullAtom, width->value());
if (const Attribute* align = findAttributeByName(alignAttr))
- attributeChanged(alignAttr, align->value());
+ attributeChanged(alignAttr, nullAtom, align->value());
}
if (renderer())
return child.isTextNode() || child.isMathMLElement();
}
-void MathMLElement::attributeChanged(const QualifiedName& name, const AtomicString& newValue, AttributeModificationReason reason)
+void MathMLElement::attributeChanged(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue, AttributeModificationReason reason)
{
if (isSemanticAnnotation() && (name == MathMLNames::srcAttr || name == MathMLNames::encodingAttr)) {
Element* parent = parentElement();
if (parent && parent->isMathMLElement() && parent->hasTagName(semanticsTag))
toMathMLElement(parent)->updateSelectedChild();
}
- StyledElement::attributeChanged(name, newValue, reason);
+ StyledElement::attributeChanged(name, oldValue, newValue, reason);
}
}
virtual void parseAttribute(const QualifiedName&, const AtomicString&) override;
virtual bool childShouldCreateRenderer(const Node&) const override;
- virtual void attributeChanged(const QualifiedName&, const AtomicString& newValue, AttributeModificationReason) override;
+ virtual void attributeChanged(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue, AttributeModificationReason) override;
virtual bool isPresentationAttribute(const QualifiedName&) const override;
virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStyleProperties&) override;
MathMLInlineContainerElement::childrenChanged(change);
}
-void MathMLSelectElement::attributeChanged(const QualifiedName& name, const AtomicString& newValue, AttributeModificationReason reason)
+void MathMLSelectElement::attributeChanged(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue, AttributeModificationReason reason)
{
if (hasLocalName(mactionTag) && (name == MathMLNames::actiontypeAttr || name == MathMLNames::selectionAttr))
updateSelectedChild();
- MathMLInlineContainerElement::attributeChanged(name, newValue, reason);
+ MathMLInlineContainerElement::attributeChanged(name, oldValue, newValue, reason);
}
int MathMLSelectElement::getSelectedActionChildAndIndex(Element*& selectedChild)
virtual void finishParsingChildren() override;
virtual void childrenChanged(const ChildChange&) override;
- virtual void attributeChanged(const QualifiedName&, const AtomicString&, AttributeModificationReason = ModifiedDirectly) override;
+ virtual void attributeChanged(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue, AttributeModificationReason = ModifiedDirectly) override;
virtual void defaultEventHandler(Event*) override;
virtual bool willRespondToMouseClickEvents() override;
return false;
}
-void SVGElement::attributeChanged(const QualifiedName& name, const AtomicString& newValue, AttributeModificationReason)
+void SVGElement::attributeChanged(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue, AttributeModificationReason)
{
- StyledElement::attributeChanged(name, newValue);
+ StyledElement::attributeChanged(name, oldValue, newValue);
if (isIdAttributeName(name))
document().accessSVGExtensions()->rebuildAllElementReferencesForTarget(this);
virtual void parseAttribute(const QualifiedName&, const AtomicString&) override;
virtual void finishParsingChildren() override;
- virtual void attributeChanged(const QualifiedName&, const AtomicString&, AttributeModificationReason = ModifiedDirectly) override;
+ virtual void attributeChanged(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue, AttributeModificationReason = ModifiedDirectly) override;
virtual bool childShouldCreateRenderer(const Node&) const override;
SVGElementRareData& ensureSVGRareData();