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

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: Created 6 years, 11 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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 } 131 }
132 132
133 void HTMLFormElement::removedFrom(ContainerNode* insertionPoint) 133 void HTMLFormElement::removedFrom(ContainerNode* insertionPoint)
134 { 134 {
135 // FIXME: We don't need to notify formRemovedFromTree to associated elements 135 // 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 136 // attribute becuse IdTargetObserver handles it.
137 // that this form doesn't have elements associated by parser or associated 137 if (m_hasElementsAssociatedByParser) {
138 // with 'form' content attribute. 138 Node* root = highestAncestor();
139 Node* root = highestAncestor(); 139 if (!m_associatedElementsAreDirty) {
140 Vector<FormAssociatedElement*> elements(associatedElements()); 140 notifyFormRemovedFromTree(associatedElements(), root);
tkent 2014/01/29 01:02:16 We need to pass a copy of associatedElement(). Unl
141 notifyFormRemovedFromTree(elements, root); 141 } else {
142 Vector<FormAssociatedElement*> elements;
143 collectAssociatedElements(insertionPoint->highestAncestor(), element s);
144 notifyFormRemovedFromTree(elements, root);
145 collectAssociatedElements(root, elements);
146 notifyFormRemovedFromTree(elements, root);
147 }
142 148
143 if (m_hasElementsAssociatedByParser) {
144 if (!m_imageElementsAreDirty) { 149 if (!m_imageElementsAreDirty) {
145 Vector<HTMLImageElement*> images(imageElements()); 150 Vector<HTMLImageElement*> images(imageElements());
146 notifyFormRemovedFromTree(images, root); 151 notifyFormRemovedFromTree(images, root);
147 } else { 152 } else {
148 Vector<HTMLImageElement*> images; 153 Vector<HTMLImageElement*> images;
149 collectImageElements(insertionPoint->highestAncestor(), images); 154 collectImageElements(insertionPoint->highestAncestor(), images);
150 notifyFormRemovedFromTree(images, root); 155 notifyFormRemovedFromTree(images, root);
151 collectImageElements(root, images); 156 collectImageElements(root, images);
152 notifyFormRemovedFromTree(images, root); 157 notifyFormRemovedFromTree(images, root);
153 } 158 }
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after
513 else if (name == accept_charsetAttr) 518 else if (name == accept_charsetAttr)
514 m_attributes.setAcceptCharset(value); 519 m_attributes.setAcceptCharset(value);
515 else if (name == onautocompleteAttr) 520 else if (name == onautocompleteAttr)
516 setAttributeEventListener(EventTypeNames::autocomplete, createAttributeE ventListener(this, name, value)); 521 setAttributeEventListener(EventTypeNames::autocomplete, createAttributeE ventListener(this, name, value));
517 else if (name == onautocompleteerrorAttr) 522 else if (name == onautocompleteerrorAttr)
518 setAttributeEventListener(EventTypeNames::autocompleteerror, createAttri buteEventListener(this, name, value)); 523 setAttributeEventListener(EventTypeNames::autocompleteerror, createAttri buteEventListener(this, name, value));
519 else 524 else
520 HTMLElement::parseAttribute(name, value); 525 HTMLElement::parseAttribute(name, value);
521 } 526 }
522 527
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) 528 void HTMLFormElement::associate(FormAssociatedElement& e)
604 { 529 {
605 m_associatedElements.insert(formElementIndex(e), &e); 530 m_associatedElementsAreDirty = true;
531 m_associatedElements.clear();
606 } 532 }
607 533
608 void HTMLFormElement::disassociate(FormAssociatedElement& e) 534 void HTMLFormElement::disassociate(FormAssociatedElement& e)
609 { 535 {
610 unsigned index; 536 m_associatedElementsAreDirty = true;
611 for (index = 0; index < m_associatedElements.size(); ++index) { 537 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)); 538 removeFromPastNamesMap(toHTMLElement(e));
621 removeFromVector(m_associatedElements, &e);
622 } 539 }
623 540
624 bool HTMLFormElement::isURLAttribute(const Attribute& attribute) const 541 bool HTMLFormElement::isURLAttribute(const Attribute& attribute) const
625 { 542 {
626 return attribute.name() == actionAttr || HTMLElement::isURLAttribute(attribu te); 543 return attribute.name() == actionAttr || HTMLElement::isURLAttribute(attribu te);
627 } 544 }
628 545
629 void HTMLFormElement::associate(HTMLImageElement& e) 546 void HTMLFormElement::associate(HTMLImageElement& e)
630 { 547 {
631 m_imageElementsAreDirty = true; 548 m_imageElementsAreDirty = true;
(...skipping 16 matching lines...) Expand all
648 { 565 {
649 if (m_didFinishParsingChildren) 566 if (m_didFinishParsingChildren)
650 m_hasElementsAssociatedByParser = true; 567 m_hasElementsAssociatedByParser = true;
651 } 568 }
652 569
653 PassRefPtr<HTMLCollection> HTMLFormElement::elements() 570 PassRefPtr<HTMLCollection> HTMLFormElement::elements()
654 { 571 {
655 return ensureCachedHTMLCollection(FormControls); 572 return ensureCachedHTMLCollection(FormControls);
656 } 573 }
657 574
575 void HTMLFormElement::collectAssociatedElements(Node* root, Vector<FormAssociate dElement*>& elements) const
576 {
577 elements.clear();
578 for (Node* node = root; node; node = NodeTraversal::next(*node)) {
579 if (!node->isHTMLElement())
580 continue;
581 FormAssociatedElement* element = 0;
582 if (toElement(node)->isFormControlElement())
583 element = toHTMLFormControlElement(node);
584 else if (node->hasTagName(objectTag))
585 element = toHTMLObjectElement(node);
586 else
587 continue;
588 if (element->form()== this)
589 elements.append(element);
590 }
591 }
592
593 // This function should be const conceptually. However we update some fields
594 // because of lazy evaluation.
595 const Vector<FormAssociatedElement*>& HTMLFormElement::associatedElements() cons t
596 {
597 if (!m_associatedElementsAreDirty)
598 return m_associatedElements;
599 HTMLFormElement* mutableThis = const_cast<HTMLFormElement*>(this);
600 Node* scope = mutableThis;
601 if (m_hasElementsAssociatedByParser)
602 scope = highestAncestor();
603 if (inDocument() && treeScope().idTargetObserverRegistry().hasObservers(fast GetAttribute(idAttr)))
604 scope = &treeScope().rootNode();
605 collectAssociatedElements(scope, mutableThis->m_associatedElements);
606 mutableThis->m_associatedElementsAreDirty = false;
607 return m_associatedElements;
608 }
609
658 void HTMLFormElement::collectImageElements(Node* root, Vector<HTMLImageElement*> & elements) 610 void HTMLFormElement::collectImageElements(Node* root, Vector<HTMLImageElement*> & elements)
659 { 611 {
660 elements.clear(); 612 elements.clear();
661 for (Node* node = root; node; node = NodeTraversal::next(*node)) { 613 for (Node* node = root; node; node = NodeTraversal::next(*node)) {
662 if (node->isHTMLElement() && node->hasTagName(imgTag) && toHTMLElement(n ode)->formOwner() == this) 614 if (node->isHTMLElement() && node->hasTagName(imgTag) && toHTMLElement(n ode)->formOwner() == this)
663 elements.append(toHTMLImageElement(node)); 615 elements.append(toHTMLImageElement(node));
664 } 616 }
665 } 617 }
666 618
667 const Vector<HTMLImageElement*>& HTMLFormElement::imageElements() 619 const Vector<HTMLImageElement*>& HTMLFormElement::imageElements()
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
859 } 811 }
860 812
861 void HTMLFormElement::setDemoted(bool demoted) 813 void HTMLFormElement::setDemoted(bool demoted)
862 { 814 {
863 if (demoted) 815 if (demoted)
864 UseCounter::count(document(), UseCounter::DemotedFormElement); 816 UseCounter::count(document(), UseCounter::DemotedFormElement);
865 m_wasDemoted = demoted; 817 m_wasDemoted = demoted;
866 } 818 }
867 819
868 } // namespace 820 } // 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