2 * Copyright (C) 2010 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "Dictionary.h"
29 #include "ArrayValue.h"
30 #include "DOMStringList.h"
31 #include "V8Binding.h"
32 #include "V8DOMWindow.h"
33 #include "V8EventTarget.h"
34 #include "V8Storage.h"
35 #include "V8Uint8Array.h"
36 #include "V8Utilities.h"
37 #include <wtf/MathExtras.h>
39 #if ENABLE(INDEXED_DATABASE)
40 #include "IDBKeyRange.h"
41 #include "V8IDBKeyRange.h"
44 #if ENABLE(ENCRYPTED_MEDIA)
45 #include "V8MediaKeyError.h"
48 #if ENABLE(VIDEO_TRACK)
49 #include "TrackBase.h"
50 #include "V8TextTrack.h"
53 #if ENABLE(SCRIPTED_SPEECH)
54 #include "SpeechRecognitionError.h"
55 #include "SpeechRecognitionResult.h"
56 #include "SpeechRecognitionResultList.h"
57 #include "V8SpeechRecognitionError.h"
58 #include "V8SpeechRecognitionResult.h"
59 #include "V8SpeechRecognitionResultList.h"
62 #if ENABLE(MEDIA_STREAM)
63 #include "MediaStream.h"
64 #include "V8MediaStream.h"
69 Dictionary::Dictionary()
74 Dictionary::Dictionary(const v8::Local<v8::Value>& options, v8::Isolate* isolate)
81 Dictionary::~Dictionary()
85 Dictionary& Dictionary::operator=(const Dictionary& optionsObject)
87 m_options = optionsObject.m_options;
88 m_isolate = optionsObject.m_isolate;
92 bool Dictionary::isObject() const
94 return !isUndefinedOrNull() && m_options->IsObject();
97 bool Dictionary::isUndefinedOrNull() const
99 if (m_options.IsEmpty())
101 return WebCore::isUndefinedOrNull(m_options);
104 bool Dictionary::getKey(const String& key, v8::Local<v8::Value>& value) const
106 if (isUndefinedOrNull())
108 v8::Local<v8::Object> options = m_options->ToObject();
109 ASSERT(!options.IsEmpty());
112 ASSERT(m_isolate == v8::Isolate::GetCurrent());
113 v8::Handle<v8::String> v8Key = v8String(key, m_isolate);
114 if (!options->Has(v8Key))
116 value = options->Get(v8Key);
122 bool Dictionary::get(const String& key, bool& value) const
124 v8::Local<v8::Value> v8Value;
125 if (!getKey(key, v8Value))
128 v8::Local<v8::Boolean> v8Bool = v8Value->ToBoolean();
129 if (v8Bool.IsEmpty())
131 value = v8Bool->Value();
135 bool Dictionary::get(const String& key, int32_t& value) const
137 v8::Local<v8::Value> v8Value;
138 if (!getKey(key, v8Value))
141 v8::Local<v8::Int32> v8Int32 = v8Value->ToInt32();
142 if (v8Int32.IsEmpty())
144 value = v8Int32->Value();
148 bool Dictionary::get(const String& key, double& value) const
150 v8::Local<v8::Value> v8Value;
151 if (!getKey(key, v8Value))
154 v8::Local<v8::Number> v8Number = v8Value->ToNumber();
155 if (v8Number.IsEmpty())
157 value = v8Number->Value();
161 bool Dictionary::get(const String& key, String& value) const
163 v8::Local<v8::Value> v8Value;
164 if (!getKey(key, v8Value))
167 // FIXME: It is possible for this to throw in which case we'd be getting back
168 // an empty string and returning true when we should be returning false.
169 // See fast/dom/Geolocation/script-tests/argument-types.js for a similar
171 value = toWebCoreString(v8Value);
175 bool Dictionary::get(const String& key, ScriptValue& value) const
177 v8::Local<v8::Value> v8Value;
178 if (!getKey(key, v8Value))
181 value = ScriptValue(v8Value);
185 bool Dictionary::get(const String& key, unsigned short& value) const
187 v8::Local<v8::Value> v8Value;
188 if (!getKey(key, v8Value))
191 v8::Local<v8::Int32> v8Int32 = v8Value->ToInt32();
192 if (v8Int32.IsEmpty())
194 value = static_cast<unsigned short>(v8Int32->Value());
198 bool Dictionary::get(const String& key, short& value) const
200 v8::Local<v8::Value> v8Value;
201 if (!getKey(key, v8Value))
204 v8::Local<v8::Int32> v8Int32 = v8Value->ToInt32();
205 if (v8Int32.IsEmpty())
207 value = static_cast<short>(v8Int32->Value());
211 bool Dictionary::get(const String& key, unsigned& value) const
213 v8::Local<v8::Value> v8Value;
214 if (!getKey(key, v8Value))
217 v8::Local<v8::Int32> v8Int32 = v8Value->ToInt32();
218 if (v8Int32.IsEmpty())
220 value = static_cast<unsigned>(v8Int32->Value());
224 bool Dictionary::get(const String& key, unsigned long& value) const
226 v8::Local<v8::Value> v8Value;
227 if (!getKey(key, v8Value))
230 v8::Local<v8::Integer> v8Integer = v8Value->ToInteger();
231 if (v8Integer.IsEmpty())
233 value = static_cast<unsigned long>(v8Integer->Value());
237 bool Dictionary::get(const String& key, unsigned long long& value) const
239 v8::Local<v8::Value> v8Value;
240 if (!getKey(key, v8Value))
243 v8::Local<v8::Number> v8Number = v8Value->ToNumber();
244 if (v8Number.IsEmpty())
246 double d = v8Number->Value();
247 doubleToInteger(d, value);
251 bool Dictionary::get(const String& key, RefPtr<DOMWindow>& value) const
253 v8::Local<v8::Value> v8Value;
254 if (!getKey(key, v8Value))
257 // We need to handle a DOMWindow specially, because a DOMWindow wrapper
258 // exists on a prototype chain of v8Value.
260 if (v8Value->IsObject()) {
261 v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value);
262 v8::Handle<v8::Object> window = wrapper->FindInstanceInPrototypeChain(V8DOMWindow::GetTemplate(m_isolate, worldTypeInMainThread(m_isolate)));
263 if (!window.IsEmpty())
264 value = V8DOMWindow::toNative(window);
269 bool Dictionary::get(const String& key, RefPtr<Storage>& value) const
271 v8::Local<v8::Value> v8Value;
272 if (!getKey(key, v8Value))
276 if (V8Storage::HasInstance(v8Value, m_isolate))
277 value = V8Storage::toNative(v8::Handle<v8::Object>::Cast(v8Value));
281 bool Dictionary::get(const String& key, MessagePortArray& value) const
283 v8::Local<v8::Value> v8Value;
284 if (!getKey(key, v8Value))
288 ASSERT(m_isolate == v8::Isolate::GetCurrent());
289 return getMessagePortArray(v8Value, value, m_isolate);
292 bool Dictionary::get(const String& key, HashSet<AtomicString>& value) const
294 v8::Local<v8::Value> v8Value;
295 if (!getKey(key, v8Value))
298 // FIXME: Support array-like objects
299 if (!v8Value->IsArray())
303 ASSERT(m_isolate == v8::Isolate::GetCurrent());
304 v8::Local<v8::Array> v8Array = v8::Local<v8::Array>::Cast(v8Value);
305 for (size_t i = 0; i < v8Array->Length(); ++i) {
306 v8::Local<v8::Value> indexedValue = v8Array->Get(v8Integer(i, m_isolate));
307 value.add(toWebCoreString(indexedValue));
313 bool Dictionary::getWithUndefinedOrNullCheck(const String& key, String& value) const
315 v8::Local<v8::Value> v8Value;
316 if (!getKey(key, v8Value) || v8Value->IsNull() || v8Value->IsUndefined())
319 // FIXME: It is possible for this to throw in which case we'd be getting back
320 // an empty string and returning true when we should be returning false.
321 // See fast/dom/Geolocation/script-tests/argument-types.js for a similar
323 value = WebCore::isUndefinedOrNull(v8Value) ? String() : toWebCoreString(v8Value);
327 bool Dictionary::get(const String& key, RefPtr<Uint8Array>& value) const
329 v8::Local<v8::Value> v8Value;
330 if (!getKey(key, v8Value))
334 if (V8Uint8Array::HasInstance(v8Value, m_isolate))
335 value = V8Uint8Array::toNative(v8::Handle<v8::Object>::Cast(v8Value));
339 #if ENABLE(ENCRYPTED_MEDIA)
340 bool Dictionary::get(const String& key, RefPtr<MediaKeyError>& value) const
342 v8::Local<v8::Value> v8Value;
343 if (!getKey(key, v8Value))
347 if (V8MediaKeyError::HasInstance(v8Value, m_isolate))
348 value = V8MediaKeyError::toNative(v8::Handle<v8::Object>::Cast(v8Value));
353 #if ENABLE(VIDEO_TRACK)
354 bool Dictionary::get(const String& key, RefPtr<TrackBase>& value) const
356 v8::Local<v8::Value> v8Value;
357 if (!getKey(key, v8Value))
360 TrackBase* source = 0;
361 if (v8Value->IsObject()) {
362 v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value);
364 // FIXME: this will need to be changed so it can also return an AudioTrack or a VideoTrack once
366 v8::Handle<v8::Object> track = wrapper->FindInstanceInPrototypeChain(V8TextTrack::GetTemplate(m_isolate, worldType(m_isolate)));
367 if (!track.IsEmpty())
368 source = V8TextTrack::toNative(track);
375 #if ENABLE(SCRIPTED_SPEECH)
376 bool Dictionary::get(const String& key, RefPtr<SpeechRecognitionError>& value) const
378 v8::Local<v8::Value> v8Value;
379 if (!getKey(key, v8Value))
383 if (V8SpeechRecognitionError::HasInstance(v8Value, m_isolate))
384 value = V8SpeechRecognitionError::toNative(v8::Handle<v8::Object>::Cast(v8Value));
388 bool Dictionary::get(const String& key, RefPtr<SpeechRecognitionResult>& value) const
390 v8::Local<v8::Value> v8Value;
391 if (!getKey(key, v8Value))
395 if (V8SpeechRecognitionResult::HasInstance(v8Value, m_isolate))
396 value = V8SpeechRecognitionResult::toNative(v8::Handle<v8::Object>::Cast(v8Value));
400 bool Dictionary::get(const String& key, RefPtr<SpeechRecognitionResultList>& value) const
402 v8::Local<v8::Value> v8Value;
403 if (!getKey(key, v8Value))
407 if (V8SpeechRecognitionResultList::HasInstance(v8Value, m_isolate))
408 value = V8SpeechRecognitionResultList::toNative(v8::Handle<v8::Object>::Cast(v8Value));
414 #if ENABLE(MEDIA_STREAM)
415 bool Dictionary::get(const String& key, RefPtr<MediaStream>& value) const
417 v8::Local<v8::Value> v8Value;
418 if (!getKey(key, v8Value))
422 if (V8MediaStream::HasInstance(v8Value, m_isolate))
423 value = V8MediaStream::toNative(v8::Handle<v8::Object>::Cast(v8Value));
428 bool Dictionary::get(const String& key, RefPtr<EventTarget>& value) const
430 v8::Local<v8::Value> v8Value;
431 if (!getKey(key, v8Value))
435 // We need to handle a DOMWindow specially, because a DOMWindow wrapper
436 // exists on a prototype chain of v8Value.
437 if (v8Value->IsObject()) {
438 v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value);
439 v8::Handle<v8::Object> window = wrapper->FindInstanceInPrototypeChain(V8DOMWindow::GetTemplate(m_isolate, worldTypeInMainThread(m_isolate)));
440 if (!window.IsEmpty()) {
441 value = toWrapperTypeInfo(window)->toEventTarget(window);
446 if (V8DOMWrapper::isDOMWrapper(v8Value)) {
447 v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value);
448 value = toWrapperTypeInfo(wrapper)->toEventTarget(wrapper);
453 bool Dictionary::get(const String& key, Dictionary& value) const
455 v8::Local<v8::Value> v8Value;
456 if (!getKey(key, v8Value))
459 if (v8Value->IsObject()) {
461 ASSERT(m_isolate == v8::Isolate::GetCurrent());
462 value = Dictionary(v8Value, m_isolate);
468 bool Dictionary::get(const String& key, Vector<String>& value) const
470 v8::Local<v8::Value> v8Value;
471 if (!getKey(key, v8Value))
474 if (!v8Value->IsArray())
477 v8::Local<v8::Array> v8Array = v8::Local<v8::Array>::Cast(v8Value);
478 for (size_t i = 0; i < v8Array->Length(); ++i) {
479 v8::Local<v8::Value> indexedValue = v8Array->Get(v8::Uint32::New(i));
480 value.append(toWebCoreString(indexedValue));
486 bool Dictionary::get(const String& key, ArrayValue& value) const
488 v8::Local<v8::Value> v8Value;
489 if (!getKey(key, v8Value))
492 if (!v8Value->IsArray())
496 ASSERT(m_isolate == v8::Isolate::GetCurrent());
497 value = ArrayValue(v8::Local<v8::Array>::Cast(v8Value), m_isolate);
501 bool Dictionary::getOwnPropertiesAsStringHashMap(HashMap<String, String>& hashMap) const
506 v8::Handle<v8::Object> options = m_options->ToObject();
507 if (options.IsEmpty())
510 v8::Local<v8::Array> properties = options->GetOwnPropertyNames();
511 if (properties.IsEmpty())
513 for (uint32_t i = 0; i < properties->Length(); ++i) {
514 v8::Local<v8::String> key = properties->Get(i)->ToString();
515 if (!options->Has(key))
518 v8::Local<v8::Value> value = options->Get(key);
519 String stringKey = toWebCoreString(key);
520 String stringValue = toWebCoreString(value);
521 if (!stringKey.isEmpty())
522 hashMap.set(stringKey, stringValue);
528 bool Dictionary::getOwnPropertyNames(Vector<String>& names) const
533 v8::Handle<v8::Object> options = m_options->ToObject();
534 if (options.IsEmpty())
537 v8::Local<v8::Array> properties = options->GetOwnPropertyNames();
538 if (properties.IsEmpty())
540 for (uint32_t i = 0; i < properties->Length(); ++i) {
541 v8::Local<v8::String> key = properties->Get(i)->ToString();
542 if (!options->Has(key))
544 names.append(toWebCoreString(key));
550 } // namespace WebCore