Changeset 149652 in webkit


Ignore:
Timestamp:
May 6, 2013 5:20:05 PM (11 years ago)
Author:
rniwa@webkit.org
Message:

Unify ways to cache named item in HTMLCollections
https://bugs.webkit.org/show_bug.cgi?id=115584

Reviewed by Antti Koivisto.

Refactor the code to share the same infrastructure for both id and name attributes maps.

Also get rid of shouldRegisterAsNamedItem and shouldRegisterAsExtraNamedItem from various Element subclasses
as these member functions were duplicating the information in HTMLNameCollection.cpp. Nevertheless, HTMLImageElement
and HTMLObjectElement still update HTMLDocument's window and document name getter maps when their presence as named
item changes due to an attribute change and children changes respectively.

  • bindings/js/JSDOMWindowCustom.cpp:

(WebCore::namedItemGetter): Use windowNamedItemMap().containsSingle() instead of collection->hasExactlyOneItem() to
avoid instantiating HTMLCollection until we know for sure we're returning multiple items.
(WebCore::JSDOMWindow::getOwnPropertySlot): Call windowNamedItemMap().contains() instead of document->hasNamedItem()
since the latter has been removed.
(WebCore::JSDOMWindow::getOwnPropertySlotByIndex): Ditto.
(WebCore::JSDOMWindow::getOwnPropertyDescriptor): Ditto.

  • bindings/js/JSHTMLDocumentCustom.cpp:

(WebCore::JSHTMLDocument::canGetItemsForName): Call documentNamedItemMap().contains() instead of
document->hasExtraNamedItem() since the latter has been removed.
(WebCore::JSHTMLDocument::nameGetter): Use documentNamedItemMap().containsSingle() instead of
collection->hasExactlyOneItem() to avoid instantiating HTMLCollection when we're returning the first item.

  • dom/Document.cpp:

(WebCore::Document::windowNamedItems): Instantiate WindowNameCollection, which is a subclass of HTMLNameCollection,
instead of HTMLNameCollection since the latter class no longer has a public constructor.
(WebCore::Document::documentNamedItems): Ditto; instantiate DocumentNameCollection.

  • dom/DocumentOrderedMap.cpp:

(WebCore::keyMatchesName): Added for name attribute.
(WebCore::keyMatchesWindowNamedItem): Added for window name getter.
(WebCore::keyMatchesDocumentNamedItem): Added for document name getter.
(WebCore::DocumentOrderedMap::getElementByName): Added for name attribute.
(WebCore::DocumentOrderedMap::getElementByWindowNamedItem): Added for window name getter.
(WebCore::DocumentOrderedMap::getElementByDocumentNamedItem): Added for document name getter.

  • dom/DocumentOrderedMap.h:

(WebCore::DocumentOrderedMap::containsSingle): Added.
(WebCore::DocumentOrderedMap::containsMultiple): Fixed the bug that containsMultiple returns true even when
the duplicate count has been reduced to 1. Unfortunately this behavior change is not testable because the old code
worked properly (though less efficient) even if this function returned a wrong value.

  • dom/Element.cpp:

(WebCore::Element::insertedInto):
(WebCore::Element::removedFrom):
(WebCore::Element::updateName): Added. Updates TreeScope's name attribute map as well as HTMLDocument's window name
and document name maps.
(WebCore::Element::updateId): Added the code to update HTMLDocument's window name and document name maps.

  • dom/Element.h:

(Element): Removed shouldRegisterAsNamedItem, shouldRegisterAsExtraNamedItem, updateNamedItemRegistration, and
updateExtraNamedItemRegistration as they're no longer used.

  • dom/TreeScope.cpp:

(SameSizeAsTreeScope):
(WebCore::TreeScope::getElementByName): Added.
(WebCore::TreeScope::addElementByName): Added.
(WebCore::TreeScope::removeElementByName): Added.

  • dom/TreeScope.h:

(WebCore::TreeScope::hasElementWithName): Added.
(WebCore::TreeScope::containsMultipleElementsWithName): Added.

  • html/HTMLAppletElement.h:

(HTMLAppletElement):

  • html/HTMLCollection.cpp:

(WebCore::isMatchingElement): Use HTMLNameCollection subclasses' nodeMatches.
(WebCore::HTMLCollection::namedItem): Added a fast path for named item.
(WebCore::HTMLCollection::hasNamedItem): Use namedItem to avoid the work in the fast path.

  • html/HTMLCollection.h:

(HTMLCollection): Removed checkForNameMatch.

  • html/HTMLDocument.cpp:

(WebCore): Removed various member functions related to m_namedItemCounts and m_extraNamedItemCounts.

  • html/HTMLDocument.h:

(WebCore::HTMLDocument::documentNamedItemMap): Added.
(WebCore::HTMLDocument::windowNamedItemMap): Added.
(HTMLDocument): Replaced m_namedItemCounts and m_extraNamedItemCounts by m_documentNamedItem and m_windowNamedItem.
Note that they're not one to one.

  • html/HTMLEmbedElement.h:

(HTMLEmbedElement):

  • html/HTMLFormElement.h:

(HTMLFormElement):

  • html/HTMLIFrameElement.cpp: Removed the code to track the element's name since we already do this in Element.

(WebCore::HTMLIFrameElement::parseAttribute):

  • html/HTMLIFrameElement.h:

(HTMLIFrameElement):

  • html/HTMLImageElement.cpp:

(WebCore::HTMLImageElement::parseAttribute): Update the HTMLDocument's maps when the name attribute's existence
changes its presence on window and document name getters in turn. This behavior change, again, appears to be
untestable due to the old being more graceful when DocumentOrderedMap returned a wrong value.

  • html/HTMLImageElement.h:
  • html/HTMLNameCollection.cpp:

(WebCore::HTMLNameCollection::HTMLNameCollection): No longer overrides itemAfter. This enables backwards traversals
of the tree along with other optimizations in HTMLCollection.

(WebCore::WindowNameCollection::nodeMatchesIfNameAttributeMatch): Added. Used in Element::updateName to determine
whether add() or remove() should be called on HTMLDocument's maps.
(WebCore::WindowNameCollection::nodeMatches): Added.

(WebCore::DocumentNameCollection::nodeMatchesIfIdAttributeMatch): Added. Used in Element::updateName to determine
whether add() or remove() should be called on HTMLDocument's maps.
(WebCore::DocumentNameCollection::nodeMatchesIfNameAttributeMatch): Ditto.
(WebCore::DocumentNameCollection::nodeMatches): Added.

  • html/HTMLNameCollection.h:

(HTMLNameCollection): Removed create since this class shouldn't be instantiated on its own.

(WebCore::WindowNameCollection): Added.
(WebCore::WindowNameCollection::create): Added.
(WebCore::WindowNameCollection::nodeMatches): Added.
(WebCore::WindowNameCollection::nodeMatchesIfIdAttributeMatch): Added.
(WebCore::WindowNameCollection::WindowNameCollection): Added.
(WebCore::DocumentNameCollection): Added.
(WebCore::DocumentNameCollection::create): Added.
(WebCore::DocumentNameCollection::nodeMatches): Added.
(WebCore::DocumentNameCollection::DocumentNameCollection): Added.

  • html/HTMLObjectElement.cpp:

(WebCore::HTMLObjectElement::updateDocNamedItem): Update both window and document getter maps of HTMLDocument when
the visibility of this element changes due to the DOM mutations in the subtree.

  • html/HTMLObjectElement.h:

(WebCore::HTMLObjectElement):
(WebCore::toHTMLObjectElement): Added.

Location:
trunk/Source/WebCore
Files:
25 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r149648 r149652  
     12013-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
    11412013-05-06  Andreas Kling  <akling@apple.com>
    2142
  • trunk/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp

    r148696 r149652  
    9696    ASSERT(document->isHTMLDocument());
    9797
    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);
    102111}
    103112
     
    239248    if (document->isHTMLDocument()) {
    240249        AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName);
    241         if (atomicPropertyName && (toHTMLDocument(document)->hasNamedItem(atomicPropertyName) || document->hasElementWithId(atomicPropertyName))) {
     250        if (atomicPropertyName && toHTMLDocument(document)->windowNamedItemMap().contains(atomicPropertyName)) {
    242251            slot.setCustom(thisObject, namedItemGetter);
    243252            return true;
     
    315324    if (document->isHTMLDocument()) {
    316325        AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName);
    317         if (atomicPropertyName && (toHTMLDocument(document)->hasNamedItem(atomicPropertyName) || document->hasElementWithId(atomicPropertyName))) {
     326        if (atomicPropertyName && toHTMLDocument(document)->windowNamedItemMap().contains(atomicPropertyName)) {
    318327            slot.setCustom(thisObject, namedItemGetter);
    319328            return true;
     
    386395    if (document->isHTMLDocument()) {
    387396        AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName);
    388         if (atomicPropertyName && (toHTMLDocument(document)->hasNamedItem(atomicPropertyName) || document->hasElementWithId(atomicPropertyName))) {
     397        if (atomicPropertyName && toHTMLDocument(document)->windowNamedItemMap().contains(atomicPropertyName)) {
    389398            PropertySlot slot;
    390399            slot.setCustom(thisObject, namedItemGetter);
  • trunk/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp

    r148696 r149652  
    5555{
    5656    AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName);
    57     return atomicPropertyName && (document->hasNamedItem(atomicPropertyName) || document->hasExtraNamedItem(atomicPropertyName));
     57    return atomicPropertyName && document->documentNamedItemMap().contains(atomicPropertyName);
    5858}
    5959
     
    6363    HTMLDocument* document = toHTMLDocument(thisObj->impl());
    6464
    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))
    6867        return jsUndefined();
    6968
    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    }
    7275
    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);
    7680
    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);
    8182}
    8283
  • trunk/Source/WebCore/dom/Document.cpp

    r149648 r149652  
    44204420PassRefPtr<HTMLCollection> Document::windowNamedItems(const AtomicString& name)
    44214421{
    4422     return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<HTMLNameCollection>(this, WindowNamedItems, name);
     4422    return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<WindowNameCollection>(this, WindowNamedItems, name);
    44234423}
    44244424
    44254425PassRefPtr<HTMLCollection> Document::documentNamedItems(const AtomicString& name)
    44264426{
    4427     return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<HTMLNameCollection>(this, DocumentNamedItems, name);
     4427    return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<DocumentNameCollection>(this, DocumentNamedItems, name);
    44284428}
    44294429
  • trunk/Source/WebCore/dom/DocumentOrderedMap.cpp

    r148921 r149652  
    3434#include "Element.h"
    3535#include "HTMLMapElement.h"
     36#include "HTMLNameCollection.h"
    3637#include "HTMLNames.h"
    3738#include "NodeTraversal.h"
     
    4546{
    4647    return element->getIdAttribute().impl() == key;
     48}
     49
     50inline bool keyMatchesName(AtomicStringImpl* key, Element* element)
     51{
     52    return element->getNameAttribute().impl() == key;
    4753}
    4854
     
    6066{
    6167    return element->hasTagName(labelTag) && element->getAttribute(forAttr).impl() == key;
     68}
     69
     70inline bool keyMatchesWindowNamedItem(AtomicStringImpl* key, Element* element)
     71{
     72    return WindowNameCollection::nodeMatches(element, key);
     73}
     74
     75inline bool keyMatchesDocumentNamedItem(AtomicStringImpl* key, Element* element)
     76{
     77    return DocumentNameCollection::nodeMatches(element, key);
    6278}
    6379
     
    143159}
    144160
     161Element* DocumentOrderedMap::getElementByName(AtomicStringImpl* key, const TreeScope* scope) const
     162{
     163    return get<keyMatchesName>(key, scope);
     164}
     165
    145166Element* DocumentOrderedMap::getElementByMapName(AtomicStringImpl* key, const TreeScope* scope) const
    146167{
     
    158179}
    159180
     181Element* DocumentOrderedMap::getElementByWindowNamedItem(AtomicStringImpl* key, const TreeScope* scope) const
     182{
     183    return get<keyMatchesWindowNamedItem>(key, scope);
     184}
     185
     186Element* DocumentOrderedMap::getElementByDocumentNamedItem(AtomicStringImpl* key, const TreeScope* scope) const
     187{
     188    return get<keyMatchesDocumentNamedItem>(key, scope);
     189}
     190
    160191} // namespace WebCore
  • trunk/Source/WebCore/dom/DocumentOrderedMap.h

    r148921 r149652  
    4848
    4949    bool contains(AtomicStringImpl*) const;
     50    bool containsSingle(AtomicStringImpl*) const;
    5051    bool containsMultiple(AtomicStringImpl*) const;
    5152    // concrete instantiations of the get<>() method template
    5253    Element* getElementById(AtomicStringImpl*, const TreeScope*) const;
     54    Element* getElementByName(AtomicStringImpl*, const TreeScope*) const;
    5355    Element* getElementByMapName(AtomicStringImpl*, const TreeScope*) const;
    5456    Element* getElementByLowercasedMapName(AtomicStringImpl*, const TreeScope*) const;
    5557    Element* getElementByLabelForAttribute(AtomicStringImpl*, const TreeScope*) const;
     58    Element* getElementByWindowNamedItem(AtomicStringImpl*, const TreeScope*) const;
     59    Element* getElementByDocumentNamedItem(AtomicStringImpl*, const TreeScope*) const;
    5660
    5761    void checkConsistency() const;
     
    6973};
    7074
     75inline bool DocumentOrderedMap::containsSingle(AtomicStringImpl* id) const
     76{
     77    return (m_map.contains(id) ? 1 : 0) + m_duplicateCounts.count(id) == 1;
     78}
     79
    7180inline bool DocumentOrderedMap::contains(AtomicStringImpl* id) const
    7281{
     
    7685inline bool DocumentOrderedMap::containsMultiple(AtomicStringImpl* id) const
    7786{
    78     return m_duplicateCounts.contains(id);
     87    return (m_map.contains(id) ? 1 : 0) + m_duplicateCounts.count(id) > 1;
    7988}
    8089
  • trunk/Source/WebCore/dom/Element.cpp

    r149549 r149652  
    5353#include "HTMLFrameOwnerElement.h"
    5454#include "HTMLLabelElement.h"
     55#include "HTMLNameCollection.h"
    5556#include "HTMLNames.h"
    5657#include "HTMLOptionsCollection.h"
     
    12181219    const AtomicString& nameValue = getNameAttribute();
    12191220    if (!nameValue.isNull())
    1220         updateName(nullAtom, nameValue);
     1221        updateName(scope, nullAtom, nameValue);
    12211222
    12221223    if (hasTagName(labelTag)) {
     
    12611262        const AtomicString& nameValue = getNameAttribute();
    12621263        if (!nameValue.isNull())
    1263             updateName(nameValue, nullAtom);
     1264            updateName(insertionPoint->treeScope(), nameValue, nullAtom);
    12641265
    12651266        if (hasTagName(labelTag)) {
     
    26602661inline void Element::updateName(const AtomicString& oldName, const AtomicString& newName)
    26612662{
    2662     if (!inDocument() || isInShadowTree())
     2663    if (!isInTreeScope())
    26632664        return;
    26642665
     
    26662667        return;
    26672668
    2668     if (shouldRegisterAsNamedItem())
    2669         updateNamedItemRegistration(oldName, newName);
     2669    updateName(treeScope(), oldName, newName);
     2670}
     2671
     2672void 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    }
    26702702}
    26712703
     
    26812713}
    26822714
    2683 inline void Element::updateId(TreeScope* scope, const AtomicString& oldId, const AtomicString& newId)
     2715void Element::updateId(TreeScope* scope, const AtomicString& oldId, const AtomicString& newId)
    26842716{
    26852717    ASSERT(isInTreeScope());
     
    26912723        scope->addElementById(newId, this);
    26922724
    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    }
    26952745}
    26962746
     
    27552805    InspectorInstrumentation::didRemoveDOMAttr(document(), this, name.localName());
    27562806    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);
    27822807}
    27832808
  • trunk/Source/WebCore/dom/Element.h

    r149549 r149652  
    640640    virtual PassRefPtr<RenderStyle> customStyleForRenderer();
    641641
    642     virtual bool shouldRegisterAsNamedItem() const { return false; }
    643     virtual bool shouldRegisterAsExtraNamedItem() const { return false; }
    644 
    645642    void clearTabIndexExplicitlyIfNeeded();   
    646643    void setTabIndexExplicitly(short);
     
    681678    void updateId(TreeScope*, const AtomicString& oldId, const AtomicString& newId);
    682679    void updateName(const AtomicString& oldName, const AtomicString& newName);
     680    void updateName(TreeScope*, const AtomicString& oldName, const AtomicString& newName);
    683681    void updateLabel(TreeScope*, const AtomicString& oldForAttributeValue, const AtomicString& newForAttributeValue);
    684682
     
    726724    SpellcheckAttributeState spellcheckAttributeState() const;
    727725
    728     void updateNamedItemRegistration(const AtomicString& oldName, const AtomicString& newName);
    729     void updateExtraNamedItemRegistration(const AtomicString& oldName, const AtomicString& newName);
    730 
    731726    void unregisterNamedFlowContentNode();
    732727
  • trunk/Source/WebCore/dom/TreeScope.cpp

    r148921 r149652  
    5959struct SameSizeAsTreeScope {
    6060    virtual ~SameSizeAsTreeScope();
    61     void* pointers[8];
     61    void* pointers[9];
    6262    int ints[1];
    6363};
     
    164164    m_elementsById->remove(elementId.impl(), element);
    165165    m_idTargetObserverRegistry->notifyObservers(elementId);
     166}
     167
     168Element* 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
     177void 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
     184void TreeScope::removeElementByName(const AtomicString& name, Element* element)
     185{
     186    if (!m_elementsByName)
     187        return;
     188    m_elementsByName->remove(name.impl(), element);
    166189}
    167190
  • trunk/Source/WebCore/dom/TreeScope.h

    r148921 r149652  
    6262    void removeElementById(const AtomicString& elementId, Element*);
    6363
     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
    6470    Document* documentScope() const { return m_documentScope; }
    6571
     
    162168
    163169    OwnPtr<DocumentOrderedMap> m_elementsById;
     170    OwnPtr<DocumentOrderedMap> m_elementsByName;
    164171    OwnPtr<DocumentOrderedMap> m_imageMapsByName;
    165172    OwnPtr<DocumentOrderedMap> m_labelsByForAttribute;
     
    181188}
    182189
     190inline bool TreeScope::hasElementWithName(AtomicStringImpl* id) const
     191{
     192    ASSERT(id);
     193    return m_elementsByName && m_elementsByName->contains(id);
     194}
     195
     196inline bool TreeScope::containsMultipleElementsWithName(const AtomicString& name) const
     197{
     198    return m_elementsByName && m_elementsByName->containsMultiple(name.impl());
     199}
     200
    183201Node* nodeFromPoint(Document*, int x, int y, LayoutPoint* localPoint = 0);
    184202TreeScope* commonTreeScope(Node*, Node*);
  • trunk/Source/WebCore/html/HTMLAppletElement.h

    r135069 r149652  
    4444
    4545    bool canEmbedJava() const;
    46 
    47     virtual bool shouldRegisterAsNamedItem() const OVERRIDE { return true; }
    48     virtual bool shouldRegisterAsExtraNamedItem() const OVERRIDE { return true; }
    4946};
    5047
  • trunk/Source/WebCore/html/HTMLCollection.cpp

    r147135 r149652  
    2727#include "HTMLDocument.h"
    2828#include "HTMLElement.h"
     29#include "HTMLNameCollection.h"
    2930#include "HTMLNames.h"
    3031#include "HTMLObjectElement.h"
     
    245246    case NodeChildren:
    246247        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);
    247252#if ENABLE(MICRODATA)
    248253    case ItemProperties:
     
    250255#endif
    251256    case FormControls:
    252     case DocumentNamedItems:
    253257    case TableRows:
    254     case WindowNamedItems:
    255258    case ChildNodeListType:
    256259    case ClassNodeListType:
     
    544547}
    545548
    546 bool HTMLCollection::checkForNameMatch(Element* element, bool checkName, const AtomicString& name) const
    547 {
    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 
    561549inline Element* firstMatchingChildElement(const HTMLCollection* nodeList, ContainerNode* root)
    562550{
     
    625613
    626614    ContainerNode* root = rootContainerNode();
    627     if (!root)
     615    if (name.isEmpty() || !root)
    628616        return 0;
    629617
    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);
    647650    }
    648651
     
    677680bool HTMLCollection::hasNamedItem(const AtomicString& name) const
    678681{
    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);
    695684}
    696685
  • trunk/Source/WebCore/html/HTMLCollection.h

    r138195 r149652  
    8080
    8181private:
    82     bool checkForNameMatch(Element*, bool checkName, const AtomicString& name) const;
    8382    Element* traverseNextElement(unsigned& offsetInArray, Element* previous, ContainerNode* root) const;
    8483
  • trunk/Source/WebCore/html/HTMLDocument.cpp

    r148373 r149652  
    294294    }
    295295    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);
    334296}
    335297
  • trunk/Source/WebCore/html/HTMLDocument.h

    r145745 r149652  
    7070    void releaseEvents();
    7171
    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; }
    7974
    8075    static bool isCaseSensitiveAttribute(const QualifiedName&);
     
    8984    virtual PassRefPtr<DocumentParser> createParser();
    9085
    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;
    9688};
    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 }
    10989
    11090inline HTMLDocument* toHTMLDocument(Document* document)
  • trunk/Source/WebCore/html/HTMLEmbedElement.h

    r145750 r149652  
    5656    virtual void setItemValueText(const String&, ExceptionCode&) OVERRIDE;
    5757#endif
    58 
    59     virtual bool shouldRegisterAsNamedItem() const OVERRIDE { return true; }
    6058};
    6159
  • trunk/Source/WebCore/html/HTMLFormElement.h

    r148731 r149652  
    126126    virtual void didMoveToNewDocument(Document* oldDocument) OVERRIDE;
    127127
    128     virtual bool shouldRegisterAsNamedItem() const OVERRIDE { return true; }
    129 
    130128    virtual void copyNonAttributePropertiesFromElement(const Element&) OVERRIDE;
    131129
  • trunk/Source/WebCore/html/HTMLIFrameElement.cpp

    r145745 r149652  
    8080void HTMLIFrameElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
    8181{
    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) {
    9083        String invalidTokens;
    9184        setSandboxFlags(value.isNull() ? SandboxNone : SecurityContext::parseSandboxPolicy(value, invalidTokens));
     
    108101{
    109102    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);
    125103}
    126104
  • trunk/Source/WebCore/html/HTMLIFrameElement.h

    r143843 r149652  
    4242    virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) OVERRIDE;
    4343
    44     virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE;
    45     virtual void removedFrom(ContainerNode*) OVERRIDE;
    46 
    4744    virtual bool rendererIsNeeded(const NodeRenderingContext&);
    4845    virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
     
    5451    virtual void setItemValueText(const String&, ExceptionCode&) OVERRIDE;
    5552#endif
    56 
    57     AtomicString m_name;
    5853};
    5954
  • trunk/Source/WebCore/html/HTMLImageElement.cpp

    r148921 r149652  
    125125        if (!parseCompositeAndBlendOperator(value, m_compositeOperator, blendOp))
    126126            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        }
    128141        HTMLElement::parseAttribute(name, value);
     142    }
    129143}
    130144
  • trunk/Source/WebCore/html/HTMLImageElement.h

    r148921 r149652  
    102102    virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE;
    103103    virtual void removedFrom(ContainerNode*) OVERRIDE;
    104     virtual bool shouldRegisterAsNamedItem() const OVERRIDE { return true; }
    105     virtual bool shouldRegisterAsExtraNamedItem() const OVERRIDE { return true; }
    106104
    107105#if ENABLE(MICRODATA)
  • trunk/Source/WebCore/html/HTMLNameCollection.cpp

    r137406 r149652  
    3636
    3737HTMLNameCollection::HTMLNameCollection(Node* document, CollectionType type, const AtomicString& name)
    38     : HTMLCollection(document, type, OverridesItemAfter)
     38    : HTMLCollection(document, type, DoesNotOverrideItemAfter)
    3939    , m_name(name)
    4040{
     
    5050}
    5151
    52 Element* HTMLNameCollection::virtualItemAfter(unsigned& offsetInArray, Element* previous) const
     52bool WindowNameCollection::nodeMatchesIfNameAttributeMatch(Element* element)
    5353{
    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}
    5657
    57     Element* current;
    58     if (!previous)
    59         current = ElementTraversal::firstWithin(ownerNode());
    60     else
    61         current = ElementTraversal::next(previous, ownerNode());
     58bool 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}
    6265
    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     }
     66bool 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}
    10272
    103     return 0;
     73bool 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
     80bool 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;
    10493}
    10594
  • trunk/Source/WebCore/html/HTMLNameCollection.h

    r135893 r149652  
    3434class HTMLNameCollection : public HTMLCollection {
    3535public:
    36     static PassRefPtr<HTMLNameCollection> create(Node* document, CollectionType type, const AtomicString& name)
     36    ~HTMLNameCollection();
     37
     38protected:
     39    HTMLNameCollection(Node*, CollectionType, const AtomicString& name);
     40
     41    AtomicString m_name;
     42};
     43
     44class WindowNameCollection : public HTMLNameCollection {
     45public:
     46    static PassRefPtr<WindowNameCollection> create(Node* document, CollectionType type, const AtomicString& name)
    3747    {
    38         return adoptRef(new HTMLNameCollection(document, type, name));
     48        return adoptRef(new WindowNameCollection(document, type, name));
    3949    }
    4050
    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&);
    4256
    4357private:
    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};
    4564
    46     virtual Element* virtualItemAfter(unsigned& offsetInArray, Element*) const OVERRIDE;
     65class DocumentNameCollection : public HTMLNameCollection {
     66public:
     67    static PassRefPtr<DocumentNameCollection> create(Node* document, CollectionType type, const AtomicString& name)
     68    {
     69        return adoptRef(new DocumentNameCollection(document, type, name));
     70    }
    4771
    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
     78private:
     79    DocumentNameCollection(Node* document, CollectionType type, const AtomicString& name)
     80        : HTMLNameCollection(document, type, name)
     81    {
     82        ASSERT(type == DocumentNamedItems);
     83    }
    4984};
    5085
  • trunk/Source/WebCore/html/HTMLObjectElement.cpp

    r147205 r149652  
    440440        child = child->nextSibling();
    441441    }
    442     if (isNamedItem != wasNamedItem && document()->isHTMLDocument()) {
     442    if (isNamedItem != wasNamedItem && inDocument() && document()->isHTMLDocument()) {
    443443        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);
    450459        }
    451460    }
  • trunk/Source/WebCore/html/HTMLObjectElement.h

    r145750 r149652  
    107107#endif
    108108
    109     virtual bool shouldRegisterAsNamedItem() const OVERRIDE { return isDocNamedItem(); }
    110     virtual bool shouldRegisterAsExtraNamedItem() const OVERRIDE { return isDocNamedItem(); }
    111 
    112109    String m_classId;
    113110    bool m_docNamedItem : 1;
     
    115112};
    116113
     114inline HTMLObjectElement* toHTMLObjectElement(Node* node)
     115{
     116    ASSERT_WITH_SECURITY_IMPLICATION(!node || node->hasTagName(HTMLNames::objectTag));
     117    return static_cast<HTMLObjectElement*>(node);
     118}
     119
    117120}
    118121
Note: See TracChangeset for help on using the changeset viewer.