1 /* 2 * Copyright (C) 2010 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 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "bindings/core/v8/Dictionary.h" 28 29 #include "bindings/core/v8/ArrayValue.h" 30 #include "bindings/core/v8/ExceptionMessages.h" 31 #include "bindings/core/v8/ExceptionState.h" 32 #include "bindings/core/v8/V8Binding.h" 33 #include "bindings/core/v8/V8DOMError.h" 34 #include "bindings/core/v8/V8Element.h" 35 #include "bindings/core/v8/V8EventTarget.h" 36 #include "bindings/core/v8/V8MediaKeyError.h" 37 #include "bindings/core/v8/V8MessagePort.h" 38 #include "bindings/core/v8/V8Path2D.h" 39 #include "bindings/core/v8/V8Storage.h" 40 #include "bindings/core/v8/V8TextTrack.h" 41 #include "bindings/core/v8/V8VoidCallback.h" 42 #include "bindings/core/v8/V8Window.h" 43 #include "bindings/core/v8/custom/V8ArrayBufferViewCustom.h" 44 #include "bindings/core/v8/custom/V8Uint8ArrayCustom.h" 45 #include "bindings/modules/v8/V8Gamepad.h" 46 #include "bindings/modules/v8/V8Headers.h" 47 #include "bindings/modules/v8/V8IDBKeyRange.h" 48 #include "bindings/modules/v8/V8MIDIPort.h" 49 #include "bindings/modules/v8/V8MediaStream.h" 50 #include "bindings/modules/v8/V8SpeechRecognitionResult.h" 51 #include "bindings/modules/v8/V8SpeechRecognitionResultList.h" 52 #include "core/html/track/TrackBase.h" 53 #include "modules/gamepad/Gamepad.h" 54 #include "modules/indexeddb/IDBKeyRange.h" 55 #include "modules/mediastream/MediaStream.h" 56 #include "modules/speech/SpeechRecognitionResult.h" 57 #include "modules/speech/SpeechRecognitionResultList.h" 58 #include "wtf/MathExtras.h" 59 60 namespace blink { 61 62 Dictionary::Dictionary() 63 : m_isolate(0) 64 { 65 } 66 67 Dictionary::Dictionary(const v8::Handle<v8::Value>& options, v8::Isolate* isolate) 68 : m_options(options) 69 , m_isolate(isolate) 70 { 71 ASSERT(m_isolate); 72 } 73 74 Dictionary::~Dictionary() 75 { 76 } 77 78 Dictionary& Dictionary::operator=(const Dictionary& optionsObject) 79 { 80 m_options = optionsObject.m_options; 81 m_isolate = optionsObject.m_isolate; 82 return *this; 83 } 84 85 Dictionary Dictionary::createEmpty(v8::Isolate* isolate) 86 { 87 return Dictionary(v8::Object::New(isolate), isolate); 88 } 89 90 bool Dictionary::isObject() const 91 { 92 return !isUndefinedOrNull() && m_options->IsObject(); 93 } 94 95 bool Dictionary::isUndefinedOrNull() const 96 { 97 if (m_options.IsEmpty()) 98 return true; 99 return blink::isUndefinedOrNull(m_options); 100 } 101 102 bool Dictionary::hasProperty(const String& key) const 103 { 104 if (isUndefinedOrNull()) 105 return false; 106 v8::Local<v8::Object> options = m_options->ToObject(); 107 ASSERT(!options.IsEmpty()); 108 109 ASSERT(m_isolate); 110 ASSERT(m_isolate == v8::Isolate::GetCurrent()); 111 v8::Handle<v8::String> v8Key = v8String(m_isolate, key); 112 if (!options->Has(v8Key)) 113 return false; 114 115 return true; 116 } 117 118 bool Dictionary::getKey(const String& key, v8::Local<v8::Value>& value) const 119 { 120 if (isUndefinedOrNull()) 121 return false; 122 v8::Local<v8::Object> options = m_options->ToObject(); 123 ASSERT(!options.IsEmpty()); 124 125 ASSERT(m_isolate); 126 ASSERT(m_isolate == v8::Isolate::GetCurrent()); 127 v8::Handle<v8::String> v8Key = v8String(m_isolate, key); 128 if (!options->Has(v8Key)) 129 return false; 130 value = options->Get(v8Key); 131 if (value.IsEmpty()) 132 return false; 133 return true; 134 } 135 136 bool Dictionary::get(const String& key, v8::Local<v8::Value>& value) const 137 { 138 return getKey(key, value); 139 } 140 141 bool Dictionary::getWithUndefinedOrNullCheck(const String& key, String& value) const 142 { 143 v8::Local<v8::Value> v8Value; 144 if (!getKey(key, v8Value) || blink::isUndefinedOrNull(v8Value)) 145 return false; 146 147 TOSTRING_DEFAULT(V8StringResource<>, stringValue, v8Value, false); 148 value = stringValue; 149 return true; 150 } 151 152 bool Dictionary::getWithUndefinedOrNullCheck(const String& key, RefPtrWillBeMember<Element>& value) const 153 { 154 v8::Local<v8::Value> v8Value; 155 if (!getKey(key, v8Value) || blink::isUndefinedOrNull(v8Value)) 156 return false; 157 158 value = V8Element::toImplWithTypeCheck(m_isolate, v8Value); 159 return true; 160 } 161 162 bool Dictionary::getWithUndefinedOrNullCheck(const String& key, RefPtrWillBeMember<Path2D>& value) const 163 { 164 v8::Local<v8::Value> v8Value; 165 if (!getKey(key, v8Value) || blink::isUndefinedOrNull(v8Value)) 166 return false; 167 168 value = V8Path2D::toImplWithTypeCheck(m_isolate, v8Value); 169 return true; 170 } 171 172 bool Dictionary::get(const String& key, Dictionary& value) const 173 { 174 v8::Local<v8::Value> v8Value; 175 if (!getKey(key, v8Value)) 176 return false; 177 178 if (v8Value->IsObject()) { 179 ASSERT(m_isolate); 180 ASSERT(m_isolate == v8::Isolate::GetCurrent()); 181 value = Dictionary(v8Value, m_isolate); 182 } 183 184 return true; 185 } 186 187 bool Dictionary::set(const String& key, const v8::Handle<v8::Value>& value) 188 { 189 if (isUndefinedOrNull()) 190 return false; 191 v8::Local<v8::Object> options = m_options->ToObject(); 192 ASSERT(!options.IsEmpty()); 193 194 return options->Set(v8String(m_isolate, key), value); 195 } 196 197 bool Dictionary::set(const String& key, const String& value) 198 { 199 return set(key, v8String(m_isolate, value)); 200 } 201 202 bool Dictionary::set(const String& key, unsigned value) 203 { 204 return set(key, v8::Integer::NewFromUnsigned(m_isolate, value)); 205 } 206 207 bool Dictionary::set(const String& key, const Dictionary& value) 208 { 209 return set(key, value.v8Value()); 210 } 211 212 bool Dictionary::convert(ConversionContext& context, const String& key, Dictionary& value) const 213 { 214 ConversionContextScope scope(context); 215 216 v8::Local<v8::Value> v8Value; 217 if (!getKey(key, v8Value)) 218 return true; 219 220 if (v8Value->IsObject()) 221 return get(key, value); 222 223 if (context.isNullable() && blink::isUndefinedOrNull(v8Value)) 224 return true; 225 226 context.throwTypeError(ExceptionMessages::incorrectPropertyType(key, "does not have a Dictionary type.")); 227 return false; 228 } 229 230 bool Dictionary::getOwnPropertiesAsStringHashMap(HashMap<String, String>& hashMap) const 231 { 232 if (!isObject()) 233 return false; 234 235 v8::Handle<v8::Object> options = m_options->ToObject(); 236 if (options.IsEmpty()) 237 return false; 238 239 v8::Local<v8::Array> properties = options->GetOwnPropertyNames(); 240 if (properties.IsEmpty()) 241 return true; 242 for (uint32_t i = 0; i < properties->Length(); ++i) { 243 v8::Local<v8::String> key = properties->Get(i)->ToString(); 244 if (!options->Has(key)) 245 continue; 246 247 v8::Local<v8::Value> value = options->Get(key); 248 TOSTRING_DEFAULT(V8StringResource<>, stringKey, key, false); 249 TOSTRING_DEFAULT(V8StringResource<>, stringValue, value, false); 250 if (!static_cast<const String&>(stringKey).isEmpty()) 251 hashMap.set(stringKey, stringValue); 252 } 253 254 return true; 255 } 256 257 bool Dictionary::getOwnPropertyNames(Vector<String>& names) const 258 { 259 if (!isObject()) 260 return false; 261 262 v8::Handle<v8::Object> options = m_options->ToObject(); 263 if (options.IsEmpty()) 264 return false; 265 266 v8::Local<v8::Array> properties = options->GetOwnPropertyNames(); 267 if (properties.IsEmpty()) 268 return true; 269 for (uint32_t i = 0; i < properties->Length(); ++i) { 270 v8::Local<v8::String> key = properties->Get(i)->ToString(); 271 if (!options->Has(key)) 272 continue; 273 TOSTRING_DEFAULT(V8StringResource<>, stringKey, key, false); 274 names.append(stringKey); 275 } 276 277 return true; 278 } 279 280 void Dictionary::ConversionContext::resetPerPropertyContext() 281 { 282 if (m_dirty) { 283 m_dirty = false; 284 m_isNullable = false; 285 m_propertyTypeName = ""; 286 } 287 } 288 289 Dictionary::ConversionContext& Dictionary::ConversionContext::setConversionType(const String& typeName, bool isNullable) 290 { 291 ASSERT(!m_dirty); 292 m_dirty = true; 293 m_isNullable = isNullable; 294 m_propertyTypeName = typeName; 295 296 return *this; 297 } 298 299 void Dictionary::ConversionContext::throwTypeError(const String& detail) 300 { 301 exceptionState().throwTypeError(detail); 302 } 303 304 } // namespace blink 305