• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 "JSHTMLCollection.h"
22 
23 #include "AtomicString.h"
24 #include "HTMLCollection.h"
25 #include "HTMLOptionsCollection.h"
26 #include "JSHTMLAllCollection.h"
27 #include "JSHTMLOptionsCollection.h"
28 #include "JSNamedNodesCollection.h"
29 #include "JSNode.h"
30 #include "Node.h"
31 #include "JSDOMBinding.h"
32 #include <wtf/Vector.h>
33 
34 using namespace JSC;
35 
36 namespace WebCore {
37 
getNamedItems(ExecState * exec,JSHTMLCollection * collection,const Identifier & propertyName)38 static JSValue getNamedItems(ExecState* exec, JSHTMLCollection* collection, const Identifier& propertyName)
39 {
40     Vector<RefPtr<Node> > namedItems;
41     collection->impl()->namedItems(propertyName, namedItems);
42 
43     if (namedItems.isEmpty())
44         return jsUndefined();
45 
46     if (namedItems.size() == 1)
47         return toJS(exec, collection->globalObject(), namedItems[0].get());
48 
49     return new (exec) JSNamedNodesCollection(exec, collection->globalObject(), namedItems);
50 }
51 
52 // HTMLCollections are strange objects, they support both get and call,
53 // so that document.forms.item(0) and document.forms(0) both work.
callHTMLCollection(ExecState * exec,JSObject * function,JSValue,const ArgList & args)54 static JSValue JSC_HOST_CALL callHTMLCollection(ExecState* exec, JSObject* function, JSValue, const ArgList& args)
55 {
56     if (args.size() < 1)
57         return jsUndefined();
58 
59     // Do not use thisObj here. It can be the JSHTMLDocument, in the document.forms(i) case.
60     JSHTMLCollection* jsCollection = static_cast<JSHTMLCollection*>(function);
61     HTMLCollection* collection = jsCollection->impl();
62 
63     // Also, do we need the TypeError test here ?
64 
65     if (args.size() == 1) {
66         // Support for document.all(<index>) etc.
67         bool ok;
68         UString string = args.at(0).toString(exec);
69         unsigned index = string.toUInt32(&ok, false);
70         if (ok)
71             return toJS(exec, jsCollection->globalObject(), collection->item(index));
72 
73         // Support for document.images('<name>') etc.
74         return getNamedItems(exec, jsCollection, Identifier(exec, string));
75     }
76 
77     // The second arg, if set, is the index of the item we want
78     bool ok;
79     UString string = args.at(0).toString(exec);
80     unsigned index = args.at(1).toString(exec).toUInt32(&ok, false);
81     if (ok) {
82         String pstr = string;
83         Node* node = collection->namedItem(pstr);
84         while (node) {
85             if (!index)
86                 return toJS(exec, jsCollection->globalObject(), node);
87             node = collection->nextNamedItem(pstr);
88             --index;
89         }
90     }
91 
92     return jsUndefined();
93 }
94 
getCallData(CallData & callData)95 CallType JSHTMLCollection::getCallData(CallData& callData)
96 {
97     callData.native.function = callHTMLCollection;
98     return CallTypeHost;
99 }
100 
canGetItemsForName(ExecState *,HTMLCollection * collection,const Identifier & propertyName)101 bool JSHTMLCollection::canGetItemsForName(ExecState*, HTMLCollection* collection, const Identifier& propertyName)
102 {
103     Vector<RefPtr<Node> > namedItems;
104     collection->namedItems(propertyName, namedItems);
105     return !namedItems.isEmpty();
106 }
107 
nameGetter(ExecState * exec,const Identifier & propertyName,const PropertySlot & slot)108 JSValue JSHTMLCollection::nameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
109 {
110     JSHTMLCollection* thisObj = static_cast<JSHTMLCollection*>(asObject(slot.slotBase()));
111     return getNamedItems(exec, thisObj, propertyName);
112 }
113 
item(ExecState * exec,const ArgList & args)114 JSValue JSHTMLCollection::item(ExecState* exec, const ArgList& args)
115 {
116     bool ok;
117     uint32_t index = args.at(0).toString(exec).toUInt32(&ok, false);
118     if (ok)
119         return toJS(exec, globalObject(), impl()->item(index));
120     return getNamedItems(exec, this, Identifier(exec, args.at(0).toString(exec)));
121 }
122 
namedItem(ExecState * exec,const ArgList & args)123 JSValue JSHTMLCollection::namedItem(ExecState* exec, const ArgList& args)
124 {
125     return getNamedItems(exec, this, Identifier(exec, args.at(0).toString(exec)));
126 }
127 
toJS(ExecState * exec,JSDOMGlobalObject * globalObject,HTMLCollection * collection)128 JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, HTMLCollection* collection)
129 {
130     if (!collection)
131         return jsNull();
132 
133     DOMObject* wrapper = getCachedDOMObjectWrapper(exec->globalData(), collection);
134 
135     if (wrapper)
136         return wrapper;
137 
138     switch (collection->type()) {
139         case SelectOptions:
140             wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, HTMLOptionsCollection, collection);
141             break;
142         case DocAll:
143             typedef HTMLCollection HTMLAllCollection;
144             wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, HTMLAllCollection, collection);
145             break;
146         default:
147             wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, HTMLCollection, collection);
148             break;
149     }
150 
151     return wrapper;
152 }
153 
154 } // namespace WebCore
155