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