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