Home | History | Annotate | Download | only in js
      1 /*
      2  * Copyright (C) 2009 Apple 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  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  *
     25  */
     26 
     27 #ifndef SerializedScriptValue_h
     28 #define SerializedScriptValue_h
     29 
     30 #include "ScriptValue.h"
     31 
     32 typedef const struct OpaqueJSContext* JSContextRef;
     33 typedef const struct OpaqueJSValue* JSValueRef;
     34 
     35 namespace WebCore {
     36     class File;
     37     class FileList;
     38     class ImageData;
     39     class SerializedArray;
     40     class SerializedFileList;
     41     class SerializedImageData;
     42     class SerializedObject;
     43 
     44     class SharedSerializedData : public RefCounted<SharedSerializedData> {
     45     public:
     46         virtual ~SharedSerializedData() { }
     47         SerializedArray* asArray();
     48         SerializedObject* asObject();
     49         SerializedFileList* asFileList();
     50         SerializedImageData* asImageData();
     51     };
     52 
     53     class SerializedScriptValue;
     54 
     55     class SerializedScriptValueData {
     56     public:
     57         enum SerializedType {
     58             EmptyType,
     59             DateType,
     60             NumberType,
     61             ImmediateType,
     62             ObjectType,
     63             ArrayType,
     64             StringType,
     65             FileType,
     66             FileListType,
     67             ImageDataType
     68         };
     69 
     70         SerializedType type() const { return m_type; }
     71         static SerializedScriptValueData serialize(JSC::ExecState*, JSC::JSValue);
     72         JSC::JSValue deserialize(JSC::ExecState*, JSC::JSGlobalObject*, bool mustCopy) const;
     73 
     74         ~SerializedScriptValueData()
     75         {
     76             if (m_sharedData)
     77                 tearDownSerializedData();
     78         }
     79 
     80         SerializedScriptValueData()
     81             : m_type(EmptyType)
     82         {
     83         }
     84 
     85         explicit SerializedScriptValueData(const String& string)
     86             : m_type(StringType)
     87             , m_string(string.crossThreadString()) // FIXME: Should be able to just share the Rep
     88         {
     89         }
     90 
     91         explicit SerializedScriptValueData(const File*);
     92         explicit SerializedScriptValueData(const FileList*);
     93         explicit SerializedScriptValueData(const ImageData*);
     94 
     95         explicit SerializedScriptValueData(JSC::JSValue value)
     96             : m_type(ImmediateType)
     97         {
     98             ASSERT(!value.isCell());
     99             m_data.m_immediate = JSC::JSValue::encode(value);
    100         }
    101 
    102         SerializedScriptValueData(SerializedType type, double value)
    103             : m_type(type)
    104         {
    105             m_data.m_double = value;
    106         }
    107 
    108         SerializedScriptValueData(RefPtr<SerializedObject>);
    109         SerializedScriptValueData(RefPtr<SerializedArray>);
    110 
    111         JSC::JSValue asImmediate() const
    112         {
    113             ASSERT(m_type == ImmediateType);
    114             return JSC::JSValue::decode(m_data.m_immediate);
    115         }
    116 
    117         double asDouble() const
    118         {
    119             ASSERT(m_type == NumberType || m_type == DateType);
    120             return m_data.m_double;
    121         }
    122 
    123         String asString() const
    124         {
    125             ASSERT(m_type == StringType || m_type == FileType);
    126             return m_string;
    127         }
    128 
    129         SerializedObject* asObject() const
    130         {
    131             ASSERT(m_type == ObjectType);
    132             ASSERT(m_sharedData);
    133             return m_sharedData->asObject();
    134         }
    135 
    136         SerializedArray* asArray() const
    137         {
    138             ASSERT(m_type == ArrayType);
    139             ASSERT(m_sharedData);
    140             return m_sharedData->asArray();
    141         }
    142 
    143         SerializedFileList* asFileList() const
    144         {
    145             ASSERT(m_type == FileListType);
    146             ASSERT(m_sharedData);
    147             return m_sharedData->asFileList();
    148         }
    149 
    150         SerializedImageData* asImageData() const
    151         {
    152             ASSERT(m_type == ImageDataType);
    153             ASSERT(m_sharedData);
    154             return m_sharedData->asImageData();
    155         }
    156 
    157         operator bool() const { return m_type != EmptyType; }
    158 
    159         SerializedScriptValueData release()
    160         {
    161             SerializedScriptValueData result = *this;
    162             *this = SerializedScriptValueData();
    163             return result;
    164         }
    165 
    166     private:
    167         void tearDownSerializedData();
    168         SerializedType m_type;
    169         RefPtr<SharedSerializedData> m_sharedData;
    170         String m_string;
    171         union {
    172             double m_double;
    173             JSC::EncodedJSValue m_immediate;
    174         } m_data;
    175     };
    176 
    177     class SerializedScriptValue : public RefCounted<SerializedScriptValue> {
    178     public:
    179         static PassRefPtr<SerializedScriptValue> create(JSC::ExecState* exec, JSC::JSValue value)
    180         {
    181             return adoptRef(new SerializedScriptValue(SerializedScriptValueData::serialize(exec, value)));
    182         }
    183 
    184         static PassRefPtr<SerializedScriptValue> create(JSContextRef, JSValueRef value, JSValueRef* exception);
    185 
    186         static PassRefPtr<SerializedScriptValue> create(String string)
    187         {
    188             return adoptRef(new SerializedScriptValue(SerializedScriptValueData(string)));
    189         }
    190 
    191         static PassRefPtr<SerializedScriptValue> create()
    192         {
    193             return adoptRef(new SerializedScriptValue(SerializedScriptValueData()));
    194         }
    195 
    196         PassRefPtr<SerializedScriptValue> release()
    197         {
    198             PassRefPtr<SerializedScriptValue> result = adoptRef(new SerializedScriptValue(m_value));
    199             m_value = SerializedScriptValueData();
    200             result->m_mustCopy = true;
    201             return result;
    202         }
    203 
    204         String toString()
    205         {
    206             if (m_value.type() != SerializedScriptValueData::StringType)
    207                 return "";
    208             return m_value.asString();
    209         }
    210 
    211         JSC::JSValue deserialize(JSC::ExecState* exec, JSC::JSGlobalObject* globalObject)
    212         {
    213             if (!m_value)
    214                 return JSC::jsNull();
    215             return m_value.deserialize(exec, globalObject, m_mustCopy);
    216         }
    217 
    218         JSValueRef deserialize(JSContextRef, JSValueRef* exception);
    219         ~SerializedScriptValue();
    220 
    221     private:
    222         SerializedScriptValue(SerializedScriptValueData value)
    223             : m_value(value)
    224             , m_mustCopy(false)
    225         {
    226         }
    227 
    228         SerializedScriptValueData m_value;
    229         bool m_mustCopy;
    230     };
    231 }
    232 
    233 #endif // SerializedScriptValue_h
    234