Changeset 149652 in webkit
- Timestamp:
- May 6, 2013 5:20:05 PM (11 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 25 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r149648 r149652 1 2013-05-06 Ryosuke Niwa <rniwa@webkit.org> 2 3 Unify ways to cache named item in HTMLCollections 4 https://bugs.webkit.org/show_bug.cgi?id=115584 5 6 Reviewed by Antti Koivisto. 7 8 Refactor the code to share the same infrastructure for both id and name attributes maps. 9 10 Also get rid of shouldRegisterAsNamedItem and shouldRegisterAsExtraNamedItem from various Element subclasses 11 as these member functions were duplicating the information in HTMLNameCollection.cpp. Nevertheless, HTMLImageElement 12 and HTMLObjectElement still update HTMLDocument's window and document name getter maps when their presence as named 13 item changes due to an attribute change and children changes respectively. 14 15 * bindings/js/JSDOMWindowCustom.cpp: 16 (WebCore::namedItemGetter): Use windowNamedItemMap().containsSingle() instead of collection->hasExactlyOneItem() to 17 avoid instantiating HTMLCollection until we know for sure we're returning multiple items. 18 (WebCore::JSDOMWindow::getOwnPropertySlot): Call windowNamedItemMap().contains() instead of document->hasNamedItem() 19 since the latter has been removed. 20 (WebCore::JSDOMWindow::getOwnPropertySlotByIndex): Ditto. 21 (WebCore::JSDOMWindow::getOwnPropertyDescriptor): Ditto. 22 23 * bindings/js/JSHTMLDocumentCustom.cpp: 24 (WebCore::JSHTMLDocument::canGetItemsForName): Call documentNamedItemMap().contains() instead of 25 document->hasExtraNamedItem() since the latter has been removed. 26 (WebCore::JSHTMLDocument::nameGetter): Use documentNamedItemMap().containsSingle() instead of 27 collection->hasExactlyOneItem() to avoid instantiating HTMLCollection when we're returning the first item. 28 29 * dom/Document.cpp: 30 (WebCore::Document::windowNamedItems): Instantiate WindowNameCollection, which is a subclass of HTMLNameCollection, 31 instead of HTMLNameCollection since the latter class no longer has a public constructor. 32 (WebCore::Document::documentNamedItems): Ditto; instantiate DocumentNameCollection. 33 34 * dom/DocumentOrderedMap.cpp: 35 (WebCore::keyMatchesName): Added for name attribute. 36 (WebCore::keyMatchesWindowNamedItem): Added for window name getter. 37 (WebCore::keyMatchesDocumentNamedItem): Added for document name getter. 38 (WebCore::DocumentOrderedMap::getElementByName): Added for name attribute. 39 (WebCore::DocumentOrderedMap::getElementByWindowNamedItem): Added for window name getter. 40 (WebCore::DocumentOrderedMap::getElementByDocumentNamedItem): Added for document name getter. 41 42 * dom/DocumentOrderedMap.h: 43 (WebCore::DocumentOrderedMap::containsSingle): Added. 44 (WebCore::DocumentOrderedMap::containsMultiple): Fixed the bug that containsMultiple returns true even when 45 the duplicate count has been reduced to 1. Unfortunately this behavior change is not testable because the old code 46 worked properly (though less efficient) even if this function returned a wrong value. 47 48 * dom/Element.cpp: 49 (WebCore::Element::insertedInto): 50 (WebCore::Element::removedFrom): 51 (WebCore::Element::updateName): Added. Updates TreeScope's name attribute map as well as HTMLDocument's window name 52 and document name maps. 53 (WebCore::Element::updateId): Added the code to update HTMLDocument's window name and document name maps. 54 55 * dom/Element.h: 56 (Element): Removed shouldRegisterAsNamedItem, shouldRegisterAsExtraNamedItem, updateNamedItemRegistration, and 57 updateExtraNamedItemRegistration as they're no longer used. 58 59 * dom/TreeScope.cpp: 60 (SameSizeAsTreeScope): 61 (WebCore::TreeScope::getElementByName): Added. 62 (WebCore::TreeScope::addElementByName): Added. 63 (WebCore::TreeScope::removeElementByName): Added. 64 65 * dom/TreeScope.h: 66 (WebCore::TreeScope::hasElementWithName): Added. 67 (WebCore::TreeScope::containsMultipleElementsWithName): Added. 68 69 * html/HTMLAppletElement.h: 70 (HTMLAppletElement): 71 72 * html/HTMLCollection.cpp: 73 (WebCore::isMatchingElement): Use HTMLNameCollection subclasses' nodeMatches. 74 (WebCore::HTMLCollection::namedItem): Added a fast path for named item. 75 (WebCore::HTMLCollection::hasNamedItem): Use namedItem to avoid the work in the fast path. 76 77 * html/HTMLCollection.h: 78 (HTMLCollection): Removed checkForNameMatch. 79 * html/HTMLDocument.cpp: 80 (WebCore): Removed various member functions related to m_namedItemCounts and m_extraNamedItemCounts. 81 82 * html/HTMLDocument.h: 83 (WebCore::HTMLDocument::documentNamedItemMap): Added. 84 (WebCore::HTMLDocument::windowNamedItemMap): Added. 85 (HTMLDocument): Replaced m_namedItemCounts and m_extraNamedItemCounts by m_documentNamedItem and m_windowNamedItem. 86 Note that they're not one to one. 87 88 * html/HTMLEmbedElement.h: 89 (HTMLEmbedElement): 90 91 * html/HTMLFormElement.h: 92 (HTMLFormElement): 93 94 * html/HTMLIFrameElement.cpp: Removed the code to track the element's name since we already do this in Element. 95 (WebCore::HTMLIFrameElement::parseAttribute): 96 97 * html/HTMLIFrameElement.h: 98 (HTMLIFrameElement): 99 100 * html/HTMLImageElement.cpp: 101 (WebCore::HTMLImageElement::parseAttribute): Update the HTMLDocument's maps when the name attribute's existence 102 changes its presence on window and document name getters in turn. This behavior change, again, appears to be 103 untestable due to the old being more graceful when DocumentOrderedMap returned a wrong value. 104 105 * html/HTMLImageElement.h: 106 107 * html/HTMLNameCollection.cpp: 108 (WebCore::HTMLNameCollection::HTMLNameCollection): No longer overrides itemAfter. This enables backwards traversals 109 of the tree along with other optimizations in HTMLCollection. 110 111 (WebCore::WindowNameCollection::nodeMatchesIfNameAttributeMatch): Added. Used in Element::updateName to determine 112 whether add() or remove() should be called on HTMLDocument's maps. 113 (WebCore::WindowNameCollection::nodeMatches): Added. 114 115 (WebCore::DocumentNameCollection::nodeMatchesIfIdAttributeMatch): Added. Used in Element::updateName to determine 116 whether add() or remove() should be called on HTMLDocument's maps. 117 (WebCore::DocumentNameCollection::nodeMatchesIfNameAttributeMatch): Ditto. 118 (WebCore::DocumentNameCollection::nodeMatches): Added. 119 120 * html/HTMLNameCollection.h: 121 (HTMLNameCollection): Removed create since this class shouldn't be instantiated on its own. 122 123 (WebCore::WindowNameCollection): Added. 124 (WebCore::WindowNameCollection::create): Added. 125 (WebCore::WindowNameCollection::nodeMatches): Added. 126 (WebCore::WindowNameCollection::nodeMatchesIfIdAttributeMatch): Added. 127 (WebCore::WindowNameCollection::WindowNameCollection): Added. 128 (WebCore::DocumentNameCollection): Added. 129 (WebCore::DocumentNameCollection::create): Added. 130 (WebCore::DocumentNameCollection::nodeMatches): Added. 131 (WebCore::DocumentNameCollection::DocumentNameCollection): Added. 132 133 * html/HTMLObjectElement.cpp: 134 (WebCore::HTMLObjectElement::updateDocNamedItem): Update both window and document getter maps of HTMLDocument when 135 the visibility of this element changes due to the DOM mutations in the subtree. 136 137 * html/HTMLObjectElement.h: 138 (WebCore::HTMLObjectElement): 139 (WebCore::toHTMLObjectElement): Added. 140 1 141 2013-05-06 Andreas Kling <akling@apple.com> 2 142 -
trunk/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp
r148696 r149652 96 96 ASSERT(document->isHTMLDocument()); 97 97 98 RefPtr<HTMLCollection> collection = document->windowNamedItems(propertyNameToAtomicString(propertyName)); 99 if (collection->hasExactlyOneItem()) 100 return toJS(exec, thisObj, collection->item(0)); 101 return toJS(exec, thisObj, WTF::getPtr(collection)); 98 AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName); 99 if (!atomicPropertyName || !toHTMLDocument(document)->windowNamedItemMap().contains(atomicPropertyName)) 100 return jsUndefined(); 101 102 if (UNLIKELY(!toHTMLDocument(document)->windowNamedItemMap().containsSingle(atomicPropertyName))) { 103 RefPtr<HTMLCollection> collection = document->windowNamedItems(atomicPropertyName); 104 ASSERT(!collection->isEmpty()); 105 ASSERT(!collection->hasExactlyOneItem()); 106 return toJS(exec, thisObj->globalObject(), WTF::getPtr(collection)); 107 } 108 109 Node* node = toHTMLDocument(document)->windowNamedItemMap().getElementByWindowNamedItem(atomicPropertyName, document); 110 return toJS(exec, thisObj->globalObject(), node); 102 111 } 103 112 … … 239 248 if (document->isHTMLDocument()) { 240 249 AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName); 241 if (atomicPropertyName && (toHTMLDocument(document)->hasNamedItem(atomicPropertyName) || document->hasElementWithId(atomicPropertyName))) {250 if (atomicPropertyName && toHTMLDocument(document)->windowNamedItemMap().contains(atomicPropertyName)) { 242 251 slot.setCustom(thisObject, namedItemGetter); 243 252 return true; … … 315 324 if (document->isHTMLDocument()) { 316 325 AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName); 317 if (atomicPropertyName && (toHTMLDocument(document)->hasNamedItem(atomicPropertyName) || document->hasElementWithId(atomicPropertyName))) {326 if (atomicPropertyName && toHTMLDocument(document)->windowNamedItemMap().contains(atomicPropertyName)) { 318 327 slot.setCustom(thisObject, namedItemGetter); 319 328 return true; … … 386 395 if (document->isHTMLDocument()) { 387 396 AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName); 388 if (atomicPropertyName && (toHTMLDocument(document)->hasNamedItem(atomicPropertyName) || document->hasElementWithId(atomicPropertyName))) {397 if (atomicPropertyName && toHTMLDocument(document)->windowNamedItemMap().contains(atomicPropertyName)) { 389 398 PropertySlot slot; 390 399 slot.setCustom(thisObject, namedItemGetter); -
trunk/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp
r148696 r149652 55 55 { 56 56 AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName); 57 return atomicPropertyName && (document->hasNamedItem(atomicPropertyName) || document->hasExtraNamedItem(atomicPropertyName));57 return atomicPropertyName && document->documentNamedItemMap().contains(atomicPropertyName); 58 58 } 59 59 … … 63 63 HTMLDocument* document = toHTMLDocument(thisObj->impl()); 64 64 65 RefPtr<HTMLCollection> collection = document->documentNamedItems(propertyNameToAtomicString(propertyName)); 66 67 if (collection->isEmpty()) 65 AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName); 66 if (!atomicPropertyName || !document->documentNamedItemMap().contains(atomicPropertyName)) 68 67 return jsUndefined(); 69 68 70 if (collection->hasExactlyOneItem()) { 71 Node* node = collection->item(0); 69 if (UNLIKELY(!document->documentNamedItemMap().containsSingle(atomicPropertyName))) { 70 RefPtr<HTMLCollection> collection = document->documentNamedItems(atomicPropertyName); 71 ASSERT(!collection->isEmpty()); 72 ASSERT(!collection->hasExactlyOneItem()); 73 return toJS(exec, thisObj->globalObject(), WTF::getPtr(collection)); 74 } 72 75 73 Frame* frame; 74 if (node->hasTagName(iframeTag) && (frame = static_cast<HTMLIFrameElement*>(node)->contentFrame())) 75 return toJS(exec, frame); 76 Node* node = document->documentNamedItemMap().getElementByDocumentNamedItem(atomicPropertyName, document); 77 Frame* frame; 78 if (node->hasTagName(iframeTag) && (frame = static_cast<HTMLIFrameElement*>(node)->contentFrame())) 79 return toJS(exec, frame); 76 80 77 return toJS(exec, thisObj->globalObject(), node); 78 } 79 80 return toJS(exec, thisObj->globalObject(), WTF::getPtr(collection)); 81 return toJS(exec, thisObj->globalObject(), node); 81 82 } 82 83 -
trunk/Source/WebCore/dom/Document.cpp
r149648 r149652 4420 4420 PassRefPtr<HTMLCollection> Document::windowNamedItems(const AtomicString& name) 4421 4421 { 4422 return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName< HTMLNameCollection>(this, WindowNamedItems, name);4422 return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<WindowNameCollection>(this, WindowNamedItems, name); 4423 4423 } 4424 4424 4425 4425 PassRefPtr<HTMLCollection> Document::documentNamedItems(const AtomicString& name) 4426 4426 { 4427 return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName< HTMLNameCollection>(this, DocumentNamedItems, name);4427 return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<DocumentNameCollection>(this, DocumentNamedItems, name); 4428 4428 } 4429 4429 -
trunk/Source/WebCore/dom/DocumentOrderedMap.cpp
r148921 r149652 34 34 #include "Element.h" 35 35 #include "HTMLMapElement.h" 36 #include "HTMLNameCollection.h" 36 37 #include "HTMLNames.h" 37 38 #include "NodeTraversal.h" … … 45 46 { 46 47 return element->getIdAttribute().impl() == key; 48 } 49 50 inline bool keyMatchesName(AtomicStringImpl* key, Element* element) 51 { 52 return element->getNameAttribute().impl() == key; 47 53 } 48 54 … … 60 66 { 61 67 return element->hasTagName(labelTag) && element->getAttribute(forAttr).impl() == key; 68 } 69 70 inline bool keyMatchesWindowNamedItem(AtomicStringImpl* key, Element* element) 71 { 72 return WindowNameCollection::nodeMatches(element, key); 73 } 74 75 inline bool keyMatchesDocumentNamedItem(AtomicStringImpl* key, Element* element) 76 { 77 return DocumentNameCollection::nodeMatches(element, key); 62 78 } 63 79 … … 143 159 } 144 160 161 Element* DocumentOrderedMap::getElementByName(AtomicStringImpl* key, const TreeScope* scope) const 162 { 163 return get<keyMatchesName>(key, scope); 164 } 165 145 166 Element* DocumentOrderedMap::getElementByMapName(AtomicStringImpl* key, const TreeScope* scope) const 146 167 { … … 158 179 } 159 180 181 Element* DocumentOrderedMap::getElementByWindowNamedItem(AtomicStringImpl* key, const TreeScope* scope) const 182 { 183 return get<keyMatchesWindowNamedItem>(key, scope); 184 } 185 186 Element* DocumentOrderedMap::getElementByDocumentNamedItem(AtomicStringImpl* key, const TreeScope* scope) const 187 { 188 return get<keyMatchesDocumentNamedItem>(key, scope); 189 } 190 160 191 } // namespace WebCore -
trunk/Source/WebCore/dom/DocumentOrderedMap.h
r148921 r149652 48 48 49 49 bool contains(AtomicStringImpl*) const; 50 bool containsSingle(AtomicStringImpl*) const; 50 51 bool containsMultiple(AtomicStringImpl*) const; 51 52 // concrete instantiations of the get<>() method template 52 53 Element* getElementById(AtomicStringImpl*, const TreeScope*) const; 54 Element* getElementByName(AtomicStringImpl*, const TreeScope*) const; 53 55 Element* getElementByMapName(AtomicStringImpl*, const TreeScope*) const; 54 56 Element* getElementByLowercasedMapName(AtomicStringImpl*, const TreeScope*) const; 55 57 Element* getElementByLabelForAttribute(AtomicStringImpl*, const TreeScope*) const; 58 Element* getElementByWindowNamedItem(AtomicStringImpl*, const TreeScope*) const; 59 Element* getElementByDocumentNamedItem(AtomicStringImpl*, const TreeScope*) const; 56 60 57 61 void checkConsistency() const; … … 69 73 }; 70 74 75 inline bool DocumentOrderedMap::containsSingle(AtomicStringImpl* id) const 76 { 77 return (m_map.contains(id) ? 1 : 0) + m_duplicateCounts.count(id) == 1; 78 } 79 71 80 inline bool DocumentOrderedMap::contains(AtomicStringImpl* id) const 72 81 { … … 76 85 inline bool DocumentOrderedMap::containsMultiple(AtomicStringImpl* id) const 77 86 { 78 return m_duplicateCounts.contains(id);87 return (m_map.contains(id) ? 1 : 0) + m_duplicateCounts.count(id) > 1; 79 88 } 80 89 -
trunk/Source/WebCore/dom/Element.cpp
r149549 r149652 53 53 #include "HTMLFrameOwnerElement.h" 54 54 #include "HTMLLabelElement.h" 55 #include "HTMLNameCollection.h" 55 56 #include "HTMLNames.h" 56 57 #include "HTMLOptionsCollection.h" … … 1218 1219 const AtomicString& nameValue = getNameAttribute(); 1219 1220 if (!nameValue.isNull()) 1220 updateName( nullAtom, nameValue);1221 updateName(scope, nullAtom, nameValue); 1221 1222 1222 1223 if (hasTagName(labelTag)) { … … 1261 1262 const AtomicString& nameValue = getNameAttribute(); 1262 1263 if (!nameValue.isNull()) 1263 updateName( nameValue, nullAtom);1264 updateName(insertionPoint->treeScope(), nameValue, nullAtom); 1264 1265 1265 1266 if (hasTagName(labelTag)) { … … 2660 2661 inline void Element::updateName(const AtomicString& oldName, const AtomicString& newName) 2661 2662 { 2662 if (!i nDocument() || isInShadowTree())2663 if (!isInTreeScope()) 2663 2664 return; 2664 2665 … … 2666 2667 return; 2667 2668 2668 if (shouldRegisterAsNamedItem()) 2669 updateNamedItemRegistration(oldName, newName); 2669 updateName(treeScope(), oldName, newName); 2670 } 2671 2672 void Element::updateName(TreeScope* scope, const AtomicString& oldName, const AtomicString& newName) 2673 { 2674 ASSERT(isInTreeScope()); 2675 ASSERT(oldName != newName); 2676 2677 if (!oldName.isEmpty()) 2678 scope->removeElementByName(oldName, this); 2679 if (!newName.isEmpty()) 2680 scope->addElementByName(newName, this); 2681 2682 if (!inDocument()) 2683 return; 2684 2685 Document* ownerDocument = document(); 2686 if (!ownerDocument->isHTMLDocument()) 2687 return; 2688 2689 if (WindowNameCollection::nodeMatchesIfNameAttributeMatch(this)) { 2690 if (!oldName.isEmpty()) 2691 toHTMLDocument(ownerDocument)->windowNamedItemMap().remove(oldName.impl(), this); 2692 if (!newName.isEmpty()) 2693 toHTMLDocument(ownerDocument)->windowNamedItemMap().add(newName.impl(), this); 2694 } 2695 2696 if (DocumentNameCollection::nodeMatchesIfNameAttributeMatch(this)) { 2697 if (!oldName.isEmpty()) 2698 toHTMLDocument(ownerDocument)->documentNamedItemMap().remove(oldName.impl(), this); 2699 if (!newName.isEmpty()) 2700 toHTMLDocument(ownerDocument)->documentNamedItemMap().add(newName.impl(), this); 2701 } 2670 2702 } 2671 2703 … … 2681 2713 } 2682 2714 2683 inlinevoid Element::updateId(TreeScope* scope, const AtomicString& oldId, const AtomicString& newId)2715 void Element::updateId(TreeScope* scope, const AtomicString& oldId, const AtomicString& newId) 2684 2716 { 2685 2717 ASSERT(isInTreeScope()); … … 2691 2723 scope->addElementById(newId, this); 2692 2724 2693 if (shouldRegisterAsExtraNamedItem()) 2694 updateExtraNamedItemRegistration(oldId, newId); 2725 if (!inDocument()) 2726 return; 2727 2728 Document* ownerDocument = document(); 2729 if (!ownerDocument->isHTMLDocument()) 2730 return; 2731 2732 if (WindowNameCollection::nodeMatchesIfIdAttributeMatch(this)) { 2733 if (!oldId.isEmpty()) 2734 toHTMLDocument(ownerDocument)->windowNamedItemMap().remove(oldId.impl(), this); 2735 if (!newId.isEmpty()) 2736 toHTMLDocument(ownerDocument)->windowNamedItemMap().add(newId.impl(), this); 2737 } 2738 2739 if (DocumentNameCollection::nodeMatchesIfIdAttributeMatch(this)) { 2740 if (!oldId.isEmpty()) 2741 toHTMLDocument(ownerDocument)->documentNamedItemMap().remove(oldId.impl(), this); 2742 if (!newId.isEmpty()) 2743 toHTMLDocument(ownerDocument)->documentNamedItemMap().add(newId.impl(), this); 2744 } 2695 2745 } 2696 2746 … … 2755 2805 InspectorInstrumentation::didRemoveDOMAttr(document(), this, name.localName()); 2756 2806 dispatchSubtreeModifiedEvent(); 2757 }2758 2759 2760 void Element::updateNamedItemRegistration(const AtomicString& oldName, const AtomicString& newName)2761 {2762 if (!document()->isHTMLDocument())2763 return;2764 2765 if (!oldName.isEmpty())2766 toHTMLDocument(document())->removeNamedItem(oldName);2767 2768 if (!newName.isEmpty())2769 toHTMLDocument(document())->addNamedItem(newName);2770 }2771 2772 void Element::updateExtraNamedItemRegistration(const AtomicString& oldId, const AtomicString& newId)2773 {2774 if (!document()->isHTMLDocument())2775 return;2776 2777 if (!oldId.isEmpty())2778 toHTMLDocument(document())->removeExtraNamedItem(oldId);2779 2780 if (!newId.isEmpty())2781 toHTMLDocument(document())->addExtraNamedItem(newId);2782 2807 } 2783 2808 -
trunk/Source/WebCore/dom/Element.h
r149549 r149652 640 640 virtual PassRefPtr<RenderStyle> customStyleForRenderer(); 641 641 642 virtual bool shouldRegisterAsNamedItem() const { return false; }643 virtual bool shouldRegisterAsExtraNamedItem() const { return false; }644 645 642 void clearTabIndexExplicitlyIfNeeded(); 646 643 void setTabIndexExplicitly(short); … … 681 678 void updateId(TreeScope*, const AtomicString& oldId, const AtomicString& newId); 682 679 void updateName(const AtomicString& oldName, const AtomicString& newName); 680 void updateName(TreeScope*, const AtomicString& oldName, const AtomicString& newName); 683 681 void updateLabel(TreeScope*, const AtomicString& oldForAttributeValue, const AtomicString& newForAttributeValue); 684 682 … … 726 724 SpellcheckAttributeState spellcheckAttributeState() const; 727 725 728 void updateNamedItemRegistration(const AtomicString& oldName, const AtomicString& newName);729 void updateExtraNamedItemRegistration(const AtomicString& oldName, const AtomicString& newName);730 731 726 void unregisterNamedFlowContentNode(); 732 727 -
trunk/Source/WebCore/dom/TreeScope.cpp
r148921 r149652 59 59 struct SameSizeAsTreeScope { 60 60 virtual ~SameSizeAsTreeScope(); 61 void* pointers[ 8];61 void* pointers[9]; 62 62 int ints[1]; 63 63 }; … … 164 164 m_elementsById->remove(elementId.impl(), element); 165 165 m_idTargetObserverRegistry->notifyObservers(elementId); 166 } 167 168 Element* TreeScope::getElementByName(const AtomicString& name) const 169 { 170 if (name.isEmpty()) 171 return 0; 172 if (!m_elementsByName) 173 return 0; 174 return m_elementsByName->getElementByName(name.impl(), this); 175 } 176 177 void TreeScope::addElementByName(const AtomicString& name, Element* element) 178 { 179 if (!m_elementsByName) 180 m_elementsByName = adoptPtr(new DocumentOrderedMap); 181 m_elementsByName->add(name.impl(), element); 182 } 183 184 void TreeScope::removeElementByName(const AtomicString& name, Element* element) 185 { 186 if (!m_elementsByName) 187 return; 188 m_elementsByName->remove(name.impl(), element); 166 189 } 167 190 -
trunk/Source/WebCore/dom/TreeScope.h
r148921 r149652 62 62 void removeElementById(const AtomicString& elementId, Element*); 63 63 64 Element* getElementByName(const AtomicString&) const; 65 bool hasElementWithName(AtomicStringImpl*) const; 66 bool containsMultipleElementsWithName(const AtomicString&) const; 67 void addElementByName(const AtomicString&, Element*); 68 void removeElementByName(const AtomicString&, Element*); 69 64 70 Document* documentScope() const { return m_documentScope; } 65 71 … … 162 168 163 169 OwnPtr<DocumentOrderedMap> m_elementsById; 170 OwnPtr<DocumentOrderedMap> m_elementsByName; 164 171 OwnPtr<DocumentOrderedMap> m_imageMapsByName; 165 172 OwnPtr<DocumentOrderedMap> m_labelsByForAttribute; … … 181 188 } 182 189 190 inline bool TreeScope::hasElementWithName(AtomicStringImpl* id) const 191 { 192 ASSERT(id); 193 return m_elementsByName && m_elementsByName->contains(id); 194 } 195 196 inline bool TreeScope::containsMultipleElementsWithName(const AtomicString& name) const 197 { 198 return m_elementsByName && m_elementsByName->containsMultiple(name.impl()); 199 } 200 183 201 Node* nodeFromPoint(Document*, int x, int y, LayoutPoint* localPoint = 0); 184 202 TreeScope* commonTreeScope(Node*, Node*); -
trunk/Source/WebCore/html/HTMLAppletElement.h
r135069 r149652 44 44 45 45 bool canEmbedJava() const; 46 47 virtual bool shouldRegisterAsNamedItem() const OVERRIDE { return true; }48 virtual bool shouldRegisterAsExtraNamedItem() const OVERRIDE { return true; }49 46 }; 50 47 -
trunk/Source/WebCore/html/HTMLCollection.cpp
r147135 r149652 27 27 #include "HTMLDocument.h" 28 28 #include "HTMLElement.h" 29 #include "HTMLNameCollection.h" 29 30 #include "HTMLNames.h" 30 31 #include "HTMLObjectElement.h" … … 245 246 case NodeChildren: 246 247 return true; 248 case DocumentNamedItems: 249 return static_cast<const DocumentNameCollection*>(htmlCollection)->nodeMatches(element); 250 case WindowNamedItems: 251 return static_cast<const WindowNameCollection*>(htmlCollection)->nodeMatches(element); 247 252 #if ENABLE(MICRODATA) 248 253 case ItemProperties: … … 250 255 #endif 251 256 case FormControls: 252 case DocumentNamedItems:253 257 case TableRows: 254 case WindowNamedItems:255 258 case ChildNodeListType: 256 259 case ClassNodeListType: … … 544 547 } 545 548 546 bool HTMLCollection::checkForNameMatch(Element* element, bool checkName, const AtomicString& name) const547 {548 if (!element->isHTMLElement())549 return false;550 551 HTMLElement* e = toHTMLElement(element);552 if (!checkName)553 return e->getIdAttribute() == name;554 555 if (type() == DocAll && !nameShouldBeVisibleInDocumentAll(e))556 return false;557 558 return e->getNameAttribute() == name && e->getIdAttribute() != name;559 }560 561 549 inline Element* firstMatchingChildElement(const HTMLCollection* nodeList, ContainerNode* root) 562 550 { … … 625 613 626 614 ContainerNode* root = rootContainerNode(); 627 if ( !root)615 if (name.isEmpty() || !root) 628 616 return 0; 629 617 630 unsigned arrayOffset = 0; 631 unsigned i = 0; 632 for (Element* element = traverseFirstElement(arrayOffset, root); element; element = traverseNextElement(arrayOffset, element, root)) { 633 if (checkForNameMatch(element, /* checkName */ false, name)) { 634 setItemCache(element, i, arrayOffset); 635 return element; 636 } 637 i++; 638 } 639 640 i = 0; 641 for (Element* element = traverseFirstElement(arrayOffset, root); element; element = traverseNextElement(arrayOffset, element, root)) { 642 if (checkForNameMatch(element, /* checkName */ true, name)) { 643 setItemCache(element, i, arrayOffset); 644 return element; 645 } 646 i++; 618 if (!overridesItemAfter()) { 619 TreeScope* treeScope = root->treeScope(); 620 Element* candidate = 0; 621 if (treeScope->hasElementWithId(name.impl())) { 622 if (!treeScope->containsMultipleElementsWithId(name)) 623 candidate = treeScope->getElementById(name); 624 } else if (treeScope->hasElementWithName(name.impl())) { 625 if (!treeScope->containsMultipleElementsWithName(name)) { 626 candidate = treeScope->getElementByName(name); 627 if (candidate && type() == DocAll && (!candidate->isHTMLElement() || !nameShouldBeVisibleInDocumentAll(toHTMLElement(candidate)))) 628 candidate = 0; 629 } 630 } else 631 return 0; 632 633 if (candidate 634 && isMatchingElement(this, candidate) 635 && (shouldOnlyIncludeDirectChildren() ? candidate->parentNode() == root : candidate->isDescendantOf(root))) 636 return candidate; 637 } 638 639 // The pathological case. We need to walk the entire subtree. 640 updateNameCache(); 641 642 if (Vector<Element*>* idResults = idCache(name)) { 643 if (idResults->size()) 644 return idResults->at(0); 645 } 646 647 if (Vector<Element*>* nameResults = nameCache(name)) { 648 if (nameResults->size()) 649 return nameResults->at(0); 647 650 } 648 651 … … 677 680 bool HTMLCollection::hasNamedItem(const AtomicString& name) const 678 681 { 679 if (name.isEmpty()) 680 return false; 681 682 updateNameCache(); 683 684 if (Vector<Element*>* cache = idCache(name)) { 685 if (!cache->isEmpty()) 686 return true; 687 } 688 689 if (Vector<Element*>* cache = nameCache(name)) { 690 if (!cache->isEmpty()) 691 return true; 692 } 693 694 return false; 682 // FIXME: We can do better when there are multiple elements of the same name. 683 return namedItem(name); 695 684 } 696 685 -
trunk/Source/WebCore/html/HTMLCollection.h
r138195 r149652 80 80 81 81 private: 82 bool checkForNameMatch(Element*, bool checkName, const AtomicString& name) const;83 82 Element* traverseNextElement(unsigned& offsetInArray, Element* previous, ContainerNode* root) const; 84 83 -
trunk/Source/WebCore/html/HTMLDocument.cpp
r148373 r149652 294 294 } 295 295 return HTMLElementFactory::createHTMLElement(QualifiedName(nullAtom, name.lower(), xhtmlNamespaceURI), this, 0, false); 296 }297 298 void HTMLDocument::addItemToMap(HashCountedSet<AtomicStringImpl*>& map, const AtomicString& name)299 {300 if (name.isEmpty())301 return;302 map.add(name.impl());303 if (Frame* f = frame())304 f->script()->namedItemAdded(this, name);305 }306 307 void HTMLDocument::removeItemFromMap(HashCountedSet<AtomicStringImpl*>& map, const AtomicString& name)308 {309 if (name.isEmpty())310 return;311 map.remove(name.impl());312 if (Frame* f = frame())313 f->script()->namedItemRemoved(this, name);314 }315 316 void HTMLDocument::addNamedItem(const AtomicString& name)317 {318 addItemToMap(m_namedItemCounts, name);319 }320 321 void HTMLDocument::removeNamedItem(const AtomicString& name)322 {323 removeItemFromMap(m_namedItemCounts, name);324 }325 326 void HTMLDocument::addExtraNamedItem(const AtomicString& name)327 {328 addItemToMap(m_extraNamedItemCounts, name);329 }330 331 void HTMLDocument::removeExtraNamedItem(const AtomicString& name)332 {333 removeItemFromMap(m_extraNamedItemCounts, name);334 296 } 335 297 -
trunk/Source/WebCore/html/HTMLDocument.h
r145745 r149652 70 70 void releaseEvents(); 71 71 72 void addNamedItem(const AtomicString& name); 73 void removeNamedItem(const AtomicString& name); 74 bool hasNamedItem(AtomicStringImpl* name); 75 76 void addExtraNamedItem(const AtomicString& name); 77 void removeExtraNamedItem(const AtomicString& name); 78 bool hasExtraNamedItem(AtomicStringImpl* name); 72 DocumentOrderedMap& documentNamedItemMap() { return m_documentNamedItem; } 73 DocumentOrderedMap& windowNamedItemMap() { return m_windowNamedItem; } 79 74 80 75 static bool isCaseSensitiveAttribute(const QualifiedName&); … … 89 84 virtual PassRefPtr<DocumentParser> createParser(); 90 85 91 void addItemToMap(HashCountedSet<AtomicStringImpl*>&, const AtomicString&); 92 void removeItemFromMap(HashCountedSet<AtomicStringImpl*>&, const AtomicString&); 93 94 HashCountedSet<AtomicStringImpl*> m_namedItemCounts; 95 HashCountedSet<AtomicStringImpl*> m_extraNamedItemCounts; 86 DocumentOrderedMap m_documentNamedItem; 87 DocumentOrderedMap m_windowNamedItem; 96 88 }; 97 98 inline bool HTMLDocument::hasNamedItem(AtomicStringImpl* name)99 {100 ASSERT(name);101 return m_namedItemCounts.contains(name);102 }103 104 inline bool HTMLDocument::hasExtraNamedItem(AtomicStringImpl* name)105 {106 ASSERT(name);107 return m_extraNamedItemCounts.contains(name);108 }109 89 110 90 inline HTMLDocument* toHTMLDocument(Document* document) -
trunk/Source/WebCore/html/HTMLEmbedElement.h
r145750 r149652 56 56 virtual void setItemValueText(const String&, ExceptionCode&) OVERRIDE; 57 57 #endif 58 59 virtual bool shouldRegisterAsNamedItem() const OVERRIDE { return true; }60 58 }; 61 59 -
trunk/Source/WebCore/html/HTMLFormElement.h
r148731 r149652 126 126 virtual void didMoveToNewDocument(Document* oldDocument) OVERRIDE; 127 127 128 virtual bool shouldRegisterAsNamedItem() const OVERRIDE { return true; }129 130 128 virtual void copyNonAttributePropertiesFromElement(const Element&) OVERRIDE; 131 129 -
trunk/Source/WebCore/html/HTMLIFrameElement.cpp
r145745 r149652 80 80 void HTMLIFrameElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 81 81 { 82 if (name == nameAttr) { 83 if (inDocument() && document()->isHTMLDocument() && !isInShadowTree()) { 84 HTMLDocument* document = toHTMLDocument(this->document()); 85 document->removeExtraNamedItem(m_name); 86 document->addExtraNamedItem(value); 87 } 88 m_name = value; 89 } else if (name == sandboxAttr) { 82 if (name == sandboxAttr) { 90 83 String invalidTokens; 91 84 setSandboxFlags(value.isNull() ? SandboxNone : SecurityContext::parseSandboxPolicy(value, invalidTokens)); … … 108 101 { 109 102 return new (arena) RenderIFrame(this); 110 }111 112 Node::InsertionNotificationRequest HTMLIFrameElement::insertedInto(ContainerNode* insertionPoint)113 {114 InsertionNotificationRequest result = HTMLFrameElementBase::insertedInto(insertionPoint);115 if (insertionPoint->inDocument() && document()->isHTMLDocument() && !insertionPoint->isInShadowTree())116 toHTMLDocument(document())->addExtraNamedItem(m_name);117 return result;118 }119 120 void HTMLIFrameElement::removedFrom(ContainerNode* insertionPoint)121 {122 HTMLFrameElementBase::removedFrom(insertionPoint);123 if (insertionPoint->inDocument() && document()->isHTMLDocument() && !insertionPoint->isInShadowTree())124 toHTMLDocument(document())->removeExtraNamedItem(m_name);125 103 } 126 104 -
trunk/Source/WebCore/html/HTMLIFrameElement.h
r143843 r149652 42 42 virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) OVERRIDE; 43 43 44 virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE;45 virtual void removedFrom(ContainerNode*) OVERRIDE;46 47 44 virtual bool rendererIsNeeded(const NodeRenderingContext&); 48 45 virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); … … 54 51 virtual void setItemValueText(const String&, ExceptionCode&) OVERRIDE; 55 52 #endif 56 57 AtomicString m_name;58 53 }; 59 54 -
trunk/Source/WebCore/html/HTMLImageElement.cpp
r148921 r149652 125 125 if (!parseCompositeAndBlendOperator(value, m_compositeOperator, blendOp)) 126 126 m_compositeOperator = CompositeSourceOver; 127 } else 127 } else { 128 if (name == nameAttr) { 129 bool willHaveName = !value.isNull(); 130 if (hasName() != willHaveName && inDocument() && document()->isHTMLDocument()) { 131 HTMLDocument* document = toHTMLDocument(this->document()); 132 const AtomicString& id = getIdAttribute(); 133 if (!id.isEmpty()) { 134 if (willHaveName) 135 document->documentNamedItemMap().add(id.impl(), this); 136 else 137 document->documentNamedItemMap().remove(id.impl(), this); 138 } 139 } 140 } 128 141 HTMLElement::parseAttribute(name, value); 142 } 129 143 } 130 144 -
trunk/Source/WebCore/html/HTMLImageElement.h
r148921 r149652 102 102 virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; 103 103 virtual void removedFrom(ContainerNode*) OVERRIDE; 104 virtual bool shouldRegisterAsNamedItem() const OVERRIDE { return true; }105 virtual bool shouldRegisterAsExtraNamedItem() const OVERRIDE { return true; }106 104 107 105 #if ENABLE(MICRODATA) -
trunk/Source/WebCore/html/HTMLNameCollection.cpp
r137406 r149652 36 36 37 37 HTMLNameCollection::HTMLNameCollection(Node* document, CollectionType type, const AtomicString& name) 38 : HTMLCollection(document, type, OverridesItemAfter)38 : HTMLCollection(document, type, DoesNotOverrideItemAfter) 39 39 , m_name(name) 40 40 { … … 50 50 } 51 51 52 Element* HTMLNameCollection::virtualItemAfter(unsigned& offsetInArray, Element* previous) const 52 bool WindowNameCollection::nodeMatchesIfNameAttributeMatch(Element* element) 53 53 { 54 ASSERT_UNUSED(offsetInArray, !offsetInArray); 55 ASSERT(previous != ownerNode()); 54 return element->hasTagName(imgTag) || element->hasTagName(formTag) || element->hasTagName(appletTag) 55 || element->hasTagName(embedTag) || element->hasTagName(objectTag); 56 } 56 57 57 Element* current; 58 if (!previous) 59 current = ElementTraversal::firstWithin(ownerNode()); 60 else 61 current = ElementTraversal::next(previous, ownerNode()); 58 bool WindowNameCollection::nodeMatches(Element* element, const AtomicString& name) 59 { 60 // Find only images, forms, applets, embeds and objects by name, but anything by id 61 if (nodeMatchesIfNameAttributeMatch(element) && element->getNameAttribute() == name) 62 return true; 63 return element->getIdAttribute() == name; 64 } 62 65 63 for (; current; current = ElementTraversal::next(current, ownerNode())) { 64 switch (type()) { 65 case WindowNamedItems: 66 // find only images, forms, applets, embeds and objects by name, 67 // but anything by id 68 if (current->hasTagName(imgTag) 69 || current->hasTagName(formTag) 70 || current->hasTagName(appletTag) 71 || current->hasTagName(embedTag) 72 || current->hasTagName(objectTag)) { 73 if (current->getNameAttribute() == m_name) 74 return current; 75 } 76 if (current->getIdAttribute() == m_name) 77 return current; 78 break; 79 case DocumentNamedItems: 80 // find images, forms, applets, embeds, objects and iframes by name, 81 // applets and object by id, and images by id but only if they have 82 // a name attribute (this very strange rule matches IE) 83 if (current->hasTagName(formTag) || current->hasTagName(embedTag) || current->hasTagName(iframeTag)) { 84 if (current->getNameAttribute() == m_name) 85 return current; 86 } else if (current->hasTagName(appletTag)) { 87 if (current->getNameAttribute() == m_name || current->getIdAttribute() == m_name) 88 return current; 89 } else if (current->hasTagName(objectTag)) { 90 if ((current->getNameAttribute() == m_name || current->getIdAttribute() == m_name) 91 && static_cast<HTMLObjectElement*>(current)->isDocNamedItem()) 92 return current; 93 } else if (current->hasTagName(imgTag)) { 94 if (current->getNameAttribute() == m_name || (current->getIdAttribute() == m_name && current->hasName())) 95 return current; 96 } 97 break; 98 default: 99 ASSERT_NOT_REACHED(); 100 } 101 } 66 bool DocumentNameCollection::nodeMatchesIfIdAttributeMatch(Element* element) 67 { 68 // FIXME: we need to fix HTMLImageElement to update the hash map for us when name attribute has been removed. 69 return element->hasTagName(appletTag) || (element->hasTagName(objectTag) && toHTMLObjectElement(element)->isDocNamedItem()) 70 || (element->hasTagName(imgTag) && element->hasName()); 71 } 102 72 103 return 0; 73 bool DocumentNameCollection::nodeMatchesIfNameAttributeMatch(Element* element) 74 { 75 return element->hasTagName(formTag) || element->hasTagName(embedTag) || element->hasTagName(iframeTag) 76 || element->hasTagName(appletTag) || (element->hasTagName(objectTag) && toHTMLObjectElement(element)->isDocNamedItem()) 77 || element->hasTagName(imgTag); 78 } 79 80 bool DocumentNameCollection::nodeMatches(Element* element, const AtomicString& name) 81 { 82 // Find images, forms, applets, embeds, objects and iframes by name, applets and object by id, and images by id 83 // but only if they have a name attribute (this very strange rule matches IE) 84 if (element->hasTagName(formTag) || element->hasTagName(embedTag) || element->hasTagName(iframeTag)) 85 return element->getNameAttribute() == name; 86 if (element->hasTagName(appletTag)) 87 return element->getNameAttribute() == name || element->getIdAttribute() == name; 88 if (element->hasTagName(objectTag)) 89 return (element->getNameAttribute() == name || element->getIdAttribute() == name) && toHTMLObjectElement(element)->isDocNamedItem(); 90 if (element->hasTagName(imgTag)) 91 return element->getNameAttribute() == name || (element->getIdAttribute() == name && element->hasName()); 92 return false; 104 93 } 105 94 -
trunk/Source/WebCore/html/HTMLNameCollection.h
r135893 r149652 34 34 class HTMLNameCollection : public HTMLCollection { 35 35 public: 36 static PassRefPtr<HTMLNameCollection> create(Node* document, CollectionType type, const AtomicString& name) 36 ~HTMLNameCollection(); 37 38 protected: 39 HTMLNameCollection(Node*, CollectionType, const AtomicString& name); 40 41 AtomicString m_name; 42 }; 43 44 class WindowNameCollection : public HTMLNameCollection { 45 public: 46 static PassRefPtr<WindowNameCollection> create(Node* document, CollectionType type, const AtomicString& name) 37 47 { 38 return adoptRef(new HTMLNameCollection(document, type, name));48 return adoptRef(new WindowNameCollection(document, type, name)); 39 49 } 40 50 41 ~HTMLNameCollection(); 51 bool nodeMatches(Element* element) const { return nodeMatches(element, m_name); } 52 53 static bool nodeMatchesIfIdAttributeMatch(Element*) { return true; } 54 static bool nodeMatchesIfNameAttributeMatch(Element*); 55 static bool nodeMatches(Element*, const AtomicString&); 42 56 43 57 private: 44 HTMLNameCollection(Node*, CollectionType, const AtomicString& name); 58 WindowNameCollection(Node* document, CollectionType type, const AtomicString& name) 59 : HTMLNameCollection(document, type, name) 60 { 61 ASSERT(type == WindowNamedItems); 62 } 63 }; 45 64 46 virtual Element* virtualItemAfter(unsigned& offsetInArray, Element*) const OVERRIDE; 65 class DocumentNameCollection : public HTMLNameCollection { 66 public: 67 static PassRefPtr<DocumentNameCollection> create(Node* document, CollectionType type, const AtomicString& name) 68 { 69 return adoptRef(new DocumentNameCollection(document, type, name)); 70 } 47 71 48 AtomicString m_name; 72 static bool nodeMatchesIfIdAttributeMatch(Element*); 73 static bool nodeMatchesIfNameAttributeMatch(Element*); 74 bool nodeMatches(Element* element) const { return nodeMatches(element, m_name); } 75 76 static bool nodeMatches(Element*, const AtomicString&); 77 78 private: 79 DocumentNameCollection(Node* document, CollectionType type, const AtomicString& name) 80 : HTMLNameCollection(document, type, name) 81 { 82 ASSERT(type == DocumentNamedItems); 83 } 49 84 }; 50 85 -
trunk/Source/WebCore/html/HTMLObjectElement.cpp
r147205 r149652 440 440 child = child->nextSibling(); 441 441 } 442 if (isNamedItem != wasNamedItem && document()->isHTMLDocument()) {442 if (isNamedItem != wasNamedItem && inDocument() && document()->isHTMLDocument()) { 443 443 HTMLDocument* document = toHTMLDocument(this->document()); 444 if (isNamedItem) { 445 document->addNamedItem(getNameAttribute()); 446 document->addExtraNamedItem(getIdAttribute()); 447 } else { 448 document->removeNamedItem(getNameAttribute()); 449 document->removeExtraNamedItem(getIdAttribute()); 444 445 const AtomicString& id = getIdAttribute(); 446 if (!id.isEmpty()) { 447 if (isNamedItem) 448 document->documentNamedItemMap().add(id.impl(), this); 449 else 450 document->documentNamedItemMap().remove(id.impl(), this); 451 } 452 453 const AtomicString& name = getNameAttribute(); 454 if (!name.isEmpty()) { 455 if (isNamedItem) 456 document->documentNamedItemMap().add(name.impl(), this); 457 else 458 document->documentNamedItemMap().remove(name.impl(), this); 450 459 } 451 460 } -
trunk/Source/WebCore/html/HTMLObjectElement.h
r145750 r149652 107 107 #endif 108 108 109 virtual bool shouldRegisterAsNamedItem() const OVERRIDE { return isDocNamedItem(); }110 virtual bool shouldRegisterAsExtraNamedItem() const OVERRIDE { return isDocNamedItem(); }111 112 109 String m_classId; 113 110 bool m_docNamedItem : 1; … … 115 112 }; 116 113 114 inline HTMLObjectElement* toHTMLObjectElement(Node* node) 115 { 116 ASSERT_WITH_SECURITY_IMPLICATION(!node || node->hasTagName(HTMLNames::objectTag)); 117 return static_cast<HTMLObjectElement*>(node); 118 } 119 117 120 } 118 121
Note: See TracChangeset
for help on using the changeset viewer.