1cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block/* 2cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * Copyright (C) 2009 Apple Inc. All rights reserved. 3cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * 4cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * Redistribution and use in source and binary forms, with or without 5cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * modification, are permitted provided that the following conditions 6cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * are met: 7cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * 1. Redistributions of source code must retain the above copyright 8cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * notice, this list of conditions and the following disclaimer. 9cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * 2. Redistributions in binary form must reproduce the above copyright 10cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * notice, this list of conditions and the following disclaimer in the 11cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * documentation and/or other materials provided with the distribution. 12cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * 13cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block */ 25cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block 26cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#include "config.h" 27cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#include "JSHTMLAllCollection.h" 28cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block 29cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#include "HTMLAllCollection.h" 30cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#include "JSDOMBinding.h" 31cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#include "JSHTMLAllCollection.h" 32cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#include "JSNode.h" 33cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#include "JSNodeList.h" 34cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#include "Node.h" 35cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#include "StaticNodeList.h" 36545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch#include <runtime/JSValue.h> 37cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#include <wtf/Vector.h> 38f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick#include <wtf/text/AtomicString.h> 39cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block 40cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Blockusing namespace JSC; 41cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block 42cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Blocknamespace WebCore { 43cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block 44cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Blockstatic JSValue getNamedItems(ExecState* exec, JSHTMLAllCollection* collection, const Identifier& propertyName) 45cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block{ 46cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block Vector<RefPtr<Node> > namedItems; 47dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block collection->impl()->namedItems(identifierToAtomicString(propertyName), namedItems); 48cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block 49cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block if (namedItems.isEmpty()) 50cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block return jsUndefined(); 51cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block if (namedItems.size() == 1) 52cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block return toJS(exec, collection->globalObject(), namedItems[0].get()); 53cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block 54cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block // FIXME: HTML5 specifies that this should be a DynamicNodeList. 55cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block // FIXME: HTML5 specifies that non-HTMLOptionsCollection collections should return 56cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block // the first matching item instead of a NodeList. 57cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block return toJS(exec, collection->globalObject(), StaticNodeList::adopt(namedItems).get()); 58cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block} 59cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block 60cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block// HTMLCollections are strange objects, they support both get and call, 61cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block// so that document.forms.item(0) and document.forms(0) both work. 62545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdochstatic EncodedJSValue JSC_HOST_CALL callHTMLAllCollection(ExecState* exec) 63cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block{ 645af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke if (exec->argumentCount() < 1) 65545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch return JSValue::encode(jsUndefined()); 66cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block 67cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block // Do not use thisObj here. It can be the JSHTMLDocument, in the document.forms(i) case. 685af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke JSHTMLAllCollection* jsCollection = static_cast<JSHTMLAllCollection*>(exec->callee()); 69cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block HTMLAllCollection* collection = static_cast<HTMLAllCollection*>(jsCollection->impl()); 70cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block 71cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block // Also, do we need the TypeError test here ? 72cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block 735af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke if (exec->argumentCount() == 1) { 74cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block // Support for document.all(<index>) etc. 75cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block bool ok; 765af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke UString string = exec->argument(0).toString(exec); 77f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned index = Identifier::toUInt32(string, ok); 78cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block if (ok) 79545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch return JSValue::encode(toJS(exec, jsCollection->globalObject(), collection->item(index))); 80cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block 81cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block // Support for document.images('<name>') etc. 82545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch return JSValue::encode(getNamedItems(exec, jsCollection, Identifier(exec, string))); 83cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block } 84cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block 85cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block // The second arg, if set, is the index of the item we want 86cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block bool ok; 875af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke UString string = exec->argument(0).toString(exec); 88f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned index = Identifier::toUInt32(exec->argument(1).toString(exec), ok); 89cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block if (ok) { 90dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block String pstr = ustringToString(string); 91cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block Node* node = collection->namedItem(pstr); 92cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block while (node) { 93cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block if (!index) 94545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch return JSValue::encode(toJS(exec, jsCollection->globalObject(), node)); 95cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block node = collection->nextNamedItem(pstr); 96cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block --index; 97cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block } 98cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block } 99cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block 100545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch return JSValue::encode(jsUndefined()); 101cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block} 102cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block 103cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve BlockCallType JSHTMLAllCollection::getCallData(CallData& callData) 104cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block{ 105cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block callData.native.function = callHTMLAllCollection; 106cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block return CallTypeHost; 107cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block} 108cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block 109cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Blockbool JSHTMLAllCollection::canGetItemsForName(ExecState*, HTMLAllCollection* collection, const Identifier& propertyName) 110cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block{ 111cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block Vector<RefPtr<Node> > namedItems; 112dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block collection->namedItems(identifierToAtomicString(propertyName), namedItems); 113cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block return !namedItems.isEmpty(); 114cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block} 115cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block 116dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockJSValue JSHTMLAllCollection::nameGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) 117cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block{ 118dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block JSHTMLAllCollection* thisObj = static_cast<JSHTMLAllCollection*>(asObject(slotBase)); 119cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block return getNamedItems(exec, thisObj, propertyName); 120cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block} 121cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block 1225af96e2c7b73ebc627c6894727826a7576d31758Leon ClarkeJSValue JSHTMLAllCollection::item(ExecState* exec) 123cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block{ 124cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block bool ok; 125f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick uint32_t index = Identifier::toUInt32(exec->argument(0).toString(exec), ok); 126cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block if (ok) 127cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block return toJS(exec, globalObject(), impl()->item(index)); 1285af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke return getNamedItems(exec, this, Identifier(exec, exec->argument(0).toString(exec))); 129cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block} 130cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block 1315af96e2c7b73ebc627c6894727826a7576d31758Leon ClarkeJSValue JSHTMLAllCollection::namedItem(ExecState* exec) 132cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block{ 1335af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke return getNamedItems(exec, this, Identifier(exec, exec->argument(0).toString(exec))); 134cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block} 135cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block 136cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block} // namespace WebCore 137