1 /* 2 * Copyright (C) 2006, 2007, 2008, 2009 Google 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 are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #ifndef V8Collection_h 32 #define V8Collection_h 33 34 #include "HTMLFormElement.h" 35 #include "HTMLSelectElement.h" 36 #include "V8Binding.h" 37 #include "V8Proxy.h" 38 #include <v8.h> 39 40 namespace WebCore { 41 // FIXME: These functions should be named using to* since they return the item (get* is used for method that take a ref param). 42 // See https://bugs.webkit.org/show_bug.cgi?id=24664. 43 getV8Object(void * implementation,v8::Local<v8::Value> implementationType)44 static v8::Handle<v8::Value> getV8Object(void* implementation, v8::Local<v8::Value> implementationType) 45 { 46 if (!implementation) 47 return v8::Handle<v8::Value>(); 48 V8ClassIndex::V8WrapperType type = V8ClassIndex::FromInt(implementationType->Int32Value()); 49 if (type == V8ClassIndex::NODE) 50 return V8DOMWrapper::convertNodeToV8Object(static_cast<Node*>(implementation)); 51 return V8DOMWrapper::convertToV8Object(type, implementation); 52 } 53 getV8Object(PassRefPtr<T> implementation,v8::Local<v8::Value> implementationType)54 template<class T> static v8::Handle<v8::Value> getV8Object(PassRefPtr<T> implementation, v8::Local<v8::Value> implementationType) 55 { 56 return getV8Object(implementation.get(), implementationType); 57 } 58 59 // Returns named property of a collection. getNamedPropertyOfCollection(v8::Local<v8::String> name,v8::Local<v8::Object> object,v8::Local<v8::Value> implementationType)60 template<class Collection, class ItemType> static v8::Handle<v8::Value> getNamedPropertyOfCollection(v8::Local<v8::String> name, v8::Local<v8::Object> object, 61 v8::Local<v8::Value> implementationType) 62 { 63 // FIXME: assert object is a collection type 64 ASSERT(V8DOMWrapper::maybeDOMWrapper(object)); 65 V8ClassIndex::V8WrapperType wrapperType = V8DOMWrapper::domWrapperType(object); 66 ASSERT(wrapperType != V8ClassIndex::NODE); 67 Collection* collection = V8DOMWrapper::convertToNativeObject<Collection>(wrapperType, object); 68 String propertyName = toWebCoreString(name); 69 return getV8Object<ItemType>(collection->namedItem(propertyName), implementationType); 70 } 71 72 // A template of named property accessor of collections. collectionNamedPropertyGetter(v8::Local<v8::String> name,const v8::AccessorInfo & info)73 template<class Collection, class ItemType> static v8::Handle<v8::Value> collectionNamedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) 74 { 75 v8::Handle<v8::Value> value = info.Holder()->GetRealNamedPropertyInPrototypeChain(name); 76 77 if (!value.IsEmpty()) 78 return value; 79 80 // Search local callback properties next to find IDL defined 81 // properties. 82 if (info.Holder()->HasRealNamedCallbackProperty(name)) 83 return notHandledByInterceptor(); 84 return getNamedPropertyOfCollection<Collection, ItemType>(name, info.Holder(), info.Data()); 85 } 86 87 // A template of named property accessor of HTMLSelectElement and HTMLFormElement. nodeCollectionNamedPropertyGetter(v8::Local<v8::String> name,const v8::AccessorInfo & info)88 template<class Collection> static v8::Handle<v8::Value> nodeCollectionNamedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) 89 { 90 ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder())); 91 ASSERT(V8DOMWrapper::domWrapperType(info.Holder()) == V8ClassIndex::NODE); 92 v8::Handle<v8::Value> value = info.Holder()->GetRealNamedPropertyInPrototypeChain(name); 93 94 if (!value.IsEmpty()) 95 return value; 96 97 // Search local callback properties next to find IDL defined 98 // properties. 99 if (info.Holder()->HasRealNamedCallbackProperty(name)) 100 return notHandledByInterceptor(); 101 Collection* collection = V8DOMWrapper::convertDOMWrapperToNode<Collection>(info.Holder()); 102 String propertyName = toWebCoreString(name); 103 void* implementation = collection->namedItem(propertyName); 104 return getV8Object(implementation, info.Data()); 105 } 106 107 // Returns the property at the index of a collection. getIndexedPropertyOfCollection(uint32_t index,v8::Local<v8::Object> object,v8::Local<v8::Value> implementationType)108 template<class Collection, class ItemType> static v8::Handle<v8::Value> getIndexedPropertyOfCollection(uint32_t index, v8::Local<v8::Object> object, 109 v8::Local<v8::Value> implementationType) 110 { 111 // FIXME: Assert that object must be a collection type. 112 ASSERT(V8DOMWrapper::maybeDOMWrapper(object)); 113 V8ClassIndex::V8WrapperType wrapperType = V8DOMWrapper::domWrapperType(object); 114 ASSERT(wrapperType != V8ClassIndex::NODE); 115 Collection* collection = V8DOMWrapper::convertToNativeObject<Collection>(wrapperType, object); 116 return getV8Object<ItemType>(collection->item(index), implementationType); 117 } 118 119 // A template of index interceptor of collections. collectionIndexedPropertyGetter(uint32_t index,const v8::AccessorInfo & info)120 template<class Collection, class ItemType> static v8::Handle<v8::Value> collectionIndexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info) 121 { 122 return getIndexedPropertyOfCollection<Collection, ItemType>(index, info.Holder(), info.Data()); 123 } 124 125 // A template of index interceptor of HTMLSelectElement and HTMLFormElement. nodeCollectionIndexedPropertyGetter(uint32_t index,const v8::AccessorInfo & info)126 template<class Collection> static v8::Handle<v8::Value> nodeCollectionIndexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info) 127 { 128 ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder())); 129 ASSERT(V8DOMWrapper::domWrapperType(info.Holder()) == V8ClassIndex::NODE); 130 Collection* collection = V8DOMWrapper::convertDOMWrapperToNode<Collection>(info.Holder()); 131 void* implementation = collection->item(index); 132 return getV8Object(implementation, info.Data()); 133 } 134 135 // Get an array containing the names of indexed properties of HTMLSelectElement and HTMLFormElement. nodeCollectionIndexedPropertyEnumerator(const v8::AccessorInfo & info)136 template<class Collection> static v8::Handle<v8::Array> nodeCollectionIndexedPropertyEnumerator(const v8::AccessorInfo& info) 137 { 138 ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder())); 139 ASSERT(V8DOMWrapper::domWrapperType(info.Holder()) == V8ClassIndex::NODE); 140 Collection* collection = V8DOMWrapper::convertDOMWrapperToNode<Collection>(info.Holder()); 141 int length = collection->length(); 142 v8::Handle<v8::Array> properties = v8::Array::New(length); 143 for (int i = 0; i < length; ++i) { 144 // FIXME: Do we need to check that the item function returns a non-null value for this index? 145 v8::Handle<v8::Integer> integer = v8::Integer::New(i); 146 properties->Set(integer, integer); 147 } 148 return properties; 149 } 150 151 // Get an array containing the names of indexed properties in a collection. collectionIndexedPropertyEnumerator(const v8::AccessorInfo & info)152 template<class Collection> static v8::Handle<v8::Array> collectionIndexedPropertyEnumerator(const v8::AccessorInfo& info) 153 { 154 ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder())); 155 V8ClassIndex::V8WrapperType wrapperType = V8DOMWrapper::domWrapperType(info.Holder()); 156 Collection* collection = V8DOMWrapper::convertToNativeObject<Collection>(wrapperType, info.Holder()); 157 int length = collection->length(); 158 v8::Handle<v8::Array> properties = v8::Array::New(length); 159 for (int i = 0; i < length; ++i) { 160 // FIXME: Do we need to check that the item function returns a non-null value for this index? 161 v8::Handle<v8::Integer> integer = v8::Integer::New(i); 162 properties->Set(integer, integer); 163 } 164 return properties; 165 } 166 167 168 // A template for indexed getters on collections of strings that should return null if the resulting string is a null string. collectionStringOrNullIndexedPropertyGetter(uint32_t index,const v8::AccessorInfo & info)169 template<class Collection> static v8::Handle<v8::Value> collectionStringOrNullIndexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info) 170 { 171 // FIXME: assert that object must be a collection type 172 ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder())); 173 V8ClassIndex::V8WrapperType wrapperType = V8DOMWrapper::domWrapperType(info.Holder()); 174 Collection* collection = V8DOMWrapper::convertToNativeObject<Collection>(wrapperType, info.Holder()); 175 String result = collection->item(index); 176 return v8StringOrNull(result); 177 } 178 179 180 // Add indexed getter to the function template for a collection. setCollectionIndexedGetter(v8::Handle<v8::FunctionTemplate> desc,V8ClassIndex::V8WrapperType type)181 template<class Collection, class ItemType> static void setCollectionIndexedGetter(v8::Handle<v8::FunctionTemplate> desc, V8ClassIndex::V8WrapperType type) 182 { 183 desc->InstanceTemplate()->SetIndexedPropertyHandler(collectionIndexedPropertyGetter<Collection, ItemType>, 0, 0, 0, collectionIndexedPropertyEnumerator<Collection>, 184 v8::Integer::New(V8ClassIndex::ToInt(type))); 185 } 186 187 188 // Add named getter to the function template for a collection. setCollectionNamedGetter(v8::Handle<v8::FunctionTemplate> desc,V8ClassIndex::V8WrapperType type)189 template<class Collection, class ItemType> static void setCollectionNamedGetter(v8::Handle<v8::FunctionTemplate> desc, V8ClassIndex::V8WrapperType type) 190 { 191 desc->InstanceTemplate()->SetNamedPropertyHandler(collectionNamedPropertyGetter<Collection, ItemType>, 0, 0, 0, 0, v8::Integer::New(V8ClassIndex::ToInt(type))); 192 } 193 194 195 // Add named and indexed getters to the function template for a collection. setCollectionIndexedAndNamedGetters(v8::Handle<v8::FunctionTemplate> desc,V8ClassIndex::V8WrapperType type)196 template<class Collection, class ItemType> static void setCollectionIndexedAndNamedGetters(v8::Handle<v8::FunctionTemplate> desc, V8ClassIndex::V8WrapperType type) 197 { 198 // If we interceptor before object, accessing 'length' can trigger a webkit assertion error (see fast/dom/HTMLDocument/document-special-properties.html). 199 desc->InstanceTemplate()->SetNamedPropertyHandler(collectionNamedPropertyGetter<Collection, ItemType>, 0, 0, 0, 0, v8::Integer::New(V8ClassIndex::ToInt(type))); 200 desc->InstanceTemplate()->SetIndexedPropertyHandler(collectionIndexedPropertyGetter<Collection, ItemType>, 0, 0, 0, collectionIndexedPropertyEnumerator<Collection>, 201 v8::Integer::New(V8ClassIndex::ToInt(type))); 202 } 203 204 205 // Add indexed getter returning a string or null to a function template for a collection. setCollectionStringOrNullIndexedGetter(v8::Handle<v8::FunctionTemplate> desc)206 template<class Collection> static void setCollectionStringOrNullIndexedGetter(v8::Handle<v8::FunctionTemplate> desc) 207 { 208 desc->InstanceTemplate()->SetIndexedPropertyHandler(collectionStringOrNullIndexedPropertyGetter<Collection>, 0, 0, 0, collectionIndexedPropertyEnumerator<Collection>); 209 } 210 211 v8::Handle<v8::Value> toOptionsCollectionSetter(uint32_t index, v8::Handle<v8::Value>, HTMLSelectElement*); 212 213 } // namespace WebCore 214 215 #endif // V8Collection_h 216