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 |