15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *           (C) 1999 Antti Koivisto (koivisto@kde.org)
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserved.
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful,
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details.
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB.  If not, write to
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA.
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
2453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/HTMLCollection.h"
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "HTMLNames.h"
2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/ClassNodeList.h"
2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/NodeList.h"
2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/NodeRareData.h"
3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/NodeTraversal.h"
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/HTMLElement.h"
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/HTMLObjectElement.h"
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/HTMLOptionElement.h"
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace HTMLNames;
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static bool shouldOnlyIncludeDirectChildren(CollectionType type)
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (type) {
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocAll:
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocAnchors:
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocApplets:
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocEmbeds:
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocForms:
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocImages:
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocLinks:
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocScripts:
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocumentNamedItems:
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case MapAreas:
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case TableRows:
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SelectOptions:
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SelectedOptions:
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DataListOptions:
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case WindowNamedItems:
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FormControls:
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NodeChildren:
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case TRCells:
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case TSectionRows:
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case TableTBodies:
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
64926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case ChildNodeListType:
65926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case ClassNodeListType:
66926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case NameNodeListType:
67926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case TagNodeListType:
68926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case HTMLTagNodeListType:
69926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case RadioNodeListType:
70926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case LabelsNodeListType:
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT_NOT_REACHED();
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static NodeListRootType rootTypeFromCollectionType(CollectionType type)
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (type) {
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocImages:
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocApplets:
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocEmbeds:
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocForms:
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocLinks:
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocAnchors:
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocScripts:
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocAll:
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case WindowNamedItems:
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocumentNamedItems:
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FormControls:
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return NodeListIsRootedAtDocument;
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NodeChildren:
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case TableTBodies:
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case TSectionRows:
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case TableRows:
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case TRCells:
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SelectOptions:
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SelectedOptions:
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DataListOptions:
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case MapAreas:
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return NodeListIsRootedAtNode;
102926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case ChildNodeListType:
103926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case ClassNodeListType:
104926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case NameNodeListType:
105926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case TagNodeListType:
106926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case HTMLTagNodeListType:
107926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case RadioNodeListType:
108926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case LabelsNodeListType:
109926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        break;
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT_NOT_REACHED();
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return NodeListIsRootedAtNode;
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static NodeListInvalidationType invalidationTypeExcludingIdAndNameAttributes(CollectionType type)
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (type) {
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocImages:
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocEmbeds:
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocForms:
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocScripts:
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocAll:
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NodeChildren:
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case TableTBodies:
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case TSectionRows:
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case TableRows:
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case TRCells:
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SelectOptions:
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case MapAreas:
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return DoNotInvalidateOnAttributeChanges;
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocApplets:
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SelectedOptions:
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DataListOptions:
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // FIXME: We can do better some day.
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return InvalidateOnAnyAttrChange;
136926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case DocAnchors:
137926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return InvalidateOnNameAttrChange;
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocLinks:
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return InvalidateOnHRefAttrChange;
140926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case WindowNamedItems:
141926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return InvalidateOnIdNameAttrChange;
142926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case DocumentNamedItems:
143926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return InvalidateOnIdNameAttrChange;
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FormControls:
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return InvalidateForFormControls;
146926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case ChildNodeListType:
147926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case ClassNodeListType:
148926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case NameNodeListType:
149926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case TagNodeListType:
150926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case HTMLTagNodeListType:
151926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case RadioNodeListType:
152926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case LabelsNodeListType:
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT_NOT_REACHED();
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return DoNotInvalidateOnAttributeChanges;
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)HTMLCollection::HTMLCollection(Node* ownerNode, CollectionType type, ItemAfterOverrideType itemAfterOverrideType)
160926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    : LiveNodeListBase(ownerNode, rootTypeFromCollectionType(type), invalidationTypeExcludingIdAndNameAttributes(type),
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        WebCore::shouldOnlyIncludeDirectChildren(type), type, itemAfterOverrideType)
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
16353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    ScriptWrappable::init(this);
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<HTMLCollection> HTMLCollection::create(Node* base, CollectionType type)
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return adoptRef(new HTMLCollection(base, type, DoesNotOverrideItemAfter));
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)HTMLCollection::~HTMLCollection()
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
173926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // HTMLNameCollection removes cache by itself.
174926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (type() != WindowNamedItems && type() != DocumentNamedItems)
175926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        ownerNode()->nodeLists()->removeCacheWithAtomicName(this, type());
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
178926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)template <class NodeListType>
179926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)inline bool isMatchingElement(const NodeListType*, Element*);
180926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
181926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)template <> inline bool isMatchingElement(const HTMLCollection* htmlCollection, Element* element)
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
183926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    CollectionType type = htmlCollection->type();
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!element->isHTMLElement() && !(type == DocAll || type == NodeChildren))
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (type) {
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocImages:
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return element->hasLocalName(imgTag);
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocScripts:
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return element->hasLocalName(scriptTag);
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocForms:
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return element->hasLocalName(formTag);
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case TableTBodies:
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return element->hasLocalName(tbodyTag);
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case TRCells:
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return element->hasLocalName(tdTag) || element->hasLocalName(thTag);
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case TSectionRows:
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return element->hasLocalName(trTag);
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SelectOptions:
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return element->hasLocalName(optionTag);
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SelectedOptions:
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return element->hasLocalName(optionTag) && toHTMLOptionElement(element)->selected();
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DataListOptions:
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (element->hasLocalName(optionTag)) {
206591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            HTMLOptionElement* option = toHTMLOptionElement(element);
20753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            if (!option->isDisabledFormControl() && !option->value().isEmpty())
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return true;
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case MapAreas:
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return element->hasLocalName(areaTag);
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocApplets:
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return element->hasLocalName(appletTag) || (element->hasLocalName(objectTag) && static_cast<HTMLObjectElement*>(element)->containsJavaApplet());
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocEmbeds:
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return element->hasLocalName(embedTag);
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocLinks:
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return (element->hasLocalName(aTag) || element->hasLocalName(areaTag)) && element->fastHasAttribute(hrefAttr);
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocAnchors:
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return element->hasLocalName(aTag) && element->fastHasAttribute(nameAttr);
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DocAll:
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NodeChildren:
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
224f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    case FormControls:
225df95704c49daea886ddad70775bda23618d6274dBen Murdoch    case DocumentNamedItems:
226f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    case TableRows:
227df95704c49daea886ddad70775bda23618d6274dBen Murdoch    case WindowNamedItems:
228926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case ChildNodeListType:
229926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case ClassNodeListType:
230926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case NameNodeListType:
231926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case TagNodeListType:
232926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case HTMLTagNodeListType:
233926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case RadioNodeListType:
234926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    case LabelsNodeListType:
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT_NOT_REACHED();
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
240926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)template <> inline bool isMatchingElement(const LiveNodeList* nodeList, Element* element)
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
242926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return nodeList->nodeMatches(element);
243926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
244926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
245926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)template <> inline bool isMatchingElement(const HTMLTagNodeList* nodeList, Element* element)
246926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
247926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return nodeList->nodeMatchesInlined(element);
248926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
249926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
250926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)template <> inline bool isMatchingElement(const ClassNodeList* nodeList, Element* element)
251926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
252926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return nodeList->nodeMatchesInlined(element);
253926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
254926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
255926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)static Node* previousNode(Node* base, Node* previous, bool onlyIncludeDirectChildren)
256926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
257926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return onlyIncludeDirectChildren ? previous->previousSibling() : NodeTraversal::previous(previous, base);
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline Node* lastDescendent(Node* node)
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    node = node->lastChild();
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (Node* current = node; current; current = current->lastChild())
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        node = current;
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return node;
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
268926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)static Node* lastNode(Node* rootNode, bool onlyIncludeDirectChildren)
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
270926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return onlyIncludeDirectChildren ? rootNode->lastChild() : lastDescendent(rootNode);
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
273926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ALWAYS_INLINE Node* LiveNodeListBase::iterateForPreviousNode(Node* current) const
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool onlyIncludeDirectChildren = shouldOnlyIncludeDirectChildren();
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    CollectionType collectionType = type();
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Node* rootNode = this->rootNode();
278926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (; current; current = previousNode(rootNode, current, onlyIncludeDirectChildren)) {
279926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (isNodeList(collectionType)) {
280926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if (current->isElementNode() && isMatchingElement(static_cast<const LiveNodeList*>(this), toElement(current)))
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return toElement(current);
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else {
283926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if (current->isElementNode() && isMatchingElement(static_cast<const HTMLCollection*>(this), toElement(current)))
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return toElement(current);
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0;
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
290926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ALWAYS_INLINE Node* LiveNodeListBase::itemBefore(Node* previous) const
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Node* current;
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (LIKELY(!!previous)) // Without this LIKELY, length() and item() can be 10% slower.
294926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        current = previousNode(rootNode(), previous, shouldOnlyIncludeDirectChildren());
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
296926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        current = lastNode(rootNode(), shouldOnlyIncludeDirectChildren());
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
298926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (type() == ChildNodeListType)
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return current;
300926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return iterateForPreviousNode(current);
301926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
303926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)template <class NodeListType>
304926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)inline Element* firstMatchingElement(const NodeListType* nodeList, ContainerNode* root)
305926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
306926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Element* element = ElementTraversal::firstWithin(root);
307926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    while (element && !isMatchingElement(nodeList, element))
308926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        element = ElementTraversal::next(element, root);
309926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return element;
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
312926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)template <class NodeListType>
313926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)inline Element* nextMatchingElement(const NodeListType* nodeList, Element* current, ContainerNode* root)
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
315926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    do {
316926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        current = ElementTraversal::next(current, root);
317926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } while (current && !isMatchingElement(nodeList, current));
318926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return current;
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
321926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)template <class NodeListType>
322926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)inline Element* traverseMatchingElementsForwardToOffset(const NodeListType* nodeList, unsigned offset, Element* currentElement, unsigned& currentOffset, ContainerNode* root)
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
324926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(currentOffset < offset);
325926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    while ((currentElement = nextMatchingElement(nodeList, currentElement, root))) {
326926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (++currentOffset == offset)
327926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return currentElement;
328926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
329926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return 0;
330926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
331926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
332926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// FIXME: This should be in ChildNodeList
333926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)inline Node* LiveNodeListBase::traverseChildNodeListForwardToOffset(unsigned offset, Node* currentNode, unsigned& currentOffset) const
334926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
335926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(type() == ChildNodeListType);
336926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(currentOffset < offset);
337926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    while ((currentNode = currentNode->nextSibling())) {
338926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (++currentOffset == offset)
339926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return currentNode;
340926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
341926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return 0;
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
344926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// FIXME: This should be in LiveNodeList
345926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)inline Element* LiveNodeListBase::traverseLiveNodeListFirstElement(ContainerNode* root) const
346926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
347926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(isNodeList(type()));
348926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(type() != ChildNodeListType);
349926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (type() == HTMLTagNodeListType)
350926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return firstMatchingElement(static_cast<const HTMLTagNodeList*>(this), root);
351926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (type() == ClassNodeListType)
352926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return firstMatchingElement(static_cast<const ClassNodeList*>(this), root);
353926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return firstMatchingElement(static_cast<const LiveNodeList*>(this), root);
354926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
355926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
356926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// FIXME: This should be in LiveNodeList
357926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)inline Element* LiveNodeListBase::traverseLiveNodeListForwardToOffset(unsigned offset, Element* currentElement, unsigned& currentOffset, ContainerNode* root) const
358926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
359926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(isNodeList(type()));
360926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(type() != ChildNodeListType);
361926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (type() == HTMLTagNodeListType)
362926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return traverseMatchingElementsForwardToOffset(static_cast<const HTMLTagNodeList*>(this), offset, currentElement, currentOffset, root);
363926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (type() == ClassNodeListType)
364926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return traverseMatchingElementsForwardToOffset(static_cast<const ClassNodeList*>(this), offset, currentElement, currentOffset, root);
365926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return traverseMatchingElementsForwardToOffset(static_cast<const LiveNodeList*>(this), offset, currentElement, currentOffset, root);
366926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
367926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
368926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool ALWAYS_INLINE LiveNodeListBase::isLastItemCloserThanLastOrCachedItem(unsigned offset) const
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(isLengthCacheValid());
3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned distanceFromLastItem = cachedLength() - offset;
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!isItemCacheValid())
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return distanceFromLastItem < offset;
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return cachedItemOffset() < offset && distanceFromLastItem < offset - cachedItemOffset();
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
37702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
378926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool ALWAYS_INLINE LiveNodeListBase::isFirstItemCloserThanCachedItem(unsigned offset) const
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(isItemCacheValid());
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (cachedItemOffset() < offset)
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned distanceFromCachedItem = cachedItemOffset() - offset;
3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return offset < distanceFromCachedItem;
3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
388926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ALWAYS_INLINE void LiveNodeListBase::setItemCache(Node* item, unsigned offset, unsigned elementsArrayOffset) const
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setItemCache(item, offset);
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (overridesItemAfter()) {
392926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        ASSERT_WITH_SECURITY_IMPLICATION(item->isElementNode());
393926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        static_cast<const HTMLCollection*>(this)->m_cachedElementsArrayOffset = elementsArrayOffset;
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(!elementsArrayOffset);
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
398926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)unsigned LiveNodeListBase::length() const
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (isLengthCacheValid())
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return cachedLength();
4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
403926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    item(UINT_MAX);
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(isLengthCacheValid());
40502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return cachedLength();
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
409926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)// FIXME: It is silly that these functions are in HTMLCollection.cpp.
410926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Node* LiveNodeListBase::item(unsigned offset) const
4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (isItemCacheValid() && cachedItemOffset() == offset)
4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return cachedItem();
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (isLengthCacheValid() && cachedLength() <= offset)
4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
418926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ContainerNode* root = rootContainerNode();
419926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!root) {
420926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // FIMXE: In someTextNode.childNodes case the root is Text. We shouldn't even make a LiveNodeList for that.
421926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        setLengthCache(0);
422926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return 0;
423926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
424926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (isLengthCacheValid() && !overridesItemAfter() && isLastItemCloserThanLastOrCachedItem(offset)) {
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Node* lastItem = itemBefore(0);
4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(lastItem);
4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        setItemCache(lastItem, cachedLength() - 1, 0);
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else if (!isItemCacheValid() || isFirstItemCloserThanCachedItem(offset) || (overridesItemAfter() && offset < cachedItemOffset())) {
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        unsigned offsetInArray = 0;
431926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        Node* firstItem;
432926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (type() == ChildNodeListType)
433926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            firstItem = root->firstChild();
434926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        else if (isNodeList(type()))
435926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            firstItem = traverseLiveNodeListFirstElement(root);
436926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        else
437926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            firstItem = static_cast<const HTMLCollection*>(this)->traverseFirstElement(offsetInArray, root);
438926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!firstItem) {
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            setLengthCache(0);
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return 0;
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        setItemCache(firstItem, 0, offsetInArray);
4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(!cachedItemOffset());
4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (cachedItemOffset() == offset)
4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return cachedItem();
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
450926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return itemBeforeOrAfterCachedItem(offset, root);
4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
453926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)inline Node* LiveNodeListBase::itemBeforeOrAfterCachedItem(unsigned offset, ContainerNode* root) const
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned currentOffset = cachedItemOffset();
4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Node* currentItem = cachedItem();
457926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(currentItem);
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(currentOffset != offset);
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (offset < cachedItemOffset()) {
4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(!overridesItemAfter());
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while ((currentItem = itemBefore(currentItem))) {
4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ASSERT(currentOffset);
4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            currentOffset--;
4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (currentOffset == offset) {
4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                setItemCache(currentItem, currentOffset, 0);
4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return currentItem;
4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT_NOT_REACHED();
4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
474926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    unsigned offsetInArray = 0;
475926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (type() == ChildNodeListType)
476926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        currentItem = traverseChildNodeListForwardToOffset(offset, currentItem, currentOffset);
477926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else if (isNodeList(type()))
478926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        currentItem = traverseLiveNodeListForwardToOffset(offset, toElement(currentItem), currentOffset, root);
479926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else
480926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        currentItem = static_cast<const HTMLCollection*>(this)->traverseForwardToOffset(offset, toElement(currentItem), currentOffset, offsetInArray, root);
4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
482926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!currentItem) {
483926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // Did not find the item. On plus side, we now know the length.
484926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        setLengthCache(currentOffset + 1);
485926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return 0;
486926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
487926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    setItemCache(currentItem, currentOffset, offsetInArray);
488926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return currentItem;
4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Element* HTMLCollection::virtualItemAfter(unsigned&, Element*) const
4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT_NOT_REACHED();
4945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0;
4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline bool nameShouldBeVisibleInDocumentAll(HTMLElement* element)
4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The document.all collection returns only certain types of elements by name,
5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // although it returns any type of element by id.
5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return element->hasLocalName(appletTag)
5025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        || element->hasLocalName(embedTag)
5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        || element->hasLocalName(formTag)
5045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        || element->hasLocalName(imgTag)
5055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        || element->hasLocalName(inputTag)
5065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        || element->hasLocalName(objectTag)
5075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        || element->hasLocalName(selectTag);
5085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
510df95704c49daea886ddad70775bda23618d6274dBen Murdochbool HTMLCollection::checkForNameMatch(Element* element, bool checkName, const AtomicString& name) const
511df95704c49daea886ddad70775bda23618d6274dBen Murdoch{
512df95704c49daea886ddad70775bda23618d6274dBen Murdoch    if (!element->isHTMLElement())
513df95704c49daea886ddad70775bda23618d6274dBen Murdoch        return false;
514df95704c49daea886ddad70775bda23618d6274dBen Murdoch
515df95704c49daea886ddad70775bda23618d6274dBen Murdoch    HTMLElement* e = toHTMLElement(element);
516df95704c49daea886ddad70775bda23618d6274dBen Murdoch    if (!checkName)
517df95704c49daea886ddad70775bda23618d6274dBen Murdoch        return e->getIdAttribute() == name;
518df95704c49daea886ddad70775bda23618d6274dBen Murdoch
519df95704c49daea886ddad70775bda23618d6274dBen Murdoch    if (type() == DocAll && !nameShouldBeVisibleInDocumentAll(e))
520df95704c49daea886ddad70775bda23618d6274dBen Murdoch        return false;
521df95704c49daea886ddad70775bda23618d6274dBen Murdoch
522df95704c49daea886ddad70775bda23618d6274dBen Murdoch    return e->getNameAttribute() == name && e->getIdAttribute() != name;
523df95704c49daea886ddad70775bda23618d6274dBen Murdoch}
524df95704c49daea886ddad70775bda23618d6274dBen Murdoch
525926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)inline Element* firstMatchingChildElement(const HTMLCollection* nodeList, ContainerNode* root)
526926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
527926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Element* element = ElementTraversal::firstWithin(root);
528926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    while (element && !isMatchingElement(nodeList, element))
529926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        element = ElementTraversal::nextSkippingChildren(element, root);
530926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return element;
531926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
532926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
533926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)inline Element* nextMatchingChildElement(const HTMLCollection* nodeList, Element* current, ContainerNode* root)
534926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
535926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    do {
536926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        current = ElementTraversal::nextSkippingChildren(current, root);
537926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } while (current && !isMatchingElement(nodeList, current));
538926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return current;
539926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
540926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
541926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)inline Element* HTMLCollection::traverseFirstElement(unsigned& offsetInArray, ContainerNode* root) const
542926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
543926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (overridesItemAfter())
544926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return virtualItemAfter(offsetInArray, 0);
545926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(!offsetInArray);
546926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (shouldOnlyIncludeDirectChildren())
547926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return firstMatchingChildElement(static_cast<const HTMLCollection*>(this), root);
548926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return firstMatchingElement(static_cast<const HTMLCollection*>(this), root);
549926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
550926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
551926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)inline Element* HTMLCollection::traverseNextElement(unsigned& offsetInArray, Element* previous, ContainerNode* root) const
552926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
553926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (overridesItemAfter())
554926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return virtualItemAfter(offsetInArray, previous);
555926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(!offsetInArray);
556926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (shouldOnlyIncludeDirectChildren())
557926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return nextMatchingChildElement(this, previous, root);
558926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return nextMatchingElement(this, previous, root);
559926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
560926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
561926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)inline Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element* currentElement, unsigned& currentOffset, unsigned& offsetInArray, ContainerNode* root) const
562926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
563926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(currentOffset < offset);
564926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (overridesItemAfter()) {
565926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        offsetInArray = m_cachedElementsArrayOffset;
566926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        while ((currentElement = virtualItemAfter(offsetInArray, currentElement))) {
567926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if (++currentOffset == offset)
568926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                return currentElement;
569926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
570926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return 0;
571926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
572926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (shouldOnlyIncludeDirectChildren()) {
573926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        while ((currentElement = nextMatchingChildElement(this, currentElement, root))) {
574926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if (++currentOffset == offset)
575926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                return currentElement;
576926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
577926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return 0;
578926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
579926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return traverseMatchingElementsForwardToOffset(this, offset, currentElement, currentOffset, root);
580926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
581926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
5825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Node* HTMLCollection::namedItem(const AtomicString& name) const
5835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/nameditem.asp
5855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // This method first searches for an object with a matching id
5865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // attribute. If a match is not found, the method then searches for an
5875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // object with a matching name attribute, but only on those elements
5885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // that are allowed a name attribute.
5895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
590926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ContainerNode* root = rootContainerNode();
591df95704c49daea886ddad70775bda23618d6274dBen Murdoch    if (!root)
592926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return 0;
593926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
594df95704c49daea886ddad70775bda23618d6274dBen Murdoch    unsigned arrayOffset = 0;
595df95704c49daea886ddad70775bda23618d6274dBen Murdoch    unsigned i = 0;
596df95704c49daea886ddad70775bda23618d6274dBen Murdoch    for (Element* element = traverseFirstElement(arrayOffset, root); element; element = traverseNextElement(arrayOffset, element, root)) {
597df95704c49daea886ddad70775bda23618d6274dBen Murdoch        if (checkForNameMatch(element, /* checkName */ false, name)) {
598df95704c49daea886ddad70775bda23618d6274dBen Murdoch            setItemCache(element, i, arrayOffset);
599df95704c49daea886ddad70775bda23618d6274dBen Murdoch            return element;
6005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
601df95704c49daea886ddad70775bda23618d6274dBen Murdoch        i++;
602f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    }
603f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
604df95704c49daea886ddad70775bda23618d6274dBen Murdoch    i = 0;
605df95704c49daea886ddad70775bda23618d6274dBen Murdoch    for (Element* element = traverseFirstElement(arrayOffset, root); element; element = traverseNextElement(arrayOffset, element, root)) {
606df95704c49daea886ddad70775bda23618d6274dBen Murdoch        if (checkForNameMatch(element, /* checkName */ true, name)) {
607df95704c49daea886ddad70775bda23618d6274dBen Murdoch            setItemCache(element, i, arrayOffset);
608df95704c49daea886ddad70775bda23618d6274dBen Murdoch            return element;
609df95704c49daea886ddad70775bda23618d6274dBen Murdoch        }
610df95704c49daea886ddad70775bda23618d6274dBen Murdoch        i++;
6115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0;
6145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void HTMLCollection::updateNameCache() const
6175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (hasNameCache())
6195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
6205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
621926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ContainerNode* root = rootContainerNode();
622926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!root)
623926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
624926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
6255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned arrayOffset = 0;
626926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (Element* element = traverseFirstElement(arrayOffset, root); element; element = traverseNextElement(arrayOffset, element, root)) {
627926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (!element->isHTMLElement())
6285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
629926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        HTMLElement* htmlElement = toHTMLElement(element);
630926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        const AtomicString& idAttrVal = htmlElement->getIdAttribute();
631926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        const AtomicString& nameAttrVal = htmlElement->getNameAttribute();
6325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!idAttrVal.isEmpty())
633926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            appendIdCache(idAttrVal, htmlElement);
634926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && (type() != DocAll || nameShouldBeVisibleInDocumentAll(htmlElement)))
635926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            appendNameCache(nameAttrVal, htmlElement);
6365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setHasNameCache();
6395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool HTMLCollection::hasNamedItem(const AtomicString& name) const
6425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
643df95704c49daea886ddad70775bda23618d6274dBen Murdoch    if (name.isEmpty())
644df95704c49daea886ddad70775bda23618d6274dBen Murdoch        return false;
645df95704c49daea886ddad70775bda23618d6274dBen Murdoch
646df95704c49daea886ddad70775bda23618d6274dBen Murdoch    updateNameCache();
647df95704c49daea886ddad70775bda23618d6274dBen Murdoch
648df95704c49daea886ddad70775bda23618d6274dBen Murdoch    if (Vector<Element*>* cache = idCache(name)) {
649df95704c49daea886ddad70775bda23618d6274dBen Murdoch        if (!cache->isEmpty())
650df95704c49daea886ddad70775bda23618d6274dBen Murdoch            return true;
651df95704c49daea886ddad70775bda23618d6274dBen Murdoch    }
652df95704c49daea886ddad70775bda23618d6274dBen Murdoch
653df95704c49daea886ddad70775bda23618d6274dBen Murdoch    if (Vector<Element*>* cache = nameCache(name)) {
654df95704c49daea886ddad70775bda23618d6274dBen Murdoch        if (!cache->isEmpty())
655df95704c49daea886ddad70775bda23618d6274dBen Murdoch            return true;
656df95704c49daea886ddad70775bda23618d6274dBen Murdoch    }
657df95704c49daea886ddad70775bda23618d6274dBen Murdoch
658df95704c49daea886ddad70775bda23618d6274dBen Murdoch    return false;
6595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void HTMLCollection::namedItems(const AtomicString& name, Vector<RefPtr<Node> >& result) const
6625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(result.isEmpty());
6645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (name.isEmpty())
6655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
6665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateNameCache();
6685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Vector<Element*>* idResults = idCache(name);
6705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Vector<Element*>* nameResults = nameCache(name);
6715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = 0; idResults && i < idResults->size(); ++i)
6735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.append(idResults->at(i));
6745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = 0; nameResults && i < nameResults->size(); ++i)
6765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.append(nameResults->at(i));
6775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<NodeList> HTMLCollection::tags(const String& name)
6805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return ownerNode()->getElementsByTagName(name);
6825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
684926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void HTMLCollection::append(NodeCacheMap& map, const AtomicString& key, Element* element)
6855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OwnPtr<Vector<Element*> >& vector = map.add(key.impl(), nullptr).iterator->value;
6875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!vector)
6885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        vector = adoptPtr(new Vector<Element*>);
6895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    vector->append(element);
6905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore
693