Merge from Chromium at DEPS revision 240154
This commit was generated by merge_to_master.py.
Change-Id: Idca0efe87ed6b721349fbeab55bfdc919cc4941d
diff --git a/Source/core/dom/Element.cpp b/Source/core/dom/Element.cpp
index 893d1dc..369bf39 100644
--- a/Source/core/dom/Element.cpp
+++ b/Source/core/dom/Element.cpp
@@ -26,9 +26,7 @@
#include "config.h"
#include "core/dom/Element.h"
-#include "CSSPropertyNames.h"
#include "CSSValueKeywords.h"
-#include "HTMLNames.h"
#include "RuntimeEnabledFeatures.h"
#include "SVGNames.h"
#include "XMLNames.h"
@@ -43,12 +41,10 @@
#include "core/css/StylePropertySet.h"
#include "core/css/resolver/StyleResolver.h"
#include "core/dom/Attr.h"
-#include "core/dom/Attribute.h"
#include "core/dom/CSSSelectorWatch.h"
#include "core/dom/ClientRect.h"
#include "core/dom/ClientRectList.h"
#include "core/dom/DatasetDOMStringMap.h"
-#include "core/dom/Document.h"
#include "core/dom/DocumentSharedObjectPool.h"
#include "core/dom/ElementRareData.h"
#include "core/dom/ExceptionCode.h"
@@ -119,7 +115,7 @@
{
if (m_pushedStyleResolver)
return;
- m_pushedStyleResolver = m_parent.document().styleResolver();
+ m_pushedStyleResolver = &m_parent.document().ensureStyleResolver();
m_pushedStyleResolver->pushParentElement(m_parent);
}
~StyleResolverParentPusher()
@@ -394,7 +390,7 @@
bool Element::hasActiveAnimations() const
{
- if (!RuntimeEnabledFeatures::webAnimationsEnabled())
+ if (!RuntimeEnabledFeatures::webAnimationsCSSEnabled())
return false;
if (!hasRareData())
@@ -443,7 +439,7 @@
}
}
-inline void Element::synchronizeAttribute(const AtomicString& localName) const
+void Element::synchronizeAttribute(const AtomicString& localName) const
{
// This version of synchronizeAttribute() is streamlined for the case where you don't have a full QualifiedName,
// e.g when called from DOM API.
@@ -515,8 +511,7 @@
direction = ScrollUp;
units = -units;
}
- Node* stopNode = this;
- toRenderBox(renderer())->scroll(direction, granularity, units, &stopNode);
+ toRenderBox(renderer())->scroll(direction, granularity, units);
}
void Element::scrollByLines(int lines)
@@ -976,7 +971,7 @@
document().incDOMTreeVersion();
- StyleResolver* styleResolver = document().styleResolverIfExists();
+ StyleResolver* styleResolver = document().styleResolver();
bool testShouldInvalidateStyle = inActiveDocument() && styleResolver && styleChangeType() < SubtreeStyleChange;
bool shouldInvalidateStyle = false;
@@ -1098,7 +1093,7 @@
void Element::classAttributeChanged(const AtomicString& newClassString)
{
- StyleResolver* styleResolver = document().styleResolverIfExists();
+ StyleResolver* styleResolver = document().styleResolver();
bool testShouldInvalidateStyle = inActiveDocument() && styleResolver && styleChangeType() < SubtreeStyleChange;
bool shouldInvalidateStyle = false;
@@ -1495,17 +1490,32 @@
PassRefPtr<RenderStyle> Element::styleForRenderer()
{
- if (hasCustomStyleCallbacks()) {
- if (RefPtr<RenderStyle> style = customStyleForRenderer())
- return style.release();
- }
+ ASSERT(document().inStyleRecalc());
- return originalStyleForRenderer();
+ RefPtr<RenderStyle> style;
+
+ // FIXME: Instead of clearing updates that may have been added from calls to styleForElement
+ // outside recalcStyle, we should just never set them if we're not inside recalcStyle.
+ if (ActiveAnimations* activeAnimations = this->activeAnimations())
+ activeAnimations->cssAnimations().setPendingUpdate(nullptr);
+
+ if (hasCustomStyleCallbacks())
+ style = customStyleForRenderer();
+ if (!style)
+ style = originalStyleForRenderer();
+
+ // styleForElement() might add active animations so we need to get it again.
+ if (ActiveAnimations* activeAnimations = this->activeAnimations())
+ activeAnimations->cssAnimations().maybeApplyPendingUpdate(this);
+
+ ASSERT(style);
+ return style.release();
}
PassRefPtr<RenderStyle> Element::originalStyleForRenderer()
{
- return document().styleResolver()->styleForElement(this);
+ ASSERT(document().inStyleRecalc());
+ return document().ensureStyleResolver().styleForElement(this);
}
void Element::recalcStyle(StyleRecalcChange change, Text* nextTextSibling)
@@ -1521,6 +1531,11 @@
ElementRareData* data = elementRareData();
data->resetStyleState();
data->clearComputedStyle();
+
+ if (change >= Inherit) {
+ if (ActiveAnimations* activeAnimations = data->activeAnimations())
+ activeAnimations->setAnimationStyleChange(false);
+ }
}
if (parentRenderStyle())
change = recalcOwnStyle(change);
@@ -1547,11 +1562,7 @@
ASSERT(parentRenderStyle());
RefPtr<RenderStyle> oldStyle = renderStyle();
- RefPtr<RenderStyle> newStyle;
- {
- CSSAnimationUpdateScope cssAnimationUpdateScope(this);
- newStyle = styleForRenderer();
- }
+ RefPtr<RenderStyle> newStyle = styleForRenderer();
StyleRecalcChange localChange = RenderStyle::compare(oldStyle.get(), newStyle.get());
ASSERT(newStyle);
@@ -1586,7 +1597,7 @@
// 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().styleEngine()->usesRemUnits() && document().documentElement() == this && oldStyle->fontSize() != newStyle->fontSize()) {
// Cached RenderStyles may depend on the re units.
- document().styleResolver()->invalidateMatchedPropertiesCache();
+ document().ensureStyleResolver().invalidateMatchedPropertiesCache();
return Force;
}
@@ -1621,7 +1632,7 @@
// a potentially n^2 loop to find the insertion point while resolving style. Having us start from the last
// child and work our way back means in the common case, we'll find the insertion point in O(1) time.
// See crbug.com/288225
- StyleResolver& styleResolver = *document().styleResolver();
+ StyleResolver& styleResolver = document().ensureStyleResolver();
Text* lastTextNode = 0;
for (Node* child = lastChild(); child; child = child->previousSibling()) {
if (child->isTextNode()) {
@@ -1714,6 +1725,21 @@
elementShadow->didAffectSelector(mask);
}
+void Element::setAnimationStyleChange(bool animationStyleChange)
+{
+ if (ActiveAnimations* activeAnimations = elementRareData()->activeAnimations())
+ activeAnimations->setAnimationStyleChange(animationStyleChange);
+}
+
+void Element::setNeedsAnimationStyleRecalc()
+{
+ if (styleChangeType() != NoStyleChange)
+ return;
+
+ setNeedsStyleRecalc(LocalStyleChange, StyleChangeFromRenderer);
+ setAnimationStyleChange(true);
+}
+
PassRefPtr<ShadowRoot> Element::createShadowRoot(ExceptionState& exceptionState)
{
if (alwaysCreateUserAgentShadowRoot())
@@ -2001,7 +2027,7 @@
bool Element::parseAttributeName(QualifiedName& out, const AtomicString& namespaceURI, const AtomicString& qualifiedName, ExceptionState& exceptionState)
{
- String prefix, localName;
+ AtomicString prefix, localName;
if (!Document::parseQualifiedName(qualifiedName, prefix, localName, exceptionState))
return false;
ASSERT(!exceptionState.hadException());
@@ -2277,6 +2303,69 @@
mergeWithNextTextNode(prev.release(), exceptionState);
}
+Node* Element::insertAdjacent(const String& where, Node* newChild, ExceptionState& exceptionState)
+{
+ if (equalIgnoringCase(where, "beforeBegin")) {
+ if (ContainerNode* parent = this->parentNode()) {
+ parent->insertBefore(newChild, this, exceptionState);
+ if (!exceptionState.hadException())
+ return newChild;
+ }
+ return 0;
+ }
+
+ if (equalIgnoringCase(where, "afterBegin")) {
+ insertBefore(newChild, firstChild(), exceptionState);
+ return exceptionState.hadException() ? 0 : newChild;
+ }
+
+ if (equalIgnoringCase(where, "beforeEnd")) {
+ appendChild(newChild, exceptionState);
+ return exceptionState.hadException() ? 0 : newChild;
+ }
+
+ if (equalIgnoringCase(where, "afterEnd")) {
+ if (ContainerNode* parent = this->parentNode()) {
+ parent->insertBefore(newChild, nextSibling(), exceptionState);
+ if (!exceptionState.hadException())
+ return newChild;
+ }
+ return 0;
+ }
+
+ exceptionState.throwDOMException(SyntaxError, "The value provided ('" + where + "') is not one of 'beforeBegin', 'afterBegin', 'beforeEnd', or 'afterEnd'.");
+ return 0;
+}
+
+// Step 1 of http://domparsing.spec.whatwg.org/#insertadjacenthtml()
+static Element* contextElementForInsertion(const String& where, Element* element, ExceptionState& exceptionState)
+{
+ if (equalIgnoringCase(where, "beforeBegin") || equalIgnoringCase(where, "afterEnd")) {
+ ContainerNode* parent = element->parentNode();
+ if (!parent || !parent->isElementNode()) {
+ exceptionState.throwDOMException(NoModificationAllowedError, "The element has no parent.");
+ return 0;
+ }
+ return toElement(parent);
+ }
+ if (equalIgnoringCase(where, "afterBegin") || equalIgnoringCase(where, "beforeEnd"))
+ return element;
+ exceptionState.throwDOMException(SyntaxError, "The value provided ('" + where + "') is not one of 'beforeBegin', 'afterBegin', 'beforeEnd', or 'afterEnd'.");
+ return 0;
+}
+
+void Element::insertAdjacentHTML(const String& where, const String& markup, ExceptionState& exceptionState)
+{
+ RefPtr<Element> contextElement = contextElementForInsertion(where, this, exceptionState);
+ if (!contextElement)
+ return;
+
+ RefPtr<DocumentFragment> fragment = createFragmentForInnerOuterHTML(markup, contextElement.get(), AllowScriptingContent, "insertAdjacentHTML", exceptionState);
+ if (!fragment)
+ return;
+ insertAdjacent(where, fragment.get(), exceptionState);
+}
+
String Element::innerText()
{
// We need to update layout, since plainText uses line boxes in the render tree.
@@ -3017,7 +3106,7 @@
static bool hasSelectorForAttribute(Document* document, const AtomicString& localName)
{
- return document->styleResolver() && document->styleResolver()->ensureRuleFeatureSet().hasSelectorForAttribute(localName);
+ return document->ensureStyleResolver().ensureRuleFeatureSet().hasSelectorForAttribute(localName);
}
void Element::willModifyAttribute(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue)
@@ -3501,7 +3590,7 @@
if (isSVGElement() && toSVGElement(this)->animatedSMILStyleProperties())
return false;
// Ids stop style sharing if they show up in the stylesheets.
- if (hasID() && document().styleResolver()->hasRulesForId(idForStyleResolution()))
+ if (hasID() && document().ensureStyleResolver().hasRulesForId(idForStyleResolution()))
return false;
// Active and hovered elements always make a chain towards the document node
// and no siblings or cousins will have the same state.