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