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 #ifndef Dictionary_h
     27 #define Dictionary_h
     28 
     29 #include "bindings/v8/ExceptionMessages.h"
     30 #include "bindings/v8/ExceptionState.h"
     31 #include "bindings/v8/ScriptValue.h"
     32 #include "bindings/v8/V8Binding.h"
     33 #include "bindings/v8/V8BindingMacros.h"
     34 #include "core/events/EventListener.h"
     35 #include "core/dom/MessagePort.h"
     36 #include <v8.h>
     37 #include "wtf/HashMap.h"
     38 #include "wtf/HashSet.h"
     39 #include "wtf/Vector.h"
     40 #include "wtf/text/AtomicString.h"
     41 #include "wtf/text/WTFString.h"
     42 
     43 namespace WebCore {
     44 
     45 class ArrayValue;
     46 class DOMError;
     47 class DOMWindow;
     48 class IDBKeyRange;
     49 class MIDIPort;
     50 class MediaKeyError;
     51 class Notification;
     52 class SpeechRecognitionError;
     53 class SpeechRecognitionResult;
     54 class SpeechRecognitionResultList;
     55 class Storage;
     56 class TrackBase;
     57 class VoidCallback;
     58 
     59 class Dictionary {
     60 public:
     61     Dictionary();
     62     Dictionary(const v8::Handle<v8::Value>& options, v8::Isolate*);
     63     ~Dictionary();
     64 
     65     Dictionary& operator=(const Dictionary&);
     66 
     67     bool isObject() const;
     68     bool isUndefinedOrNull() const;
     69 
     70     bool get(const String&, bool&) const;
     71     bool get(const String&, int32_t&) const;
     72     bool get(const String&, double&, bool& hasValue) const;
     73     bool get(const String&, double&) const;
     74     bool get(const String&, String&) const;
     75     bool get(const String&, ScriptValue&) const;
     76     bool get(const String&, short&) const;
     77     bool get(const String&, unsigned short&) const;
     78     bool get(const String&, unsigned&) const;
     79     bool get(const String&, unsigned long&) const;
     80     bool get(const String&, unsigned long long&) const;
     81     bool get(const String&, RefPtr<DOMWindow>&) const;
     82     bool get(const String&, RefPtr<Storage>&) const;
     83     bool get(const String&, MessagePortArray&) const;
     84     bool get(const String&, RefPtr<Uint8Array>&) const;
     85     bool get(const String&, RefPtr<ArrayBufferView>&) const;
     86     bool get(const String&, RefPtr<MIDIPort>&) const;
     87     bool get(const String&, RefPtr<MediaKeyError>&) const;
     88     bool get(const String&, RefPtr<TrackBase>&) const;
     89     bool get(const String&, RefPtr<SpeechRecognitionError>&) const;
     90     bool get(const String&, RefPtr<SpeechRecognitionResult>&) const;
     91     bool get(const String&, RefPtr<SpeechRecognitionResultList>&) const;
     92     bool get(const String&, RefPtr<MediaStream>&) const;
     93     bool get(const String&, RefPtr<EventTarget>&) const;
     94     bool get(const String&, HashSet<AtomicString>&) const;
     95     bool get(const String&, Dictionary&) const;
     96     bool get(const String&, Vector<String>&) const;
     97     bool get(const String&, ArrayValue&) const;
     98     bool get(const String&, RefPtr<DOMError>&) const;
     99     bool get(const String&, OwnPtr<VoidCallback>&) const;
    100     bool get(const String&, v8::Local<v8::Value>&) const;
    101 
    102     class ConversionContext {
    103     public:
    104         ConversionContext(const String& interfaceName, const String& methodName, ExceptionState& exceptionState)
    105             : m_interfaceName(interfaceName)
    106             , m_methodName(methodName)
    107             , m_exceptionState(exceptionState)
    108             , m_dirty(true)
    109         {
    110             resetPerPropertyContext();
    111         }
    112 
    113         const String& interfaceName() const { return m_interfaceName; }
    114         const String& methodName() const { return m_methodName; }
    115         bool forConstructor() const { return m_methodName.isEmpty(); }
    116         ExceptionState& exceptionState() const { return m_exceptionState; }
    117 
    118         bool isNullable() const { return m_isNullable; }
    119         String typeName() const { return m_propertyTypeName; }
    120 
    121         ConversionContext& setConversionType(const String&, bool);
    122 
    123         void throwTypeError(const String& detail);
    124 
    125         void resetPerPropertyContext();
    126 
    127     private:
    128         const String m_interfaceName;
    129         const String m_methodName;
    130         ExceptionState& m_exceptionState;
    131         bool m_dirty;
    132 
    133         bool m_isNullable;
    134         String m_propertyTypeName;
    135     };
    136 
    137     class ConversionContextScope {
    138     public:
    139         ConversionContextScope(ConversionContext& context)
    140             : m_context(context) { }
    141         ~ConversionContextScope()
    142         {
    143             m_context.resetPerPropertyContext();
    144         }
    145     private:
    146         ConversionContext& m_context;
    147     };
    148 
    149     bool convert(ConversionContext&, const String&, bool&) const;
    150     bool convert(ConversionContext&, const String&, double&) const;
    151     bool convert(ConversionContext&, const String&, String&) const;
    152     bool convert(ConversionContext&, const String&, ScriptValue&) const;
    153 
    154     template<typename IntegralType>
    155     bool convert(ConversionContext &, const String&, IntegralType&) const;
    156     bool convert(ConversionContext &, const String&, MessagePortArray&) const;
    157     bool convert(ConversionContext &, const String&, HashSet<AtomicString>&) const;
    158     bool convert(ConversionContext &, const String&, Dictionary&) const;
    159     bool convert(ConversionContext &, const String&, Vector<String>&) const;
    160     bool convert(ConversionContext &, const String&, ArrayValue&) const;
    161     template<typename T>
    162     bool convert(ConversionContext &, const String&, RefPtr<T>&) const;
    163 
    164     bool getOwnPropertiesAsStringHashMap(HashMap<String, String>&) const;
    165     bool getOwnPropertyNames(Vector<String>&) const;
    166 
    167     bool getWithUndefinedOrNullCheck(const String&, String&) const;
    168 
    169     bool hasProperty(const String&) const;
    170 
    171     // Only allow inline allocation.
    172     void* operator new(size_t, NotNullTag, void* location) { return location; }
    173 
    174 private:
    175     // Disallow new allocation.
    176     void* operator new(size_t);
    177 
    178     bool getKey(const String& key, v8::Local<v8::Value>&) const;
    179 
    180     v8::Handle<v8::Value> m_options;
    181     v8::Isolate* m_isolate;
    182 };
    183 
    184 template<>
    185 struct NativeValueTraits<Dictionary> {
    186     static inline Dictionary nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate)
    187     {
    188         return Dictionary(value, isolate);
    189     }
    190 };
    191 
    192 template <typename T>
    193 struct IntegralTypeTraits {
    194 };
    195 
    196 template <>
    197 struct IntegralTypeTraits<uint8_t> {
    198     static inline uint8_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok)
    199     {
    200         return toUInt8(value, configuration, ok);
    201     }
    202     static const String typeName() { return "UInt8"; }
    203 };
    204 
    205 template <>
    206 struct IntegralTypeTraits<int8_t> {
    207     static inline int8_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok)
    208     {
    209         return toInt8(value, configuration, ok);
    210     }
    211     static const String typeName() { return "Int8"; }
    212 };
    213 
    214 template <>
    215 struct IntegralTypeTraits<unsigned short> {
    216     static inline uint16_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok)
    217     {
    218         return toUInt16(value, configuration, ok);
    219     }
    220     static const String typeName() { return "UInt16"; }
    221 };
    222 
    223 template <>
    224 struct IntegralTypeTraits<short> {
    225     static inline int16_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok)
    226     {
    227         return toInt16(value, configuration, ok);
    228     }
    229     static const String typeName() { return "Int16"; }
    230 };
    231 
    232 template <>
    233 struct IntegralTypeTraits<unsigned> {
    234     static inline uint32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok)
    235     {
    236         return toUInt32(value, configuration, ok);
    237     }
    238     static const String typeName() { return "UInt32"; }
    239 };
    240 
    241 template <>
    242 struct IntegralTypeTraits<unsigned long> {
    243     static inline uint32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok)
    244     {
    245         return toUInt32(value, configuration, ok);
    246     }
    247     static const String typeName() { return "UInt32"; }
    248 };
    249 
    250 template <>
    251 struct IntegralTypeTraits<int> {
    252     static inline int32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok)
    253     {
    254         return toInt32(value, configuration, ok);
    255     }
    256     static const String typeName() { return "Int32"; }
    257 };
    258 
    259 template <>
    260 struct IntegralTypeTraits<long> {
    261     static inline int32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok)
    262     {
    263         return toInt32(value, configuration, ok);
    264     }
    265     static const String typeName() { return "Int32"; }
    266 };
    267 
    268 template <>
    269 struct IntegralTypeTraits<unsigned long long> {
    270     static inline unsigned long long toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok)
    271     {
    272         return toUInt64(value, configuration, ok);
    273     }
    274     static const String typeName() { return "UInt64"; }
    275 };
    276 
    277 template <>
    278 struct IntegralTypeTraits<long long> {
    279     static inline long long toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok)
    280     {
    281         return toInt64(value, configuration, ok);
    282     }
    283     static const String typeName() { return "Int64"; }
    284 };
    285 
    286 template<typename T> bool Dictionary::convert(ConversionContext& context, const String& key, T& value) const
    287 {
    288     ConversionContextScope scope(context);
    289 
    290     v8::Local<v8::Value> v8Value;
    291     if (!getKey(key, v8Value))
    292         return true;
    293 
    294     bool ok = false;
    295     value = IntegralTypeTraits<T>::toIntegral(v8Value, NormalConversion, ok);
    296     if (ok)
    297         return true;
    298 
    299     V8TRYCATCH_RETURN(v8::Local<v8::Number>, v8Number, v8Value->ToNumber(), false);
    300     ASSERT(v8Number.IsEmpty());
    301     context.throwTypeError(ExceptionMessages::incorrectPropertyType(key, "does not have type " + IntegralTypeTraits<T>::typeName() + "."));
    302     return false;
    303 }
    304 
    305 template<typename T> bool Dictionary::convert(ConversionContext& context, const String& key, RefPtr<T>& value) const
    306 {
    307     ConversionContextScope scope(context);
    308 
    309     if (!get(key, value))
    310         return true;
    311 
    312     if (value)
    313         return true;
    314 
    315     v8::Local<v8::Value> v8Value;
    316     getKey(key, v8Value);
    317     if (context.isNullable() && WebCore::isUndefinedOrNull(v8Value))
    318         return true;
    319 
    320     context.throwTypeError(ExceptionMessages::incorrectPropertyType(key, "does not have a " + context.typeName() + " type."));
    321     return false;
    322 }
    323 
    324 }
    325 
    326 #endif // Dictionary_h
    327