• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/v8/Dictionary.h"
28 
29 #include "V8DOMError.h"
30 #include "V8EventTarget.h"
31 #include "V8IDBKeyRange.h"
32 #include "V8MIDIPort.h"
33 #include "V8MediaKeyError.h"
34 #include "V8SpeechRecognitionError.h"
35 #include "V8SpeechRecognitionResult.h"
36 #include "V8SpeechRecognitionResultList.h"
37 #include "V8Storage.h"
38 #include "V8VoidCallback.h"
39 #include "V8Window.h"
40 #include "bindings/v8/ArrayValue.h"
41 #include "bindings/v8/ExceptionMessages.h"
42 #include "bindings/v8/ExceptionState.h"
43 #include "bindings/v8/V8Binding.h"
44 #include "bindings/v8/V8Utilities.h"
45 #include "bindings/v8/custom/V8ArrayBufferViewCustom.h"
46 #include "bindings/v8/custom/V8Uint8ArrayCustom.h"
47 #include "modules/indexeddb/IDBKeyRange.h"
48 #include "modules/speech/SpeechRecognitionError.h"
49 #include "modules/speech/SpeechRecognitionResult.h"
50 #include "modules/speech/SpeechRecognitionResultList.h"
51 #include "wtf/MathExtras.h"
52 
53 #include "V8TextTrack.h"
54 #include "core/html/track/TrackBase.h"
55 
56 #include "V8MediaStream.h"
57 #include "modules/mediastream/MediaStream.h"
58 
59 namespace WebCore {
60 
Dictionary()61 Dictionary::Dictionary()
62     : m_isolate(0)
63 {
64 }
65 
Dictionary(const v8::Handle<v8::Value> & options,v8::Isolate * isolate)66 Dictionary::Dictionary(const v8::Handle<v8::Value>& options, v8::Isolate* isolate)
67     : m_options(options)
68     , m_isolate(isolate)
69 {
70     ASSERT(m_isolate);
71 }
72 
~Dictionary()73 Dictionary::~Dictionary()
74 {
75 }
76 
operator =(const Dictionary & optionsObject)77 Dictionary& Dictionary::operator=(const Dictionary& optionsObject)
78 {
79     m_options = optionsObject.m_options;
80     m_isolate = optionsObject.m_isolate;
81     return *this;
82 }
83 
isObject() const84 bool Dictionary::isObject() const
85 {
86     return !isUndefinedOrNull() && m_options->IsObject();
87 }
88 
isUndefinedOrNull() const89 bool Dictionary::isUndefinedOrNull() const
90 {
91     if (m_options.IsEmpty())
92         return true;
93     return WebCore::isUndefinedOrNull(m_options);
94 }
95 
hasProperty(const String & key) const96 bool Dictionary::hasProperty(const String& key) const
97 {
98     if (isUndefinedOrNull())
99         return false;
100     v8::Local<v8::Object> options = m_options->ToObject();
101     ASSERT(!options.IsEmpty());
102 
103     ASSERT(m_isolate);
104     ASSERT(m_isolate == v8::Isolate::GetCurrent());
105     v8::Handle<v8::String> v8Key = v8String(m_isolate, key);
106     if (!options->Has(v8Key))
107         return false;
108 
109     return true;
110 }
111 
getKey(const String & key,v8::Local<v8::Value> & value) const112 bool Dictionary::getKey(const String& key, v8::Local<v8::Value>& value) const
113 {
114     if (isUndefinedOrNull())
115         return false;
116     v8::Local<v8::Object> options = m_options->ToObject();
117     ASSERT(!options.IsEmpty());
118 
119     ASSERT(m_isolate);
120     ASSERT(m_isolate == v8::Isolate::GetCurrent());
121     v8::Handle<v8::String> v8Key = v8String(m_isolate, key);
122     if (!options->Has(v8Key))
123         return false;
124     value = options->Get(v8Key);
125     if (value.IsEmpty())
126         return false;
127     return true;
128 }
129 
get(const String & key,v8::Local<v8::Value> & value) const130 bool Dictionary::get(const String& key, v8::Local<v8::Value>& value) const
131 {
132     return getKey(key, value);
133 }
134 
get(const String & key,bool & value) const135 bool Dictionary::get(const String& key, bool& value) const
136 {
137     v8::Local<v8::Value> v8Value;
138     if (!getKey(key, v8Value))
139         return false;
140 
141     v8::Local<v8::Boolean> v8Bool = v8Value->ToBoolean();
142     if (v8Bool.IsEmpty())
143         return false;
144     value = v8Bool->Value();
145     return true;
146 }
147 
convert(ConversionContext & context,const String & key,bool & value) const148 bool Dictionary::convert(ConversionContext& context, const String& key, bool& value) const
149 {
150     ConversionContextScope scope(context);
151     get(key, value);
152     return true;
153 }
154 
get(const String & key,int32_t & value) const155 bool Dictionary::get(const String& key, int32_t& value) const
156 {
157     v8::Local<v8::Value> v8Value;
158     if (!getKey(key, v8Value))
159         return false;
160 
161     v8::Local<v8::Int32> v8Int32 = v8Value->ToInt32();
162     if (v8Int32.IsEmpty())
163         return false;
164     value = v8Int32->Value();
165     return true;
166 }
167 
get(const String & key,double & value,bool & hasValue) const168 bool Dictionary::get(const String& key, double& value, bool& hasValue) const
169 {
170     v8::Local<v8::Value> v8Value;
171     if (!getKey(key, v8Value)) {
172         hasValue = false;
173         return false;
174     }
175 
176     hasValue = true;
177     V8TRYCATCH_RETURN(v8::Local<v8::Number>, v8Number, v8Value->ToNumber(), false);
178     if (v8Number.IsEmpty())
179         return false;
180     value = v8Number->Value();
181     return true;
182 }
183 
get(const String & key,double & value) const184 bool Dictionary::get(const String& key, double& value) const
185 {
186     bool unused;
187     return get(key, value, unused);
188 }
189 
convert(ConversionContext & context,const String & key,double & value) const190 bool Dictionary::convert(ConversionContext& context, const String& key, double& value) const
191 {
192     ConversionContextScope scope(context);
193 
194     bool hasValue = false;
195     if (!get(key, value, hasValue) && hasValue) {
196         context.throwTypeError(ExceptionMessages::incorrectPropertyType(key, "is not of type 'double'."));
197         return false;
198     }
199     return true;
200 }
201 
get(const String & key,String & value) const202 bool Dictionary::get(const String& key, String& value) const
203 {
204     v8::Local<v8::Value> v8Value;
205     if (!getKey(key, v8Value))
206         return false;
207 
208     V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, v8Value, false);
209     value = stringValue;
210     return true;
211 }
212 
convert(ConversionContext & context,const String & key,String & value) const213 bool Dictionary::convert(ConversionContext& context, const String& key, String& value) const
214 {
215     ConversionContextScope scope(context);
216 
217     v8::Local<v8::Value> v8Value;
218     if (!getKey(key, v8Value))
219         return true;
220 
221     V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, v8Value, false);
222     value = stringValue;
223     return true;
224 }
225 
get(const String & key,ScriptValue & value) const226 bool Dictionary::get(const String& key, ScriptValue& value) const
227 {
228     v8::Local<v8::Value> v8Value;
229     if (!getKey(key, v8Value))
230         return false;
231 
232     value = ScriptValue(v8Value, m_isolate);
233     return true;
234 }
235 
convert(ConversionContext & context,const String & key,ScriptValue & value) const236 bool Dictionary::convert(ConversionContext& context, const String& key, ScriptValue& value) const
237 {
238     ConversionContextScope scope(context);
239 
240     get(key, value);
241     return true;
242 }
243 
get(const String & key,unsigned short & value) const244 bool Dictionary::get(const String& key, unsigned short& value) const
245 {
246     v8::Local<v8::Value> v8Value;
247     if (!getKey(key, v8Value))
248         return false;
249 
250     v8::Local<v8::Int32> v8Int32 = v8Value->ToInt32();
251     if (v8Int32.IsEmpty())
252         return false;
253     value = static_cast<unsigned short>(v8Int32->Value());
254     return true;
255 }
256 
get(const String & key,short & value) const257 bool Dictionary::get(const String& key, short& value) const
258 {
259     v8::Local<v8::Value> v8Value;
260     if (!getKey(key, v8Value))
261         return false;
262 
263     v8::Local<v8::Int32> v8Int32 = v8Value->ToInt32();
264     if (v8Int32.IsEmpty())
265         return false;
266     value = static_cast<short>(v8Int32->Value());
267     return true;
268 }
269 
get(const String & key,unsigned & value) const270 bool Dictionary::get(const String& key, unsigned& value) const
271 {
272     v8::Local<v8::Value> v8Value;
273     if (!getKey(key, v8Value))
274         return false;
275 
276     v8::Local<v8::Int32> v8Int32 = v8Value->ToInt32();
277     if (v8Int32.IsEmpty())
278         return false;
279     value = static_cast<unsigned>(v8Int32->Value());
280     return true;
281 }
282 
get(const String & key,unsigned long & value) const283 bool Dictionary::get(const String& key, unsigned long& value) const
284 {
285     v8::Local<v8::Value> v8Value;
286     if (!getKey(key, v8Value))
287         return false;
288 
289     v8::Local<v8::Integer> v8Integer = v8Value->ToInteger();
290     if (v8Integer.IsEmpty())
291         return false;
292     value = static_cast<unsigned long>(v8Integer->Value());
293     return true;
294 }
295 
get(const String & key,unsigned long long & value) const296 bool Dictionary::get(const String& key, unsigned long long& value) const
297 {
298     v8::Local<v8::Value> v8Value;
299     if (!getKey(key, v8Value))
300         return false;
301 
302     V8TRYCATCH_RETURN(v8::Local<v8::Number>, v8Number, v8Value->ToNumber(), false);
303     if (v8Number.IsEmpty())
304         return false;
305     double d = v8Number->Value();
306     doubleToInteger(d, value);
307     return true;
308 }
309 
get(const String & key,RefPtr<DOMWindow> & value) const310 bool Dictionary::get(const String& key, RefPtr<DOMWindow>& value) const
311 {
312     v8::Local<v8::Value> v8Value;
313     if (!getKey(key, v8Value))
314         return false;
315 
316     // We need to handle a DOMWindow specially, because a DOMWindow wrapper
317     // exists on a prototype chain of v8Value.
318     value = 0;
319     if (v8Value->IsObject()) {
320         v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value);
321         v8::Handle<v8::Object> window = wrapper->FindInstanceInPrototypeChain(V8Window::domTemplate(m_isolate, worldTypeInMainThread(m_isolate)));
322         if (!window.IsEmpty())
323             value = V8Window::toNative(window);
324     }
325     return true;
326 }
327 
get(const String & key,RefPtr<Storage> & value) const328 bool Dictionary::get(const String& key, RefPtr<Storage>& value) const
329 {
330     v8::Local<v8::Value> v8Value;
331     if (!getKey(key, v8Value))
332         return false;
333 
334     value = 0;
335     if (V8Storage::hasInstance(v8Value, m_isolate, worldType(m_isolate)))
336         value = V8Storage::toNative(v8::Handle<v8::Object>::Cast(v8Value));
337     return true;
338 }
339 
get(const String & key,MessagePortArray & value) const340 bool Dictionary::get(const String& key, MessagePortArray& value) const
341 {
342     v8::Local<v8::Value> v8Value;
343     if (!getKey(key, v8Value))
344         return false;
345 
346     ASSERT(m_isolate);
347     ASSERT(m_isolate == v8::Isolate::GetCurrent());
348     return getMessagePortArray(v8Value, key, value, m_isolate);
349 }
350 
convert(ConversionContext & context,const String & key,MessagePortArray & value) const351 bool Dictionary::convert(ConversionContext& context, const String& key, MessagePortArray& value) const
352 {
353     ConversionContextScope scope(context);
354 
355     v8::Local<v8::Value> v8Value;
356     if (!getKey(key, v8Value))
357         return true;
358 
359     return get(key, value);
360 }
361 
get(const String & key,HashSet<AtomicString> & value) const362 bool Dictionary::get(const String& key, HashSet<AtomicString>& value) const
363 {
364     v8::Local<v8::Value> v8Value;
365     if (!getKey(key, v8Value))
366         return false;
367 
368     // FIXME: Support array-like objects
369     if (!v8Value->IsArray())
370         return false;
371 
372     ASSERT(m_isolate);
373     ASSERT(m_isolate == v8::Isolate::GetCurrent());
374     v8::Local<v8::Array> v8Array = v8::Local<v8::Array>::Cast(v8Value);
375     for (size_t i = 0; i < v8Array->Length(); ++i) {
376         v8::Local<v8::Value> indexedValue = v8Array->Get(v8::Integer::New(i, m_isolate));
377         V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, indexedValue, false);
378         value.add(stringValue);
379     }
380 
381     return true;
382 }
383 
convert(ConversionContext & context,const String & key,HashSet<AtomicString> & value) const384 bool Dictionary::convert(ConversionContext& context, const String& key, HashSet<AtomicString>& value) const
385 {
386     ConversionContextScope scope(context);
387 
388     v8::Local<v8::Value> v8Value;
389     if (!getKey(key, v8Value))
390         return true;
391 
392     if (context.isNullable() && WebCore::isUndefinedOrNull(v8Value))
393         return true;
394 
395     if (!v8Value->IsArray()) {
396         context.throwTypeError(ExceptionMessages::notASequenceTypeProperty(key));
397         return false;
398     }
399 
400     return get(key, value);
401 }
402 
getWithUndefinedOrNullCheck(const String & key,String & value) const403 bool Dictionary::getWithUndefinedOrNullCheck(const String& key, String& value) const
404 {
405     v8::Local<v8::Value> v8Value;
406     if (!getKey(key, v8Value) || WebCore::isUndefinedOrNull(v8Value))
407         return false;
408 
409     V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, v8Value, false);
410     value = stringValue;
411     return true;
412 }
413 
get(const String & key,RefPtr<Uint8Array> & value) const414 bool Dictionary::get(const String& key, RefPtr<Uint8Array>& value) const
415 {
416     v8::Local<v8::Value> v8Value;
417     if (!getKey(key, v8Value))
418         return false;
419 
420     value = 0;
421     if (V8Uint8Array::hasInstance(v8Value, m_isolate, worldType(m_isolate)))
422         value = V8Uint8Array::toNative(v8::Handle<v8::Object>::Cast(v8Value));
423     return true;
424 }
425 
get(const String & key,RefPtr<ArrayBufferView> & value) const426 bool Dictionary::get(const String& key, RefPtr<ArrayBufferView>& value) const
427 {
428     v8::Local<v8::Value> v8Value;
429     if (!getKey(key, v8Value))
430         return false;
431 
432     value = 0;
433     if (V8ArrayBufferView::hasInstance(v8Value, m_isolate, worldType(m_isolate)))
434         value = V8ArrayBufferView::toNative(v8::Handle<v8::Object>::Cast(v8Value));
435     return true;
436 }
437 
get(const String & key,RefPtr<MIDIPort> & value) const438 bool Dictionary::get(const String& key, RefPtr<MIDIPort>& value) const
439 {
440     v8::Local<v8::Value> v8Value;
441     if (!getKey(key, v8Value))
442         return false;
443 
444     value = 0;
445     if (V8MIDIPort::hasInstance(v8Value, m_isolate, worldType(m_isolate)))
446         value = V8MIDIPort::toNative(v8::Handle<v8::Object>::Cast(v8Value));
447     return true;
448 }
449 
get(const String & key,RefPtr<MediaKeyError> & value) const450 bool Dictionary::get(const String& key, RefPtr<MediaKeyError>& value) const
451 {
452     v8::Local<v8::Value> v8Value;
453     if (!getKey(key, v8Value))
454         return false;
455 
456     value = 0;
457     if (V8MediaKeyError::hasInstance(v8Value, m_isolate, worldType(m_isolate)))
458         value = V8MediaKeyError::toNative(v8::Handle<v8::Object>::Cast(v8Value));
459     return true;
460 }
461 
get(const String & key,RefPtr<TrackBase> & value) const462 bool Dictionary::get(const String& key, RefPtr<TrackBase>& value) const
463 {
464     v8::Local<v8::Value> v8Value;
465     if (!getKey(key, v8Value))
466         return false;
467 
468     TrackBase* source = 0;
469     if (v8Value->IsObject()) {
470         v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value);
471 
472         // FIXME: this will need to be changed so it can also return an AudioTrack or a VideoTrack once
473         // we add them.
474         v8::Handle<v8::Object> track = wrapper->FindInstanceInPrototypeChain(V8TextTrack::domTemplate(m_isolate, worldType(m_isolate)));
475         if (!track.IsEmpty())
476             source = V8TextTrack::toNative(track);
477     }
478     value = source;
479     return true;
480 }
481 
get(const String & key,RefPtr<SpeechRecognitionError> & value) const482 bool Dictionary::get(const String& key, RefPtr<SpeechRecognitionError>& value) const
483 {
484     v8::Local<v8::Value> v8Value;
485     if (!getKey(key, v8Value))
486         return false;
487 
488     value = 0;
489     if (V8SpeechRecognitionError::hasInstance(v8Value, m_isolate, worldType(m_isolate)))
490         value = V8SpeechRecognitionError::toNative(v8::Handle<v8::Object>::Cast(v8Value));
491     return true;
492 }
493 
get(const String & key,RefPtr<SpeechRecognitionResult> & value) const494 bool Dictionary::get(const String& key, RefPtr<SpeechRecognitionResult>& value) const
495 {
496     v8::Local<v8::Value> v8Value;
497     if (!getKey(key, v8Value))
498         return false;
499 
500     value = 0;
501     if (V8SpeechRecognitionResult::hasInstance(v8Value, m_isolate, worldType(m_isolate)))
502         value = V8SpeechRecognitionResult::toNative(v8::Handle<v8::Object>::Cast(v8Value));
503     return true;
504 }
505 
get(const String & key,RefPtr<SpeechRecognitionResultList> & value) const506 bool Dictionary::get(const String& key, RefPtr<SpeechRecognitionResultList>& value) const
507 {
508     v8::Local<v8::Value> v8Value;
509     if (!getKey(key, v8Value))
510         return false;
511 
512     value = 0;
513     if (V8SpeechRecognitionResultList::hasInstance(v8Value, m_isolate, worldType(m_isolate)))
514         value = V8SpeechRecognitionResultList::toNative(v8::Handle<v8::Object>::Cast(v8Value));
515     return true;
516 }
517 
get(const String & key,RefPtr<MediaStream> & value) const518 bool Dictionary::get(const String& key, RefPtr<MediaStream>& value) const
519 {
520     v8::Local<v8::Value> v8Value;
521     if (!getKey(key, v8Value))
522         return false;
523 
524     value = 0;
525     if (V8MediaStream::hasInstance(v8Value, m_isolate, worldType(m_isolate)))
526         value = V8MediaStream::toNative(v8::Handle<v8::Object>::Cast(v8Value));
527     return true;
528 }
529 
get(const String & key,RefPtr<EventTarget> & value) const530 bool Dictionary::get(const String& key, RefPtr<EventTarget>& value) const
531 {
532     v8::Local<v8::Value> v8Value;
533     if (!getKey(key, v8Value))
534         return false;
535 
536     value = 0;
537     // We need to handle a DOMWindow specially, because a DOMWindow wrapper
538     // exists on a prototype chain of v8Value.
539     if (v8Value->IsObject()) {
540         v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value);
541         v8::Handle<v8::Object> window = wrapper->FindInstanceInPrototypeChain(V8Window::domTemplate(m_isolate, worldTypeInMainThread(m_isolate)));
542         if (!window.IsEmpty()) {
543             value = toWrapperTypeInfo(window)->toEventTarget(window);
544             return true;
545         }
546     }
547 
548     if (V8DOMWrapper::isDOMWrapper(v8Value)) {
549         v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value);
550         value = toWrapperTypeInfo(wrapper)->toEventTarget(wrapper);
551     }
552     return true;
553 }
554 
get(const String & key,Dictionary & value) const555 bool Dictionary::get(const String& key, Dictionary& value) const
556 {
557     v8::Local<v8::Value> v8Value;
558     if (!getKey(key, v8Value))
559         return false;
560 
561     if (v8Value->IsObject()) {
562         ASSERT(m_isolate);
563         ASSERT(m_isolate == v8::Isolate::GetCurrent());
564         value = Dictionary(v8Value, m_isolate);
565     }
566 
567     return true;
568 }
569 
convert(ConversionContext & context,const String & key,Dictionary & value) const570 bool Dictionary::convert(ConversionContext& context, const String& key, Dictionary& value) const
571 {
572     ConversionContextScope scope(context);
573 
574     v8::Local<v8::Value> v8Value;
575     if (!getKey(key, v8Value))
576         return true;
577 
578     if (v8Value->IsObject())
579         return get(key, value);
580 
581     if (context.isNullable() && WebCore::isUndefinedOrNull(v8Value))
582         return true;
583 
584     context.throwTypeError(ExceptionMessages::incorrectPropertyType(key, "does not have a Dictionary type."));
585     return false;
586 }
587 
get(const String & key,Vector<String> & value) const588 bool Dictionary::get(const String& key, Vector<String>& value) const
589 {
590     v8::Local<v8::Value> v8Value;
591     if (!getKey(key, v8Value))
592         return false;
593 
594     if (!v8Value->IsArray())
595         return false;
596 
597     v8::Local<v8::Array> v8Array = v8::Local<v8::Array>::Cast(v8Value);
598     for (size_t i = 0; i < v8Array->Length(); ++i) {
599         v8::Local<v8::Value> indexedValue = v8Array->Get(v8::Uint32::New(i, m_isolate));
600         V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, indexedValue, false);
601         value.append(stringValue);
602     }
603 
604     return true;
605 }
606 
convert(ConversionContext & context,const String & key,Vector<String> & value) const607 bool Dictionary::convert(ConversionContext& context, const String& key, Vector<String>& value) const
608 {
609     ConversionContextScope scope(context);
610 
611     v8::Local<v8::Value> v8Value;
612     if (!getKey(key, v8Value))
613         return true;
614 
615     if (context.isNullable() && WebCore::isUndefinedOrNull(v8Value))
616         return true;
617 
618     if (!v8Value->IsArray()) {
619         context.throwTypeError(ExceptionMessages::notASequenceTypeProperty(key));
620         return false;
621     }
622 
623     return get(key, value);
624 }
625 
get(const String & key,ArrayValue & value) const626 bool Dictionary::get(const String& key, ArrayValue& value) const
627 {
628     v8::Local<v8::Value> v8Value;
629     if (!getKey(key, v8Value))
630         return false;
631 
632     if (!v8Value->IsArray())
633         return false;
634 
635     ASSERT(m_isolate);
636     ASSERT(m_isolate == v8::Isolate::GetCurrent());
637     value = ArrayValue(v8::Local<v8::Array>::Cast(v8Value), m_isolate);
638     return true;
639 }
640 
convert(ConversionContext & context,const String & key,ArrayValue & value) const641 bool Dictionary::convert(ConversionContext& context, const String& key, ArrayValue& value) const
642 {
643     ConversionContextScope scope(context);
644 
645     v8::Local<v8::Value> v8Value;
646     if (!getKey(key, v8Value))
647         return true;
648 
649     if (context.isNullable() && WebCore::isUndefinedOrNull(v8Value))
650         return true;
651 
652     if (!v8Value->IsArray()) {
653         context.throwTypeError(ExceptionMessages::notASequenceTypeProperty(key));
654         return false;
655     }
656 
657     return get(key, value);
658 }
659 
get(const String & key,RefPtr<DOMError> & value) const660 bool Dictionary::get(const String& key, RefPtr<DOMError>& value) const
661 {
662     v8::Local<v8::Value> v8Value;
663     if (!getKey(key, v8Value))
664         return false;
665 
666     DOMError* error = 0;
667     if (v8Value->IsObject()) {
668         v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value);
669         v8::Handle<v8::Object> domError = wrapper->FindInstanceInPrototypeChain(V8DOMError::domTemplate(m_isolate, worldType(m_isolate)));
670         if (!domError.IsEmpty())
671             error = V8DOMError::toNative(domError);
672     }
673     value = error;
674     return true;
675 }
676 
get(const String & key,OwnPtr<VoidCallback> & value) const677 bool Dictionary::get(const String& key, OwnPtr<VoidCallback>& value) const
678 {
679     v8::Local<v8::Value> v8Value;
680     if (!getKey(key, v8Value))
681         return false;
682 
683     if (!v8Value->IsFunction())
684         return false;
685 
686     value = V8VoidCallback::create(v8::Handle<v8::Function>::Cast(v8Value), getExecutionContext());
687     return true;
688 }
689 
getOwnPropertiesAsStringHashMap(HashMap<String,String> & hashMap) const690 bool Dictionary::getOwnPropertiesAsStringHashMap(HashMap<String, String>& hashMap) const
691 {
692     if (!isObject())
693         return false;
694 
695     v8::Handle<v8::Object> options = m_options->ToObject();
696     if (options.IsEmpty())
697         return false;
698 
699     v8::Local<v8::Array> properties = options->GetOwnPropertyNames();
700     if (properties.IsEmpty())
701         return true;
702     for (uint32_t i = 0; i < properties->Length(); ++i) {
703         v8::Local<v8::String> key = properties->Get(i)->ToString();
704         if (!options->Has(key))
705             continue;
706 
707         v8::Local<v8::Value> value = options->Get(key);
708         V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringKey, key, false);
709         V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, value, false);
710         if (!static_cast<const String&>(stringKey).isEmpty())
711             hashMap.set(stringKey, stringValue);
712     }
713 
714     return true;
715 }
716 
getOwnPropertyNames(Vector<String> & names) const717 bool Dictionary::getOwnPropertyNames(Vector<String>& names) const
718 {
719     if (!isObject())
720         return false;
721 
722     v8::Handle<v8::Object> options = m_options->ToObject();
723     if (options.IsEmpty())
724         return false;
725 
726     v8::Local<v8::Array> properties = options->GetOwnPropertyNames();
727     if (properties.IsEmpty())
728         return true;
729     for (uint32_t i = 0; i < properties->Length(); ++i) {
730         v8::Local<v8::String> key = properties->Get(i)->ToString();
731         if (!options->Has(key))
732             continue;
733         V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringKey, key, false);
734         names.append(stringKey);
735     }
736 
737     return true;
738 }
739 
resetPerPropertyContext()740 void Dictionary::ConversionContext::resetPerPropertyContext()
741 {
742     if (m_dirty) {
743         m_dirty = false;
744         m_isNullable = false;
745         m_propertyTypeName = "";
746     }
747 }
748 
setConversionType(const String & typeName,bool isNullable)749 Dictionary::ConversionContext& Dictionary::ConversionContext::setConversionType(const String& typeName, bool isNullable)
750 {
751     ASSERT(!m_dirty);
752     m_dirty = true;
753     m_isNullable = isNullable;
754     m_propertyTypeName = typeName;
755 
756     return *this;
757 }
758 
throwTypeError(const String & detail)759 void Dictionary::ConversionContext::throwTypeError(const String& detail)
760 {
761     if (forConstructor()) {
762         exceptionState().throwTypeError(detail);
763     } else {
764         ASSERT(!methodName().isEmpty());
765         exceptionState().throwTypeError(ExceptionMessages::failedToExecute(interfaceName(), methodName(), detail));
766     }
767 }
768 
769 } // namespace WebCore
770