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 "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 
     60 Dictionary::Dictionary()
     61     : m_isolate(0)
     62 {
     63 }
     64 
     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 
     72 Dictionary::~Dictionary()
     73 {
     74 }
     75 
     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 
     83 bool Dictionary::isObject() const
     84 {
     85     return !isUndefinedOrNull() && m_options->IsObject();
     86 }
     87 
     88 bool Dictionary::isUndefinedOrNull() const
     89 {
     90     if (m_options.IsEmpty())
     91         return true;
     92     return WebCore::isUndefinedOrNull(m_options);
     93 }
     94 
     95 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 
    111 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 
    129 bool Dictionary::get(const String& key, v8::Local<v8::Value>& value) const
    130 {
    131     return getKey(key, value);
    132 }
    133 
    134 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 
    147 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 
    154 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 
    167 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 
    183 bool Dictionary::get(const String& key, double& value) const
    184 {
    185     bool unused;
    186     return get(key, value, unused);
    187 }
    188 
    189 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>
    202 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 
    213 bool Dictionary::get(const String& key, String& value) const
    214 {
    215     return getStringType(key, value);
    216 }
    217 
    218 bool Dictionary::get(const String& key, AtomicString& value) const
    219 {
    220     return getStringType(key, value);
    221 }
    222 
    223 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 
    236 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 
    246 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 
    254 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 
    267 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 
    280 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 
    293 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 
    306 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 
    320 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 
    332 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 
    342 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 
    357 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 
    368 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 
    390 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 
    409 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 
    420 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 
    430 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 
    440 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 
    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 = V8MediaKeyError::toNativeWithTypeCheck(m_isolate, v8Value);
    457     return true;
    458 }
    459 
    460 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 
    480 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 
    490 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 
    500 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 
    510 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 
    520 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 
    545 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 
    560 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 
    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(m_isolate, i));
    600         TOSTRING_DEFAULT(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, 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 
    670 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 
    697 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 
    720 void Dictionary::ConversionContext::resetPerPropertyContext()
    721 {
    722     if (m_dirty) {
    723         m_dirty = false;
    724         m_isNullable = false;
    725         m_propertyTypeName = "";
    726     }
    727 }
    728 
    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 
    739 void Dictionary::ConversionContext::throwTypeError(const String& detail)
    740 {
    741     exceptionState().throwTypeError(detail);
    742 }
    743 
    744 } // namespace WebCore
    745