summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--third_party/WebKit/Source/core/html/HTMLSelectElement.cpp276
-rw-r--r--third_party/WebKit/Source/core/html/HTMLSelectElement.h18
2 files changed, 149 insertions, 145 deletions
diff --git a/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp b/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp
index 31751a6..ad4c1d6 100644
--- a/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp
@@ -125,8 +125,9 @@ const AtomicString& HTMLSelectElement::formControlType() const
void HTMLSelectElement::optionSelectedByUser(int optionIndex, bool fireOnChangeNow, bool allowMultipleSelection)
{
- // User interaction such as mousedown events can cause list box select elements to send change events.
- // This produces that same behavior for changes triggered by other code running on behalf of the user.
+ // User interaction such as mousedown events can cause list box select
+ // elements to send change events. This produces that same behavior for
+ // changes triggered by other code running on behalf of the user.
if (!usesMenuList()) {
updateSelectedState(optionToListIndex(optionIndex), allowMultipleSelection, false);
setNeedsValidityCheck();
@@ -135,10 +136,12 @@ void HTMLSelectElement::optionSelectedByUser(int optionIndex, bool fireOnChangeN
return;
}
- // Bail out if this index is already the selected one, to avoid running unnecessary JavaScript that can mess up
- // autofill when there is no actual change (see https://bugs.webkit.org/show_bug.cgi?id=35256 and <rdar://7467917>).
- // The selectOption function does not behave this way, possibly because other callers need a change event even
- // in cases where the selected option is not change.
+ // Bail out if this index is already the selected one, to avoid running
+ // unnecessary JavaScript that can mess up autofill when there is no actual
+ // change (see https://bugs.webkit.org/show_bug.cgi?id=35256 and
+ // <rdar://7467917>). The selectOption function does not behave this way,
+ // possibly because other callers need a change event even in cases where
+ // the selected option is not change.
if (optionIndex == selectedIndex())
return;
@@ -147,17 +150,21 @@ void HTMLSelectElement::optionSelectedByUser(int optionIndex, bool fireOnChangeN
bool HTMLSelectElement::hasPlaceholderLabelOption() const
{
- // The select element has no placeholder label option if it has an attribute "multiple" specified or a display size of non-1.
+ // The select element has no placeholder label option if it has an attribute
+ // "multiple" specified or a display size of non-1.
//
- // The condition "size() > 1" is not compliant with the HTML5 spec as of Dec 3, 2010. "size() != 1" is correct.
- // Using "size() > 1" here because size() may be 0 in WebKit.
- // See the discussion at https://bugs.webkit.org/show_bug.cgi?id=43887
+ // The condition "size() > 1" is not compliant with the HTML5 spec as of Dec
+ // 3, 2010. "size() != 1" is correct. Using "size() > 1" here because
+ // size() may be 0 in WebKit. See the discussion at
+ // https://bugs.webkit.org/show_bug.cgi?id=43887
//
- // "0 size()" happens when an attribute "size" is absent or an invalid size attribute is specified.
- // In this case, the display size should be assumed as the default.
- // The default display size is 1 for non-multiple select elements, and 4 for multiple select elements.
+ // "0 size()" happens when an attribute "size" is absent or an invalid size
+ // attribute is specified. In this case, the display size should be assumed
+ // as the default. The default display size is 1 for non-multiple select
+ // elements, and 4 for multiple select elements.
//
- // Finally, if size() == 0 and non-multiple, the display size can be assumed as 1.
+ // Finally, if size() == 0 and non-multiple, the display size can be assumed
+ // as 1.
if (multiple() || size() > 1)
return false;
@@ -189,7 +196,8 @@ bool HTMLSelectElement::valueMissing() const
int firstSelectionIndex = selectedIndex();
- // If a non-placeholer label option is selected (firstSelectionIndex > 0), it's not value-missing.
+ // If a non-placeholer label option is selected (firstSelectionIndex > 0),
+ // it's not value-missing.
return firstSelectionIndex < 0 || (!firstSelectionIndex && hasPlaceholderLabelOption());
}
@@ -244,10 +252,8 @@ void HTMLSelectElement::add(const HTMLOptionElementOrHTMLOptGroupElement& elemen
void HTMLSelectElement::remove(int optionIndex)
{
int listIndex = optionToListIndex(optionIndex);
- if (listIndex < 0)
- return;
-
- listItems()[listIndex]->remove(IGNORE_EXCEPTION);
+ if (listIndex >= 0)
+ listItems()[listIndex]->remove(IGNORE_EXCEPTION);
}
String HTMLSelectElement::value() const
@@ -259,21 +265,22 @@ String HTMLSelectElement::value() const
void HTMLSelectElement::setValue(const String &value, bool sendEvents)
{
- // We clear the previously selected option(s) when needed, to guarantee calling setSelectedIndex() only once.
+ // We clear the previously selected option(s) when needed, to guarantee
+ // calling setSelectedIndex() only once.
int optionIndex = 0;
if (value.isNull()) {
optionIndex = -1;
} else {
- // Find the option with value() matching the given parameter and make it the current selection.
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems();
- for (unsigned i = 0; i < items.size(); i++) {
- if (isHTMLOptionElement(items[i])) {
- if (toHTMLOptionElement(items[i])->value() == value)
- break;
- optionIndex++;
- }
+ // Find the option with value() matching the given parameter and make it
+ // the current selection.
+ for (auto& item : listItems()) {
+ if (!isHTMLOptionElement(item))
+ continue;
+ if (toHTMLOptionElement(item)->value() == value)
+ break;
+ optionIndex++;
}
- if (optionIndex >= static_cast<int>(items.size()))
+ if (optionIndex >= static_cast<int>(listItems().size()))
optionIndex = -1;
}
@@ -292,7 +299,7 @@ void HTMLSelectElement::setValue(const String &value, bool sendEvents)
String HTMLSelectElement::suggestedValue() const
{
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems();
+ const ListItems& items = listItems();
for (unsigned i = 0; i < items.size(); ++i) {
if (isHTMLOptionElement(items[i]) && m_suggestedIndex >= 0) {
if (i == static_cast<unsigned>(m_suggestedIndex))
@@ -309,17 +316,16 @@ void HTMLSelectElement::setSuggestedValue(const String& value)
return;
}
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems();
unsigned optionIndex = 0;
- for (unsigned i = 0; i < items.size(); ++i) {
- if (isHTMLOptionElement(items[i])) {
- if (toHTMLOptionElement(items[i])->value() == value) {
- setSuggestedIndex(optionIndex);
- m_isAutofilledByPreview = true;
- return;
- }
- optionIndex++;
+ for (auto& item : listItems()) {
+ if (!isHTMLOptionElement(item))
+ continue;
+ if (toHTMLOptionElement(item)->value() == value) {
+ setSuggestedIndex(optionIndex);
+ m_isAutofilledByPreview = true;
+ return;
}
+ optionIndex++;
}
setSuggestedIndex(-1);
@@ -341,7 +347,8 @@ void HTMLSelectElement::parseAttribute(const QualifiedName& name, const AtomicSt
if (name == sizeAttr) {
unsigned oldSize = m_size;
// Set the attribute value to a number.
- // This is important since the style rules for this attribute can determine the appearance property.
+ // This is important since the style rules for this attribute can
+ // determine the appearance property.
unsigned size = value.string().toUInt();
AtomicString attrSize = AtomicString::number(size);
if (attrSize != value) {
@@ -351,7 +358,8 @@ void HTMLSelectElement::parseAttribute(const QualifiedName& name, const AtomicSt
}
size = std::max(size, 0u);
- // Ensure that we've determined selectedness of the items at least once prior to changing the size.
+ // Ensure that we've determined selectedness of the items at least once
+ // prior to changing the size.
if (oldSize != size)
updateListItemSelectedStates();
@@ -434,7 +442,7 @@ void HTMLSelectElement::optionElementChildrenChanged()
void HTMLSelectElement::accessKeyAction(bool sendMouseEvents)
{
focus();
- dispatchSimulatedClick(0, sendMouseEvents ? SendMouseUpDownEvents : SendNoEvents);
+ dispatchSimulatedClick(nullptr, sendMouseEvents ? SendMouseUpDownEvents : SendNoEvents);
}
void HTMLSelectElement::setMultiple(bool multiple)
@@ -509,24 +517,21 @@ void HTMLSelectElement::setLength(unsigned newLen, ExceptionState& exceptionStat
break;
} while (++diff);
} else {
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems();
-
- // Removing children fires mutation events, which might mutate the DOM further, so we first copy out a list
- // of elements that we intend to remove then attempt to remove them one at a time.
+ // Removing children fires mutation events, which might mutate the DOM
+ // further, so we first copy out a list of elements that we intend to
+ // remove then attempt to remove them one at a time.
WillBeHeapVector<RefPtrWillBeMember<Element>> itemsToRemove;
size_t optionIndex = 0;
- for (size_t i = 0; i < items.size(); ++i) {
- Element* item = items[i];
- if (isHTMLOptionElement(items[i]) && optionIndex++ >= newLen) {
+ for (auto& item : listItems()) {
+ if (isHTMLOptionElement(item) && optionIndex++ >= newLen) {
ASSERT(item->parentNode());
- itemsToRemove.append(item);
+ itemsToRemove.append(item.get());
}
}
- for (size_t i = 0; i < itemsToRemove.size(); ++i) {
- Element* item = itemsToRemove[i].get();
+ for (auto& item : itemsToRemove) {
if (item->parentNode())
- item->parentNode()->removeChild(item, exceptionState);
+ item->parentNode()->removeChild(item.get(), exceptionState);
}
}
setNeedsValidityCheck();
@@ -537,14 +542,16 @@ bool HTMLSelectElement::isRequiredFormControl() const
return isRequired();
}
-// Returns the 1st valid item |skip| items from |listIndex| in direction |direction| if there is one.
-// Otherwise, it returns the valid item closest to that boundary which is past |listIndex| if there is one.
+// Returns the 1st valid item |skip| items from |listIndex| in direction
+// |direction| if there is one.
+// Otherwise, it returns the valid item closest to that boundary which is past
+// |listIndex| if there is one.
// Otherwise, it returns |listIndex|.
// Valid means that it is enabled and an option element.
int HTMLSelectElement::nextValidIndex(int listIndex, SkipDirection direction, int skip) const
{
- ASSERT(direction == -1 || direction == 1);
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& listItems = this->listItems();
+ ASSERT(direction == SkipBackwards || direction == SkipForwards);
+ const ListItems& listItems = this->listItems();
int lastGoodIndex = listIndex;
int size = listItems.size();
for (listIndex += direction; listIndex >= 0 && listIndex < size; listIndex += direction) {
@@ -579,7 +586,7 @@ int HTMLSelectElement::previousSelectableListIndex(int startIndex) const
int HTMLSelectElement::firstSelectableListIndex() const
{
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems();
+ const ListItems& items = listItems();
int index = nextValidIndex(items.size(), SkipBackwards, INT_MAX);
if (static_cast<size_t>(index) == items.size())
return -1;
@@ -591,10 +598,11 @@ int HTMLSelectElement::lastSelectableListIndex() const
return nextValidIndex(-1, SkipForwards, INT_MAX);
}
-// Returns the index of the next valid item one page away from |startIndex| in direction |direction|.
+// Returns the index of the next valid item one page away from |startIndex| in
+// direction |direction|.
int HTMLSelectElement::nextSelectableListIndexPageAway(int startIndex, SkipDirection direction) const
{
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems();
+ const ListItems& items = listItems();
// Can't use m_size because layoutObject forces a minimum size.
int pageSize = 0;
if (layoutObject()->isListBox())
@@ -602,7 +610,8 @@ int HTMLSelectElement::nextSelectableListIndexPageAway(int startIndex, SkipDirec
// One page away, but not outside valid bounds.
// If there is a valid option item one page away, the index is chosen.
- // If there is no exact one page away valid option, returns startIndex or the most far index.
+ // If there is no exact one page away valid option, returns startIndex or
+ // the most far index.
int edgeIndex = (direction == SkipForwards) ? 0 : (items.size() - 1);
int skipAmount = pageSize + ((direction == SkipForwards) ? startIndex : (edgeIndex - startIndex));
return nextValidIndex(edgeIndex, direction, skipAmount);
@@ -635,11 +644,8 @@ void HTMLSelectElement::saveLastSelection()
}
m_lastOnChangeSelection.clear();
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems();
- for (unsigned i = 0; i < items.size(); ++i) {
- HTMLElement* element = items[i];
+ for (auto& element : listItems())
m_lastOnChangeSelection.append(isHTMLOptionElement(*element) && toHTMLOptionElement(element)->selected());
- }
}
void HTMLSelectElement::setActiveSelectionAnchorIndex(int index)
@@ -657,9 +663,7 @@ void HTMLSelectElement::setActiveSelectionAnchorIndex(int index)
// m_activeSelectionEndIndex = 3, options at 1-3 indices are selected.
// updateListBoxSelection needs to clear selection of the fifth OPTION.
m_cachedStateForActiveSelection.clear();
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems();
- for (unsigned i = 0; i < items.size(); ++i) {
- HTMLElement* element = items[i];
+ for (auto& element : listItems()) {
m_cachedStateForActiveSelection.append(isHTMLOptionElement(*element) && toHTMLOptionElement(element)->selected());
}
}
@@ -671,12 +675,13 @@ void HTMLSelectElement::setActiveSelectionEndIndex(int index)
void HTMLSelectElement::updateListBoxSelection(bool deselectOtherOptions, bool scroll)
{
- ASSERT(layoutObject() && (layoutObject()->isListBox() || m_multiple));
+ ASSERT(layoutObject());
+ ASSERT(layoutObject()->isListBox() || m_multiple);
int start = std::min(m_activeSelectionAnchorIndex, m_activeSelectionEndIndex);
int end = std::max(m_activeSelectionAnchorIndex, m_activeSelectionEndIndex);
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems();
+ const ListItems& items = listItems();
for (int i = 0; i < static_cast<int>(items.size()); ++i) {
if (!isHTMLOptionElement(*items[i]))
continue;
@@ -704,7 +709,7 @@ void HTMLSelectElement::listBoxOnChange()
{
ASSERT(!usesMenuList() || m_multiple);
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems();
+ const ListItems& items = listItems();
// If the cached selection list is empty, or the size has changed, then fire
// dispatchFormControlChangeEvent, and return early.
@@ -763,7 +768,7 @@ void HTMLSelectElement::setOptionsChangedOnLayoutObject()
}
}
-const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& HTMLSelectElement::listItems() const
+const HTMLSelectElement::ListItems& HTMLSelectElement::listItems() const
{
if (m_shouldRecalcListItems) {
recalcListItems();
@@ -798,9 +803,8 @@ void HTMLSelectElement::setRecalcListItems()
if (!inDocument()) {
if (HTMLOptionsCollection* collection = cachedCollection<HTMLOptionsCollection>(SelectOptions))
collection->invalidateCache();
- }
- if (!inDocument())
invalidateSelectedItems();
+ }
if (layoutObject()) {
if (AXObjectCache* cache = layoutObject()->document().existingAXObjectCache())
@@ -815,8 +819,8 @@ void HTMLSelectElement::recalcListItems(bool updateSelectedStates) const
m_shouldRecalcListItems = false;
- HTMLOptionElement* foundSelected = 0;
- HTMLOptionElement* firstOption = 0;
+ HTMLOptionElement* foundSelected = nullptr;
+ HTMLOptionElement* firstOption = nullptr;
for (Element* currentElement = ElementTraversal::firstWithin(*this); currentElement && m_listItems.size() < maxListItems; ) {
if (!currentElement->isHTMLElement()) {
currentElement = ElementTraversal::nextSkippingChildren(*currentElement, this);
@@ -861,11 +865,11 @@ void HTMLSelectElement::recalcListItems(bool updateSelectedStates) const
m_listItems.append(&current);
// In conforming HTML code, only <optgroup> and <option> will be found
- // within a <select>. We call NodeTraversal::nextSkippingChildren so that we only step
- // into those tags that we choose to. For web-compat, we should cope
- // with the case where odd tags like a <div> have been added but we
- // handle this because such tags have already been removed from the
- // <select>'s subtree at this point.
+ // within a <select>. We call NodeTraversal::nextSkippingChildren so
+ // that we only step into those tags that we choose to. For web-compat,
+ // we should cope with the case where odd tags like a <div> have been
+ // added but we handle this because such tags have already been removed
+ // from the <select>'s subtree at this point.
currentElement = ElementTraversal::nextSkippingChildren(*currentElement, this);
}
@@ -887,14 +891,12 @@ int HTMLSelectElement::selectedIndex() const
unsigned index = 0;
// Return the number of the first option selected.
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems();
- for (size_t i = 0; i < items.size(); ++i) {
- HTMLElement* element = items[i];
- if (isHTMLOptionElement(*element)) {
- if (toHTMLOptionElement(*element).selected())
- return index;
- ++index;
- }
+ for (auto& element : listItems()) {
+ if (!isHTMLOptionElement(*element))
+ continue;
+ if (toHTMLOptionElement(*element).selected())
+ return index;
+ ++index;
}
return -1;
@@ -928,7 +930,7 @@ void HTMLSelectElement::scrollToIndex(int listIndex)
return;
if (usesMenuList())
return;
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems();
+ const ListItems& items = listItems();
int listSize = static_cast<int>(items.size());
if (listIndex >= listSize)
return;
@@ -992,18 +994,18 @@ void HTMLSelectElement::optionRemoved(const HTMLOptionElement& option)
}
// TODO(tkent): This function is not efficient. It contains multiple O(N)
-// operations.
+// operations. crbug.com/577989.
void HTMLSelectElement::selectOption(int optionIndex, SelectOptionFlags flags)
{
TRACE_EVENT0("blink", "HTMLSelectElement::selectOption");
bool shouldDeselect = !m_multiple || (flags & DeselectOtherOptions);
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems();
+ const ListItems& items = listItems();
// optionToListIndex is O(N).
int listIndex = optionToListIndex(optionIndex);
// selectedIndex() is O(N).
- if (selectedIndex() != optionIndex && isAutofilled())
+ if (isAutofilled() && selectedIndex() != optionIndex)
setAutofilled(false);
HTMLOptionElement* element = nullptr;
@@ -1046,6 +1048,8 @@ void HTMLSelectElement::selectOption(int optionIndex, SelectOptionFlags flags)
else
m_lastOnChangeOption = element;
if (LayoutObject* layoutObject = this->layoutObject()) {
+ // Need to check usesMenuList() again because
+ // dispatchInputAndChangeEventForMenuList() might change the status.
if (usesMenuList()) {
// didSetSelectedIndex() is O(N) because of listToOptionIndex
// and optionToListIndex.
@@ -1059,7 +1063,7 @@ void HTMLSelectElement::selectOption(int optionIndex, SelectOptionFlags flags)
int HTMLSelectElement::optionToListIndex(int optionIndex) const
{
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems();
+ const ListItems& items = listItems();
int listSize = static_cast<int>(items.size());
if (optionIndex < 0 || optionIndex >= listSize)
return -1;
@@ -1078,7 +1082,7 @@ int HTMLSelectElement::optionToListIndex(int optionIndex) const
int HTMLSelectElement::listToOptionIndex(int listIndex) const
{
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems();
+ const ListItems& items = listItems();
if (listIndex < 0 || listIndex >= static_cast<int>(items.size()) || !isHTMLOptionElement(*items[listIndex]))
return -1;
@@ -1105,8 +1109,8 @@ void HTMLSelectElement::dispatchBlurEvent(Element* newFocusedElement, WebFocusTy
{
m_typeAhead.resetSession();
// We only need to fire change events here for menu lists, because we fire
- // change events for list boxes whenever the selection change is actually made.
- // This matches other browsers' behavior.
+ // change events for list boxes whenever the selection change is actually
+ // made. This matches other browsers' behavior.
if (usesMenuList())
dispatchInputAndChangeEventForMenuList();
m_lastOnChangeSelection.clear();
@@ -1115,9 +1119,7 @@ void HTMLSelectElement::dispatchBlurEvent(Element* newFocusedElement, WebFocusTy
void HTMLSelectElement::deselectItemsWithoutValidation(HTMLElement* excludeElement)
{
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems();
- for (unsigned i = 0; i < items.size(); ++i) {
- HTMLElement* element = items[i];
+ for (auto& element : listItems()) {
if (element != excludeElement && isHTMLOptionElement(*element))
toHTMLOptionElement(element)->setSelectedState(false);
}
@@ -1125,7 +1127,7 @@ void HTMLSelectElement::deselectItemsWithoutValidation(HTMLElement* excludeEleme
FormControlState HTMLSelectElement::saveFormControlState() const
{
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems();
+ const ListItems& items = listItems();
size_t length = items.size();
FormControlState state;
for (unsigned i = 0; i < length; ++i) {
@@ -1144,7 +1146,7 @@ FormControlState HTMLSelectElement::saveFormControlState() const
size_t HTMLSelectElement::searchOptionsForValue(const String& value, size_t listIndexStart, size_t listIndexEnd) const
{
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems();
+ const ListItems& items = listItems();
size_t loopEndIndex = std::min(items.size(), listIndexEnd);
for (size_t i = listIndexStart; i < loopEndIndex; ++i) {
if (!isHTMLOptionElement(items[i]))
@@ -1159,15 +1161,14 @@ void HTMLSelectElement::restoreFormControlState(const FormControlState& state)
{
recalcListItems();
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems();
+ const ListItems& items = listItems();
size_t itemsSize = items.size();
- if (!itemsSize)
+ if (itemsSize == 0)
return;
- for (size_t i = 0; i < itemsSize; ++i) {
- if (!isHTMLOptionElement(items[i]))
- continue;
- toHTMLOptionElement(items[i])->setSelectedState(false);
+ for (auto& item : items) {
+ if (isHTMLOptionElement(item))
+ toHTMLOptionElement(item)->setSelectedState(false);
}
// The saved state should have at least one value and an index.
@@ -1224,9 +1225,7 @@ void HTMLSelectElement::appendToFormData(FormData& formData)
if (name.isEmpty())
return;
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems();
- for (unsigned i = 0; i < items.size(); ++i) {
- HTMLElement* element = items[i];
+ for (auto& element : listItems()) {
if (isHTMLOptionElement(*element) && toHTMLOptionElement(*element).selected() && !toHTMLOptionElement(*element).isDisabledFormControl())
formData.append(name, toHTMLOptionElement(*element).value());
}
@@ -1234,14 +1233,13 @@ void HTMLSelectElement::appendToFormData(FormData& formData)
void HTMLSelectElement::resetImpl()
{
- HTMLOptionElement* firstOption = 0;
- HTMLOptionElement* selectedOption = 0;
+ HTMLOptionElement* firstOption = nullptr;
+ HTMLOptionElement* selectedOption = nullptr;
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems();
- for (unsigned i = 0; i < items.size(); ++i) {
- if (!isHTMLOptionElement(*items[i]))
+ for (auto& item : listItems()) {
+ if (!isHTMLOptionElement(item))
continue;
- HTMLOptionElement* option = toHTMLOptionElement(items[i]);
+ HTMLOptionElement* option = toHTMLOptionElement(item);
if (option->fastHasAttribute(selectedAttr)) {
if (selectedOption && !m_multiple)
selectedOption->setSelectedState(false);
@@ -1326,13 +1324,14 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* event)
return;
}
- // The key handling below shouldn't be used for non spatial navigation mode Mac
+ // The key handling below shouldn't be used for non spatial navigation
+ // mode Mac
if (LayoutTheme::theme().popsMenuByArrowKeys() && !isSpatialNavigationEnabled(document().frame()))
return;
const String& keyIdentifier = keyEvent->keyIdentifier();
bool handled = true;
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& listItems = this->listItems();
+ const ListItems& listItems = this->listItems();
int listIndex = optionToListIndex(selectedIndex());
if (keyIdentifier == "Down" || keyIdentifier == "Right")
@@ -1363,7 +1362,8 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* event)
int keyCode = toKeyboardEvent(event)->keyCode();
if (keyCode == ' ' && isSpatialNavigationEnabled(document().frame())) {
- // Use space to toggle arrow key handling for selection change or spatial navigation.
+ // Use space to toggle arrow key handling for selection change or
+ // spatial navigation.
m_activeSelectionState = !m_activeSelectionState;
event->setDefaultHandled();
return;
@@ -1395,8 +1395,9 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* event)
// from valueChanged, which gets called after the user makes a
// selection from the menu.
saveLastSelection();
- // TODO(lanwei): Will check if we need to add InputDeviceCapabilities here
- // when select menu list gets focus, see https://crbug.com/476530.
+ // TODO(lanwei): Will check if we need to add
+ // InputDeviceCapabilities here when select menu list gets
+ // focus, see https://crbug.com/476530.
showPopup();
}
}
@@ -1476,7 +1477,7 @@ int HTMLSelectElement::listIndexForEventTargetOption(const Event& event)
int HTMLSelectElement::listIndexForOption(const HTMLOptionElement& option)
{
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = this->listItems();
+ const ListItems& items = this->listItems();
size_t length = items.size();
for (size_t i = 0; i < length; ++i) {
if (items[i].get() == &option)
@@ -1489,7 +1490,7 @@ AutoscrollController* HTMLSelectElement::autoscrollController() const
{
if (Page* page = document().page())
return &page->autoscrollController();
- return 0;
+ return nullptr;
}
void HTMLSelectElement::handleMouseRelease()
@@ -1502,10 +1503,11 @@ void HTMLSelectElement::handleMouseRelease()
void HTMLSelectElement::listBoxDefaultEventHandler(Event* event)
{
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& listItems = this->listItems();
+ const ListItems& listItems = this->listItems();
if (event->type() == EventTypeNames::gesturetap && event->isGestureEvent()) {
focus();
- // Calling focus() may cause us to lose our layoutObject or change the layoutObject type, in which case do not want to handle the event.
+ // Calling focus() may cause us to lose our layoutObject or change the
+ // layoutObject type, in which case do not want to handle the event.
if (!layoutObject() || !layoutObject()->isListBox())
return;
@@ -1519,9 +1521,11 @@ void HTMLSelectElement::listBoxDefaultEventHandler(Event* event)
}
event->setDefaultHandled();
}
+
} else if (event->type() == EventTypeNames::mousedown && event->isMouseEvent() && toMouseEvent(event)->button() == LeftButton) {
focus();
- // Calling focus() may cause us to lose our layoutObject, in which case do not want to handle the event.
+ // Calling focus() may cause us to lose our layoutObject, in which case
+ // do not want to handle the event.
if (!layoutObject() || !layoutObject()->isListBox() || isDisabledFormControl())
return;
@@ -1541,6 +1545,7 @@ void HTMLSelectElement::listBoxDefaultEventHandler(Event* event)
event->setDefaultHandled();
}
+
} else if (event->type() == EventTypeNames::mousemove && event->isMouseEvent()) {
MouseEvent* mouseEvent = toMouseEvent(event);
if (mouseEvent->button() != LeftButton || !mouseEvent->buttonDown())
@@ -1569,11 +1574,13 @@ void HTMLSelectElement::listBoxDefaultEventHandler(Event* event)
}
}
}
+
} else if (event->type() == EventTypeNames::mouseup && event->isMouseEvent() && toMouseEvent(event)->button() == LeftButton && layoutObject()) {
if (document().page() && document().page()->autoscrollController().autoscrollInProgress(toLayoutBox(layoutObject())))
document().page()->autoscrollController().stopAutoscroll();
else
handleMouseRelease();
+
} else if (event->type() == EventTypeNames::keydown) {
if (!event->isKeyboardEvent())
return;
@@ -1659,6 +1666,7 @@ void HTMLSelectElement::listBoxDefaultEventHandler(Event* event)
event->setDefaultHandled();
}
+
} else if (event->type() == EventTypeNames::keypress) {
if (!event->isKeyboardEvent())
return;
@@ -1708,7 +1716,7 @@ void HTMLSelectElement::defaultEventHandler(Event* event)
int HTMLSelectElement::lastSelectedListIndex() const
{
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems();
+ const ListItems& items = listItems();
for (size_t i = items.size(); i;) {
HTMLElement* element = items[--i];
if (isHTMLOptionElement(*element) && toHTMLOptionElement(element)->selected())
@@ -1729,8 +1737,7 @@ int HTMLSelectElement::optionCount() const
String HTMLSelectElement::optionAtIndex(int index) const
{
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems();
-
+ const ListItems& items = listItems();
HTMLElement* element = items[index];
if (!isHTMLOptionElement(*element) || toHTMLOptionElement(element)->isDisabledFormControl())
return String();
@@ -1753,7 +1760,7 @@ void HTMLSelectElement::accessKeySetSelectedIndex(int index)
if (!focused())
accessKeyAction(false);
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems();
+ const ListItems& items = listItems();
int listIndex = optionToListIndex(index);
if (listIndex < 0)
return;
@@ -1781,13 +1788,10 @@ void HTMLSelectElement::accessKeySetSelectedIndex(int index)
unsigned HTMLSelectElement::length() const
{
unsigned options = 0;
-
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems();
- for (unsigned i = 0; i < items.size(); ++i) {
- if (isHTMLOptionElement(*items[i]))
+ for (auto& item : listItems()) {
+ if (isHTMLOptionElement(*item))
++options;
}
-
return options;
}
diff --git a/third_party/WebKit/Source/core/html/HTMLSelectElement.h b/third_party/WebKit/Source/core/html/HTMLSelectElement.h
index afb4672..13cabe5 100644
--- a/third_party/WebKit/Source/core/html/HTMLSelectElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLSelectElement.h
@@ -42,7 +42,7 @@ class HTMLOptionElementOrHTMLOptGroupElement;
class HTMLElementOrLong;
class PopupMenu;
-class CORE_EXPORT HTMLSelectElement final : public HTMLFormControlElementWithState, public TypeAheadDataSource {
+class CORE_EXPORT HTMLSelectElement final : public HTMLFormControlElementWithState, private TypeAheadDataSource {
DEFINE_WRAPPERTYPEINFO();
public:
static PassRefPtrWillBeRawPtr<HTMLSelectElement> create(Document&);
@@ -63,9 +63,12 @@ public:
void resetImpl() override;
unsigned length() const;
+ void setLength(unsigned, ExceptionState&);
unsigned size() const { return m_size; }
+ void setSize(unsigned);
bool multiple() const { return m_multiple; }
+ void setMultiple(bool);
bool usesMenuList() const;
@@ -88,17 +91,13 @@ public:
void invalidateSelectedItems();
void updateListItemSelectedStates();
- const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& listItems() const;
+ using ListItems = WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>;
+ const ListItems& listItems() const;
void accessKeyAction(bool sendMouseEvents) override;
void accessKeySetSelectedIndex(int);
- void setMultiple(bool);
-
- void setSize(unsigned);
-
void setOption(unsigned index, HTMLOptionElement*, ExceptionState&);
- void setLength(unsigned, ExceptionState&);
Element* namedItem(const AtomicString& name);
HTMLOptionElement* item(unsigned index);
@@ -249,8 +248,9 @@ private:
int optionCount() const override;
String optionAtIndex(int index) const override;
- // m_listItems contains HTMLOptionElement, HTMLOptGroupElement, and HTMLHRElement objects.
- mutable WillBeHeapVector<RawPtrWillBeMember<HTMLElement>> m_listItems;
+ // m_listItems contains HTMLOptionElement, HTMLOptGroupElement, and
+ // HTMLHRElement objects.
+ mutable ListItems m_listItems;
Vector<bool> m_lastOnChangeSelection;
Vector<bool> m_cachedStateForActiveSelection;
TypeAhead m_typeAhead;