Diff
Modified: trunk/LayoutTests/ChangeLog (121391 => 121392)
--- trunk/LayoutTests/ChangeLog 2012-06-28 00:49:55 UTC (rev 121391)
+++ trunk/LayoutTests/ChangeLog 2012-06-28 01:05:27 UTC (rev 121392)
@@ -1,3 +1,17 @@
+2012-06-27 Alexis Menard <alexis.men...@openbossa.org>
+
+ Implement selectedOptions attribute of HTMLSelectElement.
+ https://bugs.webkit.org/show_bug.cgi?id=80631
+
+ Reviewed by Ryosuke Niwa.
+
+ New tests to cover the feature.
+
+ * fast/dom/HTMLSelectElement/select-selectedOptions-expected.txt: Added.
+ * fast/dom/HTMLSelectElement/select-selectedOptions.html: Added.
+ * fast/dom/htmlcollection-non-html-expected.txt:
+ * fast/dom/htmlcollection-non-html.html:
+
2012-06-27 Filip Pizlo <fpi...@apple.com>
_javascript_ SHA-512 gives wrong hash on second and subsequent runs unless Web Inspector _javascript_ Debugging is on
Added: trunk/LayoutTests/fast/dom/HTMLSelectElement/select-selectedOptions-expected.txt (0 => 121392)
--- trunk/LayoutTests/fast/dom/HTMLSelectElement/select-selectedOptions-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/dom/HTMLSelectElement/select-selectedOptions-expected.txt 2012-06-28 01:05:27 UTC (rev 121392)
@@ -0,0 +1,51 @@
+
+1) Initial there is no selected options.
+PASS optionsLength is 2
+PASS selectedOptions.length is 0
+2) Select an option should update the selected options collection.
+PASS optionsLength is 2
+PASS selectedOptions.length is 1
+PASS selectedOptions[0].text is 'one'
+3) Select two options should update the selected options collection.
+PASS optionsLength is 2
+PASS selectedOptions.length is 2
+PASS selectedOptions[0].text is 'one'
+PASS selectedOptions[1].text is 'two'
+4) Adding a non selected option should not change the selected options collection.
+PASS optionsLength is 3
+PASS selectedOptions.length is 1
+PASS selectedOptions[0].text is 'one'
+5) Adding a selected option should change the selected options collection.
+PASS optionsLength is 4
+PASS selectedOptions.length is 2
+PASS selectedOptions[0].text is 'one'
+PASS selectedOptions[1].text is 'five'
+6) Unselect an option should update the selected options collection.
+PASS optionsLength is 4
+PASS selectedOptions.length is 1
+PASS selectedOptions[0].text is 'five'
+7) Remove an option unselected should not update the selected options collection.
+PASS optionsLength is 3
+PASS selectedOptions.length is 1
+PASS selectedOptions[0].text is 'five'
+8) Remove an option selected should update the selected options collection.
+PASS optionsLength is 2
+PASS selectedOptions.length is 0
+9) Change multiple attribute to false should update selectedOptions.
+PASS optionsLength is 2
+PASS selectedOptions.length is 1
+PASS selectedOptions[0].text is 'two'
+10) Even with an option disabled selectedOptions should be updated.
+PASS optionsLength is 2
+PASS selectedOptions.length is 1
+PASS selectedOptions[0].text is 'one'
+11) Even with select element disabled, the selectedOptions should be updated.
+PASS optionsLength is 2
+PASS selectedOptions.length is 2
+PASS selectedOptions[0].text is 'one'
+PASS selectedOptions[1].text is 'two'
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/dom/HTMLSelectElement/select-selectedOptions.html (0 => 121392)
--- trunk/LayoutTests/fast/dom/HTMLSelectElement/select-selectedOptions.html (rev 0)
+++ trunk/LayoutTests/fast/dom/HTMLSelectElement/select-selectedOptions.html 2012-06-28 01:05:27 UTC (rev 121392)
@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<select id="test" size="3" multiple="multiple">
+</select>
+<div id="console"></div>
+<script src=""
+<script>
+function reset(mySelect) {
+ mySelect.length = 0;
+ mySelect.multiple = true;
+ mySelect.options[mySelect.length] = new Option("one", "value", false);
+ mySelect.options[mySelect.length] = new Option("two", "value", false);
+}
+
+function deepCopy(array)
+{
+ var copy=[];
+ for(var i=0;i<array.length;i++)
+ copy.push(array[i]);
+ return copy;
+ }
+
+var mySelect = document.getElementById("test");
+reset(mySelect);
+var i = 0;
+
+// We use this local variable as shouldBe will modify the dom tree version. Any dom tree version update invalidates
+// the caches therefore we need to make sure that we store the values before calling shouldBe.
+var selectedOptions;
+var optionsLength = 0;
+
+debug((++i) + ") Initial there is no selected options.");
+optionsLength = mySelect.options.length;
+selectedOptions = deepCopy(mySelect.selectedOptions);
+shouldBe("optionsLength", "2");
+shouldBe("selectedOptions.length", "0");
+
+debug((++i) + ") Select an option should update the selected options collection.");
+mySelect.options[0].selected = true;
+optionsLength = mySelect.options.length;
+selectedOptions = deepCopy(mySelect.selectedOptions);
+shouldBe("optionsLength", "2");
+shouldBe("selectedOptions.length", "1");
+shouldBe("selectedOptions[0].text", "'one'");
+
+debug((++i) + ") Select two options should update the selected options collection.");
+mySelect.options[1].selected = true;
+optionsLength = mySelect.options.length;
+selectedOptions = deepCopy(mySelect.selectedOptions);
+shouldBe("optionsLength", "2");
+shouldBe("selectedOptions.length", "2");
+shouldBe("selectedOptions[0].text", "'one'");
+shouldBe("selectedOptions[1].text", "'two'");
+
+mySelect.options[1].selected = false;
+debug((++i) + ") Adding a non selected option should not change the selected options collection.");
+mySelect.options[mySelect.length] = new Option("three", "value", false);
+optionsLength = mySelect.options.length;
+selectedOptions = deepCopy(mySelect.selectedOptions);
+shouldBe("optionsLength", "3");
+shouldBe("selectedOptions.length", "1");
+shouldBe("selectedOptions[0].text", "'one'");
+
+debug((++i) + ") Adding a selected option should change the selected options collection.");
+mySelect.options[mySelect.length] = new Option("five", "value", true, true);
+selectedOptionsLength = mySelect.selectedOptions.length;
+optionsLength = mySelect.options.length;
+selectedOptions = mySelect.selectedOptions;
+shouldBe("optionsLength", "4");
+shouldBe("selectedOptions.length", "2");
+shouldBe("selectedOptions[0].text", "'one'");
+shouldBe("selectedOptions[1].text", "'five'");
+
+debug((++i) + ") Unselect an option should update the selected options collection.");
+mySelect.options[0].selected = false;
+optionsLength = mySelect.options.length;
+selectedOptions = deepCopy(mySelect.selectedOptions);
+shouldBe("optionsLength", "4");
+shouldBe("selectedOptions.length", "1");
+shouldBe("selectedOptions[0].text", "'five'");
+
+debug((++i) + ") Remove an option unselected should not update the selected options collection.");
+mySelect.remove(0);
+selectedOptionsLength = mySelect.selectedOptions.length;
+optionsLength = mySelect.options.length;
+selectedOptions = deepCopy(mySelect.selectedOptions);
+shouldBe("optionsLength", "3");
+shouldBe("selectedOptions.length", "1");
+shouldBe("selectedOptions[0].text", "'five'");
+
+debug((++i) + ") Remove an option selected should update the selected options collection.");
+mySelect.remove(2);
+optionsLength = mySelect.options.length;
+selectedOptions = deepCopy(mySelect.selectedOptions);
+shouldBe("optionsLength", "2");
+shouldBe("selectedOptions.length", "0");
+
+mySelect.options[0].selected = true;
+mySelect.options[1].selected = true;
+debug((++i) + ") Change multiple attribute to false should update selectedOptions.");
+mySelect.multiple = false;
+optionsLength = mySelect.options.length;
+selectedOptions = deepCopy(mySelect.selectedOptions);
+shouldBe("optionsLength", "2");
+shouldBe("selectedOptions.length", "1");
+shouldBe("selectedOptions[0].text", "'two'");
+
+reset(mySelect);
+debug((++i) + ") Even with an option disabled selectedOptions should be updated.");
+mySelect.options[0].disabled = true;
+mySelect.options[0].selected = true;
+optionsLength = mySelect.options.length;
+selectedOptions = deepCopy(mySelect.selectedOptions);
+shouldBe("optionsLength", "2");
+shouldBe("selectedOptions.length", "1");
+shouldBe("selectedOptions[0].text", "'one'");
+
+debug((++i) + ") Even with select element disabled, the selectedOptions should be updated.");
+mySelect.disabled = true;
+mySelect.options[1].selected = true;
+optionsLength = mySelect.options.length;
+selectedOptions = deepCopy(mySelect.selectedOptions);
+shouldBe("optionsLength", "2");
+shouldBe("selectedOptions.length", "2");
+shouldBe("selectedOptions[0].text", "'one'");
+shouldBe("selectedOptions[1].text", "'two'");
+
+debug("");
+</script>
+<script src=""
Modified: trunk/LayoutTests/fast/dom/htmlcollection-non-html-expected.txt (121391 => 121392)
--- trunk/LayoutTests/fast/dom/htmlcollection-non-html-expected.txt 2012-06-28 00:49:55 UTC (rev 121391)
+++ trunk/LayoutTests/fast/dom/htmlcollection-non-html-expected.txt 2012-06-28 01:05:27 UTC (rev 121392)
@@ -4,6 +4,7 @@
PASS select.options.length is 0
+PASS select.selectedOptions.length is 0
PASS select.options.length is 1
PASS document.images.length is 0
PASS document.images.length is 1
Modified: trunk/LayoutTests/fast/dom/htmlcollection-non-html.html (121391 => 121392)
--- trunk/LayoutTests/fast/dom/htmlcollection-non-html.html 2012-06-28 00:49:55 UTC (rev 121391)
+++ trunk/LayoutTests/fast/dom/htmlcollection-non-html.html 2012-06-28 01:05:27 UTC (rev 121392)
@@ -67,6 +67,7 @@
elem = document.createElementNS(ns, "option");
select.appendChild(elem);
shouldBe("select.options.length", "0");
+ shouldBe("select.selectedOptions.length", "0");
elem = document.createElement("option");
select.appendChild(elem);
Modified: trunk/Source/WebCore/ChangeLog (121391 => 121392)
--- trunk/Source/WebCore/ChangeLog 2012-06-28 00:49:55 UTC (rev 121391)
+++ trunk/Source/WebCore/ChangeLog 2012-06-28 01:05:27 UTC (rev 121392)
@@ -1,3 +1,41 @@
+2012-06-27 Alexis Menard <alexis.men...@openbossa.org>
+
+ Implement selectedOptions attribute of HTMLSelectElement.
+ https://bugs.webkit.org/show_bug.cgi?id=80631
+
+ Reviewed by Ryosuke Niwa.
+
+ Add a new collection as a member of HTMLSelectElement which is
+ used to store the selected elements. Extend HTMLCollection to
+ support the new collection type needed by this feature. Make sure
+ that we invalidate the collection when the select state of an
+ option changes as the select state change does not trigger a dom
+ tree version change.
+
+ Reference : http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html#dom-select-selectedoptions
+
+ Test: fast/dom/HTMLSelectElement/select-selectedOptions.html
+
+ * html/CollectionType.h:
+ * html/HTMLCollection.cpp:
+ (WebCore::shouldIncludeChildren):
+ (WebCore::HTMLCollection::clearCache):
+ (WebCore):
+ (WebCore::HTMLCollection::isAcceptableElement):
+ * html/HTMLCollection.h:
+ (HTMLCollection):
+ * html/HTMLOptionElement.cpp:
+ (WebCore::HTMLOptionElement::setSelectedState):
+ * html/HTMLSelectElement.cpp:
+ (WebCore::HTMLSelectElement::selectedOptions):
+ (WebCore):
+ (WebCore::HTMLSelectElement::invalidateSelectedItems):
+ (WebCore::HTMLSelectElement::setRecalcListItems):
+ * html/HTMLSelectElement.h:
+ (WebCore):
+ (HTMLSelectElement):
+ * html/HTMLSelectElement.idl:
+
2012-06-27 Daniel Cheng <dch...@chromium.org>
Fix crash in Frame::nodeImage.
Modified: trunk/Source/WebCore/html/CollectionType.h (121391 => 121392)
--- trunk/Source/WebCore/html/CollectionType.h 2012-06-28 00:49:55 UTC (rev 121391)
+++ trunk/Source/WebCore/html/CollectionType.h 2012-06-28 01:05:27 UTC (rev 121392)
@@ -51,6 +51,7 @@
TSectionRows, // all row elements in this table section
TRCells, // all cells in this row
SelectOptions,
+ SelectedOptions,
DataListOptions,
MapAreas,
Modified: trunk/Source/WebCore/html/HTMLCollection.cpp (121391 => 121392)
--- trunk/Source/WebCore/html/HTMLCollection.cpp 2012-06-28 00:49:55 UTC (rev 121391)
+++ trunk/Source/WebCore/html/HTMLCollection.cpp 2012-06-28 01:05:27 UTC (rev 121392)
@@ -52,6 +52,7 @@
case MapAreas:
case OtherCollection:
case SelectOptions:
+ case SelectedOptions:
case DataListOptions:
case WindowNamedItems:
#if ENABLE(MICRODATA)
@@ -98,6 +99,11 @@
m_cache.version = docversion;
}
+void HTMLCollection::clearCache()
+{
+ m_cache.clear();
+}
+
inline bool HTMLCollection::isAcceptableElement(Element* element) const
{
if (!element->isHTMLElement() && !(m_type == DocAll || m_type == NodeChildren))
@@ -118,6 +124,8 @@
return element->hasLocalName(trTag);
case SelectOptions:
return element->hasLocalName(optionTag);
+ case SelectedOptions:
+ return element->hasLocalName(optionTag) && toHTMLOptionElement(element)->selected();
case DataListOptions:
if (element->hasLocalName(optionTag)) {
HTMLOptionElement* option = static_cast<HTMLOptionElement*>(element);
Modified: trunk/Source/WebCore/html/HTMLCollection.h (121391 => 121392)
--- trunk/Source/WebCore/html/HTMLCollection.h 2012-06-28 00:49:55 UTC (rev 121391)
+++ trunk/Source/WebCore/html/HTMLCollection.h 2012-06-28 01:05:27 UTC (rev 121392)
@@ -67,11 +67,11 @@
Node* base() const { return m_base; }
CollectionType type() const { return static_cast<CollectionType>(m_type); }
+ void clearCache();
+ void invalidateCacheIfNeeded() const;
protected:
HTMLCollection(Node* base, CollectionType);
- void invalidateCacheIfNeeded() const;
-
virtual void updateNameCache() const;
virtual Element* itemAfter(Element*) const;
Modified: trunk/Source/WebCore/html/HTMLOptionElement.cpp (121391 => 121392)
--- trunk/Source/WebCore/html/HTMLOptionElement.cpp 2012-06-28 00:49:55 UTC (rev 121391)
+++ trunk/Source/WebCore/html/HTMLOptionElement.cpp 2012-06-28 01:05:27 UTC (rev 121392)
@@ -245,6 +245,9 @@
m_isSelected = selected;
setNeedsStyleRecalc();
+
+ if (HTMLSelectElement* select = ownerSelectElement())
+ select->invalidateSelectedItems();
}
void HTMLOptionElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
Modified: trunk/Source/WebCore/html/HTMLSelectElement.cpp (121391 => 121392)
--- trunk/Source/WebCore/html/HTMLSelectElement.cpp 2012-06-28 00:49:55 UTC (rev 121391)
+++ trunk/Source/WebCore/html/HTMLSelectElement.cpp 2012-06-28 01:05:27 UTC (rev 121392)
@@ -350,6 +350,13 @@
return childContext.isOnUpperEncapsulationBoundary() && HTMLFormControlElementWithState::childShouldCreateRenderer(childContext);
}
+HTMLCollection* HTMLSelectElement::selectedOptions()
+{
+ if (!m_selectedOptionsCollection)
+ m_selectedOptionsCollection = HTMLCollection::create(this, SelectedOptions);
+ return m_selectedOptionsCollection.get();
+}
+
HTMLOptionsCollection* HTMLSelectElement::options()
{
if (!m_optionsCollection)
@@ -700,6 +707,12 @@
return m_listItems;
}
+void HTMLSelectElement::invalidateSelectedItems()
+{
+ if (m_selectedOptionsCollection)
+ m_selectedOptionsCollection->clearCache();
+}
+
void HTMLSelectElement::setRecalcListItems()
{
m_shouldRecalcListItems = true;
@@ -709,6 +722,8 @@
setNeedsStyleRecalc();
if (!inDocument() && m_optionsCollection)
m_optionsCollection->invalidateCacheIfNeeded();
+ if (!inDocument() && m_selectedOptionsCollection)
+ m_selectedOptionsCollection->invalidateCacheIfNeeded();
}
void HTMLSelectElement::recalcListItems(bool updateSelectedStates) const
Modified: trunk/Source/WebCore/html/HTMLSelectElement.h (121391 => 121392)
--- trunk/Source/WebCore/html/HTMLSelectElement.h 2012-06-28 00:49:55 UTC (rev 121391)
+++ trunk/Source/WebCore/html/HTMLSelectElement.h 2012-06-28 01:05:27 UTC (rev 121392)
@@ -34,7 +34,6 @@
namespace WebCore {
class HTMLOptionElement;
-class HTMLOptionsCollection;
class HTMLSelectElement : public HTMLFormControlElementWithState {
public:
@@ -64,10 +63,12 @@
void setValue(const String&);
HTMLOptionsCollection* options();
+ HTMLCollection* selectedOptions();
void optionElementChildrenChanged();
void setRecalcListItems();
+ void invalidateSelectedItems();
void updateListItemSelectedStates();
const Vector<HTMLElement*>& listItems() const;
@@ -180,6 +181,7 @@
virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
OwnPtr<HTMLOptionsCollection> m_optionsCollection;
+ OwnPtr<HTMLCollection> m_selectedOptionsCollection;
// m_listItems contains HTMLOptionElement, HTMLOptGroupElement, and HTMLHRElement objects.
mutable Vector<HTMLElement*> m_listItems;
Modified: trunk/Source/WebCore/html/HTMLSelectElement.idl (121391 => 121392)
--- trunk/Source/WebCore/html/HTMLSelectElement.idl 2012-06-28 00:49:55 UTC (rev 121391)
+++ trunk/Source/WebCore/html/HTMLSelectElement.idl 2012-06-28 01:05:27 UTC (rev 121392)
@@ -53,6 +53,7 @@
#else
void remove(in long index);
#endif
+ readonly attribute HTMLCollection selectedOptions;
attribute long selectedIndex;
attribute [TreatNullAs=NullString] DOMString value;