| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All r
ights reserved. | 4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All r
ights reserved. |
| 5 * | 5 * |
| 6 * This library is free software; you can redistribute it and/or | 6 * This library is free software; you can redistribute it and/or |
| 7 * modify it under the terms of the GNU Library General Public | 7 * modify it under the terms of the GNU Library General Public |
| 8 * License as published by the Free Software Foundation; either | 8 * License as published by the Free Software Foundation; either |
| 9 * version 2 of the License, or (at your option) any later version. | 9 * version 2 of the License, or (at your option) any later version. |
| 10 * | 10 * |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 180 ownerNode()->nodeLists()->removeCacheWithAtomicName(this, type()); | 180 ownerNode()->nodeLists()->removeCacheWithAtomicName(this, type()); |
| 181 } | 181 } |
| 182 | 182 |
| 183 void HTMLCollection::invalidateCache() const | 183 void HTMLCollection::invalidateCache() const |
| 184 { | 184 { |
| 185 LiveNodeListBase::invalidateCache(); | 185 LiveNodeListBase::invalidateCache(); |
| 186 invalidateIdNameCacheMaps(); | 186 invalidateIdNameCacheMaps(); |
| 187 } | 187 } |
| 188 | 188 |
| 189 template <class NodeListType> | 189 template <class NodeListType> |
| 190 inline bool isMatchingElement(const NodeListType*, Element*); | 190 inline bool isMatchingElement(const NodeListType&, const Element&); |
| 191 | 191 |
| 192 template <> inline bool isMatchingElement(const HTMLCollection* htmlCollection,
Element* element) | 192 template <> inline bool isMatchingElement(const HTMLCollection& htmlCollection,
const Element& element) |
| 193 { | 193 { |
| 194 CollectionType type = htmlCollection->type(); | 194 CollectionType type = htmlCollection.type(); |
| 195 if (!element->isHTMLElement() && !(type == DocAll || type == NodeChildren ||
type == WindowNamedItems)) | 195 if (!element.isHTMLElement() && !(type == DocAll || type == NodeChildren ||
type == WindowNamedItems)) |
| 196 return false; | 196 return false; |
| 197 | 197 |
| 198 switch (type) { | 198 switch (type) { |
| 199 case DocImages: | 199 case DocImages: |
| 200 return element->hasLocalName(imgTag); | 200 return element.hasLocalName(imgTag); |
| 201 case DocScripts: | 201 case DocScripts: |
| 202 return element->hasLocalName(scriptTag); | 202 return element.hasLocalName(scriptTag); |
| 203 case DocForms: | 203 case DocForms: |
| 204 return element->hasLocalName(formTag); | 204 return element.hasLocalName(formTag); |
| 205 case TableTBodies: | 205 case TableTBodies: |
| 206 return element->hasLocalName(tbodyTag); | 206 return element.hasLocalName(tbodyTag); |
| 207 case TRCells: | 207 case TRCells: |
| 208 return element->hasLocalName(tdTag) || element->hasLocalName(thTag); | 208 return element.hasLocalName(tdTag) || element.hasLocalName(thTag); |
| 209 case TSectionRows: | 209 case TSectionRows: |
| 210 return element->hasLocalName(trTag); | 210 return element.hasLocalName(trTag); |
| 211 case SelectOptions: | 211 case SelectOptions: |
| 212 return element->hasLocalName(optionTag); | 212 return element.hasLocalName(optionTag); |
| 213 case SelectedOptions: | 213 case SelectedOptions: |
| 214 return element->hasLocalName(optionTag) && toHTMLOptionElement(element)-
>selected(); | 214 return element.hasLocalName(optionTag) && toHTMLOptionElement(element).s
elected(); |
| 215 case DataListOptions: | 215 case DataListOptions: |
| 216 if (element->hasLocalName(optionTag)) { | 216 if (element.hasLocalName(optionTag)) { |
| 217 HTMLOptionElement* option = toHTMLOptionElement(element); | 217 const HTMLOptionElement& option = toHTMLOptionElement(element); |
| 218 if (!option->isDisabledFormControl() && !option->value().isEmpty()) | 218 if (!option.isDisabledFormControl() && !option.value().isEmpty()) |
| 219 return true; | 219 return true; |
| 220 } | 220 } |
| 221 return false; | 221 return false; |
| 222 case MapAreas: | 222 case MapAreas: |
| 223 return element->hasLocalName(areaTag); | 223 return element.hasLocalName(areaTag); |
| 224 case DocApplets: | 224 case DocApplets: |
| 225 return element->hasLocalName(appletTag) || (element->hasLocalName(object
Tag) && toHTMLObjectElement(element)->containsJavaApplet()); | 225 return element.hasLocalName(appletTag) || (element.hasLocalName(objectTa
g) && toHTMLObjectElement(element).containsJavaApplet()); |
| 226 case DocEmbeds: | 226 case DocEmbeds: |
| 227 return element->hasLocalName(embedTag); | 227 return element.hasLocalName(embedTag); |
| 228 case DocLinks: | 228 case DocLinks: |
| 229 return (element->hasLocalName(aTag) || element->hasLocalName(areaTag)) &
& element->fastHasAttribute(hrefAttr); | 229 return (element.hasLocalName(aTag) || element.hasLocalName(areaTag)) &&
element.fastHasAttribute(hrefAttr); |
| 230 case DocAnchors: | 230 case DocAnchors: |
| 231 return element->hasLocalName(aTag) && element->fastHasAttribute(nameAttr
); | 231 return element.hasLocalName(aTag) && element.fastHasAttribute(nameAttr); |
| 232 case DocAll: | 232 case DocAll: |
| 233 case NodeChildren: | 233 case NodeChildren: |
| 234 return true; | 234 return true; |
| 235 case FormControls: | 235 case FormControls: |
| 236 case DocumentNamedItems: | 236 case DocumentNamedItems: |
| 237 case TableRows: | 237 case TableRows: |
| 238 case WindowNamedItems: | 238 case WindowNamedItems: |
| 239 case ChildNodeListType: | 239 case ChildNodeListType: |
| 240 case ClassNodeListType: | 240 case ClassNodeListType: |
| 241 case NameNodeListType: | 241 case NameNodeListType: |
| 242 case TagNodeListType: | 242 case TagNodeListType: |
| 243 case HTMLTagNodeListType: | 243 case HTMLTagNodeListType: |
| 244 case RadioNodeListType: | 244 case RadioNodeListType: |
| 245 case RadioImgNodeListType: | 245 case RadioImgNodeListType: |
| 246 case LabelsNodeListType: | 246 case LabelsNodeListType: |
| 247 ASSERT_NOT_REACHED(); | 247 ASSERT_NOT_REACHED(); |
| 248 } | 248 } |
| 249 return false; | 249 return false; |
| 250 } | 250 } |
| 251 | 251 |
| 252 template <> inline bool isMatchingElement(const LiveNodeList* nodeList, Element*
element) | 252 template <> inline bool isMatchingElement(const LiveNodeList& nodeList, const El
ement& element) |
| 253 { | 253 { |
| 254 return nodeList->nodeMatches(element); | 254 return nodeList.nodeMatches(element); |
| 255 } | 255 } |
| 256 | 256 |
| 257 template <> inline bool isMatchingElement(const HTMLTagNodeList* nodeList, Eleme
nt* element) | 257 template <> inline bool isMatchingElement(const HTMLTagNodeList& nodeList, const
Element& element) |
| 258 { | 258 { |
| 259 return nodeList->nodeMatchesInlined(element); | 259 return nodeList.nodeMatchesInlined(element); |
| 260 } | 260 } |
| 261 | 261 |
| 262 template <> inline bool isMatchingElement(const ClassNodeList* nodeList, Element
* element) | 262 template <> inline bool isMatchingElement(const ClassNodeList& nodeList, const E
lement& element) |
| 263 { | 263 { |
| 264 return nodeList->nodeMatchesInlined(element); | 264 return nodeList.nodeMatchesInlined(element); |
| 265 } | 265 } |
| 266 | 266 |
| 267 static Node* previousNode(Node& base, Node& previous, bool onlyIncludeDirectChil
dren) | 267 static Node* previousNode(const Node& base, const Node& previous, bool onlyInclu
deDirectChildren) |
| 268 { | 268 { |
| 269 return onlyIncludeDirectChildren ? previous.previousSibling() : NodeTraversa
l::previous(previous, &base); | 269 return onlyIncludeDirectChildren ? previous.previousSibling() : NodeTraversa
l::previous(previous, &base); |
| 270 } | 270 } |
| 271 | 271 |
| 272 static inline Node* lastDescendent(Node& node) | 272 static inline Node* lastDescendant(const Node& node) |
| 273 { | 273 { |
| 274 Node* descendent = node.lastChild(); | 274 Node* descendant = node.lastChild(); |
| 275 for (Node* current = descendent; current; current = current->lastChild()) | 275 for (Node* current = descendant; current; current = current->lastChild()) |
| 276 descendent = current; | 276 descendant = current; |
| 277 return descendent; | 277 return descendant; |
| 278 } | 278 } |
| 279 | 279 |
| 280 static Node* lastNode(Node& rootNode, bool onlyIncludeDirectChildren) | 280 static Node* lastNode(const Node& rootNode, bool onlyIncludeDirectChildren) |
| 281 { | 281 { |
| 282 return onlyIncludeDirectChildren ? rootNode.lastChild() : lastDescendent(roo
tNode); | 282 return onlyIncludeDirectChildren ? rootNode.lastChild() : lastDescendant(roo
tNode); |
| 283 } | 283 } |
| 284 | 284 |
| 285 ALWAYS_INLINE Node* LiveNodeListBase::iterateForPreviousNode(Node* current) cons
t | 285 ALWAYS_INLINE Node* LiveNodeListBase::iterateForPreviousNode(Node* current) cons
t |
| 286 { | 286 { |
| 287 bool onlyIncludeDirectChildren = shouldOnlyIncludeDirectChildren(); | 287 bool onlyIncludeDirectChildren = shouldOnlyIncludeDirectChildren(); |
| 288 CollectionType collectionType = type(); | 288 CollectionType collectionType = type(); |
| 289 Node& rootNode = this->rootNode(); | 289 Node& rootNode = this->rootNode(); |
| 290 for (; current; current = previousNode(rootNode, *current, onlyIncludeDirect
Children)) { | 290 for (; current; current = previousNode(rootNode, *current, onlyIncludeDirect
Children)) { |
| 291 if (isLiveNodeListType(collectionType)) { | 291 if (isLiveNodeListType(collectionType)) { |
| 292 if (current->isElementNode() && isMatchingElement(static_cast<const
LiveNodeList*>(this), toElement(current))) | 292 if (current->isElementNode() && isMatchingElement(static_cast<const
LiveNodeList&>(*this), toElement(*current))) |
| 293 return toElement(current); | 293 return toElement(current); |
| 294 } else { | 294 } else { |
| 295 if (current->isElementNode() && isMatchingElement(static_cast<const
HTMLCollection*>(this), toElement(current))) | 295 if (current->isElementNode() && isMatchingElement(static_cast<const
HTMLCollection&>(*this), toElement(*current))) |
| 296 return toElement(current); | 296 return toElement(current); |
| 297 } | 297 } |
| 298 } | 298 } |
| 299 return 0; | 299 return 0; |
| 300 } | 300 } |
| 301 | 301 |
| 302 ALWAYS_INLINE Node* LiveNodeListBase::itemBefore(Node* previous) const | 302 ALWAYS_INLINE Node* LiveNodeListBase::itemBefore(const Node* previous) const |
| 303 { | 303 { |
| 304 Node* current; | 304 Node* current; |
| 305 if (LIKELY(!!previous)) // Without this LIKELY, length() and item() can be 1
0% slower. | 305 if (LIKELY(!!previous)) // Without this LIKELY, length() and item() can be 1
0% slower. |
| 306 current = previousNode(rootNode(), *previous, shouldOnlyIncludeDirectChi
ldren()); | 306 current = previousNode(rootNode(), *previous, shouldOnlyIncludeDirectChi
ldren()); |
| 307 else | 307 else |
| 308 current = lastNode(rootNode(), shouldOnlyIncludeDirectChildren()); | 308 current = lastNode(rootNode(), shouldOnlyIncludeDirectChildren()); |
| 309 | 309 |
| 310 if (type() == ChildNodeListType) | 310 if (type() == ChildNodeListType) |
| 311 return current; | 311 return current; |
| 312 return iterateForPreviousNode(current); | 312 return iterateForPreviousNode(current); |
| 313 } | 313 } |
| 314 | 314 |
| 315 template <class NodeListType> | 315 template <class NodeListType> |
| 316 inline Element* firstMatchingElement(const NodeListType* nodeList, ContainerNode
& root) | 316 inline Element* firstMatchingElement(const NodeListType& nodeList, const Contain
erNode& root) |
| 317 { | 317 { |
| 318 Element* element = ElementTraversal::firstWithin(root); | 318 Element* element = ElementTraversal::firstWithin(root); |
| 319 while (element && !isMatchingElement(nodeList, element)) | 319 while (element && !isMatchingElement(nodeList, *element)) |
| 320 element = ElementTraversal::next(*element, &root); | 320 element = ElementTraversal::next(*element, &root); |
| 321 return element; | 321 return element; |
| 322 } | 322 } |
| 323 | 323 |
| 324 template <class NodeListType> | 324 template <class NodeListType> |
| 325 inline Element* nextMatchingElement(const NodeListType* nodeList, Element& curre
nt, ContainerNode* root) | 325 inline Element* nextMatchingElement(const NodeListType& nodeList, Element& curre
nt, const ContainerNode& root) |
| 326 { | 326 { |
| 327 Element* next = ¤t; | 327 Element* next = ¤t; |
| 328 do { | 328 do { |
| 329 next = ElementTraversal::next(*next, root); | 329 next = ElementTraversal::next(*next, &root); |
| 330 } while (next && !isMatchingElement(nodeList, next)); | 330 } while (next && !isMatchingElement(nodeList, *next)); |
| 331 return next; | 331 return next; |
| 332 } | 332 } |
| 333 | 333 |
| 334 template <class NodeListType> | 334 template <class NodeListType> |
| 335 inline Element* traverseMatchingElementsForwardToOffset(const NodeListType* node
List, unsigned offset, Element& currentElement, unsigned& currentOffset, Contain
erNode* root) | 335 inline Element* traverseMatchingElementsForwardToOffset(const NodeListType& node
List, unsigned offset, Element& currentElement, unsigned& currentOffset, const C
ontainerNode& root) |
| 336 { | 336 { |
| 337 ASSERT(currentOffset < offset); | 337 ASSERT(currentOffset < offset); |
| 338 Element* next = ¤tElement; | 338 Element* next = ¤tElement; |
| 339 while ((next = nextMatchingElement(nodeList, *next, root))) { | 339 while ((next = nextMatchingElement(nodeList, *next, root))) { |
| 340 if (++currentOffset == offset) | 340 if (++currentOffset == offset) |
| 341 return next; | 341 return next; |
| 342 } | 342 } |
| 343 return 0; | 343 return 0; |
| 344 } | 344 } |
| 345 | 345 |
| 346 static inline Node* traverseSiblingsForwardToOffset(unsigned offset, Node& curre
ntNode, unsigned& currentOffset) | 346 static inline Node* traverseSiblingsForwardToOffset(unsigned offset, Node& curre
ntNode, unsigned& currentOffset) |
| 347 { | 347 { |
| 348 ASSERT(currentOffset < offset); | 348 ASSERT(currentOffset < offset); |
| 349 Node* next = ¤tNode; | 349 Node* next = ¤tNode; |
| 350 while ((next = next->nextSibling())) { | 350 while ((next = next->nextSibling())) { |
| 351 if (++currentOffset == offset) | 351 if (++currentOffset == offset) |
| 352 return next; | 352 return next; |
| 353 } | 353 } |
| 354 return 0; | 354 return 0; |
| 355 } | 355 } |
| 356 | 356 |
| 357 // FIXME: This should be in LiveNodeList.cpp but it needs to stay here until fir
stMatchingElement() | 357 // FIXME: This should be in LiveNodeList.cpp but it needs to stay here until fir
stMatchingElement() |
| 358 // and others are moved to a separate header. | 358 // and others are moved to a separate header. |
| 359 inline Node* LiveNodeList::traverseToFirstElement(ContainerNode& root) const | 359 inline Node* LiveNodeList::traverseToFirstElement(const ContainerNode& root) con
st |
| 360 { | 360 { |
| 361 ASSERT(isLiveNodeListType(type())); | 361 ASSERT(isLiveNodeListType(type())); |
| 362 switch (type()) { | 362 switch (type()) { |
| 363 case ChildNodeListType: | 363 case ChildNodeListType: |
| 364 return root.firstChild(); | 364 return root.firstChild(); |
| 365 case HTMLTagNodeListType: | 365 case HTMLTagNodeListType: |
| 366 return firstMatchingElement(static_cast<const HTMLTagNodeList*>(this), r
oot); | 366 return firstMatchingElement(static_cast<const HTMLTagNodeList&>(*this),
root); |
| 367 case ClassNodeListType: | 367 case ClassNodeListType: |
| 368 return firstMatchingElement(static_cast<const ClassNodeList*>(this), roo
t); | 368 return firstMatchingElement(static_cast<const ClassNodeList&>(*this), ro
ot); |
| 369 default: | 369 default: |
| 370 return firstMatchingElement(static_cast<const LiveNodeList*>(this), root
); | 370 return firstMatchingElement(static_cast<const LiveNodeList&>(*this), roo
t); |
| 371 } | 371 } |
| 372 } | 372 } |
| 373 | 373 |
| 374 // FIXME: This should be in LiveNodeList.cpp but it needs to stay here until tra
verseMatchingElementsForwardToOffset() | 374 // FIXME: This should be in LiveNodeList.cpp but it needs to stay here until tra
verseMatchingElementsForwardToOffset() |
| 375 // and others are moved to a separate header. | 375 // and others are moved to a separate header. |
| 376 inline Node* LiveNodeList::traverseForwardToOffset(unsigned offset, Node& curren
tNode, unsigned& currentOffset, ContainerNode* root) const | 376 inline Node* LiveNodeList::traverseForwardToOffset(unsigned offset, Node& curren
tNode, unsigned& currentOffset, const ContainerNode& root) const |
| 377 { | 377 { |
| 378 switch (type()) { | 378 switch (type()) { |
| 379 case ChildNodeListType: | 379 case ChildNodeListType: |
| 380 return traverseSiblingsForwardToOffset(offset, currentNode, currentOffse
t); | 380 return traverseSiblingsForwardToOffset(offset, currentNode, currentOffse
t); |
| 381 case HTMLTagNodeListType: | 381 case HTMLTagNodeListType: |
| 382 return traverseMatchingElementsForwardToOffset(static_cast<const HTMLTag
NodeList*>(this), offset, toElement(currentNode), currentOffset, root); | 382 return traverseMatchingElementsForwardToOffset(static_cast<const HTMLTag
NodeList&>(*this), offset, toElement(currentNode), currentOffset, root); |
| 383 case ClassNodeListType: | 383 case ClassNodeListType: |
| 384 return traverseMatchingElementsForwardToOffset(static_cast<const ClassNo
deList*>(this), offset, toElement(currentNode), currentOffset, root); | 384 return traverseMatchingElementsForwardToOffset(static_cast<const ClassNo
deList&>(*this), offset, toElement(currentNode), currentOffset, root); |
| 385 default: | 385 default: |
| 386 return traverseMatchingElementsForwardToOffset(this, offset, toElement(c
urrentNode), currentOffset, root); | 386 return traverseMatchingElementsForwardToOffset(*this, offset, toElement(
currentNode), currentOffset, root); |
| 387 } | 387 } |
| 388 } | 388 } |
| 389 | 389 |
| 390 bool ALWAYS_INLINE LiveNodeListBase::isLastItemCloserThanLastOrCachedItem(unsign
ed offset) const | 390 bool ALWAYS_INLINE LiveNodeListBase::isLastItemCloserThanLastOrCachedItem(unsign
ed offset) const |
| 391 { | 391 { |
| 392 ASSERT(isLengthCacheValid()); | 392 ASSERT(isLengthCacheValid()); |
| 393 unsigned distanceFromLastItem = cachedLength() - offset; | 393 unsigned distanceFromLastItem = cachedLength() - offset; |
| 394 if (!cachedItem()) | 394 if (!cachedItem()) |
| 395 return distanceFromLastItem < offset; | 395 return distanceFromLastItem < offset; |
| 396 | 396 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 448 setLengthCache(0); | 448 setLengthCache(0); |
| 449 return 0; | 449 return 0; |
| 450 } | 450 } |
| 451 setItemCache(firstItem, 0); | 451 setItemCache(firstItem, 0); |
| 452 ASSERT(!cachedItemOffset()); | 452 ASSERT(!cachedItemOffset()); |
| 453 } | 453 } |
| 454 | 454 |
| 455 if (cachedItemOffset() == offset) | 455 if (cachedItemOffset() == offset) |
| 456 return cachedItem(); | 456 return cachedItem(); |
| 457 | 457 |
| 458 return itemBeforeOrAfterCachedItem(offset, root); | 458 return itemBeforeOrAfterCachedItem(offset, *root); |
| 459 } | 459 } |
| 460 | 460 |
| 461 inline Node* LiveNodeListBase::itemBeforeOrAfterCachedItem(unsigned offset, Cont
ainerNode* root) const | 461 inline Node* LiveNodeListBase::itemBeforeOrAfterCachedItem(unsigned offset, cons
t ContainerNode& root) const |
| 462 { | 462 { |
| 463 unsigned currentOffset = cachedItemOffset(); | 463 unsigned currentOffset = cachedItemOffset(); |
| 464 Node* currentItem = cachedItem(); | 464 Node* currentItem = cachedItem(); |
| 465 ASSERT(currentItem); | 465 ASSERT(currentItem); |
| 466 ASSERT(currentOffset != offset); | 466 ASSERT(currentOffset != offset); |
| 467 | 467 |
| 468 if (offset < cachedItemOffset()) { | 468 if (offset < cachedItemOffset()) { |
| 469 ASSERT(!overridesItemAfter()); | 469 ASSERT(!overridesItemAfter()); |
| 470 while ((currentItem = itemBefore(currentItem))) { | 470 while ((currentItem = itemBefore(currentItem))) { |
| 471 ASSERT(currentOffset); | 471 ASSERT(currentOffset); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 492 setItemCache(currentItem, currentOffset); | 492 setItemCache(currentItem, currentOffset); |
| 493 return currentItem; | 493 return currentItem; |
| 494 } | 494 } |
| 495 | 495 |
| 496 Element* HTMLCollection::virtualItemAfter(Element*) const | 496 Element* HTMLCollection::virtualItemAfter(Element*) const |
| 497 { | 497 { |
| 498 ASSERT_NOT_REACHED(); | 498 ASSERT_NOT_REACHED(); |
| 499 return 0; | 499 return 0; |
| 500 } | 500 } |
| 501 | 501 |
| 502 static inline bool nameShouldBeVisibleInDocumentAll(HTMLElement* element) | 502 static inline bool nameShouldBeVisibleInDocumentAll(const HTMLElement& element) |
| 503 { | 503 { |
| 504 // The document.all collection returns only certain types of elements by nam
e, | 504 // The document.all collection returns only certain types of elements by nam
e, |
| 505 // although it returns any type of element by id. | 505 // although it returns any type of element by id. |
| 506 return element->hasLocalName(appletTag) | 506 return element.hasLocalName(appletTag) |
| 507 || element->hasLocalName(embedTag) | 507 || element.hasLocalName(embedTag) |
| 508 || element->hasLocalName(formTag) | 508 || element.hasLocalName(formTag) |
| 509 || element->hasLocalName(imgTag) | 509 || element.hasLocalName(imgTag) |
| 510 || element->hasLocalName(inputTag) | 510 || element.hasLocalName(inputTag) |
| 511 || element->hasLocalName(objectTag) | 511 || element.hasLocalName(objectTag) |
| 512 || element->hasLocalName(selectTag); | 512 || element.hasLocalName(selectTag); |
| 513 } | 513 } |
| 514 | 514 |
| 515 bool HTMLCollection::checkForNameMatch(Element* element, bool checkName, const A
tomicString& name) const | 515 bool HTMLCollection::checkForNameMatch(const Element& element, bool checkName, c
onst AtomicString& name) const |
| 516 { | 516 { |
| 517 if (!element->isHTMLElement()) | 517 if (!element.isHTMLElement()) |
| 518 return false; | 518 return false; |
| 519 | 519 |
| 520 HTMLElement* e = toHTMLElement(element); | 520 const HTMLElement& e = toHTMLElement(element); |
| 521 if (!checkName) | 521 if (!checkName) |
| 522 return e->getIdAttribute() == name; | 522 return e.getIdAttribute() == name; |
| 523 | 523 |
| 524 if (type() == DocAll && !nameShouldBeVisibleInDocumentAll(e)) | 524 if (type() == DocAll && !nameShouldBeVisibleInDocumentAll(e)) |
| 525 return false; | 525 return false; |
| 526 | 526 |
| 527 return e->getNameAttribute() == name && e->getIdAttribute() != name; | 527 return e.getNameAttribute() == name && e.getIdAttribute() != name; |
| 528 } | 528 } |
| 529 | 529 |
| 530 inline Element* firstMatchingChildElement(const HTMLCollection* nodeList, Contai
nerNode& root) | 530 inline Element* firstMatchingChildElement(const HTMLCollection& nodeList, const
ContainerNode& root) |
| 531 { | 531 { |
| 532 Element* element = ElementTraversal::firstWithin(root); | 532 Element* element = ElementTraversal::firstWithin(root); |
| 533 while (element && !isMatchingElement(nodeList, element)) | 533 while (element && !isMatchingElement(nodeList, *element)) |
| 534 element = ElementTraversal::nextSkippingChildren(*element, &root); | 534 element = ElementTraversal::nextSkippingChildren(*element, &root); |
| 535 return element; | 535 return element; |
| 536 } | 536 } |
| 537 | 537 |
| 538 inline Element* nextMatchingChildElement(const HTMLCollection* nodeList, Element
& current, ContainerNode* root) | 538 inline Element* nextMatchingChildElement(const HTMLCollection& nodeList, Element
& current, const ContainerNode& root) |
| 539 { | 539 { |
| 540 Element* next = ¤t; | 540 Element* next = ¤t; |
| 541 do { | 541 do { |
| 542 next = ElementTraversal::nextSkippingChildren(*next, root); | 542 next = ElementTraversal::nextSkippingChildren(*next, &root); |
| 543 } while (next && !isMatchingElement(nodeList, next)); | 543 } while (next && !isMatchingElement(nodeList, *next)); |
| 544 return next; | 544 return next; |
| 545 } | 545 } |
| 546 | 546 |
| 547 inline Element* HTMLCollection::traverseToFirstElement(ContainerNode& root) cons
t | 547 inline Element* HTMLCollection::traverseToFirstElement(const ContainerNode& root
) const |
| 548 { | 548 { |
| 549 if (overridesItemAfter()) | 549 if (overridesItemAfter()) |
| 550 return virtualItemAfter(0); | 550 return virtualItemAfter(0); |
| 551 if (shouldOnlyIncludeDirectChildren()) | 551 if (shouldOnlyIncludeDirectChildren()) |
| 552 return firstMatchingChildElement(static_cast<const HTMLCollection*>(this
), root); | 552 return firstMatchingChildElement(*this, root); |
| 553 return firstMatchingElement(static_cast<const HTMLCollection*>(this), root); | 553 return firstMatchingElement(*this, root); |
| 554 } | 554 } |
| 555 | 555 |
| 556 inline Element* HTMLCollection::traverseNextElement(Element& previous, Container
Node* root) const | 556 inline Element* HTMLCollection::traverseNextElement(Element& previous, const Con
tainerNode& root) const |
| 557 { | 557 { |
| 558 if (overridesItemAfter()) | 558 if (overridesItemAfter()) |
| 559 return virtualItemAfter(&previous); | 559 return virtualItemAfter(&previous); |
| 560 if (shouldOnlyIncludeDirectChildren()) | 560 if (shouldOnlyIncludeDirectChildren()) |
| 561 return nextMatchingChildElement(this, previous, root); | 561 return nextMatchingChildElement(*this, previous, root); |
| 562 return nextMatchingElement(this, previous, root); | 562 return nextMatchingElement(*this, previous, root); |
| 563 } | 563 } |
| 564 | 564 |
| 565 inline Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element
& currentElement, unsigned& currentOffset, ContainerNode* root) const | 565 inline Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element
& currentElement, unsigned& currentOffset, const ContainerNode& root) const |
| 566 { | 566 { |
| 567 ASSERT(currentOffset < offset); | 567 ASSERT(currentOffset < offset); |
| 568 if (overridesItemAfter()) { | 568 if (overridesItemAfter()) { |
| 569 Element* next = ¤tElement; | 569 Element* next = ¤tElement; |
| 570 while ((next = virtualItemAfter(next))) { | 570 while ((next = virtualItemAfter(next))) { |
| 571 if (++currentOffset == offset) | 571 if (++currentOffset == offset) |
| 572 return next; | 572 return next; |
| 573 } | 573 } |
| 574 return 0; | 574 return 0; |
| 575 } | 575 } |
| 576 if (shouldOnlyIncludeDirectChildren()) { | 576 if (shouldOnlyIncludeDirectChildren()) { |
| 577 Element* next = ¤tElement; | 577 Element* next = ¤tElement; |
| 578 while ((next = nextMatchingChildElement(this, *next, root))) { | 578 while ((next = nextMatchingChildElement(*this, *next, root))) { |
| 579 if (++currentOffset == offset) | 579 if (++currentOffset == offset) |
| 580 return next; | 580 return next; |
| 581 } | 581 } |
| 582 return 0; | 582 return 0; |
| 583 } | 583 } |
| 584 return traverseMatchingElementsForwardToOffset(this, offset, currentElement,
currentOffset, root); | 584 return traverseMatchingElementsForwardToOffset(*this, offset, currentElement
, currentOffset, root); |
| 585 } | 585 } |
| 586 | 586 |
| 587 Node* HTMLCollection::namedItem(const AtomicString& name) const | 587 Node* HTMLCollection::namedItem(const AtomicString& name) const |
| 588 { | 588 { |
| 589 // http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/namedit
em.asp | 589 // http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/namedit
em.asp |
| 590 // This method first searches for an object with a matching id | 590 // This method first searches for an object with a matching id |
| 591 // attribute. If a match is not found, the method then searches for an | 591 // attribute. If a match is not found, the method then searches for an |
| 592 // object with a matching name attribute, but only on those elements | 592 // object with a matching name attribute, but only on those elements |
| 593 // that are allowed a name attribute. | 593 // that are allowed a name attribute. |
| 594 | 594 |
| 595 ContainerNode* root = rootContainerNode(); | 595 ContainerNode* root = rootContainerNode(); |
| 596 if (!root) | 596 if (!root) |
| 597 return 0; | 597 return 0; |
| 598 | 598 |
| 599 unsigned i = 0; | 599 unsigned i = 0; |
| 600 for (Element* element = traverseToFirstElement(*root); element; element = tr
averseNextElement(*element, root)) { | 600 for (Element* element = traverseToFirstElement(*root); element; element = tr
averseNextElement(*element, *root)) { |
| 601 if (checkForNameMatch(element, /* checkName */ false, name)) { | 601 if (checkForNameMatch(*element, /* checkName */ false, name)) { |
| 602 setItemCache(element, i); | 602 setItemCache(element, i); |
| 603 return element; | 603 return element; |
| 604 } | 604 } |
| 605 i++; | 605 i++; |
| 606 } | 606 } |
| 607 | 607 |
| 608 i = 0; | 608 i = 0; |
| 609 for (Element* element = traverseToFirstElement(*root); element; element = tr
averseNextElement(*element, root)) { | 609 for (Element* element = traverseToFirstElement(*root); element; element = tr
averseNextElement(*element, *root)) { |
| 610 if (checkForNameMatch(element, /* checkName */ true, name)) { | 610 if (checkForNameMatch(*element, /* checkName */ true, name)) { |
| 611 setItemCache(element, i); | 611 setItemCache(element, i); |
| 612 return element; | 612 return element; |
| 613 } | 613 } |
| 614 i++; | 614 i++; |
| 615 } | 615 } |
| 616 | 616 |
| 617 return 0; | 617 return 0; |
| 618 } | 618 } |
| 619 | 619 |
| 620 void HTMLCollection::updateNameCache() const | 620 void HTMLCollection::updateNameCache() const |
| 621 { | 621 { |
| 622 if (hasNameCache()) | 622 if (hasNameCache()) |
| 623 return; | 623 return; |
| 624 | 624 |
| 625 ContainerNode* root = rootContainerNode(); | 625 ContainerNode* root = rootContainerNode(); |
| 626 if (!root) | 626 if (!root) |
| 627 return; | 627 return; |
| 628 | 628 |
| 629 for (Element* element = traverseToFirstElement(*root); element; element = tr
averseNextElement(*element, root)) { | 629 for (Element* element = traverseToFirstElement(*root); element; element = tr
averseNextElement(*element, *root)) { |
| 630 const AtomicString& idAttrVal = element->getIdAttribute(); | 630 const AtomicString& idAttrVal = element->getIdAttribute(); |
| 631 if (!idAttrVal.isEmpty()) | 631 if (!idAttrVal.isEmpty()) |
| 632 appendIdCache(idAttrVal, element); | 632 appendIdCache(idAttrVal, element); |
| 633 if (!element->isHTMLElement()) | 633 if (!element->isHTMLElement()) |
| 634 continue; | 634 continue; |
| 635 const AtomicString& nameAttrVal = element->getNameAttribute(); | 635 const AtomicString& nameAttrVal = element->getNameAttribute(); |
| 636 if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && (type() != Doc
All || nameShouldBeVisibleInDocumentAll(toHTMLElement(element)))) | 636 if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && (type() != Doc
All || nameShouldBeVisibleInDocumentAll(toHTMLElement(*element)))) |
| 637 appendNameCache(nameAttrVal, element); | 637 appendNameCache(nameAttrVal, element); |
| 638 } | 638 } |
| 639 | 639 |
| 640 setHasNameCache(); | 640 setHasNameCache(); |
| 641 } | 641 } |
| 642 | 642 |
| 643 void HTMLCollection::namedItems(const AtomicString& name, Vector<RefPtr<Node> >&
result) const | 643 void HTMLCollection::namedItems(const AtomicString& name, Vector<RefPtr<Node> >&
result) const |
| 644 { | 644 { |
| 645 ASSERT(result.isEmpty()); | 645 ASSERT(result.isEmpty()); |
| 646 if (name.isEmpty()) | 646 if (name.isEmpty()) |
| (...skipping 13 matching lines...) Expand all Loading... |
| 660 | 660 |
| 661 void HTMLCollection::append(NodeCacheMap& map, const AtomicString& key, Element*
element) | 661 void HTMLCollection::append(NodeCacheMap& map, const AtomicString& key, Element*
element) |
| 662 { | 662 { |
| 663 OwnPtr<Vector<Element*> >& vector = map.add(key.impl(), nullptr).iterator->v
alue; | 663 OwnPtr<Vector<Element*> >& vector = map.add(key.impl(), nullptr).iterator->v
alue; |
| 664 if (!vector) | 664 if (!vector) |
| 665 vector = adoptPtr(new Vector<Element*>); | 665 vector = adoptPtr(new Vector<Element*>); |
| 666 vector->append(element); | 666 vector->append(element); |
| 667 } | 667 } |
| 668 | 668 |
| 669 } // namespace WebCore | 669 } // namespace WebCore |
| OLD | NEW |