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

Side by Side Diff: third_party/WebKit/Source/core/html/HTMLSelectElement.cpp

Issue 2110003002: Improve performance of HTMLSelectElement::resetToDefaultSelection(). (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 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
« no previous file with comments | « third_party/WebKit/Source/core/html/HTMLSelectElement.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) 2010 Nokia Corporation and/or its subsidiary(-ies). 2 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
3 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 3 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
4 * (C) 1999 Antti Koivisto (koivisto@kde.org) 4 * (C) 1999 Antti Koivisto (koivisto@kde.org)
5 * (C) 2001 Dirk Mueller (mueller@kde.org) 5 * (C) 2001 Dirk Mueller (mueller@kde.org)
6 * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 Apple Inc. All rights reserved. 6 * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 Apple Inc. All rights reserved.
7 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) 7 * (C) 2006 Alexey Proskuryakov (ap@nypop.com)
8 * Copyright (C) 2010 Google Inc. All rights reserved. 8 * Copyright (C) 2010 Google Inc. All rights reserved.
9 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo bile.com/) 9 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo bile.com/)
10 * 10 *
(...skipping 859 matching lines...) Expand 10 before | Expand all | Expand 10 after
870 firstEnabledOption = option; 870 firstEnabledOption = option;
871 firstEnabledOptionIndex = optionIndex; 871 firstEnabledOptionIndex = optionIndex;
872 if (reason == ResetReasonSelectedOptionRemoved) { 872 if (reason == ResetReasonSelectedOptionRemoved) {
873 // There must be no selected OPTIONs. 873 // There must be no selected OPTIONs.
874 break; 874 break;
875 } 875 }
876 } 876 }
877 ++optionIndex; 877 ++optionIndex;
878 } 878 }
879 if (!lastSelectedOption && m_size <= 1 && firstEnabledOption && !firstEnable dOption->selected()) { 879 if (!lastSelectedOption && m_size <= 1 && firstEnabledOption && !firstEnable dOption->selected()) {
880 selectOption(firstEnabledOption, firstEnabledOptionIndex, 0); 880 selectOption(firstEnabledOption, firstEnabledOptionIndex, reason == Rese tReasonSelectedOptionRemoved ? 0 : DeselectOtherOptions);
tkent 2016/06/29 04:45:56 This is the main change.
881 lastSelectedOption = firstEnabledOption; 881 lastSelectedOption = firstEnabledOption;
882 didChange = true; 882 didChange = true;
883 } 883 }
884 if (didChange) 884 if (didChange)
885 setNeedsValidityCheck(); 885 setNeedsValidityCheck();
886 m_lastOnChangeOption = lastSelectedOption; 886 m_lastOnChangeOption = lastSelectedOption;
887 } 887 }
888 888
889 HTMLOptionElement* HTMLSelectElement::selectedOption() const 889 HTMLOptionElement* HTMLSelectElement::selectedOption() const
890 { 890 {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
960 if (!layoutObject() || !layoutObject()->isListBox()) 960 if (!layoutObject() || !layoutObject()->isListBox())
961 return; 961 return;
962 LayoutRect bounds = option->boundingBox(); 962 LayoutRect bounds = option->boundingBox();
963 toLayoutListBox(layoutObject())->scrollToRect(bounds); 963 toLayoutListBox(layoutObject())->scrollToRect(bounds);
964 } 964 }
965 965
966 void HTMLSelectElement::optionSelectionStateChanged(HTMLOptionElement* option, b ool optionIsSelected) 966 void HTMLSelectElement::optionSelectionStateChanged(HTMLOptionElement* option, b ool optionIsSelected)
967 { 967 {
968 ASSERT(option->ownerSelectElement() == this); 968 ASSERT(option->ownerSelectElement() == this);
969 if (optionIsSelected) 969 if (optionIsSelected)
970 selectOption(option); 970 selectOption(option, multiple() ? 0 : DeselectOtherOptions);
971 else if (!usesMenuList() || multiple()) 971 else if (!usesMenuList() || multiple())
972 selectOption(nullptr); 972 selectOption(nullptr, multiple() ? 0 : DeselectOtherOptions);
973 else 973 else
974 selectOption(nextSelectableOption(nullptr)); 974 selectOption(nextSelectableOption(nullptr), DeselectOtherOptions);
975 } 975 }
976 976
977 void HTMLSelectElement::optionInserted(HTMLOptionElement& option, bool optionIsS elected) 977 void HTMLSelectElement::optionInserted(HTMLOptionElement& option, bool optionIsS elected)
978 { 978 {
979 ASSERT(option.ownerSelectElement() == this); 979 ASSERT(option.ownerSelectElement() == this);
980 setRecalcListItems(); 980 setRecalcListItems();
981 if (optionIsSelected) { 981 if (optionIsSelected) {
982 selectOption(&option); 982 selectOption(&option, multiple() ? 0 : DeselectOtherOptions);
983 } else { 983 } else {
984 // No need to reset if we already have a selected option. 984 // No need to reset if we already have a selected option.
985 if (!m_lastOnChangeOption) 985 if (!m_lastOnChangeOption)
986 resetToDefaultSelection(); 986 resetToDefaultSelection();
987 } 987 }
988 } 988 }
989 989
990 void HTMLSelectElement::optionRemoved(const HTMLOptionElement& option) 990 void HTMLSelectElement::optionRemoved(const HTMLOptionElement& option)
991 { 991 {
992 setRecalcListItems(); 992 setRecalcListItems();
(...skipping 21 matching lines...) Expand all
1014 void HTMLSelectElement::selectOption(HTMLOptionElement* option, SelectOptionFlag s flags) 1014 void HTMLSelectElement::selectOption(HTMLOptionElement* option, SelectOptionFlag s flags)
1015 { 1015 {
1016 selectOption(option, option ? option->index() : -1, flags); 1016 selectOption(option, option ? option->index() : -1, flags);
1017 } 1017 }
1018 1018
1019 // TODO(tkent): This function is not efficient. It contains multiple O(N) 1019 // TODO(tkent): This function is not efficient. It contains multiple O(N)
1020 // operations. crbug.com/577989. 1020 // operations. crbug.com/577989.
1021 void HTMLSelectElement::selectOption(HTMLOptionElement* element, int optionIndex , SelectOptionFlags flags) 1021 void HTMLSelectElement::selectOption(HTMLOptionElement* element, int optionIndex , SelectOptionFlags flags)
1022 { 1022 {
1023 TRACE_EVENT0("blink", "HTMLSelectElement::selectOption"); 1023 TRACE_EVENT0("blink", "HTMLSelectElement::selectOption");
1024 bool shouldDeselect = !m_multiple || (flags & DeselectOtherOptions);
1025
1026 ASSERT((!element && optionIndex < 0) || (element && optionIndex >= 0)); 1024 ASSERT((!element && optionIndex < 0) || (element && optionIndex >= 0));
1027 1025
1028 // selectedIndex() is O(N). 1026 // selectedIndex() is O(N).
1029 if (isAutofilled() && selectedIndex() != optionIndex) 1027 if (isAutofilled() && selectedIndex() != optionIndex)
1030 setAutofilled(false); 1028 setAutofilled(false);
1031 1029
1032 if (element) { 1030 if (element) {
1033 element->setSelectedState(true); 1031 element->setSelectedState(true);
1034 if (flags & MakeOptionDirty) 1032 if (flags & MakeOptionDirty)
1035 element->setDirty(true); 1033 element->setDirty(true);
1036 } 1034 }
1037 1035
1038 // deselectItemsWithoutValidation() is O(N). 1036 // deselectItemsWithoutValidation() is O(N).
1039 if (shouldDeselect) 1037 if (flags & DeselectOtherOptions)
1040 deselectItemsWithoutValidation(element); 1038 deselectItemsWithoutValidation(element);
1041 1039
1042 // We should update active selection after finishing OPTION state change 1040 // We should update active selection after finishing OPTION state change
1043 // because setActiveSelectionAnchorIndex() stores OPTION's selection state. 1041 // because setActiveSelectionAnchorIndex() stores OPTION's selection state.
1044 if (element) { 1042 if (element) {
1045 // setActiveSelectionAnchor is O(N). 1043 // setActiveSelectionAnchor is O(N).
1046 if (!m_activeSelectionAnchor || shouldDeselect) 1044 if (!m_activeSelectionAnchor || !multiple() || flags & DeselectOtherOpti ons)
1047 setActiveSelectionAnchor(element); 1045 setActiveSelectionAnchor(element);
1048 if (!m_activeSelectionEnd || shouldDeselect) 1046 if (!m_activeSelectionEnd || !multiple() || flags & DeselectOtherOptions )
1049 setActiveSelectionEnd(element); 1047 setActiveSelectionEnd(element);
1050 } 1048 }
1051 1049
1052 // For the menu list case, this is what makes the selected element appear. 1050 // For the menu list case, this is what makes the selected element appear.
1053 if (LayoutObject* layoutObject = this->layoutObject()) 1051 if (LayoutObject* layoutObject = this->layoutObject())
1054 layoutObject->updateFromElement(); 1052 layoutObject->updateFromElement();
1055 // PopupMenu::updateFromElement() posts an O(N) task. 1053 // PopupMenu::updateFromElement() posts an O(N) task.
1056 if (popupIsVisible()) 1054 if (popupIsVisible())
1057 m_popup->updateFromElement(PopupMenu::BySelectionChange); 1055 m_popup->updateFromElement(PopupMenu::BySelectionChange);
1058 1056
(...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after
1757 const ListItems& items = listItems(); 1755 const ListItems& items = listItems();
1758 int listIndex = optionToListIndex(index); 1756 int listIndex = optionToListIndex(index);
1759 if (listIndex < 0) 1757 if (listIndex < 0)
1760 return; 1758 return;
1761 HTMLElement& element = *items[listIndex]; 1759 HTMLElement& element = *items[listIndex];
1762 if (!isHTMLOptionElement(element)) 1760 if (!isHTMLOptionElement(element))
1763 return; 1761 return;
1764 EventQueueScope scope; 1762 EventQueueScope scope;
1765 // If this index is already selected, unselect. otherwise update the 1763 // If this index is already selected, unselect. otherwise update the
1766 // selected index. 1764 // selected index.
1765 SelectOptionFlags flags = DispatchInputAndChangeEvent | (multiple() ? 0 : De selectOtherOptions);
1767 if (toHTMLOptionElement(element).selected()) { 1766 if (toHTMLOptionElement(element).selected()) {
1768 if (usesMenuList()) 1767 if (usesMenuList())
1769 selectOption(-1, DispatchInputAndChangeEvent); 1768 selectOption(-1, flags);
1770 else 1769 else
1771 toHTMLOptionElement(element).setSelectedState(false); 1770 toHTMLOptionElement(element).setSelectedState(false);
1772 } else { 1771 } else {
1773 selectOption(index, DispatchInputAndChangeEvent); 1772 selectOption(index, flags);
1774 } 1773 }
1775 toHTMLOptionElement(element).setDirty(true); 1774 toHTMLOptionElement(element).setDirty(true);
1776 if (usesMenuList()) 1775 if (usesMenuList())
1777 return; 1776 return;
1778 listBoxOnChange(); 1777 listBoxOnChange();
1779 scrollToSelection(); 1778 scrollToSelection();
1780 } 1779 }
1781 1780
1782 unsigned HTMLSelectElement::length() const 1781 unsigned HTMLSelectElement::length() const
1783 { 1782 {
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
2078 } 2077 }
2079 2078
2080 void HTMLSelectElement::didMutateSubtree() 2079 void HTMLSelectElement::didMutateSubtree()
2081 { 2080 {
2082 DCHECK(popupIsVisible()); 2081 DCHECK(popupIsVisible());
2083 DCHECK(m_popup); 2082 DCHECK(m_popup);
2084 m_popup->updateFromElement(PopupMenu::ByDOMChange); 2083 m_popup->updateFromElement(PopupMenu::ByDOMChange);
2085 } 2084 }
2086 2085
2087 } // namespace blink 2086 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/html/HTMLSelectElement.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698