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
28#include "bindings/core/v8/ArrayValue.h"
29#include "bindings/core/v8/DictionaryHelperForBindings.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 "core/html/track/TrackBase.h"
46#include "wtf/MathExtras.h"
47
48namespace blink {
49
50template <>
51bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, v8::Local<v8::Value>& value)
52{
53    return dictionary.get(key, value);
54}
55
56template <>
57bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, Dictionary& value)
58{
59    return dictionary.get(key, value);
60}
61
62template <>
63bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, bool& value)
64{
65    v8::Local<v8::Value> v8Value;
66    if (!dictionary.get(key, v8Value))
67        return false;
68
69    v8::Local<v8::Boolean> v8Bool = v8Value->ToBoolean();
70    if (v8Bool.IsEmpty())
71        return false;
72    value = v8Bool->Value();
73    return true;
74}
75
76template <>
77bool DictionaryHelper::convert(const Dictionary& dictionary, Dictionary::ConversionContext& context, const String& key, bool& value)
78{
79    Dictionary::ConversionContextScope scope(context);
80    DictionaryHelper::get(dictionary, key, value);
81    return true;
82}
83
84template <>
85bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, int32_t& value)
86{
87    v8::Local<v8::Value> v8Value;
88    if (!dictionary.get(key, v8Value))
89        return false;
90
91    v8::Local<v8::Int32> v8Int32 = v8Value->ToInt32();
92    if (v8Int32.IsEmpty())
93        return false;
94    value = v8Int32->Value();
95    return true;
96}
97
98template <>
99bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, double& value, bool& hasValue)
100{
101    v8::Local<v8::Value> v8Value;
102    if (!dictionary.get(key, v8Value)) {
103        hasValue = false;
104        return false;
105    }
106
107    hasValue = true;
108    TONATIVE_DEFAULT(v8::Local<v8::Number>, v8Number, v8Value->ToNumber(), false);
109    if (v8Number.IsEmpty())
110        return false;
111    value = v8Number->Value();
112    return true;
113}
114
115template <>
116bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, double& value)
117{
118    bool unused;
119    return DictionaryHelper::get(dictionary, key, value, unused);
120}
121
122template <>
123bool DictionaryHelper::convert(const Dictionary& dictionary, Dictionary::ConversionContext& context, const String& key, double& value)
124{
125    Dictionary::ConversionContextScope scope(context);
126
127    bool hasValue = false;
128    if (!DictionaryHelper::get(dictionary, key, value, hasValue) && hasValue) {
129        context.throwTypeError(ExceptionMessages::incorrectPropertyType(key, "is not of type 'double'."));
130        return false;
131    }
132    return true;
133}
134
135template<typename StringType>
136bool getStringType(const Dictionary& dictionary, const String& key, StringType& value)
137{
138    v8::Local<v8::Value> v8Value;
139    if (!dictionary.get(key, v8Value))
140        return false;
141
142    TOSTRING_DEFAULT(V8StringResource<>, stringValue, v8Value, false);
143    value = stringValue;
144    return true;
145}
146
147template <>
148bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, String& value)
149{
150    return getStringType(dictionary, key, value);
151}
152
153template <>
154bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, AtomicString& value)
155{
156    return getStringType(dictionary, key, value);
157}
158
159template <>
160bool DictionaryHelper::convert(const Dictionary& dictionary, Dictionary::ConversionContext& context, const String& key, String& value)
161{
162    Dictionary::ConversionContextScope scope(context);
163
164    v8::Local<v8::Value> v8Value;
165    if (!dictionary.get(key, v8Value))
166        return true;
167
168    TOSTRING_DEFAULT(V8StringResource<>, stringValue, v8Value, false);
169    value = stringValue;
170    return true;
171}
172
173template <>
174bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, ScriptValue& value)
175{
176    v8::Local<v8::Value> v8Value;
177    if (!dictionary.get(key, v8Value))
178        return false;
179
180    value = ScriptValue(ScriptState::current(dictionary.isolate()), v8Value);
181    return true;
182}
183
184template <>
185bool DictionaryHelper::convert(const Dictionary& dictionary, Dictionary::ConversionContext& context, const String& key, ScriptValue& value)
186{
187    Dictionary::ConversionContextScope scope(context);
188
189    DictionaryHelper::get(dictionary, key, value);
190    return true;
191}
192
193template<typename NumericType>
194bool getNumericType(const Dictionary& dictionary, const String& key, NumericType& value)
195{
196    v8::Local<v8::Value> v8Value;
197    if (!dictionary.get(key, v8Value))
198        return false;
199
200    v8::Local<v8::Int32> v8Int32 = v8Value->ToInt32();
201    if (v8Int32.IsEmpty())
202        return false;
203    value = static_cast<NumericType>(v8Int32->Value());
204    return true;
205}
206
207template <>
208bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, short& value)
209{
210    return getNumericType<short>(dictionary, key, value);
211}
212
213template <>
214bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, unsigned short& value)
215{
216    return getNumericType<unsigned short>(dictionary, key, value);
217}
218
219template <>
220bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, unsigned& value)
221{
222    return getNumericType<unsigned>(dictionary, key, value);
223}
224
225template <>
226bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, unsigned long& value)
227{
228    v8::Local<v8::Value> v8Value;
229    if (!dictionary.get(key, v8Value))
230        return false;
231
232    v8::Local<v8::Integer> v8Integer = v8Value->ToInteger();
233    if (v8Integer.IsEmpty())
234        return false;
235    value = static_cast<unsigned long>(v8Integer->Value());
236    return true;
237}
238
239template <>
240bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, unsigned long long& value)
241{
242    v8::Local<v8::Value> v8Value;
243    if (!dictionary.get(key, v8Value))
244        return false;
245
246    TONATIVE_DEFAULT(v8::Local<v8::Number>, v8Number, v8Value->ToNumber(), false);
247    if (v8Number.IsEmpty())
248        return false;
249    double d = v8Number->Value();
250    doubleToInteger(d, value);
251    return true;
252}
253
254template <>
255bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, RefPtrWillBeMember<LocalDOMWindow>& value)
256{
257    v8::Local<v8::Value> v8Value;
258    if (!dictionary.get(key, v8Value))
259        return false;
260
261    // We need to handle a DOMWindow specially, because a DOMWindow wrapper
262    // exists on a prototype chain of v8Value.
263    value = toDOMWindow(v8Value, dictionary.isolate());
264    return true;
265}
266
267template <>
268bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, HashSet<AtomicString>& value)
269{
270    v8::Local<v8::Value> v8Value;
271    if (!dictionary.get(key, v8Value))
272        return false;
273
274    // FIXME: Support array-like objects
275    if (!v8Value->IsArray())
276        return false;
277
278    ASSERT(dictionary.isolate());
279    ASSERT(dictionary.isolate() == v8::Isolate::GetCurrent());
280    v8::Local<v8::Array> v8Array = v8::Local<v8::Array>::Cast(v8Value);
281    for (size_t i = 0; i < v8Array->Length(); ++i) {
282        v8::Local<v8::Value> indexedValue = v8Array->Get(v8::Integer::New(dictionary.isolate(), i));
283        TOSTRING_DEFAULT(V8StringResource<>, stringValue, indexedValue, false);
284        value.add(stringValue);
285    }
286
287    return true;
288}
289
290template <>
291bool DictionaryHelper::convert(const Dictionary& dictionary, Dictionary::ConversionContext& context, const String& key, HashSet<AtomicString>& value)
292{
293    Dictionary::ConversionContextScope scope(context);
294
295    v8::Local<v8::Value> v8Value;
296    if (!dictionary.get(key, v8Value))
297        return true;
298
299    if (context.isNullable() && blink::isUndefinedOrNull(v8Value))
300        return true;
301
302    if (!v8Value->IsArray()) {
303        context.throwTypeError(ExceptionMessages::notASequenceTypeProperty(key));
304        return false;
305    }
306
307    return DictionaryHelper::get(dictionary, key, value);
308}
309
310template <>
311bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, RefPtrWillBeMember<TrackBase>& value)
312{
313    v8::Local<v8::Value> v8Value;
314    if (!dictionary.get(key, v8Value))
315        return false;
316
317    TrackBase* source = 0;
318    if (v8Value->IsObject()) {
319        v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value);
320
321        // FIXME: this will need to be changed so it can also return an AudioTrack or a VideoTrack once
322        // we add them.
323        v8::Handle<v8::Object> track = V8TextTrack::findInstanceInPrototypeChain(wrapper, dictionary.isolate());
324        if (!track.IsEmpty())
325            source = V8TextTrack::toImpl(track);
326    }
327    value = source;
328    return true;
329}
330
331template <>
332bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, RefPtrWillBeMember<EventTarget>& value)
333{
334    v8::Local<v8::Value> v8Value;
335    if (!dictionary.get(key, v8Value))
336        return false;
337
338    value = nullptr;
339    // We need to handle a LocalDOMWindow specially, because a LocalDOMWindow wrapper
340    // exists on a prototype chain of v8Value.
341    if (v8Value->IsObject()) {
342        v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value);
343        v8::Handle<v8::Object> window = V8Window::findInstanceInPrototypeChain(wrapper, dictionary.isolate());
344        if (!window.IsEmpty()) {
345            value = toWrapperTypeInfo(window)->toEventTarget(window);
346            return true;
347        }
348    }
349
350    if (V8DOMWrapper::isDOMWrapper(v8Value)) {
351        v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value);
352        value = toWrapperTypeInfo(wrapper)->toEventTarget(wrapper);
353    }
354    return true;
355}
356
357template <>
358bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, Vector<String>& value)
359{
360    v8::Local<v8::Value> v8Value;
361    if (!dictionary.get(key, v8Value))
362        return false;
363
364    if (!v8Value->IsArray())
365        return false;
366
367    v8::Local<v8::Array> v8Array = v8::Local<v8::Array>::Cast(v8Value);
368    for (size_t i = 0; i < v8Array->Length(); ++i) {
369        v8::Local<v8::Value> indexedValue = v8Array->Get(v8::Uint32::New(dictionary.isolate(), i));
370        TOSTRING_DEFAULT(V8StringResource<>, stringValue, indexedValue, false);
371        value.append(stringValue);
372    }
373
374    return true;
375}
376
377template <>
378bool DictionaryHelper::convert(const Dictionary& dictionary, Dictionary::ConversionContext& context, const String& key, Vector<String>& value)
379{
380    Dictionary::ConversionContextScope scope(context);
381
382    v8::Local<v8::Value> v8Value;
383    if (!dictionary.get(key, v8Value))
384        return true;
385
386    if (context.isNullable() && blink::isUndefinedOrNull(v8Value))
387        return true;
388
389    if (!v8Value->IsArray()) {
390        context.throwTypeError(ExceptionMessages::notASequenceTypeProperty(key));
391        return false;
392    }
393
394    return DictionaryHelper::get(dictionary, key, value);
395}
396
397template <>
398bool DictionaryHelper::get(const Dictionary& dictionary, const String& key, ArrayValue& value)
399{
400    v8::Local<v8::Value> v8Value;
401    if (!dictionary.get(key, v8Value))
402        return false;
403
404    if (!v8Value->IsArray())
405        return false;
406
407    ASSERT(dictionary.isolate());
408    ASSERT(dictionary.isolate() == v8::Isolate::GetCurrent());
409    value = ArrayValue(v8::Local<v8::Array>::Cast(v8Value), dictionary.isolate());
410    return true;
411}
412
413template <>
414bool DictionaryHelper::convert(const Dictionary& dictionary, Dictionary::ConversionContext& context, const String& key, ArrayValue& value)
415{
416    Dictionary::ConversionContextScope scope(context);
417
418    v8::Local<v8::Value> v8Value;
419    if (!dictionary.get(key, v8Value))
420        return true;
421
422    if (context.isNullable() && blink::isUndefinedOrNull(v8Value))
423        return true;
424
425    if (!v8Value->IsArray()) {
426        context.throwTypeError(ExceptionMessages::notASequenceTypeProperty(key));
427        return false;
428    }
429
430    return DictionaryHelper::get(dictionary, key, value);
431}
432
433template <>
434struct DictionaryHelperTraits<Uint8Array> {
435    typedef V8Uint8Array type;
436};
437
438template <>
439struct DictionaryHelperTraits<ArrayBufferView> {
440    typedef V8ArrayBufferView type;
441};
442
443template <>
444struct DictionaryHelperTraits<MediaKeyError> {
445    typedef V8MediaKeyError type;
446};
447
448template <>
449struct DictionaryHelperTraits<DOMError> {
450    typedef V8DOMError type;
451};
452
453template <>
454struct DictionaryHelperTraits<Storage> {
455    typedef V8Storage type;
456};
457
458template <>
459struct DictionaryHelperTraits<Element> {
460    typedef V8Element type;
461};
462
463template <>
464struct DictionaryHelperTraits<Path2D> {
465    typedef V8Path2D type;
466};
467
468template bool DictionaryHelper::get(const Dictionary&, const String& key, RefPtr<Uint8Array>& value);
469template bool DictionaryHelper::get(const Dictionary&, const String& key, RefPtr<ArrayBufferView>& value);
470template bool DictionaryHelper::get(const Dictionary&, const String& key, RefPtrWillBeMember<MediaKeyError>& value);
471template bool DictionaryHelper::get(const Dictionary&, const String& key, RefPtrWillBeMember<DOMError>& value);
472template bool DictionaryHelper::get(const Dictionary&, const String& key, RefPtrWillBeMember<Storage>& value);
473template bool DictionaryHelper::get(const Dictionary&, const String& key, RefPtrWillBeMember<Element>& value);
474template bool DictionaryHelper::get(const Dictionary&, const String& key, RawPtr<Element>& value);
475template bool DictionaryHelper::get(const Dictionary&, const String& key, RefPtrWillBeMember<Path2D>& value);
476template bool DictionaryHelper::get(const Dictionary&, const String& key, RawPtr<Path2D>& value);
477
478template <typename T>
479struct IntegralTypeTraits {
480};
481
482template <>
483struct IntegralTypeTraits<uint8_t> {
484    static inline uint8_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
485    {
486        return toUInt8(value, configuration, exceptionState);
487    }
488    static const String typeName() { return "UInt8"; }
489};
490
491template <>
492struct IntegralTypeTraits<int8_t> {
493    static inline int8_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
494    {
495        return toInt8(value, configuration, exceptionState);
496    }
497    static const String typeName() { return "Int8"; }
498};
499
500template <>
501struct IntegralTypeTraits<unsigned short> {
502    static inline uint16_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
503    {
504        return toUInt16(value, configuration, exceptionState);
505    }
506    static const String typeName() { return "UInt16"; }
507};
508
509template <>
510struct IntegralTypeTraits<short> {
511    static inline int16_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
512    {
513        return toInt16(value, configuration, exceptionState);
514    }
515    static const String typeName() { return "Int16"; }
516};
517
518template <>
519struct IntegralTypeTraits<unsigned> {
520    static inline uint32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
521    {
522        return toUInt32(value, configuration, exceptionState);
523    }
524    static const String typeName() { return "UInt32"; }
525};
526
527template <>
528struct IntegralTypeTraits<unsigned long> {
529    static inline uint32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
530    {
531        return toUInt32(value, configuration, exceptionState);
532    }
533    static const String typeName() { return "UInt32"; }
534};
535
536template <>
537struct IntegralTypeTraits<int> {
538    static inline int32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
539    {
540        return toInt32(value, configuration, exceptionState);
541    }
542    static const String typeName() { return "Int32"; }
543};
544
545template <>
546struct IntegralTypeTraits<long> {
547    static inline int32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
548    {
549        return toInt32(value, configuration, exceptionState);
550    }
551    static const String typeName() { return "Int32"; }
552};
553
554template <>
555struct IntegralTypeTraits<unsigned long long> {
556    static inline unsigned long long toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
557    {
558        return toUInt64(value, configuration, exceptionState);
559    }
560    static const String typeName() { return "UInt64"; }
561};
562
563template <>
564struct IntegralTypeTraits<long long> {
565    static inline long long toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
566    {
567        return toInt64(value, configuration, exceptionState);
568    }
569    static const String typeName() { return "Int64"; }
570};
571
572template<typename T>
573bool DictionaryHelper::convert(const Dictionary& dictionary, Dictionary::ConversionContext& context, const String& key, T& value)
574{
575    Dictionary::ConversionContextScope scope(context);
576
577    v8::Local<v8::Value> v8Value;
578    if (!dictionary.get(key, v8Value))
579        return true;
580
581    value = IntegralTypeTraits<T>::toIntegral(v8Value, NormalConversion, context.exceptionState());
582    if (context.exceptionState().throwIfNeeded())
583        return false;
584
585    return true;
586}
587
588template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, uint8_t& value);
589template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, int8_t& value);
590template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, unsigned short& value);
591template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, short& value);
592template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, unsigned& value);
593template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, unsigned long& value);
594template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, int& value);
595template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, long& value);
596template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, long long& value);
597template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, unsigned long long& value);
598
599template<typename T>
600bool DictionaryHelper::convert(const Dictionary& dictionary, Dictionary::ConversionContext& context, const String& key, Nullable<T>& value)
601{
602    Dictionary::ConversionContextScope scope(context);
603
604    v8::Local<v8::Value> v8Value;
605    if (!dictionary.get(key, v8Value))
606        return true;
607
608    if (context.isNullable() && blink::isUndefinedOrNull(v8Value)) {
609        value = Nullable<T>();
610        return true;
611    }
612
613    T converted = IntegralTypeTraits<T>::toIntegral(v8Value, NormalConversion, context.exceptionState());
614
615    if (context.exceptionState().throwIfNeeded())
616        return false;
617
618    value = Nullable<T>(converted);
619    return true;
620}
621
622template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, Nullable<uint8_t>& value);
623template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, Nullable<int8_t>& value);
624template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, Nullable<unsigned short>& value);
625template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, Nullable<short>& value);
626template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, Nullable<unsigned>& value);
627template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, Nullable<unsigned long>& value);
628template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, Nullable<int>& value);
629template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, Nullable<long>& value);
630template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, Nullable<long long>& value);
631template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, Nullable<unsigned long long>& value);
632
633template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, RefPtrWillBeMember<LocalDOMWindow>& value);
634template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, RefPtrWillBeMember<Storage>& value);
635template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, RefPtr<Uint8Array>& value);
636template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, RefPtr<ArrayBufferView>& value);
637template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, RefPtrWillBeMember<MediaKeyError>& value);
638template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, RefPtrWillBeMember<TrackBase>& value);
639template bool DictionaryHelper::convert(const Dictionary&, Dictionary::ConversionContext&, const String& key, RefPtrWillBeMember<EventTarget>& value);
640
641template <>
642bool DictionaryHelper::convert(const Dictionary& dictionary, Dictionary::ConversionContext& context, const String& key, MessagePortArray& value)
643{
644    Dictionary::ConversionContextScope scope(context);
645
646    v8::Local<v8::Value> v8Value;
647    if (!dictionary.get(key, v8Value))
648        return true;
649
650    ASSERT(dictionary.isolate());
651    ASSERT(dictionary.isolate() == v8::Isolate::GetCurrent());
652
653    if (isUndefinedOrNull(v8Value))
654        return true;
655
656    value = toRefPtrWillBeMemberNativeArray<MessagePort, V8MessagePort>(v8Value, key, dictionary.isolate(), context.exceptionState());
657
658    if (context.exceptionState().throwIfNeeded())
659        return false;
660
661    return true;
662}
663
664} // namespace blink
665