Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / html / HTMLOptionsCollection.cpp
index 94c808c..fdf20fe 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2006, 2011, 2012 Apple Computer, Inc.
+ * Copyright (C) 2014 Samsung Electronics. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -21,6 +22,7 @@
 #include "config.h"
 #include "core/html/HTMLOptionsCollection.h"
 
+#include "bindings/v8/ExceptionMessages.h"
 #include "bindings/v8/ExceptionState.h"
 #include "core/dom/ExceptionCode.h"
 #include "core/dom/NamedNodesCollection.h"
 
 namespace WebCore {
 
-HTMLOptionsCollection::HTMLOptionsCollection(Node* select)
+HTMLOptionsCollection::HTMLOptionsCollection(ContainerNode& select)
     : HTMLCollection(select, SelectOptions, DoesNotOverrideItemAfter)
 {
-    ASSERT(select->hasTagName(HTMLNames::selectTag));
+    ASSERT(isHTMLSelectElement(select));
     ScriptWrappable::init(this);
 }
 
-PassRefPtr<HTMLOptionsCollection> HTMLOptionsCollection::create(Node* select, CollectionType)
+void HTMLOptionsCollection::supportedPropertyNames(Vector<String>& names)
+{
+    // As per http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#htmloptionscollection:
+    // The supported property names consist of the non-empty values of all the id and name attributes of all the elements
+    // represented by the collection, in tree order, ignoring later duplicates, with the id of an element preceding its
+    // name if it contributes both, they differ from each other, and neither is the duplicate of an earlier entry.
+    HashSet<AtomicString> existingNames;
+    unsigned length = this->length();
+    for (unsigned i = 0; i < length; ++i) {
+        Element* element = item(i);
+        ASSERT(element);
+        const AtomicString& idAttribute = element->getIdAttribute();
+        if (!idAttribute.isEmpty()) {
+            HashSet<AtomicString>::AddResult addResult = existingNames.add(idAttribute);
+            if (addResult.isNewEntry)
+                names.append(idAttribute);
+        }
+        const AtomicString& nameAttribute = element->getNameAttribute();
+        if (!nameAttribute.isEmpty()) {
+            HashSet<AtomicString>::AddResult addResult = existingNames.add(nameAttribute);
+            if (addResult.isNewEntry)
+                names.append(nameAttribute);
+        }
+    }
+}
+
+PassRefPtr<HTMLOptionsCollection> HTMLOptionsCollection::create(ContainerNode& select, CollectionType)
 {
     return adoptRef(new HTMLOptionsCollection(select));
 }
 
-void HTMLOptionsCollection::add(PassRefPtr<HTMLOptionElement> element, ExceptionState& es)
+void HTMLOptionsCollection::add(PassRefPtrWillBeRawPtr<HTMLOptionElement> element, ExceptionState& exceptionState)
 {
-    add(element, length(), es);
+    add(element, length(), exceptionState);
 }
 
-void HTMLOptionsCollection::add(PassRefPtr<HTMLOptionElement> element, int index, ExceptionState& es)
+void HTMLOptionsCollection::add(PassRefPtrWillBeRawPtr<HTMLOptionElement> element, int index, ExceptionState& exceptionState)
 {
     HTMLOptionElement* newOption = element.get();
 
     if (!newOption) {
-        es.throwUninformativeAndGenericDOMException(TypeMismatchError);
+        exceptionState.throwTypeError("The element provided was not an HTMLOptionElement.");
         return;
     }
 
     if (index < -1) {
-        es.throwUninformativeAndGenericDOMException(IndexSizeError);
+        exceptionState.throwDOMException(IndexSizeError, "The index provided (" + String::number(index) + ") is less than -1.");
         return;
     }
 
-    HTMLSelectElement* select = toHTMLSelectElement(ownerNode());
+    HTMLSelectElement& select = toHTMLSelectElement(ownerNode());
 
     if (index == -1 || unsigned(index) >= length())
-        select->add(newOption, 0, es);
+        select.add(newOption, 0, exceptionState);
     else
-        select->add(newOption, toHTMLOptionElement(item(index)), es);
+        select.addBeforeOptionAtIndex(newOption, index, exceptionState);
 
-    ASSERT(!es.hadException());
+    ASSERT(!exceptionState.hadException());
 }
 
 void HTMLOptionsCollection::remove(int index)
 {
-    toHTMLSelectElement(ownerNode())->remove(index);
+    toHTMLSelectElement(ownerNode()).remove(index);
 }
 
 void HTMLOptionsCollection::remove(HTMLOptionElement* option)
@@ -82,22 +110,22 @@ void HTMLOptionsCollection::remove(HTMLOptionElement* option)
 
 int HTMLOptionsCollection::selectedIndex() const
 {
-    return toHTMLSelectElement(ownerNode())->selectedIndex();
+    return toHTMLSelectElement(ownerNode()).selectedIndex();
 }
 
 void HTMLOptionsCollection::setSelectedIndex(int index)
 {
-    toHTMLSelectElement(ownerNode())->setSelectedIndex(index);
+    toHTMLSelectElement(ownerNode()).setSelectedIndex(index);
 }
 
-void HTMLOptionsCollection::setLength(unsigned length, ExceptionState& es)
+void HTMLOptionsCollection::setLength(unsigned length, ExceptionState& exceptionState)
 {
-    toHTMLSelectElement(ownerNode())->setLength(length, es);
+    toHTMLSelectElement(ownerNode()).setLength(length, exceptionState);
 }
 
-void HTMLOptionsCollection::anonymousNamedGetter(const AtomicString& name, bool& returnValue0Enabled, RefPtr<NodeList>& returnValue0, bool& returnValue1Enabled, RefPtr<Node>& returnValue1)
+void HTMLOptionsCollection::namedGetter(const AtomicString& name, bool& returnValue0Enabled, RefPtr<NodeList>& returnValue0, bool& returnValue1Enabled, RefPtr<Element>& returnValue1)
 {
-    Vector<RefPtr<Node> > namedItems;
+    Vector<RefPtr<Element> > namedItems;
     this->namedItems(name, namedItems);
 
     if (!namedItems.size())
@@ -109,25 +137,19 @@ void HTMLOptionsCollection::anonymousNamedGetter(const AtomicString& name, bool&
         return;
     }
 
+    // FIXME: The spec and Firefox do not return a NodeList. They always return the first matching Element.
     returnValue0Enabled = true;
     returnValue0 = NamedNodesCollection::create(namedItems);
 }
 
-bool HTMLOptionsCollection::anonymousIndexedSetterRemove(unsigned index, ExceptionState& es)
-{
-    HTMLSelectElement* base = toHTMLSelectElement(ownerNode());
-    base->remove(index);
-    return true;
-}
-
-bool HTMLOptionsCollection::anonymousIndexedSetter(unsigned index, PassRefPtr<HTMLOptionElement> value, ExceptionState& es)
+bool HTMLOptionsCollection::anonymousIndexedSetter(unsigned index, PassRefPtrWillBeRawPtr<HTMLOptionElement> value, ExceptionState& exceptionState)
 {
-    HTMLSelectElement* base = toHTMLSelectElement(ownerNode());
-    if (!value) {
-        es.throwUninformativeAndGenericDOMException(TypeMismatchError);
+    HTMLSelectElement& base = toHTMLSelectElement(ownerNode());
+    if (!value) { // undefined or null
+        base.remove(index);
         return true;
     }
-    base->setOption(index, value.get(), es);
+    base.setOption(index, value.get(), exceptionState);
     return true;
 }