18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is free software; you can redistribute it and/or
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modify it under the terms of the GNU Library General Public
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * License as published by the Free Software Foundation; either
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * version 2 of the License, or (at your option) any later version.
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is distributed in the hope that it will be useful,
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Library General Public License for more details.
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * You should have received a copy of the GNU Library General Public License
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * along with this library; see the file COPYING.LIB.  If not, write to
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Boston, MA 02110-1301, USA.
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "JSHTMLCollection.h"
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLCollection.h"
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLOptionsCollection.h"
25cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#include "HTMLAllCollection.h"
26231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "JSDOMBinding.h"
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "JSHTMLAllCollection.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "JSHTMLOptionsCollection.h"
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "JSNode.h"
30231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "JSNodeList.h"
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Node.h"
32231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "StaticNodeList.h"
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/Vector.h>
34f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick#include <wtf/text/AtomicString.h>
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace JSC;
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic JSValue getNamedItems(ExecState* exec, JSHTMLCollection* collection, const Identifier& propertyName)
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Vector<RefPtr<Node> > namedItems;
43dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    collection->impl()->namedItems(identifierToAtomicString(propertyName), namedItems);
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (namedItems.isEmpty())
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return jsUndefined();
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (namedItems.size() == 1)
480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return toJS(exec, collection->globalObject(), namedItems[0].get());
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
50231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // FIXME: HTML5 specifies that this should be a DynamicNodeList.
51231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // FIXME: HTML5 specifies that non-HTMLOptionsCollection collections should return
52231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // the first matching item instead of a NodeList.
53231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return toJS(exec, collection->globalObject(), StaticNodeList::adopt(namedItems).get());
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// HTMLCollections are strange objects, they support both get and call,
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// so that document.forms.item(0) and document.forms(0) both work.
58545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdochstatic EncodedJSValue JSC_HOST_CALL callHTMLCollection(ExecState* exec)
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
605af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    if (exec->argumentCount() < 1)
61545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch        return JSValue::encode(jsUndefined());
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Do not use thisObj here. It can be the JSHTMLDocument, in the document.forms(i) case.
645af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    JSHTMLCollection* jsCollection = static_cast<JSHTMLCollection*>(exec->callee());
650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    HTMLCollection* collection = jsCollection->impl();
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Also, do we need the TypeError test here ?
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
695af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    if (exec->argumentCount() == 1) {
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Support for document.all(<index>) etc.
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        bool ok;
725af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        UString string = exec->argument(0).toString(exec);
73f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        unsigned index = Identifier::toUInt32(string, ok);
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (ok)
75545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch            return JSValue::encode(toJS(exec, jsCollection->globalObject(), collection->item(index)));
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Support for document.images('<name>') etc.
78545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch        return JSValue::encode(getNamedItems(exec, jsCollection, Identifier(exec, string)));
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // The second arg, if set, is the index of the item we want
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool ok;
835af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    UString string = exec->argument(0).toString(exec);
84f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unsigned index = Identifier::toUInt32(exec->argument(1).toString(exec), ok);
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (ok) {
86dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        String pstr = ustringToString(string);
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Node* node = collection->namedItem(pstr);
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        while (node) {
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (!index)
90545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch                return JSValue::encode(toJS(exec, jsCollection->globalObject(), node));
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            node = collection->nextNamedItem(pstr);
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            --index;
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
96545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    return JSValue::encode(jsUndefined());
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectCallType JSHTMLCollection::getCallData(CallData& callData)
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    callData.native.function = callHTMLCollection;
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return CallTypeHost;
1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochbool JSHTMLCollection::canGetItemsForName(ExecState*, HTMLCollection* collection, const Identifier& propertyName)
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    Vector<RefPtr<Node> > namedItems;
108dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    collection->namedItems(identifierToAtomicString(propertyName), namedItems);
1090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return !namedItems.isEmpty();
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
112dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockJSValue JSHTMLCollection::nameGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName)
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
114dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    JSHTMLCollection* thisObj = static_cast<JSHTMLCollection*>(asObject(slotBase));
1150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return getNamedItems(exec, thisObj, propertyName);
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1185af96e2c7b73ebc627c6894727826a7576d31758Leon ClarkeJSValue JSHTMLCollection::item(ExecState* exec)
1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool ok;
121f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    uint32_t index = Identifier::toUInt32(exec->argument(0).toString(exec), ok);
1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (ok)
1230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return toJS(exec, globalObject(), impl()->item(index));
1245af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    return getNamedItems(exec, this, Identifier(exec, exec->argument(0).toString(exec)));
1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1275af96e2c7b73ebc627c6894727826a7576d31758Leon ClarkeJSValue JSHTMLCollection::namedItem(ExecState* exec)
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1295af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    return getNamedItems(exec, this, Identifier(exec, exec->argument(0).toString(exec)));
1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochJSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, HTMLCollection* collection)
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!collection)
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return jsNull();
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), collection);
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (wrapper)
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return wrapper;
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    switch (collection->type()) {
1435f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        case SelectOptions:
1440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, HTMLOptionsCollection, collection);
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
1465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        case DocAll:
1470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, HTMLAllCollection, collection);
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        default:
1500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, HTMLCollection, collection);
1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return wrapper;
1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace WebCore
158