summaryrefslogtreecommitdiff
path: root/Source/WebCore/dom
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/dom')
-rw-r--r--Source/WebCore/dom/ContainerNode.cpp21
-rw-r--r--Source/WebCore/dom/ContainerNode.h12
-rw-r--r--Source/WebCore/dom/DOMImplementation.idl3
-rw-r--r--Source/WebCore/dom/Document.cpp6
-rw-r--r--Source/WebCore/dom/DocumentOrderedMap.cpp11
-rw-r--r--Source/WebCore/dom/DocumentOrderedMap.h2
-rw-r--r--Source/WebCore/dom/DocumentStyleSheetCollection.cpp90
-rw-r--r--Source/WebCore/dom/DocumentStyleSheetCollection.h10
-rw-r--r--Source/WebCore/dom/Element.cpp46
-rw-r--r--Source/WebCore/dom/Element.h1
-rw-r--r--Source/WebCore/dom/QualifiedName.cpp12
-rw-r--r--Source/WebCore/dom/QualifiedName.h15
-rw-r--r--Source/WebCore/dom/ShadowRoot.cpp2
-rw-r--r--Source/WebCore/dom/TreeScope.cpp33
-rw-r--r--Source/WebCore/dom/TreeScope.h10
-rw-r--r--[-rwxr-xr-x]Source/WebCore/dom/WheelEvent.cpp0
-rw-r--r--[-rwxr-xr-x]Source/WebCore/dom/WheelEvent.h0
17 files changed, 189 insertions, 85 deletions
diff --git a/Source/WebCore/dom/ContainerNode.cpp b/Source/WebCore/dom/ContainerNode.cpp
index 9b178d82a..06aae46e1 100644
--- a/Source/WebCore/dom/ContainerNode.cpp
+++ b/Source/WebCore/dom/ContainerNode.cpp
@@ -33,6 +33,7 @@
#include "Frame.h"
#include "FrameView.h"
#include "InlineTextBox.h"
+#include "InsertionPoint.h"
#include "InspectorInstrumentation.h"
#include "MemoryCache.h"
#include "MutationEvent.h"
@@ -976,8 +977,10 @@ static void dispatchChildInsertionEvents(Node* child)
static void dispatchChildRemovalEvents(Node* child)
{
- if (child->isInShadowTree())
+ if (child->isInShadowTree()) {
+ InspectorInstrumentation::willRemoveDOMNode(child->document(), child);
return;
+ }
ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
@@ -1030,4 +1033,20 @@ static void updateTreeAfterInsertion(ContainerNode* parent, Node* child, bool sh
dispatchChildInsertionEvents(child);
}
+#ifndef NDEBUG
+bool childAttachedAllowedWhenAttachingChildren(ContainerNode* node)
+{
+ if (node->isShadowRoot())
+ return true;
+
+ if (isInsertionPoint(node))
+ return true;
+
+ if (node->isElementNode() && toElement(node)->shadow())
+ return true;
+
+ return false;
+}
+#endif
+
} // namespace WebCore
diff --git a/Source/WebCore/dom/ContainerNode.h b/Source/WebCore/dom/ContainerNode.h
index 7979c63c8..dd4a9898d 100644
--- a/Source/WebCore/dom/ContainerNode.h
+++ b/Source/WebCore/dom/ContainerNode.h
@@ -126,7 +126,6 @@ public:
void attachAsNode();
void attachChildren();
- void attachChildrenIfNeeded();
void attachChildrenLazily();
void detachChildren();
void detachChildrenIfNeeded();
@@ -175,6 +174,10 @@ private:
Node* m_lastChild;
};
+#ifndef NDEBUG
+bool childAttachedAllowedWhenAttachingChildren(ContainerNode*);
+#endif
+
inline ContainerNode* toContainerNode(Node* node)
{
ASSERT(!node || node->isContainerNode());
@@ -204,13 +207,8 @@ inline void ContainerNode::attachAsNode()
inline void ContainerNode::attachChildren()
{
- for (Node* child = firstChild(); child; child = child->nextSibling())
- child->attach();
-}
-
-inline void ContainerNode::attachChildrenIfNeeded()
-{
for (Node* child = firstChild(); child; child = child->nextSibling()) {
+ ASSERT(!child->attached() || childAttachedAllowedWhenAttachingChildren(this));
if (!child->attached())
child->attach();
}
diff --git a/Source/WebCore/dom/DOMImplementation.idl b/Source/WebCore/dom/DOMImplementation.idl
index e1ff7b973..1b9205420 100644
--- a/Source/WebCore/dom/DOMImplementation.idl
+++ b/Source/WebCore/dom/DOMImplementation.idl
@@ -19,8 +19,7 @@
*/
[
- JSGenerateIsReachable=ImplDocument,
- V8DependentLifetime
+ GenerateIsReachable=ImplDocument,
] interface DOMImplementation {
// DOM Level 1
diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp
index efe89f40f..e85c8f1c0 100644
--- a/Source/WebCore/dom/Document.cpp
+++ b/Source/WebCore/dom/Document.cpp
@@ -797,7 +797,7 @@ void Document::setCompatibilityMode(CompatibilityMode mode)
{
if (m_compatibilityModeLocked || mode == m_compatibilityMode)
return;
- ASSERT(m_styleSheetCollection->authorStyleSheets().isEmpty());
+ ASSERT(m_styleSheetCollection->activeAuthorStyleSheets().isEmpty());
bool wasInQuirksMode = inQuirksMode();
m_compatibilityMode = mode;
selectorQueryCache()->invalidate();
@@ -1926,6 +1926,7 @@ void Document::updateLayout()
updateStyleIfNeeded();
+ StackStats::LayoutCheckPoint layoutCheckPoint;
// Only do a layout if changes have occurred that make it necessary.
FrameView* v = view();
if (v && renderer() && (v->layoutPending() || renderer()->needsLayout()))
@@ -5241,6 +5242,9 @@ void Document::webkitExitFullscreen()
// 6. Return, and run the remaining steps asynchronously.
// 7. Optionally, perform some animation.
+ if (!page())
+ return;
+
// Only exit out of full screen window mode if there are no remaining elements in the
// full screen stack.
if (!newTop) {
diff --git a/Source/WebCore/dom/DocumentOrderedMap.cpp b/Source/WebCore/dom/DocumentOrderedMap.cpp
index 1297e5102..bbd8b3b16 100644
--- a/Source/WebCore/dom/DocumentOrderedMap.cpp
+++ b/Source/WebCore/dom/DocumentOrderedMap.cpp
@@ -55,6 +55,11 @@ inline bool keyMatchesLowercasedMapName(AtomicStringImpl* key, Element* element)
return element->hasTagName(mapTag) && static_cast<HTMLMapElement*>(element)->getName().lower().impl() == key;
}
+inline bool keyMatchesLabelForAttribute(AtomicStringImpl* key, Element* element)
+{
+ return element->hasTagName(labelTag) && element->getAttribute(forAttr).impl() == key;
+}
+
void DocumentOrderedMap::clear()
{
m_map.clear();
@@ -149,5 +154,9 @@ Element* DocumentOrderedMap::getElementByLowercasedMapName(AtomicStringImpl* key
return get<keyMatchesLowercasedMapName>(key, scope);
}
-} // namespace WebCore
+Element* DocumentOrderedMap::getElementByLabelForAttribute(AtomicStringImpl* key, const TreeScope* scope) const
+{
+ return get<keyMatchesLabelForAttribute>(key, scope);
+}
+} // namespace WebCore
diff --git a/Source/WebCore/dom/DocumentOrderedMap.h b/Source/WebCore/dom/DocumentOrderedMap.h
index 7d12686c3..1f9039e61 100644
--- a/Source/WebCore/dom/DocumentOrderedMap.h
+++ b/Source/WebCore/dom/DocumentOrderedMap.h
@@ -52,6 +52,7 @@ public:
Element* getElementById(AtomicStringImpl*, const TreeScope*) const;
Element* getElementByMapName(AtomicStringImpl*, const TreeScope*) const;
Element* getElementByLowercasedMapName(AtomicStringImpl*, const TreeScope*) const;
+ Element* getElementByLabelForAttribute(AtomicStringImpl*, const TreeScope*) const;
void checkConsistency() const;
@@ -80,4 +81,3 @@ inline bool DocumentOrderedMap::containsMultiple(AtomicStringImpl* id) const
} // namespace WebCore
#endif // DocumentOrderedMap_h
-
diff --git a/Source/WebCore/dom/DocumentStyleSheetCollection.cpp b/Source/WebCore/dom/DocumentStyleSheetCollection.cpp
index 84cb8fce9..bfd1e5f0f 100644
--- a/Source/WebCore/dom/DocumentStyleSheetCollection.cpp
+++ b/Source/WebCore/dom/DocumentStyleSheetCollection.cpp
@@ -41,6 +41,7 @@
#include "SVGStyleElement.h"
#include "SelectorChecker.h"
#include "Settings.h"
+#include "StyleInvalidationAnalysis.h"
#include "StyleResolver.h"
#include "StyleSheetContents.h"
#include "StyleSheetList.h"
@@ -347,34 +348,7 @@ void DocumentStyleSheetCollection::collectActiveStyleSheets(Vector<RefPtr<StyleS
}
}
-bool DocumentStyleSheetCollection::testAddedStyleSheetRequiresStyleRecalc(StyleSheetContents* stylesheet)
-{
- // See if all rules on the sheet are scoped to some specific ids or classes.
- // Then test if we actually have any of those in the tree at the moment.
- HashSet<AtomicStringImpl*> idScopes;
- HashSet<AtomicStringImpl*> classScopes;
- if (!StyleResolver::determineStylesheetSelectorScopes(stylesheet, idScopes, classScopes))
- return true;
- // Invalidate the subtrees that match the scopes.
- Node* node = m_document->firstChild();
- while (node) {
- if (!node->isStyledElement()) {
- node = node->traverseNextNode();
- continue;
- }
- StyledElement* element = static_cast<StyledElement*>(node);
- if (SelectorChecker::elementMatchesSelectorScopes(element, idScopes, classScopes)) {
- element->setNeedsStyleRecalc();
- // The whole subtree is now invalidated, we can skip to the next sibling.
- node = node->traverseNextSibling();
- continue;
- }
- node = node->traverseNextNode();
- }
- return false;
-}
-
-void DocumentStyleSheetCollection::analyzeStyleSheetChange(UpdateFlag updateFlag, const Vector<RefPtr<StyleSheet> >& newStylesheets, StyleResolverUpdateType& styleResolverUpdateType, bool& requiresFullStyleRecalc)
+void DocumentStyleSheetCollection::analyzeStyleSheetChange(UpdateFlag updateFlag, const Vector<RefPtr<CSSStyleSheet> >& newStylesheets, StyleResolverUpdateType& styleResolverUpdateType, bool& requiresFullStyleRecalc)
{
styleResolverUpdateType = Reconstruct;
requiresFullStyleRecalc = true;
@@ -398,16 +372,16 @@ void DocumentStyleSheetCollection::analyzeStyleSheetChange(UpdateFlag updateFlag
return;
// Find out which stylesheets are new.
- unsigned oldStylesheetCount = m_authorStyleSheets.size();
+ unsigned oldStylesheetCount = m_activeAuthorStyleSheets.size();
if (newStylesheetCount < oldStylesheetCount)
return;
- Vector<StyleSheet*> addedSheets;
+ Vector<StyleSheetContents*> addedSheets;
unsigned newIndex = 0;
for (unsigned oldIndex = 0; oldIndex < oldStylesheetCount; ++oldIndex) {
if (newIndex >= newStylesheetCount)
return;
- while (m_authorStyleSheets[oldIndex] != newStylesheets[newIndex]) {
- addedSheets.append(newStylesheets[newIndex].get());
+ while (m_activeAuthorStyleSheets[oldIndex] != newStylesheets[newIndex]) {
+ addedSheets.append(newStylesheets[newIndex]->contents());
++newIndex;
if (newIndex == newStylesheetCount)
return;
@@ -416,7 +390,7 @@ void DocumentStyleSheetCollection::analyzeStyleSheetChange(UpdateFlag updateFlag
}
bool hasInsertions = !addedSheets.isEmpty();
while (newIndex < newStylesheetCount) {
- addedSheets.append(newStylesheets[newIndex].get());
+ addedSheets.append(newStylesheets[newIndex]->contents());
++newIndex;
}
// If all new sheets were added at the end of the list we can just add them to existing StyleResolver.
@@ -426,28 +400,33 @@ void DocumentStyleSheetCollection::analyzeStyleSheetChange(UpdateFlag updateFlag
// If we are already parsing the body and so may have significant amount of elements, put some effort into trying to avoid style recalcs.
if (!m_document->body() || m_document->hasNodesWithPlaceholderStyle())
return;
- for (unsigned i = 0; i < addedSheets.size(); ++i) {
- if (!addedSheets[i]->isCSSStyleSheet())
- return;
- if (addedSheets[i]->disabled())
- continue;
- if (testAddedStyleSheetRequiresStyleRecalc(static_cast<CSSStyleSheet*>(addedSheets[i])->contents()))
- return;
- }
+ StyleInvalidationAnalysis invalidationAnalysis(addedSheets);
+ if (invalidationAnalysis.dirtiesAllStyle())
+ return;
+ invalidationAnalysis.invalidateStyle(m_document);
requiresFullStyleRecalc = false;
}
-static bool styleSheetsUseRemUnits(const Vector<RefPtr<StyleSheet> >& sheets)
+static bool styleSheetsUseRemUnits(const Vector<RefPtr<CSSStyleSheet> >& sheets)
{
for (unsigned i = 0; i < sheets.size(); ++i) {
- if (!sheets[i]->isCSSStyleSheet())
- continue;
- if (static_cast<CSSStyleSheet*>(sheets[i].get())->contents()->usesRemUnits())
+ if (sheets[i]->contents()->usesRemUnits())
return true;
}
return false;
}
+static void filterEnabledCSSStyleSheets(Vector<RefPtr<CSSStyleSheet> >& result, const Vector<RefPtr<StyleSheet> >& sheets)
+{
+ for (unsigned i = 0; i < sheets.size(); ++i) {
+ if (!sheets[i]->isCSSStyleSheet())
+ continue;
+ if (sheets[i]->disabled())
+ continue;
+ result.append(static_cast<CSSStyleSheet*>(sheets[i].get()));
+ }
+}
+
bool DocumentStyleSheetCollection::updateActiveStyleSheets(UpdateFlag updateFlag)
{
if (m_document->inStyleRecalc()) {
@@ -462,12 +441,15 @@ bool DocumentStyleSheetCollection::updateActiveStyleSheets(UpdateFlag updateFlag
if (!m_document->renderer() || !m_document->attached())
return false;
- Vector<RefPtr<StyleSheet> > newStylesheets;
- collectActiveStyleSheets(newStylesheets);
+ Vector<RefPtr<StyleSheet> > activeStyleSheets;
+ collectActiveStyleSheets(activeStyleSheets);
+
+ Vector<RefPtr<CSSStyleSheet> > activeCSSStyleSheets;
+ filterEnabledCSSStyleSheets(activeCSSStyleSheets, activeStyleSheets);
StyleResolverUpdateType styleResolverUpdateType;
bool requiresFullStyleRecalc;
- analyzeStyleSheetChange(updateFlag, newStylesheets, styleResolverUpdateType, requiresFullStyleRecalc);
+ analyzeStyleSheetChange(updateFlag, activeCSSStyleSheets, styleResolverUpdateType, requiresFullStyleRecalc);
if (styleResolverUpdateType == Reconstruct)
m_document->clearStyleResolver();
@@ -475,16 +457,17 @@ bool DocumentStyleSheetCollection::updateActiveStyleSheets(UpdateFlag updateFlag
StyleResolver* styleResolver = m_document->styleResolver();
if (styleResolverUpdateType == Reset) {
styleResolver->resetAuthorStyle();
- styleResolver->appendAuthorStylesheets(0, newStylesheets);
+ styleResolver->appendAuthorStyleSheets(0, activeCSSStyleSheets);
} else {
ASSERT(styleResolverUpdateType == Additive);
- styleResolver->appendAuthorStylesheets(m_authorStyleSheets.size(), newStylesheets);
+ styleResolver->appendAuthorStyleSheets(m_activeAuthorStyleSheets.size(), activeCSSStyleSheets);
}
resetCSSFeatureFlags();
}
- m_authorStyleSheets.swap(newStylesheets);
+ m_activeAuthorStyleSheets.swap(activeCSSStyleSheets);
+ m_styleSheetsForStyleSheetList.swap(activeStyleSheets);
- m_usesRemUnits = styleSheetsUseRemUnits(m_authorStyleSheets);
+ m_usesRemUnits = styleSheetsUseRemUnits(m_activeAuthorStyleSheets);
m_needsUpdateActiveStylesheetsOnStyleRecalc = false;
m_document->notifySeamlessChildDocumentsOfStylesheetUpdate();
@@ -498,7 +481,8 @@ void DocumentStyleSheetCollection::reportMemoryUsage(MemoryObjectInfo* memoryObj
info.addMember(m_pageUserSheet);
info.addMember(m_pageGroupUserSheets);
info.addMember(m_userSheets);
- info.addMember(m_authorStyleSheets);
+ info.addMember(m_activeAuthorStyleSheets);
+ info.addMember(m_styleSheetsForStyleSheetList);
info.addListHashSet(m_styleSheetCandidateNodes);
info.addMember(m_preferredStylesheetSetName);
info.addMember(m_selectedStylesheetSetName);
diff --git a/Source/WebCore/dom/DocumentStyleSheetCollection.h b/Source/WebCore/dom/DocumentStyleSheetCollection.h
index 3fb45f9ed..b67d88866 100644
--- a/Source/WebCore/dom/DocumentStyleSheetCollection.h
+++ b/Source/WebCore/dom/DocumentStyleSheetCollection.h
@@ -49,7 +49,9 @@ public:
DocumentStyleSheetCollection(Document*);
~DocumentStyleSheetCollection();
- const Vector<RefPtr<StyleSheet> >& authorStyleSheets() { return m_authorStyleSheets; }
+ const Vector<RefPtr<StyleSheet> >& styleSheetsForStyleSheetList() { return m_styleSheetsForStyleSheetList; }
+
+ const Vector<RefPtr<CSSStyleSheet> >& activeAuthorStyleSheets() { return m_activeAuthorStyleSheets; }
CSSStyleSheet* pageUserSheet();
const Vector<RefPtr<CSSStyleSheet> >* pageGroupUserSheets() const;
@@ -101,17 +103,17 @@ public:
private:
void collectActiveStyleSheets(Vector<RefPtr<StyleSheet> >&);
- bool testAddedStyleSheetRequiresStyleRecalc(StyleSheetContents*);
enum StyleResolverUpdateType {
Reconstruct,
Reset,
Additive
};
- void analyzeStyleSheetChange(UpdateFlag, const Vector<RefPtr<StyleSheet> >& newStylesheets, StyleResolverUpdateType&, bool& requiresFullStyleRecalc);
+ void analyzeStyleSheetChange(UpdateFlag, const Vector<RefPtr<CSSStyleSheet> >& newStylesheets, StyleResolverUpdateType&, bool& requiresFullStyleRecalc);
Document* m_document;
- Vector<RefPtr<StyleSheet> > m_authorStyleSheets;
+ Vector<RefPtr<StyleSheet> > m_styleSheetsForStyleSheetList;
+ Vector<RefPtr<CSSStyleSheet> > m_activeAuthorStyleSheets;
// Track the number of currently loading top-level stylesheets needed for rendering.
// Sheets loaded using the @import directive are not included in this count.
diff --git a/Source/WebCore/dom/Element.cpp b/Source/WebCore/dom/Element.cpp
index 7cba51f0d..97dc9c9f6 100644
--- a/Source/WebCore/dom/Element.cpp
+++ b/Source/WebCore/dom/Element.cpp
@@ -48,6 +48,7 @@
#include "HTMLElement.h"
#include "HTMLFormCollection.h"
#include "HTMLFrameOwnerElement.h"
+#include "HTMLLabelElement.h"
#include "HTMLNames.h"
#include "HTMLOptionsCollection.h"
#include "HTMLParserIdioms.h"
@@ -959,17 +960,15 @@ Node::InsertionNotificationRequest Element::insertedInto(ContainerNode* insertio
if (!nameValue.isNull())
updateName(nullAtom, nameValue);
- return InsertionDone;
-}
+ if (hasTagName(labelTag)) {
+ TreeScope* scope = treeScope();
+ if (scope->shouldCacheLabelsByForAttribute())
+ updateLabel(scope, nullAtom, fastGetAttribute(forAttr));
+ }
-static inline TreeScope* treeScopeOfParent(Node* node, ContainerNode* insertionPoint)
-{
- if (Node* parent = node->parentNode())
- parent->treeScope();
- return insertionPoint->treeScope();
+ return InsertionDone;
}
-
void Element::removedFrom(ContainerNode* insertionPoint)
{
#if ENABLE(FULLSCREEN_API)
@@ -986,11 +985,17 @@ void Element::removedFrom(ContainerNode* insertionPoint)
if (insertionPoint->inDocument()) {
const AtomicString& idValue = getIdAttribute();
if (!idValue.isNull() && inDocument())
- updateId(treeScopeOfParent(this, insertionPoint), idValue, nullAtom);
+ updateId(insertionPoint->treeScope(), idValue, nullAtom);
const AtomicString& nameValue = getNameAttribute();
if (!nameValue.isNull())
updateName(nameValue, nullAtom);
+
+ if (hasTagName(labelTag)) {
+ TreeScope* treeScope = insertionPoint->treeScope();
+ if (treeScope->shouldCacheLabelsByForAttribute())
+ updateLabel(treeScope, fastGetAttribute(forAttr), nullAtom);
+ }
}
ContainerNode::removedFrom(insertionPoint);
@@ -1011,7 +1016,7 @@ void Element::attach()
if (ElementShadow* shadow = this->shadow()) {
parentPusher.push();
shadow->attach();
- attachChildrenIfNeeded();
+ attachChildren();
attachAsNode();
} else {
if (firstChild())
@@ -2133,12 +2138,33 @@ bool Element::hasNamedNodeMap() const
}
#endif
+void Element::updateLabel(TreeScope* scope, const AtomicString& oldForAttributeValue, const AtomicString& newForAttributeValue)
+{
+ ASSERT(hasTagName(labelTag));
+
+ if (!inDocument())
+ return;
+
+ if (oldForAttributeValue == newForAttributeValue)
+ return;
+
+ if (!oldForAttributeValue.isEmpty())
+ scope->removeLabel(oldForAttributeValue, static_cast<HTMLLabelElement*>(this));
+ if (!newForAttributeValue.isEmpty())
+ scope->addLabel(newForAttributeValue, static_cast<HTMLLabelElement*>(this));
+}
+
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);
+ else if (name == HTMLNames::forAttr && hasTagName(labelTag)) {
+ TreeScope* scope = treeScope();
+ if (scope->shouldCacheLabelsByForAttribute())
+ updateLabel(scope, oldValue, newValue);
+ }
#if ENABLE(MUTATION_OBSERVERS)
if (OwnPtr<MutationObserverInterestGroup> recipients = MutationObserverInterestGroup::createForAttributesMutation(this, name))
diff --git a/Source/WebCore/dom/Element.h b/Source/WebCore/dom/Element.h
index 58e297d15..519c50d77 100644
--- a/Source/WebCore/dom/Element.h
+++ b/Source/WebCore/dom/Element.h
@@ -315,6 +315,7 @@ public:
void updateId(const AtomicString& oldId, const AtomicString& newId);
void updateId(TreeScope*, const AtomicString& oldId, const AtomicString& newId);
void updateName(const AtomicString& oldName, const AtomicString& newName);
+ void updateLabel(TreeScope*, const AtomicString& oldForAttributeValue, const AtomicString& newForAttributeValue);
void removeCachedHTMLCollection(HTMLCollection*, CollectionType);
diff --git a/Source/WebCore/dom/QualifiedName.cpp b/Source/WebCore/dom/QualifiedName.cpp
index 783604732..daf11ce0c 100644
--- a/Source/WebCore/dom/QualifiedName.cpp
+++ b/Source/WebCore/dom/QualifiedName.cpp
@@ -135,6 +135,12 @@ void QualifiedName::init()
}
}
+const QualifiedName& nullQName()
+{
+ DEFINE_STATIC_LOCAL(QualifiedName, nullName, (nullAtom, nullAtom, nullAtom));
+ return nullName;
+}
+
const AtomicString& QualifiedName::localNameUpper() const
{
if (!m_impl->m_localNameUpper)
@@ -158,6 +164,12 @@ void QualifiedName::QualifiedNameImpl::reportMemoryUsage(MemoryObjectInfo* memor
info.addMember(m_localNameUpper);
}
+unsigned QualifiedName::QualifiedNameImpl::computeHash() const
+{
+ QualifiedNameComponents components = { m_prefix.impl(), m_localName.impl(), m_namespace.impl() };
+ return hashComponents(components);
+}
+
void createQualifiedName(void* targetAddress, const char* name, unsigned nameLength, const AtomicString& nameNamespace)
{
AtomicString atomicName(name, nameLength, AtomicString::ConstructFromLiteral);
diff --git a/Source/WebCore/dom/QualifiedName.h b/Source/WebCore/dom/QualifiedName.h
index 28fab552c..cb84611a3 100644
--- a/Source/WebCore/dom/QualifiedName.h
+++ b/Source/WebCore/dom/QualifiedName.h
@@ -44,6 +44,9 @@ public:
return adoptRef(new QualifiedNameImpl(prefix, localName, namespaceURI));
}
+ unsigned computeHash() const;
+
+ mutable unsigned m_existingHash;
const AtomicString m_prefix;
const AtomicString m_localName;
const AtomicString m_namespace;
@@ -53,7 +56,8 @@ public:
private:
QualifiedNameImpl(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI)
- : m_prefix(prefix)
+ : m_existingHash(0)
+ , m_prefix(prefix)
, m_localName(localName)
, m_namespace(namespaceURI)
{
@@ -110,6 +114,8 @@ extern const QualifiedName anyName;
inline const QualifiedName& anyQName() { return anyName; }
#endif
+const QualifiedName& nullQName();
+
inline bool operator==(const AtomicString& a, const QualifiedName& q) { return a == q.localName(); }
inline bool operator!=(const AtomicString& a, const QualifiedName& q) { return a != q.localName(); }
inline bool operator==(const QualifiedName& q, const AtomicString& a) { return a == q.localName(); }
@@ -125,8 +131,9 @@ struct QualifiedNameHash {
static unsigned hash(const QualifiedName::QualifiedNameImpl* name)
{
- QualifiedNameComponents c = { name->m_prefix.impl(), name->m_localName.impl(), name->m_namespace.impl() };
- return hashComponents(c);
+ if (!name->m_existingHash)
+ name->m_existingHash = name->computeHash();
+ return name->m_existingHash;
}
static bool equal(const QualifiedName& a, const QualifiedName& b) { return a == b; }
@@ -150,7 +157,7 @@ namespace WTF {
template<> struct HashTraits<WebCore::QualifiedName> : SimpleClassHashTraits<WebCore::QualifiedName> {
static const bool emptyValueIsZero = false;
- static WebCore::QualifiedName emptyValue() { return WebCore::QualifiedName(nullAtom, nullAtom, nullAtom); }
+ static WebCore::QualifiedName emptyValue() { return WebCore::nullQName(); }
};
}
diff --git a/Source/WebCore/dom/ShadowRoot.cpp b/Source/WebCore/dom/ShadowRoot.cpp
index 5180a1c22..0da9f27a9 100644
--- a/Source/WebCore/dom/ShadowRoot.cpp
+++ b/Source/WebCore/dom/ShadowRoot.cpp
@@ -215,7 +215,7 @@ void ShadowRoot::attach()
{
StyleResolver* styleResolver = document()->styleResolver();
styleResolver->pushParentShadowRoot(this);
- attachChildrenIfNeeded();
+ attachChildren();
attachAsNode();
styleResolver->popParentShadowRoot(this);
}
diff --git a/Source/WebCore/dom/TreeScope.cpp b/Source/WebCore/dom/TreeScope.cpp
index afd343fb6..ec723d3da 100644
--- a/Source/WebCore/dom/TreeScope.cpp
+++ b/Source/WebCore/dom/TreeScope.cpp
@@ -36,6 +36,7 @@
#include "Frame.h"
#include "HTMLAnchorElement.h"
#include "HTMLFrameOwnerElement.h"
+#include "HTMLLabelElement.h"
#include "HTMLMapElement.h"
#include "HTMLNames.h"
#include "IdTargetObserverRegistry.h"
@@ -55,6 +56,7 @@ using namespace HTMLNames;
TreeScope::TreeScope(ContainerNode* rootNode)
: m_rootNode(rootNode)
, m_parentTreeScope(0)
+ , m_shouldCacheLabelsByForAttribute(false)
, m_idTargetObserverRegistry(IdTargetObserverRegistry::create())
{
ASSERT(rootNode);
@@ -72,6 +74,7 @@ void TreeScope::destroyTreeScopeData()
{
m_elementsById.clear();
m_imageMapsByName.clear();
+ m_labelsByForAttribute.clear();
}
void TreeScope::setParentTreeScope(TreeScope* newParentScope)
@@ -144,6 +147,36 @@ HTMLMapElement* TreeScope::getImageMap(const String& url) const
return static_cast<HTMLMapElement*>(m_imageMapsByName.getElementByMapName(AtomicString(name).impl(), this));
}
+void TreeScope::addLabel(const AtomicString& forAttributeValue, HTMLLabelElement* element)
+{
+ m_labelsByForAttribute.add(forAttributeValue.impl(), element);
+}
+
+void TreeScope::removeLabel(const AtomicString& forAttributeValue, HTMLLabelElement* element)
+{
+ m_labelsByForAttribute.remove(forAttributeValue.impl(), element);
+}
+
+HTMLLabelElement* TreeScope::labelElementForId(const AtomicString& forAttributeValue)
+{
+ if (!m_shouldCacheLabelsByForAttribute) {
+ m_shouldCacheLabelsByForAttribute = true;
+ for (Node* node = rootNode(); node; node = node->traverseNextNode()) {
+ if (node->hasTagName(labelTag)) {
+ HTMLLabelElement* label = static_cast<HTMLLabelElement*>(node);
+ const AtomicString& forValue = label->fastGetAttribute(forAttr);
+ if (!forValue.isEmpty())
+ addLabel(forValue, label);
+ }
+ }
+ }
+
+ if (forAttributeValue.isEmpty())
+ return 0;
+
+ return static_cast<HTMLLabelElement*>(m_labelsByForAttribute.getElementByLabelForAttribute(forAttributeValue.impl(), this));
+}
+
DOMSelection* TreeScope::getSelection() const
{
if (!rootNode()->document()->frame())
diff --git a/Source/WebCore/dom/TreeScope.h b/Source/WebCore/dom/TreeScope.h
index d9758b028..9cae54de8 100644
--- a/Source/WebCore/dom/TreeScope.h
+++ b/Source/WebCore/dom/TreeScope.h
@@ -35,6 +35,7 @@ namespace WebCore {
class ContainerNode;
class DOMSelection;
class Element;
+class HTMLLabelElement;
class HTMLMapElement;
class IdTargetObserverRegistry;
class Node;
@@ -62,6 +63,12 @@ public:
void removeImageMap(HTMLMapElement*);
HTMLMapElement* getImageMap(const String& url) const;
+ // For accessibility.
+ bool shouldCacheLabelsByForAttribute() const { return m_shouldCacheLabelsByForAttribute; }
+ void addLabel(const AtomicString& forAttributeValue, HTMLLabelElement*);
+ void removeLabel(const AtomicString& forAttributeValue, HTMLLabelElement*);
+ HTMLLabelElement* labelElementForId(const AtomicString& forAttributeValue);
+
DOMSelection* getSelection() const;
// Find first anchor with the given name.
@@ -94,6 +101,9 @@ private:
DocumentOrderedMap m_elementsById;
DocumentOrderedMap m_imageMapsByName;
+ DocumentOrderedMap m_labelsByForAttribute;
+ bool m_shouldCacheLabelsByForAttribute;
+
OwnPtr<IdTargetObserverRegistry> m_idTargetObserverRegistry;
mutable RefPtr<DOMSelection> m_selection;
diff --git a/Source/WebCore/dom/WheelEvent.cpp b/Source/WebCore/dom/WheelEvent.cpp
index e76c33ace..e76c33ace 100755..100644
--- a/Source/WebCore/dom/WheelEvent.cpp
+++ b/Source/WebCore/dom/WheelEvent.cpp
diff --git a/Source/WebCore/dom/WheelEvent.h b/Source/WebCore/dom/WheelEvent.h
index 13576890d..13576890d 100755..100644
--- a/Source/WebCore/dom/WheelEvent.h
+++ b/Source/WebCore/dom/WheelEvent.h