Home | History | Annotate | Download | only in v8
      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 
     61 Dictionary::Dictionary()
     62     : m_isolate(0)
     63 {
     64 }
     65 
     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 
     73 Dictionary::~Dictionary()
     74 {
     75 }
     76 
     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 
     84 bool Dictionary::isObject() const
     85 {
     86     return !isUndefinedOrNull() && m_options->IsObject();
     87 }
     88 
     89 bool Dictionary::isUndefinedOrNull() const
     90 {
     91     if (m_options.IsEmpty())
     92         return true;
     93     return WebCore::isUndefinedOrNull(m_options);
     94 }
     95 
     96 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 
    112 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 
    130 bool Dictionary::get(const String& key, v8::Local<v8::Value>& value) const
    131 {
    132     return getKey(key, value);
    133 }
    134 
    135 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 
    148 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 
    155 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 
    168 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 
    184 bool Dictionary::get(const String& key, double& value) const
    185 {
    186     bool unused;
    187     return get(key, value, unused);
    188 }
    189 
    190 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 
    202 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 
    213 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 
    226 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 
    236 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 
    244 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 
    257 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 
    270 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 
    283 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 
    296 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 
    310 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 
    328 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 
    340 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 
    351 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 
    362 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 
    384 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 
    403 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 
    414 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 
    426 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 
    438 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 
    450 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 
    462 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 
    482 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 
    494 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 
    506 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 
    518 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 
    530 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 
    555 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 
    570 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 
    588 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 
    607 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 
    626 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 
    641 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 
    660 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 
    677 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 
    690 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 
    717 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 
    740 void Dictionary::ConversionContext::resetPerPropertyContext()
    741 {
    742     if (m_dirty) {
    743         m_dirty = false;
    744         m_isNullable = false;
    745         m_propertyTypeName = "";
    746     }
    747 }
    748 
    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 
    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