• 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 "bindings/core/v8/V8DOMError.h"
30 #include "bindings/core/v8/V8EventTarget.h"
31 #include "bindings/core/v8/V8MediaKeyError.h"
32 #include "bindings/core/v8/V8MessagePort.h"
33 #include "bindings/core/v8/V8Storage.h"
34 #include "bindings/core/v8/V8TextTrack.h"
35 #include "bindings/core/v8/V8VoidCallback.h"
36 #include "bindings/core/v8/V8Window.h"
37 #include "bindings/modules/v8/V8Gamepad.h"
38 #include "bindings/modules/v8/V8HeaderMap.h"
39 #include "bindings/modules/v8/V8IDBKeyRange.h"
40 #include "bindings/modules/v8/V8MIDIPort.h"
41 #include "bindings/modules/v8/V8MediaStream.h"
42 #include "bindings/modules/v8/V8SpeechRecognitionResult.h"
43 #include "bindings/modules/v8/V8SpeechRecognitionResultList.h"
44 #include "bindings/v8/ArrayValue.h"
45 #include "bindings/v8/ExceptionMessages.h"
46 #include "bindings/v8/ExceptionState.h"
47 #include "bindings/v8/V8Binding.h"
48 #include "bindings/v8/custom/V8ArrayBufferViewCustom.h"
49 #include "bindings/v8/custom/V8Uint8ArrayCustom.h"
50 #include "core/html/track/TrackBase.h"
51 #include "modules/gamepad/Gamepad.h"
52 #include "modules/indexeddb/IDBKeyRange.h"
53 #include "modules/mediastream/MediaStream.h"
54 #include "modules/speech/SpeechRecognitionResult.h"
55 #include "modules/speech/SpeechRecognitionResultList.h"
56 #include "wtf/MathExtras.h"
57 
58 namespace WebCore {
59 
Dictionary()60 Dictionary::Dictionary()
61     : m_isolate(0)
62 {
63 }
64 
Dictionary(const v8::Handle<v8::Value> & options,v8::Isolate * isolate)65 Dictionary::Dictionary(const v8::Handle<v8::Value>& options, v8::Isolate* isolate)
66     : m_options(options)
67     , m_isolate(isolate)
68 {
69     ASSERT(m_isolate);
70 }
71 
~Dictionary()72 Dictionary::~Dictionary()
73 {
74 }
75 
operator =(const Dictionary & optionsObject)76 Dictionary& Dictionary::operator=(const Dictionary& optionsObject)
77 {
78     m_options = optionsObject.m_options;
79     m_isolate = optionsObject.m_isolate;
80     return *this;
81 }
82 
isObject() const83 bool Dictionary::isObject() const
84 {
85     return !isUndefinedOrNull() && m_options->IsObject();
86 }
87 
isUndefinedOrNull() const88 bool Dictionary::isUndefinedOrNull() const
89 {
90     if (m_options.IsEmpty())
91         return true;
92     return WebCore::isUndefinedOrNull(m_options);
93 }
94 
hasProperty(const String & key) const95 bool Dictionary::hasProperty(const String& key) const
96 {
97     if (isUndefinedOrNull())
98         return false;
99     v8::Local<v8::Object> options = m_options->ToObject();
100     ASSERT(!options.IsEmpty());
101 
102     ASSERT(m_isolate);
103     ASSERT(m_isolate == v8::Isolate::GetCurrent());
104     v8::Handle<v8::String> v8Key = v8String(m_isolate, key);
105     if (!options->Has(v8Key))
106         return false;
107 
108     return true;
109 }
110 
getKey(const String & key,v8::Local<v8::Value> & value) const111 bool Dictionary::getKey(const String& key, v8::Local<v8::Value>& value) const
112 {
113     if (isUndefinedOrNull())
114         return false;
115     v8::Local<v8::Object> options = m_options->ToObject();
116     ASSERT(!options.IsEmpty());
117 
118     ASSERT(m_isolate);
119     ASSERT(m_isolate == v8::Isolate::GetCurrent());
120     v8::Handle<v8::String> v8Key = v8String(m_isolate, key);
121     if (!options->Has(v8Key))
122         return false;
123     value = options->Get(v8Key);
124     if (value.IsEmpty())
125         return false;
126     return true;
127 }
128 
get(const String & key,v8::Local<v8::Value> & value) const129 bool Dictionary::get(const String& key, v8::Local<v8::Value>& value) const
130 {
131     return getKey(key, value);
132 }
133 
get(const String & key,bool & value) const134 bool Dictionary::get(const String& key, bool& value) const
135 {
136     v8::Local<v8::Value> v8Value;
137     if (!getKey(key, v8Value))
138         return false;
139 
140     v8::Local<v8::Boolean> v8Bool = v8Value->ToBoolean();
141     if (v8Bool.IsEmpty())
142         return false;
143     value = v8Bool->Value();
144     return true;
145 }
146 
convert(ConversionContext & context,const String & key,bool & value) const147 bool Dictionary::convert(ConversionContext& context, const String& key, bool& value) const
148 {
149     ConversionContextScope scope(context);
150     get(key, value);
151     return true;
152 }
153 
get(const String & key,int32_t & value) const154 bool Dictionary::get(const String& key, int32_t& value) const
155 {
156     v8::Local<v8::Value> v8Value;
157     if (!getKey(key, v8Value))
158         return false;
159 
160     v8::Local<v8::Int32> v8Int32 = v8Value->ToInt32();
161     if (v8Int32.IsEmpty())
162         return false;
163     value = v8Int32->Value();
164     return true;
165 }
166 
get(const String & key,double & value,bool & hasValue) const167 bool Dictionary::get(const String& key, double& value, bool& hasValue) const
168 {
169     v8::Local<v8::Value> v8Value;
170     if (!getKey(key, v8Value)) {
171         hasValue = false;
172         return false;
173     }
174 
175     hasValue = true;
176     TONATIVE_DEFAULT(v8::Local<v8::Number>, v8Number, v8Value->ToNumber(), false);
177     if (v8Number.IsEmpty())
178         return false;
179     value = v8Number->Value();
180     return true;
181 }
182 
get(const String & key,double & value) const183 bool Dictionary::get(const String& key, double& value) const
184 {
185     bool unused;
186     return get(key, value, unused);
187 }
188 
convert(ConversionContext & context,const String & key,double & value) const189 bool Dictionary::convert(ConversionContext& context, const String& key, double& value) const
190 {
191     ConversionContextScope scope(context);
192 
193     bool hasValue = false;
194     if (!get(key, value, hasValue) && hasValue) {
195         context.throwTypeError(ExceptionMessages::incorrectPropertyType(key, "is not of type 'double'."));
196         return false;
197     }
198     return true;
199 }
200 
201 template<typename StringType>
getStringType(const String & key,StringType & value) const202 inline bool Dictionary::getStringType(const String& key, StringType& value) const
203 {
204     v8::Local<v8::Value> v8Value;
205     if (!getKey(key, v8Value))
206         return false;
207 
208     TOSTRING_DEFAULT(V8StringResource<>, stringValue, v8Value, false);
209     value = stringValue;
210     return true;
211 }
212 
get(const String & key,String & value) const213 bool Dictionary::get(const String& key, String& value) const
214 {
215     return getStringType(key, value);
216 }
217 
get(const String & key,AtomicString & value) const218 bool Dictionary::get(const String& key, AtomicString& value) const
219 {
220     return getStringType(key, value);
221 }
222 
convert(ConversionContext & context,const String & key,String & value) const223 bool Dictionary::convert(ConversionContext& context, const String& key, String& value) const
224 {
225     ConversionContextScope scope(context);
226 
227     v8::Local<v8::Value> v8Value;
228     if (!getKey(key, v8Value))
229         return true;
230 
231     TOSTRING_DEFAULT(V8StringResource<>, stringValue, v8Value, false);
232     value = stringValue;
233     return true;
234 }
235 
get(const String & key,ScriptValue & value) const236 bool Dictionary::get(const String& key, ScriptValue& value) const
237 {
238     v8::Local<v8::Value> v8Value;
239     if (!getKey(key, v8Value))
240         return false;
241 
242     value = ScriptValue(ScriptState::current(m_isolate), v8Value);
243     return true;
244 }
245 
convert(ConversionContext & context,const String & key,ScriptValue & value) const246 bool Dictionary::convert(ConversionContext& context, const String& key, ScriptValue& value) const
247 {
248     ConversionContextScope scope(context);
249 
250     get(key, value);
251     return true;
252 }
253 
get(const String & key,unsigned short & value) const254 bool Dictionary::get(const String& key, unsigned short& value) const
255 {
256     v8::Local<v8::Value> v8Value;
257     if (!getKey(key, v8Value))
258         return false;
259 
260     v8::Local<v8::Int32> v8Int32 = v8Value->ToInt32();
261     if (v8Int32.IsEmpty())
262         return false;
263     value = static_cast<unsigned short>(v8Int32->Value());
264     return true;
265 }
266 
get(const String & key,short & value) const267 bool Dictionary::get(const String& key, short& value) const
268 {
269     v8::Local<v8::Value> v8Value;
270     if (!getKey(key, v8Value))
271         return false;
272 
273     v8::Local<v8::Int32> v8Int32 = v8Value->ToInt32();
274     if (v8Int32.IsEmpty())
275         return false;
276     value = static_cast<short>(v8Int32->Value());
277     return true;
278 }
279 
get(const String & key,unsigned & value) const280 bool Dictionary::get(const String& key, unsigned& value) const
281 {
282     v8::Local<v8::Value> v8Value;
283     if (!getKey(key, v8Value))
284         return false;
285 
286     v8::Local<v8::Int32> v8Int32 = v8Value->ToInt32();
287     if (v8Int32.IsEmpty())
288         return false;
289     value = static_cast<unsigned>(v8Int32->Value());
290     return true;
291 }
292 
get(const String & key,unsigned long & value) const293 bool Dictionary::get(const String& key, unsigned long& value) const
294 {
295     v8::Local<v8::Value> v8Value;
296     if (!getKey(key, v8Value))
297         return false;
298 
299     v8::Local<v8::Integer> v8Integer = v8Value->ToInteger();
300     if (v8Integer.IsEmpty())
301         return false;
302     value = static_cast<unsigned long>(v8Integer->Value());
303     return true;
304 }
305 
get(const String & key,unsigned long long & value) const306 bool Dictionary::get(const String& key, unsigned long long& value) const
307 {
308     v8::Local<v8::Value> v8Value;
309     if (!getKey(key, v8Value))
310         return false;
311 
312     TONATIVE_DEFAULT(v8::Local<v8::Number>, v8Number, v8Value->ToNumber(), false);
313     if (v8Number.IsEmpty())
314         return false;
315     double d = v8Number->Value();
316     doubleToInteger(d, value);
317     return true;
318 }
319 
get(const String & key,RefPtrWillBeMember<LocalDOMWindow> & value) const320 bool Dictionary::get(const String& key, RefPtrWillBeMember<LocalDOMWindow>& value) const
321 {
322     v8::Local<v8::Value> v8Value;
323     if (!getKey(key, v8Value))
324         return false;
325 
326     // We need to handle a DOMWindow specially, because a DOMWindow wrapper
327     // exists on a prototype chain of v8Value.
328     value = toDOMWindow(v8Value, m_isolate);
329     return true;
330 }
331 
get(const String & key,RefPtrWillBeMember<Storage> & value) const332 bool Dictionary::get(const String& key, RefPtrWillBeMember<Storage>& value) const
333 {
334     v8::Local<v8::Value> v8Value;
335     if (!getKey(key, v8Value))
336         return false;
337 
338     value = V8Storage::toNativeWithTypeCheck(m_isolate, v8Value);
339     return true;
340 }
341 
get(const String & key,MessagePortArray & value) const342 bool Dictionary::get(const String& key, MessagePortArray& value) const
343 {
344     v8::Local<v8::Value> v8Value;
345     if (!getKey(key, v8Value))
346         return false;
347 
348     ASSERT(m_isolate);
349     ASSERT(m_isolate == v8::Isolate::GetCurrent());
350     if (WebCore::isUndefinedOrNull(v8Value))
351         return true;
352     bool success = false;
353     value = toRefPtrNativeArray<MessagePort, V8MessagePort>(v8Value, key, m_isolate, &success);
354     return success;
355 }
356 
convert(ConversionContext & context,const String & key,MessagePortArray & value) const357 bool Dictionary::convert(ConversionContext& context, const String& key, MessagePortArray& value) const
358 {
359     ConversionContextScope scope(context);
360 
361     v8::Local<v8::Value> v8Value;
362     if (!getKey(key, v8Value))
363         return true;
364 
365     return get(key, value);
366 }
367 
get(const String & key,HashSet<AtomicString> & value) const368 bool Dictionary::get(const String& key, HashSet<AtomicString>& value) const
369 {
370     v8::Local<v8::Value> v8Value;
371     if (!getKey(key, v8Value))
372         return false;
373 
374     // FIXME: Support array-like objects
375     if (!v8Value->IsArray())
376         return false;
377 
378     ASSERT(m_isolate);
379     ASSERT(m_isolate == v8::Isolate::GetCurrent());
380     v8::Local<v8::Array> v8Array = v8::Local<v8::Array>::Cast(v8Value);
381     for (size_t i = 0; i < v8Array->Length(); ++i) {
382         v8::Local<v8::Value> indexedValue = v8Array->Get(v8::Integer::New(m_isolate, i));
383         TOSTRING_DEFAULT(V8StringResource<>, stringValue, indexedValue, false);
384         value.add(stringValue);
385     }
386 
387     return true;
388 }
389 
convert(ConversionContext & context,const String & key,HashSet<AtomicString> & value) const390 bool Dictionary::convert(ConversionContext& context, const String& key, HashSet<AtomicString>& value) const
391 {
392     ConversionContextScope scope(context);
393 
394     v8::Local<v8::Value> v8Value;
395     if (!getKey(key, v8Value))
396         return true;
397 
398     if (context.isNullable() && WebCore::isUndefinedOrNull(v8Value))
399         return true;
400 
401     if (!v8Value->IsArray()) {
402         context.throwTypeError(ExceptionMessages::notASequenceTypeProperty(key));
403         return false;
404     }
405 
406     return get(key, value);
407 }
408 
getWithUndefinedOrNullCheck(const String & key,String & value) const409 bool Dictionary::getWithUndefinedOrNullCheck(const String& key, String& value) const
410 {
411     v8::Local<v8::Value> v8Value;
412     if (!getKey(key, v8Value) || WebCore::isUndefinedOrNull(v8Value))
413         return false;
414 
415     TOSTRING_DEFAULT(V8StringResource<>, stringValue, v8Value, false);
416     value = stringValue;
417     return true;
418 }
419 
get(const String & key,RefPtr<Uint8Array> & value) const420 bool Dictionary::get(const String& key, RefPtr<Uint8Array>& value) const
421 {
422     v8::Local<v8::Value> v8Value;
423     if (!getKey(key, v8Value))
424         return false;
425 
426     value = V8Uint8Array::toNativeWithTypeCheck(m_isolate, v8Value);
427     return true;
428 }
429 
get(const String & key,RefPtr<ArrayBufferView> & value) const430 bool Dictionary::get(const String& key, RefPtr<ArrayBufferView>& value) const
431 {
432     v8::Local<v8::Value> v8Value;
433     if (!getKey(key, v8Value))
434         return false;
435 
436     value = V8ArrayBufferView::toNativeWithTypeCheck(m_isolate, v8Value);
437     return true;
438 }
439 
get(const String & key,RefPtrWillBeMember<MIDIPort> & value) const440 bool Dictionary::get(const String& key, RefPtrWillBeMember<MIDIPort>& value) const
441 {
442     v8::Local<v8::Value> v8Value;
443     if (!getKey(key, v8Value))
444         return false;
445 
446     value = V8MIDIPort::toNativeWithTypeCheck(m_isolate, 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 = V8MediaKeyError::toNativeWithTypeCheck(m_isolate, v8Value);
457     return true;
458 }
459 
get(const String & key,RefPtrWillBeMember<TrackBase> & value) const460 bool Dictionary::get(const String& key, RefPtrWillBeMember<TrackBase>& value) const
461 {
462     v8::Local<v8::Value> v8Value;
463     if (!getKey(key, v8Value))
464         return false;
465 
466     TrackBase* source = 0;
467     if (v8Value->IsObject()) {
468         v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value);
469 
470         // FIXME: this will need to be changed so it can also return an AudioTrack or a VideoTrack once
471         // we add them.
472         v8::Handle<v8::Object> track = V8TextTrack::findInstanceInPrototypeChain(wrapper, m_isolate);
473         if (!track.IsEmpty())
474             source = V8TextTrack::toNative(track);
475     }
476     value = source;
477     return true;
478 }
479 
get(const String & key,Member<SpeechRecognitionResult> & value) const480 bool Dictionary::get(const String& key, Member<SpeechRecognitionResult>& value) const
481 {
482     v8::Local<v8::Value> v8Value;
483     if (!getKey(key, v8Value))
484         return false;
485 
486     value = V8SpeechRecognitionResult::toNativeWithTypeCheck(m_isolate, v8Value);
487     return true;
488 }
489 
get(const String & key,Member<SpeechRecognitionResultList> & value) const490 bool Dictionary::get(const String& key, Member<SpeechRecognitionResultList>& value) const
491 {
492     v8::Local<v8::Value> v8Value;
493     if (!getKey(key, v8Value))
494         return false;
495 
496     value = V8SpeechRecognitionResultList::toNativeWithTypeCheck(m_isolate, v8Value);
497     return true;
498 }
499 
get(const String & key,Member<Gamepad> & value) const500 bool Dictionary::get(const String& key, Member<Gamepad>& value) const
501 {
502     v8::Local<v8::Value> v8Value;
503     if (!getKey(key, v8Value))
504         return false;
505 
506     value = V8Gamepad::toNativeWithTypeCheck(m_isolate, v8Value);
507     return true;
508 }
509 
get(const String & key,RefPtr<MediaStream> & value) const510 bool Dictionary::get(const String& key, RefPtr<MediaStream>& value) const
511 {
512     v8::Local<v8::Value> v8Value;
513     if (!getKey(key, v8Value))
514         return false;
515 
516     value = V8MediaStream::toNativeWithTypeCheck(m_isolate, v8Value);
517     return true;
518 }
519 
get(const String & key,RefPtrWillBeMember<EventTarget> & value) const520 bool Dictionary::get(const String& key, RefPtrWillBeMember<EventTarget>& value) const
521 {
522     v8::Local<v8::Value> v8Value;
523     if (!getKey(key, v8Value))
524         return false;
525 
526     value = nullptr;
527     // We need to handle a LocalDOMWindow specially, because a LocalDOMWindow wrapper
528     // exists on a prototype chain of v8Value.
529     if (v8Value->IsObject()) {
530         v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value);
531         v8::Handle<v8::Object> window = V8Window::findInstanceInPrototypeChain(wrapper, m_isolate);
532         if (!window.IsEmpty()) {
533             value = toWrapperTypeInfo(window)->toEventTarget(window);
534             return true;
535         }
536     }
537 
538     if (V8DOMWrapper::isDOMWrapper(v8Value)) {
539         v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value);
540         value = toWrapperTypeInfo(wrapper)->toEventTarget(wrapper);
541     }
542     return true;
543 }
544 
get(const String & key,Dictionary & value) const545 bool Dictionary::get(const String& key, Dictionary& value) const
546 {
547     v8::Local<v8::Value> v8Value;
548     if (!getKey(key, v8Value))
549         return false;
550 
551     if (v8Value->IsObject()) {
552         ASSERT(m_isolate);
553         ASSERT(m_isolate == v8::Isolate::GetCurrent());
554         value = Dictionary(v8Value, m_isolate);
555     }
556 
557     return true;
558 }
559 
get(const String & key,RefPtr<HeaderMap> & value) const560 bool Dictionary::get(const String& key, RefPtr<HeaderMap>& value) const
561 {
562     v8::Local<v8::Value> v8Value;
563     if (!getKey(key, v8Value))
564         return false;
565 
566     value = V8HeaderMap::toNativeWithTypeCheck(m_isolate, v8Value);
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(m_isolate, i));
600         TOSTRING_DEFAULT(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,RefPtrWillBeMember<DOMError> & value) const660 bool Dictionary::get(const String& key, RefPtrWillBeMember<DOMError>& value) const
661 {
662     v8::Local<v8::Value> v8Value;
663     if (!getKey(key, v8Value))
664         return false;
665 
666     value = V8DOMError::toNativeWithTypeCheck(m_isolate, v8Value);
667     return true;
668 }
669 
getOwnPropertiesAsStringHashMap(HashMap<String,String> & hashMap) const670 bool Dictionary::getOwnPropertiesAsStringHashMap(HashMap<String, String>& hashMap) const
671 {
672     if (!isObject())
673         return false;
674 
675     v8::Handle<v8::Object> options = m_options->ToObject();
676     if (options.IsEmpty())
677         return false;
678 
679     v8::Local<v8::Array> properties = options->GetOwnPropertyNames();
680     if (properties.IsEmpty())
681         return true;
682     for (uint32_t i = 0; i < properties->Length(); ++i) {
683         v8::Local<v8::String> key = properties->Get(i)->ToString();
684         if (!options->Has(key))
685             continue;
686 
687         v8::Local<v8::Value> value = options->Get(key);
688         TOSTRING_DEFAULT(V8StringResource<>, stringKey, key, false);
689         TOSTRING_DEFAULT(V8StringResource<>, stringValue, value, false);
690         if (!static_cast<const String&>(stringKey).isEmpty())
691             hashMap.set(stringKey, stringValue);
692     }
693 
694     return true;
695 }
696 
getOwnPropertyNames(Vector<String> & names) const697 bool Dictionary::getOwnPropertyNames(Vector<String>& names) const
698 {
699     if (!isObject())
700         return false;
701 
702     v8::Handle<v8::Object> options = m_options->ToObject();
703     if (options.IsEmpty())
704         return false;
705 
706     v8::Local<v8::Array> properties = options->GetOwnPropertyNames();
707     if (properties.IsEmpty())
708         return true;
709     for (uint32_t i = 0; i < properties->Length(); ++i) {
710         v8::Local<v8::String> key = properties->Get(i)->ToString();
711         if (!options->Has(key))
712             continue;
713         TOSTRING_DEFAULT(V8StringResource<>, stringKey, key, false);
714         names.append(stringKey);
715     }
716 
717     return true;
718 }
719 
resetPerPropertyContext()720 void Dictionary::ConversionContext::resetPerPropertyContext()
721 {
722     if (m_dirty) {
723         m_dirty = false;
724         m_isNullable = false;
725         m_propertyTypeName = "";
726     }
727 }
728 
setConversionType(const String & typeName,bool isNullable)729 Dictionary::ConversionContext& Dictionary::ConversionContext::setConversionType(const String& typeName, bool isNullable)
730 {
731     ASSERT(!m_dirty);
732     m_dirty = true;
733     m_isNullable = isNullable;
734     m_propertyTypeName = typeName;
735 
736     return *this;
737 }
738 
throwTypeError(const String & detail)739 void Dictionary::ConversionContext::throwTypeError(const String& detail)
740 {
741     exceptionState().throwTypeError(detail);
742 }
743 
744 } // namespace WebCore
745