Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: Source/core/html/HTMLFormElement.cpp

Issue 145353004: Build HTMLFormElement::m_associatedElements lazily (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Fix crash Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/html/HTMLFormElement.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 * (C) 2001 Dirk Mueller (mueller@kde.org) 4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv ed. 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv ed.
6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) 6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com)
7 * 7 *
8 * This library is free software; you can redistribute it and/or 8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public 9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either 10 * License as published by the Free Software Foundation; either
(...skipping 14 matching lines...) Expand all
25 #include "config.h" 25 #include "config.h"
26 #include "core/html/HTMLFormElement.h" 26 #include "core/html/HTMLFormElement.h"
27 27
28 #include <limits> 28 #include <limits>
29 #include "HTMLNames.h" 29 #include "HTMLNames.h"
30 #include "bindings/v8/ScriptController.h" 30 #include "bindings/v8/ScriptController.h"
31 #include "bindings/v8/ScriptEventListener.h" 31 #include "bindings/v8/ScriptEventListener.h"
32 #include "core/dom/Attribute.h" 32 #include "core/dom/Attribute.h"
33 #include "core/dom/Document.h" 33 #include "core/dom/Document.h"
34 #include "core/dom/ElementTraversal.h" 34 #include "core/dom/ElementTraversal.h"
35 #include "core/dom/IdTargetObserverRegistry.h"
35 #include "core/events/AutocompleteErrorEvent.h" 36 #include "core/events/AutocompleteErrorEvent.h"
36 #include "core/events/Event.h" 37 #include "core/events/Event.h"
37 #include "core/events/ScopedEventQueue.h" 38 #include "core/events/ScopedEventQueue.h"
38 #include "core/events/ThreadLocalEventNames.h" 39 #include "core/events/ThreadLocalEventNames.h"
39 #include "core/html/HTMLCollection.h" 40 #include "core/html/HTMLCollection.h"
40 #include "core/html/HTMLDialogElement.h" 41 #include "core/html/HTMLDialogElement.h"
41 #include "core/html/HTMLImageElement.h" 42 #include "core/html/HTMLImageElement.h"
42 #include "core/html/HTMLInputElement.h" 43 #include "core/html/HTMLInputElement.h"
43 #include "core/html/HTMLObjectElement.h" 44 #include "core/html/HTMLObjectElement.h"
44 #include "core/html/RadioNodeList.h" 45 #include "core/html/RadioNodeList.h"
45 #include "core/html/forms/FormController.h" 46 #include "core/html/forms/FormController.h"
46 #include "core/loader/FrameLoader.h" 47 #include "core/loader/FrameLoader.h"
47 #include "core/loader/FrameLoaderClient.h" 48 #include "core/loader/FrameLoaderClient.h"
48 #include "core/frame/ContentSecurityPolicy.h" 49 #include "core/frame/ContentSecurityPolicy.h"
49 #include "core/frame/DOMWindow.h" 50 #include "core/frame/DOMWindow.h"
50 #include "core/frame/Frame.h" 51 #include "core/frame/Frame.h"
51 #include "core/frame/UseCounter.h" 52 #include "core/frame/UseCounter.h"
52 #include "core/rendering/RenderTextControl.h" 53 #include "core/rendering/RenderTextControl.h"
53 #include "platform/UserGestureIndicator.h" 54 #include "platform/UserGestureIndicator.h"
54 55
55 using namespace std; 56 using namespace std;
56 57
57 namespace WebCore { 58 namespace WebCore {
58 59
59 using namespace HTMLNames; 60 using namespace HTMLNames;
60 61
61 HTMLFormElement::HTMLFormElement(Document& document) 62 HTMLFormElement::HTMLFormElement(Document& document)
62 : HTMLElement(formTag, document) 63 : HTMLElement(formTag, document)
63 , m_associatedElementsBeforeIndex(0)
64 , m_associatedElementsAfterIndex(0)
65 , m_weakPtrFactory(this) 64 , m_weakPtrFactory(this)
65 , m_associatedElementsAreDirty(false)
66 , m_imageElementsAreDirty(false) 66 , m_imageElementsAreDirty(false)
67 , m_hasElementsAssociatedByParser(false) 67 , m_hasElementsAssociatedByParser(false)
68 , m_didFinishParsingChildren(false) 68 , m_didFinishParsingChildren(false)
69 , m_wasUserSubmitted(false) 69 , m_wasUserSubmitted(false)
70 , m_isSubmittingOrPreparingForSubmission(false) 70 , m_isSubmittingOrPreparingForSubmission(false)
71 , m_shouldSubmit(false) 71 , m_shouldSubmit(false)
72 , m_isInResetFunction(false) 72 , m_isInResetFunction(false)
73 , m_wasDemoted(false) 73 , m_wasDemoted(false)
74 , m_requestAutocompleteTimer(this, &HTMLFormElement::requestAutocompleteTime rFired) 74 , m_requestAutocompleteTimer(this, &HTMLFormElement::requestAutocompleteTime rFired)
75 { 75 {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 this->document().didAssociateFormControl(this); 121 this->document().didAssociateFormControl(this);
122 return InsertionDone; 122 return InsertionDone;
123 } 123 }
124 124
125 template<class T> 125 template<class T>
126 void notifyFormRemovedFromTree(const Vector<T*>& elements, Node* root) 126 void notifyFormRemovedFromTree(const Vector<T*>& elements, Node* root)
127 { 127 {
128 size_t size = elements.size(); 128 size_t size = elements.size();
129 for (size_t i = 0; i < size; ++i) 129 for (size_t i = 0; i < size; ++i)
130 elements[i]->formRemovedFromTree(root); 130 elements[i]->formRemovedFromTree(root);
131 ASSERT(elements.size() == size);
131 } 132 }
132 133
133 void HTMLFormElement::removedFrom(ContainerNode* insertionPoint) 134 void HTMLFormElement::removedFrom(ContainerNode* insertionPoint)
134 { 135 {
135 // FIXME: We don't need to notify formRemovedFromTree to associated elements 136 // We don't need to take care of form association by 'form' content
136 // which are descendants of this form. We can skip this process if we know 137 // attribute becuse IdTargetObserver handles it.
137 // that this form doesn't have elements associated by parser or associated 138 if (m_hasElementsAssociatedByParser) {
138 // with 'form' content attribute. 139 Node* root = highestAncestor();
139 Node* root = highestAncestor(); 140 if (!m_associatedElementsAreDirty) {
140 Vector<FormAssociatedElement*> elements(associatedElements()); 141 Vector<FormAssociatedElement*> elements(associatedElements());
141 notifyFormRemovedFromTree(elements, root); 142 notifyFormRemovedFromTree(elements, root);
143 } else {
144 Vector<FormAssociatedElement*> elements;
145 collectAssociatedElements(insertionPoint->highestAncestor(), element s);
146 notifyFormRemovedFromTree(elements, root);
147 collectAssociatedElements(root, elements);
148 notifyFormRemovedFromTree(elements, root);
149 }
142 150
143 if (m_hasElementsAssociatedByParser) {
144 if (!m_imageElementsAreDirty) { 151 if (!m_imageElementsAreDirty) {
145 Vector<HTMLImageElement*> images(imageElements()); 152 Vector<HTMLImageElement*> images(imageElements());
146 notifyFormRemovedFromTree(images, root); 153 notifyFormRemovedFromTree(images, root);
147 } else { 154 } else {
148 Vector<HTMLImageElement*> images; 155 Vector<HTMLImageElement*> images;
149 collectImageElements(insertionPoint->highestAncestor(), images); 156 collectImageElements(insertionPoint->highestAncestor(), images);
150 notifyFormRemovedFromTree(images, root); 157 notifyFormRemovedFromTree(images, root);
151 collectImageElements(root, images); 158 collectImageElements(root, images);
152 notifyFormRemovedFromTree(images, root); 159 notifyFormRemovedFromTree(images, root);
153 } 160 }
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after
513 else if (name == accept_charsetAttr) 520 else if (name == accept_charsetAttr)
514 m_attributes.setAcceptCharset(value); 521 m_attributes.setAcceptCharset(value);
515 else if (name == onautocompleteAttr) 522 else if (name == onautocompleteAttr)
516 setAttributeEventListener(EventTypeNames::autocomplete, createAttributeE ventListener(this, name, value)); 523 setAttributeEventListener(EventTypeNames::autocomplete, createAttributeE ventListener(this, name, value));
517 else if (name == onautocompleteerrorAttr) 524 else if (name == onautocompleteerrorAttr)
518 setAttributeEventListener(EventTypeNames::autocompleteerror, createAttri buteEventListener(this, name, value)); 525 setAttributeEventListener(EventTypeNames::autocompleteerror, createAttri buteEventListener(this, name, value));
519 else 526 else
520 HTMLElement::parseAttribute(name, value); 527 HTMLElement::parseAttribute(name, value);
521 } 528 }
522 529
523 template<class T, size_t n> static void removeFromVector(Vector<T*, n> & vec, T* item)
524 {
525 size_t size = vec.size();
526 for (size_t i = 0; i != size; ++i)
527 if (vec[i] == item) {
528 vec.remove(i);
529 break;
530 }
531 }
532
533 unsigned HTMLFormElement::formElementIndexWithFormAttribute(Element* element, un signed rangeStart, unsigned rangeEnd)
534 {
535 if (m_associatedElements.isEmpty())
536 return 0;
537
538 ASSERT(rangeStart <= rangeEnd);
539
540 if (rangeStart == rangeEnd)
541 return rangeStart;
542
543 unsigned left = rangeStart;
544 unsigned right = rangeEnd - 1;
545 unsigned short position;
546
547 // Does binary search on m_associatedElements in order to find the index
548 // to be inserted.
549 while (left != right) {
550 unsigned middle = left + ((right - left) / 2);
551 ASSERT(middle < m_associatedElementsBeforeIndex || middle >= m_associate dElementsAfterIndex);
552 position = element->compareDocumentPosition(toHTMLElement(m_associatedEl ements[middle]));
553 if (position & DOCUMENT_POSITION_FOLLOWING)
554 right = middle;
555 else
556 left = middle + 1;
557 }
558
559 ASSERT(left < m_associatedElementsBeforeIndex || left >= m_associatedElement sAfterIndex);
560 position = element->compareDocumentPosition(toHTMLElement(m_associatedElemen ts[left]));
561 if (position & DOCUMENT_POSITION_FOLLOWING)
562 return left;
563 return left + 1;
564 }
565
566 unsigned HTMLFormElement::formElementIndex(FormAssociatedElement& associatedElem ent)
567 {
568 HTMLElement& associatedHTMLElement = toHTMLElement(associatedElement);
569 // Treats separately the case where this element has the form attribute
570 // for performance consideration.
571 if (associatedHTMLElement.fastHasAttribute(formAttr)) {
572 unsigned short position = compareDocumentPosition(&associatedHTMLElement );
573 if (position & DOCUMENT_POSITION_PRECEDING) {
574 ++m_associatedElementsBeforeIndex;
575 ++m_associatedElementsAfterIndex;
576 return HTMLFormElement::formElementIndexWithFormAttribute(&associate dHTMLElement, 0, m_associatedElementsBeforeIndex - 1);
577 }
578 if (position & DOCUMENT_POSITION_FOLLOWING && !(position & DOCUMENT_POSI TION_CONTAINED_BY))
579 return HTMLFormElement::formElementIndexWithFormAttribute(&associate dHTMLElement, m_associatedElementsAfterIndex, m_associatedElements.size());
580 }
581
582 // Check for the special case where this element is the very last thing in
583 // the form's tree of children; we don't want to walk the entire tree in tha t
584 // common case that occurs during parsing; instead we'll just return a value
585 // that says "add this form element to the end of the array".
586 if (ElementTraversal::next(associatedHTMLElement, this)) {
587 unsigned i = m_associatedElementsBeforeIndex;
588 for (Element* element = this; element; element = ElementTraversal::next( *element, this)) {
589 if (element == associatedHTMLElement) {
590 ++m_associatedElementsAfterIndex;
591 return i;
592 }
593 if (!element->isFormControlElement() && !element->hasTagName(objectT ag))
594 continue;
595 if (!element->isHTMLElement() || toHTMLElement(element)->formOwner() != this)
596 continue;
597 ++i;
598 }
599 }
600 return m_associatedElementsAfterIndex++;
601 }
602
603 void HTMLFormElement::associate(FormAssociatedElement& e) 530 void HTMLFormElement::associate(FormAssociatedElement& e)
604 { 531 {
605 m_associatedElements.insert(formElementIndex(e), &e); 532 m_associatedElementsAreDirty = true;
533 m_associatedElements.clear();
606 } 534 }
607 535
608 void HTMLFormElement::disassociate(FormAssociatedElement& e) 536 void HTMLFormElement::disassociate(FormAssociatedElement& e)
609 { 537 {
610 unsigned index; 538 m_associatedElementsAreDirty = true;
611 for (index = 0; index < m_associatedElements.size(); ++index) { 539 m_associatedElements.clear();
612 if (m_associatedElements[index] == &e)
613 break;
614 }
615 ASSERT_WITH_SECURITY_IMPLICATION(index < m_associatedElements.size());
616 if (index < m_associatedElementsBeforeIndex)
617 --m_associatedElementsBeforeIndex;
618 if (index < m_associatedElementsAfterIndex)
619 --m_associatedElementsAfterIndex;
620 removeFromPastNamesMap(toHTMLElement(e)); 540 removeFromPastNamesMap(toHTMLElement(e));
621 removeFromVector(m_associatedElements, &e);
622 } 541 }
623 542
624 bool HTMLFormElement::isURLAttribute(const Attribute& attribute) const 543 bool HTMLFormElement::isURLAttribute(const Attribute& attribute) const
625 { 544 {
626 return attribute.name() == actionAttr || HTMLElement::isURLAttribute(attribu te); 545 return attribute.name() == actionAttr || HTMLElement::isURLAttribute(attribu te);
627 } 546 }
628 547
629 void HTMLFormElement::associate(HTMLImageElement& e) 548 void HTMLFormElement::associate(HTMLImageElement& e)
630 { 549 {
631 m_imageElementsAreDirty = true; 550 m_imageElementsAreDirty = true;
(...skipping 18 matching lines...) Expand all
650 return; 569 return;
651 m_hasElementsAssociatedByParser = true; 570 m_hasElementsAssociatedByParser = true;
652 UseCounter::count(document(), UseCounter::FormAssociationByParser); 571 UseCounter::count(document(), UseCounter::FormAssociationByParser);
653 } 572 }
654 573
655 PassRefPtr<HTMLCollection> HTMLFormElement::elements() 574 PassRefPtr<HTMLCollection> HTMLFormElement::elements()
656 { 575 {
657 return ensureCachedHTMLCollection(FormControls); 576 return ensureCachedHTMLCollection(FormControls);
658 } 577 }
659 578
579 void HTMLFormElement::collectAssociatedElements(Node* root, Vector<FormAssociate dElement*>& elements) const
580 {
581 elements.clear();
582 for (Node* node = root; node; node = NodeTraversal::next(*node)) {
583 if (!node->isHTMLElement())
584 continue;
585 FormAssociatedElement* element = 0;
586 if (toElement(node)->isFormControlElement())
587 element = toHTMLFormControlElement(node);
588 else if (node->hasTagName(objectTag))
589 element = toHTMLObjectElement(node);
590 else
591 continue;
592 if (element->form()== this)
593 elements.append(element);
594 }
595 }
596
597 // This function should be const conceptually. However we update some fields
598 // because of lazy evaluation.
599 const Vector<FormAssociatedElement*>& HTMLFormElement::associatedElements() cons t
600 {
601 if (!m_associatedElementsAreDirty)
602 return m_associatedElements;
603 HTMLFormElement* mutableThis = const_cast<HTMLFormElement*>(this);
604 Node* scope = mutableThis;
605 if (m_hasElementsAssociatedByParser)
606 scope = highestAncestor();
607 if (inDocument() && treeScope().idTargetObserverRegistry().hasObservers(fast GetAttribute(idAttr)))
608 scope = &treeScope().rootNode();
609 collectAssociatedElements(scope, mutableThis->m_associatedElements);
610 mutableThis->m_associatedElementsAreDirty = false;
611 return m_associatedElements;
612 }
613
660 void HTMLFormElement::collectImageElements(Node* root, Vector<HTMLImageElement*> & elements) 614 void HTMLFormElement::collectImageElements(Node* root, Vector<HTMLImageElement*> & elements)
661 { 615 {
662 elements.clear(); 616 elements.clear();
663 for (Node* node = root; node; node = NodeTraversal::next(*node)) { 617 for (Node* node = root; node; node = NodeTraversal::next(*node)) {
664 if (node->isHTMLElement() && node->hasTagName(imgTag) && toHTMLElement(n ode)->formOwner() == this) 618 if (node->isHTMLElement() && node->hasTagName(imgTag) && toHTMLElement(n ode)->formOwner() == this)
665 elements.append(toHTMLImageElement(node)); 619 elements.append(toHTMLImageElement(node));
666 } 620 }
667 } 621 }
668 622
669 const Vector<HTMLImageElement*>& HTMLFormElement::imageElements() 623 const Vector<HTMLImageElement*>& HTMLFormElement::imageElements()
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
863 } 817 }
864 818
865 void HTMLFormElement::setDemoted(bool demoted) 819 void HTMLFormElement::setDemoted(bool demoted)
866 { 820 {
867 if (demoted) 821 if (demoted)
868 UseCounter::count(document(), UseCounter::DemotedFormElement); 822 UseCounter::count(document(), UseCounter::DemotedFormElement);
869 m_wasDemoted = demoted; 823 m_wasDemoted = demoted;
870 } 824 }
871 825
872 } // namespace 826 } // namespace
OLDNEW
« no previous file with comments | « Source/core/html/HTMLFormElement.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698