diff options
Diffstat (limited to 'Source/WebCore/dom')
-rw-r--r-- | Source/WebCore/dom/ContainerNode.cpp | 21 | ||||
-rw-r--r-- | Source/WebCore/dom/ContainerNode.h | 12 | ||||
-rw-r--r-- | Source/WebCore/dom/DOMImplementation.idl | 3 | ||||
-rw-r--r-- | Source/WebCore/dom/Document.cpp | 6 | ||||
-rw-r--r-- | Source/WebCore/dom/DocumentOrderedMap.cpp | 11 | ||||
-rw-r--r-- | Source/WebCore/dom/DocumentOrderedMap.h | 2 | ||||
-rw-r--r-- | Source/WebCore/dom/DocumentStyleSheetCollection.cpp | 90 | ||||
-rw-r--r-- | Source/WebCore/dom/DocumentStyleSheetCollection.h | 10 | ||||
-rw-r--r-- | Source/WebCore/dom/Element.cpp | 46 | ||||
-rw-r--r-- | Source/WebCore/dom/Element.h | 1 | ||||
-rw-r--r-- | Source/WebCore/dom/QualifiedName.cpp | 12 | ||||
-rw-r--r-- | Source/WebCore/dom/QualifiedName.h | 15 | ||||
-rw-r--r-- | Source/WebCore/dom/ShadowRoot.cpp | 2 | ||||
-rw-r--r-- | Source/WebCore/dom/TreeScope.cpp | 33 | ||||
-rw-r--r-- | Source/WebCore/dom/TreeScope.h | 10 | ||||
-rw-r--r--[-rwxr-xr-x] | Source/WebCore/dom/WheelEvent.cpp | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | Source/WebCore/dom/WheelEvent.h | 0 |
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 |