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/core/v8/Dictionary.h"
     28 
     29 #include "bindings/core/v8/ArrayValue.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 "bindings/modules/v8/V8Gamepad.h"
     46 #include "bindings/modules/v8/V8Headers.h"
     47 #include "bindings/modules/v8/V8IDBKeyRange.h"
     48 #include "bindings/modules/v8/V8MIDIPort.h"
     49 #include "bindings/modules/v8/V8MediaStream.h"
     50 #include "bindings/modules/v8/V8SpeechRecognitionResult.h"
     51 #include "bindings/modules/v8/V8SpeechRecognitionResultList.h"
     52 #include "core/html/track/TrackBase.h"
     53 #include "modules/gamepad/Gamepad.h"
     54 #include "modules/indexeddb/IDBKeyRange.h"
     55 #include "modules/mediastream/MediaStream.h"
     56 #include "modules/speech/SpeechRecognitionResult.h"
     57 #include "modules/speech/SpeechRecognitionResultList.h"
     58 #include "wtf/MathExtras.h"
     59 
     60 namespace blink {
     61 
     62 Dictionary::Dictionary()
     63     : m_isolate(0)
     64 {
     65 }
     66 
     67 Dictionary::Dictionary(const v8::Handle<v8::Value>& options, v8::Isolate* isolate)
     68     : m_options(options)
     69     , m_isolate(isolate)
     70 {
     71     ASSERT(m_isolate);
     72 }
     73 
     74 Dictionary::~Dictionary()
     75 {
     76 }
     77 
     78 Dictionary& Dictionary::operator=(const Dictionary& optionsObject)
     79 {
     80     m_options = optionsObject.m_options;
     81     m_isolate = optionsObject.m_isolate;
     82     return *this;
     83 }
     84 
     85 Dictionary Dictionary::createEmpty(v8::Isolate* isolate)
     86 {
     87     return Dictionary(v8::Object::New(isolate), isolate);
     88 }
     89 
     90 bool Dictionary::isObject() const
     91 {
     92     return !isUndefinedOrNull() && m_options->IsObject();
     93 }
     94 
     95 bool Dictionary::isUndefinedOrNull() const
     96 {
     97     if (m_options.IsEmpty())
     98         return true;
     99     return blink::isUndefinedOrNull(m_options);
    100 }
    101 
    102 bool Dictionary::hasProperty(const String& key) const
    103 {
    104     if (isUndefinedOrNull())
    105         return false;
    106     v8::Local<v8::Object> options = m_options->ToObject();
    107     ASSERT(!options.IsEmpty());
    108 
    109     ASSERT(m_isolate);
    110     ASSERT(m_isolate == v8::Isolate::GetCurrent());
    111     v8::Handle<v8::String> v8Key = v8String(m_isolate, key);
    112     if (!options->Has(v8Key))
    113         return false;
    114 
    115     return true;
    116 }
    117 
    118 bool Dictionary::getKey(const String& key, v8::Local<v8::Value>& value) const
    119 {
    120     if (isUndefinedOrNull())
    121         return false;
    122     v8::Local<v8::Object> options = m_options->ToObject();
    123     ASSERT(!options.IsEmpty());
    124 
    125     ASSERT(m_isolate);
    126     ASSERT(m_isolate == v8::Isolate::GetCurrent());
    127     v8::Handle<v8::String> v8Key = v8String(m_isolate, key);
    128     if (!options->Has(v8Key))
    129         return false;
    130     value = options->Get(v8Key);
    131     if (value.IsEmpty())
    132         return false;
    133     return true;
    134 }
    135 
    136 bool Dictionary::get(const String& key, v8::Local<v8::Value>& value) const
    137 {
    138     return getKey(key, value);
    139 }
    140 
    141 bool Dictionary::getWithUndefinedOrNullCheck(const String& key, String& value) const
    142 {
    143     v8::Local<v8::Value> v8Value;
    144     if (!getKey(key, v8Value) || blink::isUndefinedOrNull(v8Value))
    145         return false;
    146 
    147     TOSTRING_DEFAULT(V8StringResource<>, stringValue, v8Value, false);
    148     value = stringValue;
    149     return true;
    150 }
    151 
    152 bool Dictionary::getWithUndefinedOrNullCheck(const String& key, RefPtrWillBeMember<Element>& value) const
    153 {
    154     v8::Local<v8::Value> v8Value;
    155     if (!getKey(key, v8Value) || blink::isUndefinedOrNull(v8Value))
    156         return false;
    157 
    158     value = V8Element::toImplWithTypeCheck(m_isolate, v8Value);
    159     return true;
    160 }
    161 
    162 bool Dictionary::getWithUndefinedOrNullCheck(const String& key, RefPtrWillBeMember<Path2D>& value) const
    163 {
    164     v8::Local<v8::Value> v8Value;
    165     if (!getKey(key, v8Value) || blink::isUndefinedOrNull(v8Value))
    166         return false;
    167 
    168     value = V8Path2D::toImplWithTypeCheck(m_isolate, v8Value);
    169     return true;
    170 }
    171 
    172 bool Dictionary::get(const String& key, Dictionary& value) const
    173 {
    174     v8::Local<v8::Value> v8Value;
    175     if (!getKey(key, v8Value))
    176         return false;
    177 
    178     if (v8Value->IsObject()) {
    179         ASSERT(m_isolate);
    180         ASSERT(m_isolate == v8::Isolate::GetCurrent());
    181         value = Dictionary(v8Value, m_isolate);
    182     }
    183 
    184     return true;
    185 }
    186 
    187 bool Dictionary::set(const String& key, const v8::Handle<v8::Value>& value)
    188 {
    189     if (isUndefinedOrNull())
    190         return false;
    191     v8::Local<v8::Object> options = m_options->ToObject();
    192     ASSERT(!options.IsEmpty());
    193 
    194     return options->Set(v8String(m_isolate, key), value);
    195 }
    196 
    197 bool Dictionary::set(const String& key, const String& value)
    198 {
    199     return set(key, v8String(m_isolate, value));
    200 }
    201 
    202 bool Dictionary::set(const String& key, unsigned value)
    203 {
    204     return set(key, v8::Integer::NewFromUnsigned(m_isolate, value));
    205 }
    206 
    207 bool Dictionary::set(const String& key, const Dictionary& value)
    208 {
    209     return set(key, value.v8Value());
    210 }
    211 
    212 bool Dictionary::convert(ConversionContext& context, const String& key, Dictionary& value) const
    213 {
    214     ConversionContextScope scope(context);
    215 
    216     v8::Local<v8::Value> v8Value;
    217     if (!getKey(key, v8Value))
    218         return true;
    219 
    220     if (v8Value->IsObject())
    221         return get(key, value);
    222 
    223     if (context.isNullable() && blink::isUndefinedOrNull(v8Value))
    224         return true;
    225 
    226     context.throwTypeError(ExceptionMessages::incorrectPropertyType(key, "does not have a Dictionary type."));
    227     return false;
    228 }
    229 
    230 bool Dictionary::getOwnPropertiesAsStringHashMap(HashMap<String, String>& hashMap) const
    231 {
    232     if (!isObject())
    233         return false;
    234 
    235     v8::Handle<v8::Object> options = m_options->ToObject();
    236     if (options.IsEmpty())
    237         return false;
    238 
    239     v8::Local<v8::Array> properties = options->GetOwnPropertyNames();
    240     if (properties.IsEmpty())
    241         return true;
    242     for (uint32_t i = 0; i < properties->Length(); ++i) {
    243         v8::Local<v8::String> key = properties->Get(i)->ToString();
    244         if (!options->Has(key))
    245             continue;
    246 
    247         v8::Local<v8::Value> value = options->Get(key);
    248         TOSTRING_DEFAULT(V8StringResource<>, stringKey, key, false);
    249         TOSTRING_DEFAULT(V8StringResource<>, stringValue, value, false);
    250         if (!static_cast<const String&>(stringKey).isEmpty())
    251             hashMap.set(stringKey, stringValue);
    252     }
    253 
    254     return true;
    255 }
    256 
    257 bool Dictionary::getOwnPropertyNames(Vector<String>& names) const
    258 {
    259     if (!isObject())
    260         return false;
    261 
    262     v8::Handle<v8::Object> options = m_options->ToObject();
    263     if (options.IsEmpty())
    264         return false;
    265 
    266     v8::Local<v8::Array> properties = options->GetOwnPropertyNames();
    267     if (properties.IsEmpty())
    268         return true;
    269     for (uint32_t i = 0; i < properties->Length(); ++i) {
    270         v8::Local<v8::String> key = properties->Get(i)->ToString();
    271         if (!options->Has(key))
    272             continue;
    273         TOSTRING_DEFAULT(V8StringResource<>, stringKey, key, false);
    274         names.append(stringKey);
    275     }
    276 
    277     return true;
    278 }
    279 
    280 void Dictionary::ConversionContext::resetPerPropertyContext()
    281 {
    282     if (m_dirty) {
    283         m_dirty = false;
    284         m_isNullable = false;
    285         m_propertyTypeName = "";
    286     }
    287 }
    288 
    289 Dictionary::ConversionContext& Dictionary::ConversionContext::setConversionType(const String& typeName, bool isNullable)
    290 {
    291     ASSERT(!m_dirty);
    292     m_dirty = true;
    293     m_isNullable = isNullable;
    294     m_propertyTypeName = typeName;
    295 
    296     return *this;
    297 }
    298 
    299 void Dictionary::ConversionContext::throwTypeError(const String& detail)
    300 {
    301     exceptionState().throwTypeError(detail);
    302 }
    303 
    304 } // namespace blink
    305