48d23649a79ff6e9a769b20bb4ca32e9541bc4b1
[WebKit-https.git] / Source / WebCore / bindings / js / JSHTMLOptionsCollectionCustom.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #include "config.h"
21 #include "JSHTMLOptionsCollection.h"
22
23 #include "ExceptionCode.h"
24 #include "HTMLNames.h"
25 #include "HTMLOptionElement.h"
26 #include "HTMLOptionsCollection.h"
27 #include "HTMLSelectElement.h"
28 #include "JSHTMLOptionElement.h"
29 #include "JSHTMLSelectElement.h"
30 #include "JSHTMLSelectElementCustom.h"
31 #include "JSNodeList.h"
32 #include "StaticNodeList.h"
33
34 #include <wtf/MathExtras.h>
35
36 using namespace JSC;
37
38 namespace WebCore {
39
40 static JSValue getNamedItems(ExecState* exec, JSHTMLOptionsCollection* collection, PropertyName propertyName)
41 {
42     Vector<RefPtr<Node> > namedItems;
43     const AtomicString& name = propertyNameToAtomicString(propertyName);
44     collection->impl()->namedItems(name, namedItems);
45
46     if (namedItems.isEmpty())
47         return jsUndefined();
48     if (namedItems.size() == 1)
49         return toJS(exec, collection->globalObject(), namedItems[0].get());
50
51     // FIXME: HTML5 specifies that this should be a LiveNodeList.
52     return toJS(exec, collection->globalObject(), StaticNodeList::adopt(namedItems).get());
53 }
54
55 bool JSHTMLOptionsCollection::canGetItemsForName(ExecState*, HTMLOptionsCollection* collection, PropertyName propertyName)
56 {
57     return collection->hasNamedItem(propertyNameToAtomicString(propertyName));
58 }
59
60 JSValue JSHTMLOptionsCollection::nameGetter(ExecState* exec, JSValue slotBase, PropertyName propertyName)
61 {
62     JSHTMLOptionsCollection* thisObj = jsCast<JSHTMLOptionsCollection*>(asObject(slotBase));
63     return getNamedItems(exec, thisObj, propertyName);
64 }
65
66 JSValue JSHTMLOptionsCollection::namedItem(ExecState* exec)
67 {
68     JSValue value = getNamedItems(exec, this, Identifier(exec, exec->argument(0).toString(exec)->value(exec)));
69     return value.isUndefined() ? jsNull() : value;
70 }
71
72 void JSHTMLOptionsCollection::setLength(ExecState* exec, JSValue value)
73 {
74     HTMLOptionsCollection* imp = static_cast<HTMLOptionsCollection*>(impl());
75     ExceptionCode ec = 0;
76     unsigned newLength = 0;
77     double lengthValue = value.toNumber(exec);
78     if (!std::isnan(lengthValue) && !std::isinf(lengthValue)) {
79         if (lengthValue < 0.0)
80             ec = INDEX_SIZE_ERR;
81         else if (lengthValue > static_cast<double>(UINT_MAX))
82             newLength = UINT_MAX;
83         else
84             newLength = static_cast<unsigned>(lengthValue);
85     }
86     if (!ec)
87         imp->setLength(newLength, ec);
88     setDOMException(exec, ec);
89 }
90
91 void JSHTMLOptionsCollection::indexSetter(ExecState* exec, unsigned index, JSValue value)
92 {
93     HTMLOptionsCollection* imp = static_cast<HTMLOptionsCollection*>(impl());
94     HTMLSelectElement* base = toHTMLSelectElement(imp->ownerNode());
95     selectIndexSetter(base, exec, index, value);
96 }
97
98 JSValue JSHTMLOptionsCollection::add(ExecState* exec)
99 {
100     HTMLOptionsCollection* imp = static_cast<HTMLOptionsCollection*>(impl());
101     HTMLOptionElement* option = toHTMLOptionElement(exec->argument(0));
102     ExceptionCode ec = 0;
103     if (exec->argumentCount() < 2)
104         imp->add(option, ec);
105     else {
106         int index = exec->argument(1).toInt32(exec);
107         if (exec->hadException())
108             return jsUndefined();
109         imp->add(option, index, ec);
110     }
111     setDOMException(exec, ec);
112     return jsUndefined();
113 }
114
115 JSValue JSHTMLOptionsCollection::remove(ExecState* exec)
116 {
117     HTMLOptionsCollection* imp = static_cast<HTMLOptionsCollection*>(impl());
118     JSHTMLSelectElement* base = jsCast<JSHTMLSelectElement*>(asObject(toJS(exec, globalObject(), imp->ownerNode())));
119     return base->remove(exec);
120 }
121
122 }