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 are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #include "bindings/v8/SerializedScriptValue.h"
     33 
     34 #include "V8Blob.h"
     35 #include "V8DOMFileSystem.h"
     36 #include "V8File.h"
     37 #include "V8FileList.h"
     38 #include "V8ImageData.h"
     39 #include "V8MessagePort.h"
     40 #include "bindings/v8/ScriptScope.h"
     41 #include "bindings/v8/ScriptState.h"
     42 #include "bindings/v8/V8Binding.h"
     43 #include "bindings/v8/V8Utilities.h"
     44 #include "bindings/v8/custom/V8ArrayBufferCustom.h"
     45 #include "bindings/v8/custom/V8ArrayBufferViewCustom.h"
     46 #include "bindings/v8/custom/V8DataViewCustom.h"
     47 #include "bindings/v8/custom/V8Float32ArrayCustom.h"
     48 #include "bindings/v8/custom/V8Float64ArrayCustom.h"
     49 #include "bindings/v8/custom/V8Int16ArrayCustom.h"
     50 #include "bindings/v8/custom/V8Int32ArrayCustom.h"
     51 #include "bindings/v8/custom/V8Int8ArrayCustom.h"
     52 #include "bindings/v8/custom/V8Uint16ArrayCustom.h"
     53 #include "bindings/v8/custom/V8Uint32ArrayCustom.h"
     54 #include "bindings/v8/custom/V8Uint8ArrayCustom.h"
     55 #include "bindings/v8/custom/V8Uint8ClampedArrayCustom.h"
     56 #include "core/dom/ExceptionCode.h"
     57 #include "core/dom/MessagePort.h"
     58 #include "core/fileapi/Blob.h"
     59 #include "core/fileapi/File.h"
     60 #include "core/fileapi/FileList.h"
     61 #include "core/html/ImageData.h"
     62 #include "core/html/canvas/DataView.h"
     63 #include "platform/SharedBuffer.h"
     64 #include "wtf/ArrayBuffer.h"
     65 #include "wtf/ArrayBufferContents.h"
     66 #include "wtf/ArrayBufferView.h"
     67 #include "wtf/Assertions.h"
     68 #include "wtf/ByteOrder.h"
     69 #include "wtf/Float32Array.h"
     70 #include "wtf/Float64Array.h"
     71 #include "wtf/Int16Array.h"
     72 #include "wtf/Int32Array.h"
     73 #include "wtf/Int8Array.h"
     74 #include "wtf/RefCounted.h"
     75 #include "wtf/Uint16Array.h"
     76 #include "wtf/Uint32Array.h"
     77 #include "wtf/Uint8Array.h"
     78 #include "wtf/Uint8ClampedArray.h"
     79 #include "wtf/Vector.h"
     80 #include "wtf/text/StringBuffer.h"
     81 #include "wtf/text/StringUTF8Adaptor.h"
     82 
     83 // FIXME: consider crashing in debug mode on deserialization errors
     84 // NOTE: be sure to change wireFormatVersion as necessary!
     85 
     86 namespace WebCore {
     87 
     88 namespace {
     89 
     90 // This code implements the HTML5 Structured Clone algorithm:
     91 // http://www.whatwg.org/specs/web-apps/current-work/multipage/urls.html#safe-passing-of-structured-data
     92 
     93 // V8ObjectMap is a map from V8 objects to arbitrary values of type T.
     94 // V8 objects (or handles to V8 objects) cannot be used as keys in ordinary wtf::HashMaps;
     95 // this class should be used instead. GCObject must be a subtype of v8::Object.
     96 // Suggested usage:
     97 //     V8ObjectMap<v8::Object, int> map;
     98 //     v8::Handle<v8::Object> obj = ...;
     99 //     map.set(obj, 42);
    100 template<typename GCObject, typename T>
    101 class V8ObjectMap {
    102 public:
    103     bool contains(const v8::Handle<GCObject>& handle)
    104     {
    105         return m_map.contains(*handle);
    106     }
    107 
    108     bool tryGet(const v8::Handle<GCObject>& handle, T* valueOut)
    109     {
    110         typename HandleToT::iterator result = m_map.find(*handle);
    111         if (result != m_map.end()) {
    112             *valueOut = result->value;
    113             return true;
    114         }
    115         return false;
    116     }
    117 
    118     void set(const v8::Handle<GCObject>& handle, const T& value)
    119     {
    120         m_map.set(*handle, value);
    121     }
    122 
    123 private:
    124     // This implementation uses GetIdentityHash(), which sets a hidden property on the object containing
    125     // a random integer (or returns the one that had been previously set). This ensures that the table
    126     // never needs to be rebuilt across garbage collections at the expense of doing additional allocation
    127     // and making more round trips into V8. Note that since GetIdentityHash() is defined only on
    128     // v8::Objects, this V8ObjectMap cannot be used to map v8::Strings to T (because the public V8 API
    129     // considers a v8::String to be a v8::Primitive).
    130 
    131     // If V8 exposes a way to get at the address of the object held by a handle, then we can produce
    132     // an alternate implementation that does not need to do any V8-side allocation; however, it will
    133     // need to rehash after every garbage collection because a key object may have been moved.
    134     template<typename G>
    135     struct V8HandlePtrHash {
    136         static unsigned hash(const G* key)
    137         {
    138             return static_cast<unsigned>(unsafeHandleFromRawValue(key)->GetIdentityHash());
    139         }
    140         static bool equal(const G* a, const G* b)
    141         {
    142             return unsafeHandleFromRawValue(a) == unsafeHandleFromRawValue(b);
    143         }
    144         // For HashArg.
    145         static const bool safeToCompareToEmptyOrDeleted = false;
    146     };
    147 
    148     typedef WTF::HashMap<GCObject*, T, V8HandlePtrHash<GCObject> > HandleToT;
    149     HandleToT m_map;
    150 };
    151 
    152 typedef UChar BufferValueType;
    153 
    154 // Serialization format is a sequence of tags followed by zero or more data arguments.
    155 // Tags always take exactly one byte. A serialized stream first begins with
    156 // a complete VersionTag. If the stream does not begin with a VersionTag, we assume that
    157 // the stream is in format 0.
    158 
    159 // This format is private to the implementation of SerializedScriptValue. Do not rely on it
    160 // externally. It is safe to persist a SerializedScriptValue as a binary blob, but this
    161 // code should always be used to interpret it.
    162 
    163 // WebCoreStrings are read as (length:uint32_t, string:UTF8[length]).
    164 // RawStrings are read as (length:uint32_t, string:UTF8[length]).
    165 // RawUCharStrings are read as (length:uint32_t, string:UChar[length/sizeof(UChar)]).
    166 // RawFiles are read as (path:WebCoreString, url:WebCoreStrng, type:WebCoreString).
    167 // There is a reference table that maps object references (uint32_t) to v8::Values.
    168 // Tokens marked with (ref) are inserted into the reference table and given the next object reference ID after decoding.
    169 // All tags except InvalidTag, PaddingTag, ReferenceCountTag, VersionTag, GenerateFreshObjectTag
    170 //     and GenerateFreshArrayTag push their results to the deserialization stack.
    171 // There is also an 'open' stack that is used to resolve circular references. Objects or arrays may
    172 //     contain self-references. Before we begin to deserialize the contents of these values, they
    173 //     are first given object reference IDs (by GenerateFreshObjectTag/GenerateFreshArrayTag);
    174 //     these reference IDs are then used with ObjectReferenceTag to tie the recursive knot.
    175 enum SerializationTag {
    176     InvalidTag = '!', // Causes deserialization to fail.
    177     PaddingTag = '\0', // Is ignored (but consumed).
    178     UndefinedTag = '_', // -> <undefined>
    179     NullTag = '0', // -> <null>
    180     TrueTag = 'T', // -> <true>
    181     FalseTag = 'F', // -> <false>
    182     StringTag = 'S', // string:RawString -> string
    183     StringUCharTag = 'c', // string:RawUCharString -> string
    184     Int32Tag = 'I', // value:ZigZag-encoded int32 -> Integer
    185     Uint32Tag = 'U', // value:uint32_t -> Integer
    186     DateTag = 'D', // value:double -> Date (ref)
    187     MessagePortTag = 'M', // index:int -> MessagePort. Fills the result with transferred MessagePort.
    188     NumberTag = 'N', // value:double -> Number
    189     BlobTag = 'b', // url:WebCoreString, type:WebCoreString, size:uint64_t -> Blob (ref)
    190     FileTag = 'f', // file:RawFile -> File (ref)
    191     DOMFileSystemTag = 'd', // type:int32_t, name:WebCoreString, url:WebCoreString -> FileSystem (ref)
    192     FileListTag = 'l', // length:uint32_t, files:RawFile[length] -> FileList (ref)
    193     ImageDataTag = '#', // width:uint32_t, height:uint32_t, pixelDataLength:uint32_t, data:byte[pixelDataLength] -> ImageData (ref)
    194     ObjectTag = '{', // numProperties:uint32_t -> pops the last object from the open stack;
    195                      //                           fills it with the last numProperties name,value pairs pushed onto the deserialization stack
    196     SparseArrayTag = '@', // numProperties:uint32_t, length:uint32_t -> pops the last object from the open stack;
    197                           //                                            fills it with the last numProperties name,value pairs pushed onto the deserialization stack
    198     DenseArrayTag = '$', // numProperties:uint32_t, length:uint32_t -> pops the last object from the open stack;
    199                          //                                            fills it with the last length elements and numProperties name,value pairs pushed onto deserialization stack
    200     RegExpTag = 'R', // pattern:RawString, flags:uint32_t -> RegExp (ref)
    201     ArrayBufferTag = 'B', // byteLength:uint32_t, data:byte[byteLength] -> ArrayBuffer (ref)
    202     ArrayBufferTransferTag = 't', // index:uint32_t -> ArrayBuffer. For ArrayBuffer transfer
    203     ArrayBufferViewTag = 'V', // subtag:byte, byteOffset:uint32_t, byteLength:uint32_t -> ArrayBufferView (ref). Consumes an ArrayBuffer from the top of the deserialization stack.
    204     ObjectReferenceTag = '^', // ref:uint32_t -> reference table[ref]
    205     GenerateFreshObjectTag = 'o', // -> empty object allocated an object ID and pushed onto the open stack (ref)
    206     GenerateFreshSparseArrayTag = 'a', // length:uint32_t -> empty array[length] allocated an object ID and pushed onto the open stack (ref)
    207     GenerateFreshDenseArrayTag = 'A', // length:uint32_t -> empty array[length] allocated an object ID and pushed onto the open stack (ref)
    208     ReferenceCountTag = '?', // refTableSize:uint32_t -> If the reference table is not refTableSize big, fails.
    209     StringObjectTag = 's', //  string:RawString -> new String(string) (ref)
    210     NumberObjectTag = 'n', // value:double -> new Number(value) (ref)
    211     TrueObjectTag = 'y', // new Boolean(true) (ref)
    212     FalseObjectTag = 'x', // new Boolean(false) (ref)
    213     VersionTag = 0xFF // version:uint32_t -> Uses this as the file version.
    214 };
    215 
    216 enum ArrayBufferViewSubTag {
    217     ByteArrayTag = 'b',
    218     UnsignedByteArrayTag = 'B',
    219     UnsignedByteClampedArrayTag = 'C',
    220     ShortArrayTag = 'w',
    221     UnsignedShortArrayTag = 'W',
    222     IntArrayTag = 'd',
    223     UnsignedIntArrayTag = 'D',
    224     FloatArrayTag = 'f',
    225     DoubleArrayTag = 'F',
    226     DataViewTag = '?'
    227 };
    228 
    229 static bool shouldCheckForCycles(int depth)
    230 {
    231     ASSERT(depth >= 0);
    232     // Since we are not required to spot the cycle as soon as it
    233     // happens we can check for cycles only when the current depth
    234     // is a power of two.
    235     return !(depth & (depth - 1));
    236 }
    237 
    238 static const int maxDepth = 20000;
    239 
    240 // VarInt encoding constants.
    241 static const int varIntShift = 7;
    242 static const int varIntMask = (1 << varIntShift) - 1;
    243 
    244 // ZigZag encoding helps VarInt encoding stay small for negative
    245 // numbers with small absolute values.
    246 class ZigZag {
    247 public:
    248     static uint32_t encode(uint32_t value)
    249     {
    250         if (value & (1U << 31))
    251             value = ((~value) << 1) + 1;
    252         else
    253             value <<= 1;
    254         return value;
    255     }
    256 
    257     static uint32_t decode(uint32_t value)
    258     {
    259         if (value & 1)
    260             value = ~(value >> 1);
    261         else
    262             value >>= 1;
    263         return value;
    264     }
    265 
    266 private:
    267     ZigZag();
    268 };
    269 
    270 // Writer is responsible for serializing primitive types and storing
    271 // information used to reconstruct composite types.
    272 class Writer {
    273     WTF_MAKE_NONCOPYABLE(Writer);
    274 public:
    275     explicit Writer(v8::Isolate* isolate)
    276         : m_position(0)
    277         , m_isolate(isolate)
    278     {
    279     }
    280 
    281     // Write functions for primitive types.
    282 
    283     void writeUndefined() { append(UndefinedTag); }
    284 
    285     void writeNull() { append(NullTag); }
    286 
    287     void writeTrue() { append(TrueTag); }
    288 
    289     void writeFalse() { append(FalseTag); }
    290 
    291     void writeBooleanObject(bool value)
    292     {
    293         append(value ? TrueObjectTag : FalseObjectTag);
    294     }
    295 
    296     void writeOneByteString(v8::Handle<v8::String>& string)
    297     {
    298         int stringLength = string->Length();
    299         int utf8Length = string->Utf8Length();
    300         ASSERT(stringLength >= 0 && utf8Length >= 0);
    301 
    302         append(StringTag);
    303         doWriteUint32(static_cast<uint32_t>(utf8Length));
    304         ensureSpace(utf8Length);
    305 
    306         // ASCII fast path.
    307         if (stringLength == utf8Length)
    308             string->WriteOneByte(byteAt(m_position), 0, utf8Length, v8StringWriteOptions());
    309         else {
    310             char* buffer = reinterpret_cast<char*>(byteAt(m_position));
    311             string->WriteUtf8(buffer, utf8Length, 0, v8StringWriteOptions());
    312         }
    313         m_position += utf8Length;
    314     }
    315 
    316     void writeUCharString(v8::Handle<v8::String>& string)
    317     {
    318         int length = string->Length();
    319         ASSERT(length >= 0);
    320 
    321         int size = length * sizeof(UChar);
    322         int bytes = bytesNeededToWireEncode(static_cast<uint32_t>(size));
    323         if ((m_position + 1 + bytes) & 1)
    324             append(PaddingTag);
    325 
    326         append(StringUCharTag);
    327         doWriteUint32(static_cast<uint32_t>(size));
    328         ensureSpace(size);
    329 
    330         ASSERT(!(m_position & 1));
    331         uint16_t* buffer = reinterpret_cast<uint16_t*>(byteAt(m_position));
    332         string->Write(buffer, 0, length, v8StringWriteOptions());
    333         m_position += size;
    334     }
    335 
    336     void writeStringObject(const char* data, int length)
    337     {
    338         ASSERT(length >= 0);
    339         append(StringObjectTag);
    340         doWriteString(data, length);
    341     }
    342 
    343     void writeWebCoreString(const String& string)
    344     {
    345         // Uses UTF8 encoding so we can read it back as either V8 or
    346         // WebCore string.
    347         append(StringTag);
    348         doWriteWebCoreString(string);
    349     }
    350 
    351     void writeVersion()
    352     {
    353         append(VersionTag);
    354         doWriteUint32(SerializedScriptValue::wireFormatVersion);
    355     }
    356 
    357     void writeInt32(int32_t value)
    358     {
    359         append(Int32Tag);
    360         doWriteUint32(ZigZag::encode(static_cast<uint32_t>(value)));
    361     }
    362 
    363     void writeUint32(uint32_t value)
    364     {
    365         append(Uint32Tag);
    366         doWriteUint32(value);
    367     }
    368 
    369     void writeDate(double numberValue)
    370     {
    371         append(DateTag);
    372         doWriteNumber(numberValue);
    373     }
    374 
    375     void writeNumber(double number)
    376     {
    377         append(NumberTag);
    378         doWriteNumber(number);
    379     }
    380 
    381     void writeNumberObject(double number)
    382     {
    383         append(NumberObjectTag);
    384         doWriteNumber(number);
    385     }
    386 
    387     void writeBlob(const String& uuid, const String& type, unsigned long long size)
    388     {
    389         append(BlobTag);
    390         doWriteWebCoreString(uuid);
    391         doWriteWebCoreString(type);
    392         doWriteUint64(size);
    393     }
    394 
    395     void writeDOMFileSystem(int type, const String& name, const String& url)
    396     {
    397         append(DOMFileSystemTag);
    398         doWriteUint32(type);
    399         doWriteWebCoreString(name);
    400         doWriteWebCoreString(url);
    401     }
    402 
    403     void writeFile(const File& file)
    404     {
    405         append(FileTag);
    406         doWriteFile(file);
    407     }
    408 
    409     void writeFileList(const FileList& fileList)
    410     {
    411         append(FileListTag);
    412         uint32_t length = fileList.length();
    413         doWriteUint32(length);
    414         for (unsigned i = 0; i < length; ++i)
    415             doWriteFile(*fileList.item(i));
    416     }
    417 
    418     void writeArrayBuffer(const ArrayBuffer& arrayBuffer)
    419     {
    420         append(ArrayBufferTag);
    421         doWriteArrayBuffer(arrayBuffer);
    422     }
    423 
    424     void writeArrayBufferView(const ArrayBufferView& arrayBufferView)
    425     {
    426         append(ArrayBufferViewTag);
    427 #ifndef NDEBUG
    428         const ArrayBuffer& arrayBuffer = *arrayBufferView.buffer();
    429         ASSERT(static_cast<const uint8_t*>(arrayBuffer.data()) + arrayBufferView.byteOffset() ==
    430                static_cast<const uint8_t*>(arrayBufferView.baseAddress()));
    431 #endif
    432         ArrayBufferView::ViewType type = arrayBufferView.getType();
    433 
    434         if (type == ArrayBufferView::TypeInt8)
    435             append(ByteArrayTag);
    436         else if (type == ArrayBufferView::TypeUint8Clamped)
    437             append(UnsignedByteClampedArrayTag);
    438         else if (type == ArrayBufferView::TypeUint8)
    439             append(UnsignedByteArrayTag);
    440         else if (type == ArrayBufferView::TypeInt16)
    441             append(ShortArrayTag);
    442         else if (type == ArrayBufferView::TypeUint16)
    443             append(UnsignedShortArrayTag);
    444         else if (type == ArrayBufferView::TypeInt32)
    445             append(IntArrayTag);
    446         else if (type == ArrayBufferView::TypeUint32)
    447             append(UnsignedIntArrayTag);
    448         else if (type == ArrayBufferView::TypeFloat32)
    449             append(FloatArrayTag);
    450         else if (type == ArrayBufferView::TypeFloat64)
    451             append(DoubleArrayTag);
    452         else if (type == ArrayBufferView::TypeDataView)
    453             append(DataViewTag);
    454         else
    455             ASSERT_NOT_REACHED();
    456         doWriteUint32(arrayBufferView.byteOffset());
    457         doWriteUint32(arrayBufferView.byteLength());
    458     }
    459 
    460     void writeImageData(uint32_t width, uint32_t height, const uint8_t* pixelData, uint32_t pixelDataLength)
    461     {
    462         append(ImageDataTag);
    463         doWriteUint32(width);
    464         doWriteUint32(height);
    465         doWriteUint32(pixelDataLength);
    466         append(pixelData, pixelDataLength);
    467     }
    468 
    469     void writeRegExp(v8::Local<v8::String> pattern, v8::RegExp::Flags flags)
    470     {
    471         append(RegExpTag);
    472         v8::String::Utf8Value patternUtf8Value(pattern);
    473         doWriteString(*patternUtf8Value, patternUtf8Value.length());
    474         doWriteUint32(static_cast<uint32_t>(flags));
    475     }
    476 
    477     void writeTransferredMessagePort(uint32_t index)
    478     {
    479         append(MessagePortTag);
    480         doWriteUint32(index);
    481     }
    482 
    483     void writeTransferredArrayBuffer(uint32_t index)
    484     {
    485         append(ArrayBufferTransferTag);
    486         doWriteUint32(index);
    487     }
    488 
    489     void writeObjectReference(uint32_t reference)
    490     {
    491         append(ObjectReferenceTag);
    492         doWriteUint32(reference);
    493     }
    494 
    495     void writeObject(uint32_t numProperties)
    496     {
    497         append(ObjectTag);
    498         doWriteUint32(numProperties);
    499     }
    500 
    501     void writeSparseArray(uint32_t numProperties, uint32_t length)
    502     {
    503         append(SparseArrayTag);
    504         doWriteUint32(numProperties);
    505         doWriteUint32(length);
    506     }
    507 
    508     void writeDenseArray(uint32_t numProperties, uint32_t length)
    509     {
    510         append(DenseArrayTag);
    511         doWriteUint32(numProperties);
    512         doWriteUint32(length);
    513     }
    514 
    515     String takeWireString()
    516     {
    517         COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
    518         fillHole();
    519         String data = String(m_buffer.data(), m_buffer.size());
    520         data.impl()->truncateAssumingIsolated((m_position + 1) / sizeof(BufferValueType));
    521         return data;
    522     }
    523 
    524     void writeReferenceCount(uint32_t numberOfReferences)
    525     {
    526         append(ReferenceCountTag);
    527         doWriteUint32(numberOfReferences);
    528     }
    529 
    530     void writeGenerateFreshObject()
    531     {
    532         append(GenerateFreshObjectTag);
    533     }
    534 
    535     void writeGenerateFreshSparseArray(uint32_t length)
    536     {
    537         append(GenerateFreshSparseArrayTag);
    538         doWriteUint32(length);
    539     }
    540 
    541     void writeGenerateFreshDenseArray(uint32_t length)
    542     {
    543         append(GenerateFreshDenseArrayTag);
    544         doWriteUint32(length);
    545     }
    546 
    547     v8::Isolate* getIsolate() { return m_isolate; }
    548 
    549 private:
    550     void doWriteFile(const File& file)
    551     {
    552         doWriteWebCoreString(file.hasBackingFile() ? file.path() : "");
    553         doWriteWebCoreString(file.name());
    554         doWriteWebCoreString(file.webkitRelativePath());
    555         doWriteWebCoreString(file.uuid());
    556         doWriteWebCoreString(file.type());
    557 
    558         // FIXME don't use 4 bytes to encode a flag.
    559         if (file.hasValidSnapshotMetadata()) {
    560             doWriteUint32(static_cast<uint8_t>(1));
    561 
    562             long long size;
    563             double lastModified;
    564             file.captureSnapshot(size, lastModified);
    565             doWriteUint64(static_cast<uint64_t>(size));
    566             doWriteNumber(lastModified);
    567         } else {
    568             append(static_cast<uint8_t>(0));
    569         }
    570     }
    571 
    572     void doWriteArrayBuffer(const ArrayBuffer& arrayBuffer)
    573     {
    574         uint32_t byteLength = arrayBuffer.byteLength();
    575         doWriteUint32(byteLength);
    576         append(static_cast<const uint8_t*>(arrayBuffer.data()), byteLength);
    577     }
    578 
    579     void doWriteString(const char* data, int length)
    580     {
    581         doWriteUint32(static_cast<uint32_t>(length));
    582         append(reinterpret_cast<const uint8_t*>(data), length);
    583     }
    584 
    585     void doWriteWebCoreString(const String& string)
    586     {
    587         StringUTF8Adaptor stringUTF8(string);
    588         doWriteString(stringUTF8.data(), stringUTF8.length());
    589     }
    590 
    591     int bytesNeededToWireEncode(uint32_t value)
    592     {
    593         int bytes = 1;
    594         while (true) {
    595             value >>= varIntShift;
    596             if (!value)
    597                 break;
    598             ++bytes;
    599         }
    600 
    601         return bytes;
    602     }
    603 
    604     template<class T>
    605     void doWriteUintHelper(T value)
    606     {
    607         while (true) {
    608             uint8_t b = (value & varIntMask);
    609             value >>= varIntShift;
    610             if (!value) {
    611                 append(b);
    612                 break;
    613             }
    614             append(b | (1 << varIntShift));
    615         }
    616     }
    617 
    618     void doWriteUint32(uint32_t value)
    619     {
    620         doWriteUintHelper(value);
    621     }
    622 
    623     void doWriteUint64(uint64_t value)
    624     {
    625         doWriteUintHelper(value);
    626     }
    627 
    628     void doWriteNumber(double number)
    629     {
    630         append(reinterpret_cast<uint8_t*>(&number), sizeof(number));
    631     }
    632 
    633     void append(SerializationTag tag)
    634     {
    635         append(static_cast<uint8_t>(tag));
    636     }
    637 
    638     void append(uint8_t b)
    639     {
    640         ensureSpace(1);
    641         *byteAt(m_position++) = b;
    642     }
    643 
    644     void append(const uint8_t* data, int length)
    645     {
    646         ensureSpace(length);
    647         memcpy(byteAt(m_position), data, length);
    648         m_position += length;
    649     }
    650 
    651     void ensureSpace(unsigned extra)
    652     {
    653         COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
    654         m_buffer.resize((m_position + extra + 1) / sizeof(BufferValueType)); // "+ 1" to round up.
    655     }
    656 
    657     void fillHole()
    658     {
    659         COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
    660         // If the writer is at odd position in the buffer, then one of
    661         // the bytes in the last UChar is not initialized.
    662         if (m_position % 2)
    663             *byteAt(m_position) = static_cast<uint8_t>(PaddingTag);
    664     }
    665 
    666     uint8_t* byteAt(int position)
    667     {
    668         return reinterpret_cast<uint8_t*>(m_buffer.data()) + position;
    669     }
    670 
    671     int v8StringWriteOptions()
    672     {
    673         return v8::String::NO_NULL_TERMINATION;
    674     }
    675 
    676     Vector<BufferValueType> m_buffer;
    677     unsigned m_position;
    678     v8::Isolate* m_isolate;
    679 };
    680 
    681 static v8::Handle<v8::Object> toV8Object(MessagePort* impl, v8::Isolate* isolate)
    682 {
    683     if (!impl)
    684         return v8::Handle<v8::Object>();
    685     v8::Handle<v8::Value> wrapper = toV8(impl, v8::Handle<v8::Object>(), isolate);
    686     ASSERT(wrapper->IsObject());
    687     return wrapper.As<v8::Object>();
    688 }
    689 
    690 static v8::Handle<v8::ArrayBuffer> toV8Object(ArrayBuffer* impl, v8::Isolate* isolate)
    691 {
    692     if (!impl)
    693         return v8::Handle<v8::ArrayBuffer>();
    694     v8::Handle<v8::Value> wrapper = toV8(impl, v8::Handle<v8::Object>(), isolate);
    695     ASSERT(wrapper->IsArrayBuffer());
    696     return wrapper.As<v8::ArrayBuffer>();
    697 }
    698 
    699 class Serializer {
    700     class StateBase;
    701 public:
    702     enum Status {
    703         Success,
    704         InputError,
    705         DataCloneError,
    706         InvalidStateError,
    707         JSException,
    708         JSFailure
    709     };
    710 
    711     Serializer(Writer& writer, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, v8::Isolate* isolate)
    712         : m_writer(writer)
    713         , m_tryCatch(tryCatch)
    714         , m_depth(0)
    715         , m_status(Success)
    716         , m_nextObjectReference(0)
    717         , m_blobDataHandles(blobDataHandles)
    718         , m_isolate(isolate)
    719     {
    720         ASSERT(!tryCatch.HasCaught());
    721         if (messagePorts) {
    722             for (size_t i = 0; i < messagePorts->size(); i++)
    723                 m_transferredMessagePorts.set(toV8Object(messagePorts->at(i).get(), m_writer.getIsolate()), i);
    724         }
    725         if (arrayBuffers) {
    726             for (size_t i = 0; i < arrayBuffers->size(); i++)  {
    727                 v8::Handle<v8::Object> v8ArrayBuffer = toV8Object(arrayBuffers->at(i).get(), m_writer.getIsolate());
    728                 // Coalesce multiple occurences of the same buffer to the first index.
    729                 if (!m_transferredArrayBuffers.contains(v8ArrayBuffer))
    730                     m_transferredArrayBuffers.set(v8ArrayBuffer, i);
    731             }
    732         }
    733     }
    734 
    735     Status serialize(v8::Handle<v8::Value> value)
    736     {
    737         v8::HandleScope scope(m_isolate);
    738         m_writer.writeVersion();
    739         StateBase* state = doSerialize(value, 0);
    740         while (state)
    741             state = state->advance(*this);
    742         return m_status;
    743     }
    744 
    745     // Functions used by serialization states.
    746     StateBase* doSerialize(v8::Handle<v8::Value>, StateBase* next);
    747 
    748     StateBase* doSerializeArrayBuffer(v8::Handle<v8::Value> arrayBuffer, StateBase* next)
    749     {
    750         return doSerialize(arrayBuffer, next);
    751     }
    752 
    753     StateBase* checkException(StateBase* state)
    754     {
    755         return m_tryCatch.HasCaught() ? handleError(JSException, state) : 0;
    756     }
    757 
    758     StateBase* reportFailure(StateBase* state)
    759     {
    760         return handleError(JSFailure, state);
    761     }
    762 
    763     StateBase* writeObject(uint32_t numProperties, StateBase* state)
    764     {
    765         m_writer.writeObject(numProperties);
    766         return pop(state);
    767     }
    768 
    769     StateBase* writeSparseArray(uint32_t numProperties, uint32_t length, StateBase* state)
    770     {
    771         m_writer.writeSparseArray(numProperties, length);
    772         return pop(state);
    773     }
    774 
    775     StateBase* writeDenseArray(uint32_t numProperties, uint32_t length, StateBase* state)
    776     {
    777         m_writer.writeDenseArray(numProperties, length);
    778         return pop(state);
    779     }
    780 
    781 
    782 private:
    783     class StateBase {
    784         WTF_MAKE_NONCOPYABLE(StateBase);
    785     public:
    786         virtual ~StateBase() { }
    787 
    788         // Link to the next state to form a stack.
    789         StateBase* nextState() { return m_next; }
    790 
    791         // Composite object we're processing in this state.
    792         v8::Handle<v8::Value> composite() { return m_composite; }
    793 
    794         // Serializes (a part of) the current composite and returns
    795         // the next state to process or null when this is the final
    796         // state.
    797         virtual StateBase* advance(Serializer&) = 0;
    798 
    799         // Returns 1 if this state is currently serializing a property
    800         // via an accessor and 0 otherwise.
    801         virtual uint32_t execDepth() const { return 0; }
    802 
    803     protected:
    804         StateBase(v8::Handle<v8::Value> composite, StateBase* next)
    805             : m_composite(composite)
    806             , m_next(next)
    807         {
    808         }
    809 
    810     private:
    811         v8::Handle<v8::Value> m_composite;
    812         StateBase* m_next;
    813     };
    814 
    815     // Dummy state that is used to signal serialization errors.
    816     class ErrorState : public StateBase {
    817     public:
    818         ErrorState()
    819             : StateBase(v8Undefined(), 0)
    820         {
    821         }
    822 
    823         virtual StateBase* advance(Serializer&)
    824         {
    825             delete this;
    826             return 0;
    827         }
    828     };
    829 
    830     template <typename T>
    831     class State : public StateBase {
    832     public:
    833         v8::Handle<T> composite() { return v8::Handle<T>::Cast(StateBase::composite()); }
    834 
    835     protected:
    836         State(v8::Handle<T> composite, StateBase* next)
    837             : StateBase(composite, next)
    838         {
    839         }
    840     };
    841 
    842     class AbstractObjectState : public State<v8::Object> {
    843     public:
    844         AbstractObjectState(v8::Handle<v8::Object> object, StateBase* next)
    845             : State<v8::Object>(object, next)
    846             , m_index(0)
    847             , m_numSerializedProperties(0)
    848             , m_nameDone(false)
    849         {
    850         }
    851 
    852     protected:
    853         virtual StateBase* objectDone(unsigned numProperties, Serializer&) = 0;
    854 
    855         StateBase* serializeProperties(bool ignoreIndexed, Serializer& serializer)
    856         {
    857             while (m_index < m_propertyNames->Length()) {
    858                 if (!m_nameDone) {
    859                     v8::Local<v8::Value> propertyName = m_propertyNames->Get(m_index);
    860                     if (StateBase* newState = serializer.checkException(this))
    861                         return newState;
    862                     if (propertyName.IsEmpty())
    863                         return serializer.reportFailure(this);
    864                     bool hasStringProperty = propertyName->IsString() && composite()->HasRealNamedProperty(propertyName.As<v8::String>());
    865                     if (StateBase* newState = serializer.checkException(this))
    866                         return newState;
    867                     bool hasIndexedProperty = !hasStringProperty && propertyName->IsUint32() && composite()->HasRealIndexedProperty(propertyName->Uint32Value());
    868                     if (StateBase* newState = serializer.checkException(this))
    869                         return newState;
    870                     if (hasStringProperty || (hasIndexedProperty && !ignoreIndexed))
    871                         m_propertyName = propertyName;
    872                     else {
    873                         ++m_index;
    874                         continue;
    875                     }
    876                 }
    877                 ASSERT(!m_propertyName.IsEmpty());
    878                 if (!m_nameDone) {
    879                     m_nameDone = true;
    880                     if (StateBase* newState = serializer.doSerialize(m_propertyName, this))
    881                         return newState;
    882                 }
    883                 v8::Local<v8::Value> value = composite()->Get(m_propertyName);
    884                 if (StateBase* newState = serializer.checkException(this))
    885                     return newState;
    886                 m_nameDone = false;
    887                 m_propertyName.Clear();
    888                 ++m_index;
    889                 ++m_numSerializedProperties;
    890                 // If we return early here, it's either because we have pushed a new state onto the
    891                 // serialization state stack or because we have encountered an error (and in both cases
    892                 // we are unwinding the native stack).
    893                 if (StateBase* newState = serializer.doSerialize(value, this))
    894                     return newState;
    895             }
    896             return objectDone(m_numSerializedProperties, serializer);
    897         }
    898 
    899         v8::Local<v8::Array> m_propertyNames;
    900 
    901     private:
    902         v8::Local<v8::Value> m_propertyName;
    903         unsigned m_index;
    904         unsigned m_numSerializedProperties;
    905         bool m_nameDone;
    906     };
    907 
    908     class ObjectState : public AbstractObjectState {
    909     public:
    910         ObjectState(v8::Handle<v8::Object> object, StateBase* next)
    911             : AbstractObjectState(object, next)
    912         {
    913         }
    914 
    915         virtual StateBase* advance(Serializer& serializer)
    916         {
    917             if (m_propertyNames.IsEmpty()) {
    918                 m_propertyNames = composite()->GetPropertyNames();
    919                 if (StateBase* newState = serializer.checkException(this))
    920                     return newState;
    921                 if (m_propertyNames.IsEmpty())
    922                     return serializer.reportFailure(this);
    923             }
    924             return serializeProperties(false, serializer);
    925         }
    926 
    927     protected:
    928         virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer)
    929         {
    930             return serializer.writeObject(numProperties, this);
    931         }
    932     };
    933 
    934     class DenseArrayState : public AbstractObjectState {
    935     public:
    936         DenseArrayState(v8::Handle<v8::Array> array, v8::Handle<v8::Array> propertyNames, StateBase* next, v8::Isolate* isolate)
    937             : AbstractObjectState(array, next)
    938             , m_arrayIndex(0)
    939             , m_arrayLength(array->Length())
    940         {
    941             m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames);
    942         }
    943 
    944         virtual StateBase* advance(Serializer& serializer)
    945         {
    946             while (m_arrayIndex < m_arrayLength) {
    947                 v8::Handle<v8::Value> value = composite().As<v8::Array>()->Get(m_arrayIndex);
    948                 m_arrayIndex++;
    949                 if (StateBase* newState = serializer.checkException(this))
    950                     return newState;
    951                 if (StateBase* newState = serializer.doSerialize(value, this))
    952                     return newState;
    953             }
    954             return serializeProperties(true, serializer);
    955         }
    956 
    957     protected:
    958         virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer)
    959         {
    960             return serializer.writeDenseArray(numProperties, m_arrayLength, this);
    961         }
    962 
    963     private:
    964         uint32_t m_arrayIndex;
    965         uint32_t m_arrayLength;
    966     };
    967 
    968     class SparseArrayState : public AbstractObjectState {
    969     public:
    970         SparseArrayState(v8::Handle<v8::Array> array, v8::Handle<v8::Array> propertyNames, StateBase* next, v8::Isolate* isolate)
    971             : AbstractObjectState(array, next)
    972         {
    973             m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames);
    974         }
    975 
    976         virtual StateBase* advance(Serializer& serializer)
    977         {
    978             return serializeProperties(false, serializer);
    979         }
    980 
    981     protected:
    982         virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer)
    983         {
    984             return serializer.writeSparseArray(numProperties, composite().As<v8::Array>()->Length(), this);
    985         }
    986     };
    987 
    988     StateBase* push(StateBase* state)
    989     {
    990         ASSERT(state);
    991         ++m_depth;
    992         return checkComposite(state) ? state : handleError(InputError, state);
    993     }
    994 
    995     StateBase* pop(StateBase* state)
    996     {
    997         ASSERT(state);
    998         --m_depth;
    999         StateBase* next = state->nextState();
   1000         delete state;
   1001         return next;
   1002     }
   1003 
   1004     StateBase* handleError(Status errorStatus, StateBase* state)
   1005     {
   1006         ASSERT(errorStatus != Success);
   1007         m_status = errorStatus;
   1008         while (state) {
   1009             StateBase* tmp = state->nextState();
   1010             delete state;
   1011             state = tmp;
   1012         }
   1013         return new ErrorState;
   1014     }
   1015 
   1016     bool checkComposite(StateBase* top)
   1017     {
   1018         ASSERT(top);
   1019         if (m_depth > maxDepth)
   1020             return false;
   1021         if (!shouldCheckForCycles(m_depth))
   1022             return true;
   1023         v8::Handle<v8::Value> composite = top->composite();
   1024         for (StateBase* state = top->nextState(); state; state = state->nextState()) {
   1025             if (state->composite() == composite)
   1026                 return false;
   1027         }
   1028         return true;
   1029     }
   1030 
   1031     void writeString(v8::Handle<v8::Value> value)
   1032     {
   1033         v8::Handle<v8::String> string = value.As<v8::String>();
   1034         if (!string->Length() || string->IsOneByte())
   1035             m_writer.writeOneByteString(string);
   1036         else
   1037             m_writer.writeUCharString(string);
   1038     }
   1039 
   1040     void writeStringObject(v8::Handle<v8::Value> value)
   1041     {
   1042         v8::Handle<v8::StringObject> stringObject = value.As<v8::StringObject>();
   1043         v8::String::Utf8Value stringValue(stringObject->ValueOf());
   1044         m_writer.writeStringObject(*stringValue, stringValue.length());
   1045     }
   1046 
   1047     void writeNumberObject(v8::Handle<v8::Value> value)
   1048     {
   1049         v8::Handle<v8::NumberObject> numberObject = value.As<v8::NumberObject>();
   1050         m_writer.writeNumberObject(numberObject->ValueOf());
   1051     }
   1052 
   1053     void writeBooleanObject(v8::Handle<v8::Value> value)
   1054     {
   1055         v8::Handle<v8::BooleanObject> booleanObject = value.As<v8::BooleanObject>();
   1056         m_writer.writeBooleanObject(booleanObject->ValueOf());
   1057     }
   1058 
   1059     void writeBlob(v8::Handle<v8::Value> value)
   1060     {
   1061         Blob* blob = V8Blob::toNative(value.As<v8::Object>());
   1062         if (!blob)
   1063             return;
   1064         m_writer.writeBlob(blob->uuid(), blob->type(), blob->size());
   1065         m_blobDataHandles.add(blob->uuid(), blob->blobDataHandle());
   1066     }
   1067 
   1068     StateBase* writeDOMFileSystem(v8::Handle<v8::Value> value, StateBase* next)
   1069     {
   1070         DOMFileSystem* fs = V8DOMFileSystem::toNative(value.As<v8::Object>());
   1071         if (!fs)
   1072             return 0;
   1073         if (!fs->clonable())
   1074             return handleError(DataCloneError, next);
   1075         m_writer.writeDOMFileSystem(fs->type(), fs->name(), fs->rootURL().string());
   1076         return 0;
   1077     }
   1078 
   1079     void writeFile(v8::Handle<v8::Value> value)
   1080     {
   1081         File* file = V8File::toNative(value.As<v8::Object>());
   1082         if (!file)
   1083             return;
   1084         m_writer.writeFile(*file);
   1085         m_blobDataHandles.add(file->uuid(), file->blobDataHandle());
   1086     }
   1087 
   1088     void writeFileList(v8::Handle<v8::Value> value)
   1089     {
   1090         FileList* fileList = V8FileList::toNative(value.As<v8::Object>());
   1091         if (!fileList)
   1092             return;
   1093         m_writer.writeFileList(*fileList);
   1094         unsigned length = fileList->length();
   1095         for (unsigned i = 0; i < length; ++i)
   1096             m_blobDataHandles.add(fileList->item(i)->uuid(), fileList->item(i)->blobDataHandle());
   1097     }
   1098 
   1099     void writeImageData(v8::Handle<v8::Value> value)
   1100     {
   1101         ImageData* imageData = V8ImageData::toNative(value.As<v8::Object>());
   1102         if (!imageData)
   1103             return;
   1104         Uint8ClampedArray* pixelArray = imageData->data();
   1105         m_writer.writeImageData(imageData->width(), imageData->height(), pixelArray->data(), pixelArray->length());
   1106     }
   1107 
   1108     void writeRegExp(v8::Handle<v8::Value> value)
   1109     {
   1110         v8::Handle<v8::RegExp> regExp = value.As<v8::RegExp>();
   1111         m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags());
   1112     }
   1113 
   1114     StateBase* writeAndGreyArrayBufferView(v8::Handle<v8::Object> object, StateBase* next)
   1115     {
   1116         ASSERT(!object.IsEmpty());
   1117         ArrayBufferView* arrayBufferView = V8ArrayBufferView::toNative(object);
   1118         if (!arrayBufferView)
   1119             return 0;
   1120         if (!arrayBufferView->buffer())
   1121             return handleError(DataCloneError, next);
   1122         v8::Handle<v8::Value> underlyingBuffer = toV8(arrayBufferView->buffer(), v8::Handle<v8::Object>(), m_writer.getIsolate());
   1123         if (underlyingBuffer.IsEmpty())
   1124             return handleError(DataCloneError, next);
   1125         StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next);
   1126         if (stateOut)
   1127             return stateOut;
   1128         m_writer.writeArrayBufferView(*arrayBufferView);
   1129         // This should be safe: we serialize something that we know to be a wrapper (see
   1130         // the toV8 call above), so the call to doSerializeArrayBuffer should neither
   1131         // cause the system stack to overflow nor should it have potential to reach
   1132         // this ArrayBufferView again.
   1133         //
   1134         // We do need to grey the underlying buffer before we grey its view, however;
   1135         // ArrayBuffers may be shared, so they need to be given reference IDs, and an
   1136         // ArrayBufferView cannot be constructed without a corresponding ArrayBuffer
   1137         // (or without an additional tag that would allow us to do two-stage construction
   1138         // like we do for Objects and Arrays).
   1139         greyObject(object);
   1140         return 0;
   1141     }
   1142 
   1143     StateBase* writeArrayBuffer(v8::Handle<v8::Value> value, StateBase* next)
   1144     {
   1145         ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(value.As<v8::Object>());
   1146         if (!arrayBuffer)
   1147             return 0;
   1148         if (arrayBuffer->isNeutered())
   1149             return handleError(InvalidStateError, next);
   1150         ASSERT(!m_transferredArrayBuffers.contains(value.As<v8::Object>()));
   1151         m_writer.writeArrayBuffer(*arrayBuffer);
   1152         return 0;
   1153     }
   1154 
   1155     StateBase* writeTransferredArrayBuffer(v8::Handle<v8::Value> value, uint32_t index, StateBase* next)
   1156     {
   1157         ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(value.As<v8::Object>());
   1158         if (!arrayBuffer)
   1159             return 0;
   1160         if (arrayBuffer->isNeutered())
   1161             return handleError(DataCloneError, next);
   1162         m_writer.writeTransferredArrayBuffer(index);
   1163         return 0;
   1164     }
   1165 
   1166     static bool shouldSerializeDensely(uint32_t length, uint32_t propertyCount)
   1167     {
   1168         // Let K be the cost of serializing all property values that are there
   1169         // Cost of serializing sparsely: 5*propertyCount + K (5 bytes per uint32_t key)
   1170         // Cost of serializing densely: K + 1*(length - propertyCount) (1 byte for all properties that are not there)
   1171         // so densely is better than sparsly whenever 6*propertyCount > length
   1172         return 6 * propertyCount >= length;
   1173     }
   1174 
   1175     StateBase* startArrayState(v8::Handle<v8::Array> array, StateBase* next)
   1176     {
   1177         v8::Handle<v8::Array> propertyNames = array->GetPropertyNames();
   1178         if (StateBase* newState = checkException(next))
   1179             return newState;
   1180         uint32_t length = array->Length();
   1181 
   1182         if (shouldSerializeDensely(length, propertyNames->Length())) {
   1183             m_writer.writeGenerateFreshDenseArray(length);
   1184             return push(new DenseArrayState(array, propertyNames, next, m_isolate));
   1185         }
   1186 
   1187         m_writer.writeGenerateFreshSparseArray(length);
   1188         return push(new SparseArrayState(array, propertyNames, next, m_isolate));
   1189     }
   1190 
   1191     StateBase* startObjectState(v8::Handle<v8::Object> object, StateBase* next)
   1192     {
   1193         m_writer.writeGenerateFreshObject();
   1194         // FIXME: check not a wrapper
   1195         return push(new ObjectState(object, next));
   1196     }
   1197 
   1198     // Marks object as having been visited by the serializer and assigns it a unique object reference ID.
   1199     // An object may only be greyed once.
   1200     void greyObject(const v8::Handle<v8::Object>& object)
   1201     {
   1202         ASSERT(!m_objectPool.contains(object));
   1203         uint32_t objectReference = m_nextObjectReference++;
   1204         m_objectPool.set(object, objectReference);
   1205     }
   1206 
   1207     Writer& m_writer;
   1208     v8::TryCatch& m_tryCatch;
   1209     int m_depth;
   1210     Status m_status;
   1211     typedef V8ObjectMap<v8::Object, uint32_t> ObjectPool;
   1212     ObjectPool m_objectPool;
   1213     ObjectPool m_transferredMessagePorts;
   1214     ObjectPool m_transferredArrayBuffers;
   1215     uint32_t m_nextObjectReference;
   1216     BlobDataHandleMap& m_blobDataHandles;
   1217     v8::Isolate* m_isolate;
   1218 };
   1219 
   1220 Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, StateBase* next)
   1221 {
   1222     m_writer.writeReferenceCount(m_nextObjectReference);
   1223     uint32_t objectReference;
   1224     uint32_t arrayBufferIndex;
   1225     WrapperWorldType currentWorldType = worldType(m_isolate);
   1226     if ((value->IsObject() || value->IsDate() || value->IsRegExp())
   1227         && m_objectPool.tryGet(value.As<v8::Object>(), &objectReference)) {
   1228         // Note that IsObject() also detects wrappers (eg, it will catch the things
   1229         // that we grey and write below).
   1230         ASSERT(!value->IsString());
   1231         m_writer.writeObjectReference(objectReference);
   1232     } else if (value.IsEmpty())
   1233         return reportFailure(next);
   1234     else if (value->IsUndefined())
   1235         m_writer.writeUndefined();
   1236     else if (value->IsNull())
   1237         m_writer.writeNull();
   1238     else if (value->IsTrue())
   1239         m_writer.writeTrue();
   1240     else if (value->IsFalse())
   1241         m_writer.writeFalse();
   1242     else if (value->IsInt32())
   1243         m_writer.writeInt32(value->Int32Value());
   1244     else if (value->IsUint32())
   1245         m_writer.writeUint32(value->Uint32Value());
   1246     else if (value->IsNumber())
   1247         m_writer.writeNumber(value.As<v8::Number>()->Value());
   1248     else if (V8ArrayBufferView::hasInstance(value, m_isolate, currentWorldType))
   1249         return writeAndGreyArrayBufferView(value.As<v8::Object>(), next);
   1250     else if (value->IsString())
   1251         writeString(value);
   1252     else if (V8MessagePort::hasInstance(value, m_isolate, currentWorldType)) {
   1253         uint32_t messagePortIndex;
   1254         if (m_transferredMessagePorts.tryGet(value.As<v8::Object>(), &messagePortIndex))
   1255                 m_writer.writeTransferredMessagePort(messagePortIndex);
   1256             else
   1257                 return handleError(DataCloneError, next);
   1258     } else if (V8ArrayBuffer::hasInstance(value, m_isolate, currentWorldType) && m_transferredArrayBuffers.tryGet(value.As<v8::Object>(), &arrayBufferIndex))
   1259         return writeTransferredArrayBuffer(value, arrayBufferIndex, next);
   1260     else {
   1261         v8::Handle<v8::Object> jsObject = value.As<v8::Object>();
   1262         if (jsObject.IsEmpty())
   1263             return handleError(DataCloneError, next);
   1264         greyObject(jsObject);
   1265         if (value->IsDate())
   1266             m_writer.writeDate(value->NumberValue());
   1267         else if (value->IsStringObject())
   1268             writeStringObject(value);
   1269         else if (value->IsNumberObject())
   1270             writeNumberObject(value);
   1271         else if (value->IsBooleanObject())
   1272             writeBooleanObject(value);
   1273         else if (value->IsArray()) {
   1274             return startArrayState(value.As<v8::Array>(), next);
   1275         } else if (V8File::hasInstance(value, m_isolate, currentWorldType))
   1276             writeFile(value);
   1277         else if (V8Blob::hasInstance(value, m_isolate, currentWorldType))
   1278             writeBlob(value);
   1279         else if (V8DOMFileSystem::hasInstance(value, m_isolate, currentWorldType))
   1280             return writeDOMFileSystem(value, next);
   1281         else if (V8FileList::hasInstance(value, m_isolate, currentWorldType))
   1282             writeFileList(value);
   1283         else if (V8ImageData::hasInstance(value, m_isolate, currentWorldType))
   1284             writeImageData(value);
   1285         else if (value->IsRegExp())
   1286             writeRegExp(value);
   1287         else if (V8ArrayBuffer::hasInstance(value, m_isolate, currentWorldType))
   1288             return writeArrayBuffer(value, next);
   1289         else if (value->IsObject()) {
   1290             if (isHostObject(jsObject) || jsObject->IsCallable() || value->IsNativeError())
   1291                 return handleError(DataCloneError, next);
   1292             return startObjectState(jsObject, next);
   1293         } else
   1294             return handleError(DataCloneError, next);
   1295     }
   1296     return 0;
   1297 }
   1298 
   1299 // Interface used by Reader to create objects of composite types.
   1300 class CompositeCreator {
   1301 public:
   1302     virtual ~CompositeCreator() { }
   1303 
   1304     virtual bool consumeTopOfStack(v8::Handle<v8::Value>*) = 0;
   1305     virtual uint32_t objectReferenceCount() = 0;
   1306     virtual void pushObjectReference(const v8::Handle<v8::Value>&) = 0;
   1307     virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle<v8::Value>*) = 0;
   1308     virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Value>*) = 0;
   1309     virtual bool tryGetTransferredArrayBuffer(uint32_t index, v8::Handle<v8::Value>*) = 0;
   1310     virtual bool newSparseArray(uint32_t length) = 0;
   1311     virtual bool newDenseArray(uint32_t length) = 0;
   1312     virtual bool newObject() = 0;
   1313     virtual bool completeObject(uint32_t numProperties, v8::Handle<v8::Value>*) = 0;
   1314     virtual bool completeSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>*) = 0;
   1315     virtual bool completeDenseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>*) = 0;
   1316 };
   1317 
   1318 // Reader is responsible for deserializing primitive types and
   1319 // restoring information about saved objects of composite types.
   1320 class Reader {
   1321 public:
   1322     Reader(const uint8_t* buffer, int length, v8::Isolate* isolate,  const BlobDataHandleMap& blobDataHandles)
   1323         : m_buffer(buffer)
   1324         , m_length(length)
   1325         , m_position(0)
   1326         , m_version(0)
   1327         , m_isolate(isolate)
   1328         , m_blobDataHandles(blobDataHandles)
   1329     {
   1330         ASSERT(!(reinterpret_cast<size_t>(buffer) & 1));
   1331         ASSERT(length >= 0);
   1332     }
   1333 
   1334     bool isEof() const { return m_position >= m_length; }
   1335 
   1336     v8::Isolate* isolate() const { return m_isolate; }
   1337 
   1338     bool read(v8::Handle<v8::Value>* value, CompositeCreator& creator)
   1339     {
   1340         SerializationTag tag;
   1341         if (!readTag(&tag))
   1342             return false;
   1343         switch (tag) {
   1344         case ReferenceCountTag: {
   1345             if (m_version <= 0)
   1346                 return false;
   1347             uint32_t referenceTableSize;
   1348             if (!doReadUint32(&referenceTableSize))
   1349                 return false;
   1350             // If this test fails, then the serializer and deserializer disagree about the assignment
   1351             // of object reference IDs. On the deserialization side, this means there are too many or too few
   1352             // calls to pushObjectReference.
   1353             if (referenceTableSize != creator.objectReferenceCount())
   1354                 return false;
   1355             return true;
   1356         }
   1357         case InvalidTag:
   1358             return false;
   1359         case PaddingTag:
   1360             return true;
   1361         case UndefinedTag:
   1362             *value = v8::Undefined(m_isolate);
   1363             break;
   1364         case NullTag:
   1365             *value = v8::Null(m_isolate);
   1366             break;
   1367         case TrueTag:
   1368             *value = v8BooleanWithCheck(true, m_isolate);
   1369             break;
   1370         case FalseTag:
   1371             *value = v8BooleanWithCheck(false, m_isolate);
   1372             break;
   1373         case TrueObjectTag:
   1374             *value = v8::BooleanObject::New(true);
   1375             creator.pushObjectReference(*value);
   1376             break;
   1377         case FalseObjectTag:
   1378             *value = v8::BooleanObject::New(false);
   1379             creator.pushObjectReference(*value);
   1380             break;
   1381         case StringTag:
   1382             if (!readString(value))
   1383                 return false;
   1384             break;
   1385         case StringUCharTag:
   1386             if (!readUCharString(value))
   1387                 return false;
   1388             break;
   1389         case StringObjectTag:
   1390             if (!readStringObject(value))
   1391                 return false;
   1392             creator.pushObjectReference(*value);
   1393             break;
   1394         case Int32Tag:
   1395             if (!readInt32(value))
   1396                 return false;
   1397             break;
   1398         case Uint32Tag:
   1399             if (!readUint32(value))
   1400                 return false;
   1401             break;
   1402         case DateTag:
   1403             if (!readDate(value))
   1404                 return false;
   1405             creator.pushObjectReference(*value);
   1406             break;
   1407         case NumberTag:
   1408             if (!readNumber(value))
   1409                 return false;
   1410             break;
   1411         case NumberObjectTag:
   1412             if (!readNumberObject(value))
   1413                 return false;
   1414             creator.pushObjectReference(*value);
   1415             break;
   1416         case BlobTag:
   1417             if (!readBlob(value))
   1418                 return false;
   1419             creator.pushObjectReference(*value);
   1420             break;
   1421         case FileTag:
   1422             if (!readFile(value))
   1423                 return false;
   1424             creator.pushObjectReference(*value);
   1425             break;
   1426         case DOMFileSystemTag:
   1427             if (!readDOMFileSystem(value))
   1428                 return false;
   1429             creator.pushObjectReference(*value);
   1430             break;
   1431         case FileListTag:
   1432             if (!readFileList(value))
   1433                 return false;
   1434             creator.pushObjectReference(*value);
   1435             break;
   1436         case ImageDataTag:
   1437             if (!readImageData(value))
   1438                 return false;
   1439             creator.pushObjectReference(*value);
   1440             break;
   1441 
   1442         case RegExpTag:
   1443             if (!readRegExp(value))
   1444                 return false;
   1445             creator.pushObjectReference(*value);
   1446             break;
   1447         case ObjectTag: {
   1448             uint32_t numProperties;
   1449             if (!doReadUint32(&numProperties))
   1450                 return false;
   1451             if (!creator.completeObject(numProperties, value))
   1452                 return false;
   1453             break;
   1454         }
   1455         case SparseArrayTag: {
   1456             uint32_t numProperties;
   1457             uint32_t length;
   1458             if (!doReadUint32(&numProperties))
   1459                 return false;
   1460             if (!doReadUint32(&length))
   1461                 return false;
   1462             if (!creator.completeSparseArray(numProperties, length, value))
   1463                 return false;
   1464             break;
   1465         }
   1466         case DenseArrayTag: {
   1467             uint32_t numProperties;
   1468             uint32_t length;
   1469             if (!doReadUint32(&numProperties))
   1470                 return false;
   1471             if (!doReadUint32(&length))
   1472                 return false;
   1473             if (!creator.completeDenseArray(numProperties, length, value))
   1474                 return false;
   1475             break;
   1476         }
   1477         case ArrayBufferViewTag: {
   1478             if (m_version <= 0)
   1479                 return false;
   1480             if (!readArrayBufferView(value, creator))
   1481                 return false;
   1482             creator.pushObjectReference(*value);
   1483             break;
   1484         }
   1485         case ArrayBufferTag: {
   1486             if (m_version <= 0)
   1487                 return false;
   1488             if (!readArrayBuffer(value))
   1489                 return false;
   1490             creator.pushObjectReference(*value);
   1491             break;
   1492         }
   1493         case GenerateFreshObjectTag: {
   1494             if (m_version <= 0)
   1495                 return false;
   1496             if (!creator.newObject())
   1497                 return false;
   1498             return true;
   1499         }
   1500         case GenerateFreshSparseArrayTag: {
   1501             if (m_version <= 0)
   1502                 return false;
   1503             uint32_t length;
   1504             if (!doReadUint32(&length))
   1505                 return false;
   1506             if (!creator.newSparseArray(length))
   1507                 return false;
   1508             return true;
   1509         }
   1510         case GenerateFreshDenseArrayTag: {
   1511             if (m_version <= 0)
   1512                 return false;
   1513             uint32_t length;
   1514             if (!doReadUint32(&length))
   1515                 return false;
   1516             if (!creator.newDenseArray(length))
   1517                 return false;
   1518             return true;
   1519         }
   1520         case MessagePortTag: {
   1521             if (m_version <= 0)
   1522                 return false;
   1523             uint32_t index;
   1524             if (!doReadUint32(&index))
   1525                 return false;
   1526             if (!creator.tryGetTransferredMessagePort(index, value))
   1527                 return false;
   1528             break;
   1529         }
   1530         case ArrayBufferTransferTag: {
   1531             if (m_version <= 0)
   1532                 return false;
   1533             uint32_t index;
   1534             if (!doReadUint32(&index))
   1535                 return false;
   1536             if (!creator.tryGetTransferredArrayBuffer(index, value))
   1537                 return false;
   1538             break;
   1539         }
   1540         case ObjectReferenceTag: {
   1541             if (m_version <= 0)
   1542                 return false;
   1543             uint32_t reference;
   1544             if (!doReadUint32(&reference))
   1545                 return false;
   1546             if (!creator.tryGetObjectFromObjectReference(reference, value))
   1547                 return false;
   1548             break;
   1549         }
   1550         default:
   1551             return false;
   1552         }
   1553         return !value->IsEmpty();
   1554     }
   1555 
   1556     bool readVersion(uint32_t& version)
   1557     {
   1558         SerializationTag tag;
   1559         if (!readTag(&tag)) {
   1560             // This is a nullary buffer. We're still version 0.
   1561             version = 0;
   1562             return true;
   1563         }
   1564         if (tag != VersionTag) {
   1565             // Versions of the format past 0 start with the version tag.
   1566             version = 0;
   1567             // Put back the tag.
   1568             undoReadTag();
   1569             return true;
   1570         }
   1571         // Version-bearing messages are obligated to finish the version tag.
   1572         return doReadUint32(&version);
   1573     }
   1574 
   1575     void setVersion(uint32_t version)
   1576     {
   1577         m_version = version;
   1578     }
   1579 
   1580     v8::Isolate* getIsolate() { return m_isolate; }
   1581 
   1582 private:
   1583     bool readTag(SerializationTag* tag)
   1584     {
   1585         if (m_position >= m_length)
   1586             return false;
   1587         *tag = static_cast<SerializationTag>(m_buffer[m_position++]);
   1588         return true;
   1589     }
   1590 
   1591     void undoReadTag()
   1592     {
   1593         if (m_position > 0)
   1594             --m_position;
   1595     }
   1596 
   1597     bool readArrayBufferViewSubTag(ArrayBufferViewSubTag* tag)
   1598     {
   1599         if (m_position >= m_length)
   1600             return false;
   1601         *tag = static_cast<ArrayBufferViewSubTag>(m_buffer[m_position++]);
   1602         return true;
   1603     }
   1604 
   1605     bool readString(v8::Handle<v8::Value>* value)
   1606     {
   1607         uint32_t length;
   1608         if (!doReadUint32(&length))
   1609             return false;
   1610         if (m_position + length > m_length)
   1611             return false;
   1612         *value = v8::String::NewFromUtf8(m_isolate, reinterpret_cast<const char*>(m_buffer + m_position), v8::String::kNormalString, length);
   1613         m_position += length;
   1614         return true;
   1615     }
   1616 
   1617     bool readUCharString(v8::Handle<v8::Value>* value)
   1618     {
   1619         uint32_t length;
   1620         if (!doReadUint32(&length) || (length & 1))
   1621             return false;
   1622         if (m_position + length > m_length)
   1623             return false;
   1624         ASSERT(!(m_position & 1));
   1625         *value = v8::String::NewFromTwoByte(m_isolate, reinterpret_cast<const uint16_t*>(m_buffer + m_position), v8::String::kNormalString, length / sizeof(UChar));
   1626         m_position += length;
   1627         return true;
   1628     }
   1629 
   1630     bool readStringObject(v8::Handle<v8::Value>* value)
   1631     {
   1632         v8::Handle<v8::Value> stringValue;
   1633         if (!readString(&stringValue) || !stringValue->IsString())
   1634             return false;
   1635         *value = v8::StringObject::New(stringValue.As<v8::String>());
   1636         return true;
   1637     }
   1638 
   1639     bool readWebCoreString(String* string)
   1640     {
   1641         uint32_t length;
   1642         if (!doReadUint32(&length))
   1643             return false;
   1644         if (m_position + length > m_length)
   1645             return false;
   1646         *string = String::fromUTF8(reinterpret_cast<const char*>(m_buffer + m_position), length);
   1647         m_position += length;
   1648         return true;
   1649     }
   1650 
   1651     bool readInt32(v8::Handle<v8::Value>* value)
   1652     {
   1653         uint32_t rawValue;
   1654         if (!doReadUint32(&rawValue))
   1655             return false;
   1656         *value = v8::Integer::New(static_cast<int32_t>(ZigZag::decode(rawValue)), m_isolate);
   1657         return true;
   1658     }
   1659 
   1660     bool readUint32(v8::Handle<v8::Value>* value)
   1661     {
   1662         uint32_t rawValue;
   1663         if (!doReadUint32(&rawValue))
   1664             return false;
   1665         *value = v8::Integer::NewFromUnsigned(rawValue, m_isolate);
   1666         return true;
   1667     }
   1668 
   1669     bool readDate(v8::Handle<v8::Value>* value)
   1670     {
   1671         double numberValue;
   1672         if (!doReadNumber(&numberValue))
   1673             return false;
   1674         *value = v8DateOrNull(numberValue, m_isolate);
   1675         return true;
   1676     }
   1677 
   1678     bool readNumber(v8::Handle<v8::Value>* value)
   1679     {
   1680         double number;
   1681         if (!doReadNumber(&number))
   1682             return false;
   1683         *value = v8::Number::New(m_isolate, number);
   1684         return true;
   1685     }
   1686 
   1687     bool readNumberObject(v8::Handle<v8::Value>* value)
   1688     {
   1689         double number;
   1690         if (!doReadNumber(&number))
   1691             return false;
   1692         *value = v8::NumberObject::New(m_isolate, number);
   1693         return true;
   1694     }
   1695 
   1696     bool readImageData(v8::Handle<v8::Value>* value)
   1697     {
   1698         uint32_t width;
   1699         uint32_t height;
   1700         uint32_t pixelDataLength;
   1701         if (!doReadUint32(&width))
   1702             return false;
   1703         if (!doReadUint32(&height))
   1704             return false;
   1705         if (!doReadUint32(&pixelDataLength))
   1706             return false;
   1707         if (m_position + pixelDataLength > m_length)
   1708             return false;
   1709         RefPtr<ImageData> imageData = ImageData::create(IntSize(width, height));
   1710         Uint8ClampedArray* pixelArray = imageData->data();
   1711         ASSERT(pixelArray);
   1712         ASSERT(pixelArray->length() >= pixelDataLength);
   1713         memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength);
   1714         m_position += pixelDataLength;
   1715         *value = toV8(imageData.release(), v8::Handle<v8::Object>(), m_isolate);
   1716         return true;
   1717     }
   1718 
   1719     PassRefPtr<ArrayBuffer> doReadArrayBuffer()
   1720     {
   1721         uint32_t byteLength;
   1722         if (!doReadUint32(&byteLength))
   1723             return 0;
   1724         if (m_position + byteLength > m_length)
   1725             return 0;
   1726         const void* bufferStart = m_buffer + m_position;
   1727         RefPtr<ArrayBuffer> arrayBuffer = ArrayBuffer::create(bufferStart, byteLength);
   1728         arrayBuffer->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instanceTemplate());
   1729         m_position += byteLength;
   1730         return arrayBuffer.release();
   1731     }
   1732 
   1733     bool readArrayBuffer(v8::Handle<v8::Value>* value)
   1734     {
   1735         RefPtr<ArrayBuffer> arrayBuffer = doReadArrayBuffer();
   1736         if (!arrayBuffer)
   1737             return false;
   1738         *value = toV8(arrayBuffer.release(), v8::Handle<v8::Object>(), m_isolate);
   1739         return true;
   1740     }
   1741 
   1742     bool readArrayBufferView(v8::Handle<v8::Value>* value, CompositeCreator& creator)
   1743     {
   1744         ArrayBufferViewSubTag subTag;
   1745         uint32_t byteOffset;
   1746         uint32_t byteLength;
   1747         RefPtr<ArrayBuffer> arrayBuffer;
   1748         v8::Handle<v8::Value> arrayBufferV8Value;
   1749         if (!readArrayBufferViewSubTag(&subTag))
   1750             return false;
   1751         if (!doReadUint32(&byteOffset))
   1752             return false;
   1753         if (!doReadUint32(&byteLength))
   1754             return false;
   1755         if (!creator.consumeTopOfStack(&arrayBufferV8Value))
   1756             return false;
   1757         if (arrayBufferV8Value.IsEmpty())
   1758             return false;
   1759         arrayBuffer = V8ArrayBuffer::toNative(arrayBufferV8Value.As<v8::Object>());
   1760         if (!arrayBuffer)
   1761             return false;
   1762         switch (subTag) {
   1763         case ByteArrayTag:
   1764             *value = toV8(Int8Array::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate);
   1765             break;
   1766         case UnsignedByteArrayTag:
   1767             *value = toV8(Uint8Array::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(),  m_isolate);
   1768             break;
   1769         case UnsignedByteClampedArrayTag:
   1770             *value = toV8(Uint8ClampedArray::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate);
   1771             break;
   1772         case ShortArrayTag: {
   1773             uint32_t shortLength = byteLength / sizeof(int16_t);
   1774             if (shortLength * sizeof(int16_t) != byteLength)
   1775                 return false;
   1776             *value = toV8(Int16Array::create(arrayBuffer.release(), byteOffset, shortLength), v8::Handle<v8::Object>(), m_isolate);
   1777             break;
   1778         }
   1779         case UnsignedShortArrayTag: {
   1780             uint32_t shortLength = byteLength / sizeof(uint16_t);
   1781             if (shortLength * sizeof(uint16_t) != byteLength)
   1782                 return false;
   1783             *value = toV8(Uint16Array::create(arrayBuffer.release(), byteOffset, shortLength), v8::Handle<v8::Object>(), m_isolate);
   1784             break;
   1785         }
   1786         case IntArrayTag: {
   1787             uint32_t intLength = byteLength / sizeof(int32_t);
   1788             if (intLength * sizeof(int32_t) != byteLength)
   1789                 return false;
   1790             *value = toV8(Int32Array::create(arrayBuffer.release(), byteOffset, intLength), v8::Handle<v8::Object>(), m_isolate);
   1791             break;
   1792         }
   1793         case UnsignedIntArrayTag: {
   1794             uint32_t intLength = byteLength / sizeof(uint32_t);
   1795             if (intLength * sizeof(uint32_t) != byteLength)
   1796                 return false;
   1797             *value = toV8(Uint32Array::create(arrayBuffer.release(), byteOffset, intLength), v8::Handle<v8::Object>(), m_isolate);
   1798             break;
   1799         }
   1800         case FloatArrayTag: {
   1801             uint32_t floatLength = byteLength / sizeof(float);
   1802             if (floatLength * sizeof(float) != byteLength)
   1803                 return false;
   1804             *value = toV8(Float32Array::create(arrayBuffer.release(), byteOffset, floatLength), v8::Handle<v8::Object>(), m_isolate);
   1805             break;
   1806         }
   1807         case DoubleArrayTag: {
   1808             uint32_t floatLength = byteLength / sizeof(double);
   1809             if (floatLength * sizeof(double) != byteLength)
   1810                 return false;
   1811             *value = toV8(Float64Array::create(arrayBuffer.release(), byteOffset, floatLength), v8::Handle<v8::Object>(), m_isolate);
   1812             break;
   1813         }
   1814         case DataViewTag:
   1815             *value = toV8(DataView::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate);
   1816             break;
   1817         default:
   1818             return false;
   1819         }
   1820         // The various *Array::create() methods will return null if the range the view expects is
   1821         // mismatched with the range the buffer can provide or if the byte offset is not aligned
   1822         // to the size of the element type.
   1823         return !value->IsEmpty();
   1824     }
   1825 
   1826     bool readRegExp(v8::Handle<v8::Value>* value)
   1827     {
   1828         v8::Handle<v8::Value> pattern;
   1829         if (!readString(&pattern))
   1830             return false;
   1831         uint32_t flags;
   1832         if (!doReadUint32(&flags))
   1833             return false;
   1834         *value = v8::RegExp::New(pattern.As<v8::String>(), static_cast<v8::RegExp::Flags>(flags));
   1835         return true;
   1836     }
   1837 
   1838     bool readBlob(v8::Handle<v8::Value>* value)
   1839     {
   1840         if (m_version < 3)
   1841             return false;
   1842         String uuid;
   1843         String type;
   1844         uint64_t size;
   1845         if (!readWebCoreString(&uuid))
   1846             return false;
   1847         if (!readWebCoreString(&type))
   1848             return false;
   1849         if (!doReadUint64(&size))
   1850             return false;
   1851         RefPtr<Blob> blob = Blob::create(getOrCreateBlobDataHandle(uuid, type, size));
   1852         *value = toV8(blob.release(), v8::Handle<v8::Object>(), m_isolate);
   1853         return true;
   1854     }
   1855 
   1856     bool readDOMFileSystem(v8::Handle<v8::Value>* value)
   1857     {
   1858         uint32_t type;
   1859         String name;
   1860         String url;
   1861         if (!doReadUint32(&type))
   1862             return false;
   1863         if (!readWebCoreString(&name))
   1864             return false;
   1865         if (!readWebCoreString(&url))
   1866             return false;
   1867         RefPtr<DOMFileSystem> fs = DOMFileSystem::create(getExecutionContext(), name, static_cast<WebCore::FileSystemType>(type), KURL(ParsedURLString, url));
   1868         *value = toV8(fs.release(), v8::Handle<v8::Object>(), m_isolate);
   1869         return true;
   1870     }
   1871 
   1872     bool readFile(v8::Handle<v8::Value>* value)
   1873     {
   1874         RefPtr<File> file = doReadFileHelper();
   1875         if (!file)
   1876             return false;
   1877         *value = toV8(file.release(), v8::Handle<v8::Object>(), m_isolate);
   1878         return true;
   1879     }
   1880 
   1881     bool readFileList(v8::Handle<v8::Value>* value)
   1882     {
   1883         if (m_version < 3)
   1884             return false;
   1885         uint32_t length;
   1886         if (!doReadUint32(&length))
   1887             return false;
   1888         RefPtr<FileList> fileList = FileList::create();
   1889         for (unsigned i = 0; i < length; ++i) {
   1890             RefPtr<File> file = doReadFileHelper();
   1891             if (!file)
   1892                 return false;
   1893             fileList->append(file.release());
   1894         }
   1895         *value = toV8(fileList.release(), v8::Handle<v8::Object>(), m_isolate);
   1896         return true;
   1897     }
   1898 
   1899     PassRefPtr<File> doReadFileHelper()
   1900     {
   1901         if (m_version < 3)
   1902             return 0;
   1903         String path;
   1904         String name;
   1905         String relativePath;
   1906         String uuid;
   1907         String type;
   1908         uint32_t hasSnapshot = 0;
   1909         uint64_t size = 0;
   1910         double lastModified = 0;
   1911         if (!readWebCoreString(&path))
   1912             return 0;
   1913         if (m_version >= 4 && !readWebCoreString(&name))
   1914             return 0;
   1915         if (m_version >= 4 && !readWebCoreString(&relativePath))
   1916             return 0;
   1917         if (!readWebCoreString(&uuid))
   1918             return 0;
   1919         if (!readWebCoreString(&type))
   1920             return 0;
   1921         if (m_version >= 4 && !doReadUint32(&hasSnapshot))
   1922             return 0;
   1923         if (hasSnapshot) {
   1924             if (!doReadUint64(&size))
   1925                 return 0;
   1926             if (!doReadNumber(&lastModified))
   1927                 return 0;
   1928         }
   1929         return File::create(path, name, relativePath, hasSnapshot > 0, size, lastModified, getOrCreateBlobDataHandle(uuid, type));
   1930     }
   1931 
   1932     template<class T>
   1933     bool doReadUintHelper(T* value)
   1934     {
   1935         *value = 0;
   1936         uint8_t currentByte;
   1937         int shift = 0;
   1938         do {
   1939             if (m_position >= m_length)
   1940                 return false;
   1941             currentByte = m_buffer[m_position++];
   1942             *value |= ((currentByte & varIntMask) << shift);
   1943             shift += varIntShift;
   1944         } while (currentByte & (1 << varIntShift));
   1945         return true;
   1946     }
   1947 
   1948     bool doReadUint32(uint32_t* value)
   1949     {
   1950         return doReadUintHelper(value);
   1951     }
   1952 
   1953     bool doReadUint64(uint64_t* value)
   1954     {
   1955         return doReadUintHelper(value);
   1956     }
   1957 
   1958     bool doReadNumber(double* number)
   1959     {
   1960         if (m_position + sizeof(double) > m_length)
   1961             return false;
   1962         uint8_t* numberAsByteArray = reinterpret_cast<uint8_t*>(number);
   1963         for (unsigned i = 0; i < sizeof(double); ++i)
   1964             numberAsByteArray[i] = m_buffer[m_position++];
   1965         return true;
   1966     }
   1967 
   1968     PassRefPtr<BlobDataHandle> getOrCreateBlobDataHandle(const String& uuid, const String& type, long long size = -1)
   1969     {
   1970         // The containing ssv may have a BDH for this uuid if this ssv is just being
   1971         // passed from main to worker thread (for example). We use those values when creating
   1972         // the new blob instead of cons'ing up a new BDH.
   1973         //
   1974         // FIXME: Maybe we should require that it work that way where the ssv must have a BDH for any
   1975         // blobs it comes across during deserialization. Would require callers to explicitly populate
   1976         // the collection of BDH's for blobs to work, which would encourage lifetimes to be considered
   1977         // when passing ssv's around cross process. At present, we get 'lucky' in some cases because
   1978         // the blob in the src process happens to still exist at the time the dest process is deserializing.
   1979         // For example in sharedWorker.postMesssage(...).
   1980         BlobDataHandleMap::const_iterator it = m_blobDataHandles.find(uuid);
   1981         if (it != m_blobDataHandles.end()) {
   1982             // make assertions about type and size?
   1983             return it->value;
   1984         }
   1985         return BlobDataHandle::create(uuid, type, size);
   1986     }
   1987 
   1988     const uint8_t* m_buffer;
   1989     const unsigned m_length;
   1990     unsigned m_position;
   1991     uint32_t m_version;
   1992     v8::Isolate* m_isolate;
   1993     const BlobDataHandleMap& m_blobDataHandles;
   1994 };
   1995 
   1996 
   1997 typedef Vector<WTF::ArrayBufferContents, 1> ArrayBufferContentsArray;
   1998 
   1999 class Deserializer : public CompositeCreator {
   2000 public:
   2001     Deserializer(Reader& reader, MessagePortArray* messagePorts, ArrayBufferContentsArray* arrayBufferContents)
   2002         : m_reader(reader)
   2003         , m_transferredMessagePorts(messagePorts)
   2004         , m_arrayBufferContents(arrayBufferContents)
   2005         , m_arrayBuffers(arrayBufferContents ? arrayBufferContents->size() : 0)
   2006         , m_version(0)
   2007     {
   2008     }
   2009 
   2010     v8::Handle<v8::Value> deserialize()
   2011     {
   2012         if (!m_reader.readVersion(m_version) || m_version > SerializedScriptValue::wireFormatVersion)
   2013             return v8::Null(m_reader.getIsolate());
   2014         m_reader.setVersion(m_version);
   2015         v8::EscapableHandleScope scope(m_reader.getIsolate());
   2016         while (!m_reader.isEof()) {
   2017             if (!doDeserialize())
   2018                 return v8::Null(m_reader.getIsolate());
   2019         }
   2020         if (stackDepth() != 1 || m_openCompositeReferenceStack.size())
   2021             return v8::Null(m_reader.getIsolate());
   2022         v8::Handle<v8::Value> result = scope.Escape(element(0));
   2023         return result;
   2024     }
   2025 
   2026     virtual bool newSparseArray(uint32_t)
   2027     {
   2028         v8::Local<v8::Array> array = v8::Array::New(m_reader.isolate(), 0);
   2029         openComposite(array);
   2030         return true;
   2031     }
   2032 
   2033     virtual bool newDenseArray(uint32_t length)
   2034     {
   2035         v8::Local<v8::Array> array = v8::Array::New(m_reader.isolate(), length);
   2036         openComposite(array);
   2037         return true;
   2038     }
   2039 
   2040     virtual bool consumeTopOfStack(v8::Handle<v8::Value>* object)
   2041     {
   2042         if (stackDepth() < 1)
   2043             return false;
   2044         *object = element(stackDepth() - 1);
   2045         pop(1);
   2046         return true;
   2047     }
   2048 
   2049     virtual bool completeArray(uint32_t length, v8::Handle<v8::Value>* value)
   2050     {
   2051         if (length > stackDepth())
   2052             return false;
   2053         v8::Local<v8::Array> array;
   2054         if (m_version > 0) {
   2055             v8::Local<v8::Value> composite;
   2056             if (!closeComposite(&composite))
   2057                 return false;
   2058             array = composite.As<v8::Array>();
   2059         } else {
   2060             array = v8::Array::New(m_reader.isolate(), length);
   2061         }
   2062         if (array.IsEmpty())
   2063             return false;
   2064         const int depth = stackDepth() - length;
   2065         // The V8 API ensures space exists for any index argument to Set; it will (eg) resize arrays as necessary.
   2066         for (unsigned i = 0; i < length; ++i)
   2067             array->Set(i, element(depth + i));
   2068         pop(length);
   2069         *value = array;
   2070         return true;
   2071     }
   2072 
   2073     virtual bool newObject()
   2074     {
   2075         v8::Local<v8::Object> object = v8::Object::New();
   2076         if (object.IsEmpty())
   2077             return false;
   2078         openComposite(object);
   2079         return true;
   2080     }
   2081 
   2082     virtual bool completeObject(uint32_t numProperties, v8::Handle<v8::Value>* value)
   2083     {
   2084         v8::Local<v8::Object> object;
   2085         if (m_version > 0) {
   2086             v8::Local<v8::Value> composite;
   2087             if (!closeComposite(&composite))
   2088                 return false;
   2089             object = composite.As<v8::Object>();
   2090         } else
   2091             object = v8::Object::New();
   2092         if (object.IsEmpty())
   2093             return false;
   2094         return initializeObject(object, numProperties, value);
   2095     }
   2096 
   2097     virtual bool completeSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value)
   2098     {
   2099         v8::Local<v8::Array> array;
   2100         if (m_version > 0) {
   2101             v8::Local<v8::Value> composite;
   2102             if (!closeComposite(&composite))
   2103                 return false;
   2104             array = composite.As<v8::Array>();
   2105         } else {
   2106             array = v8::Array::New(m_reader.isolate());
   2107         }
   2108         if (array.IsEmpty())
   2109             return false;
   2110         return initializeObject(array, numProperties, value);
   2111     }
   2112 
   2113     virtual bool completeDenseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value)
   2114     {
   2115         v8::Local<v8::Array> array;
   2116         if (m_version > 0) {
   2117             v8::Local<v8::Value> composite;
   2118             if (!closeComposite(&composite))
   2119                 return false;
   2120             array = composite.As<v8::Array>();
   2121         }
   2122         if (array.IsEmpty())
   2123             return false;
   2124         if (!initializeObject(array, numProperties, value))
   2125             return false;
   2126         if (length > stackDepth())
   2127             return false;
   2128         for (unsigned i = 0, stackPos = stackDepth() - length; i < length; i++, stackPos++) {
   2129             v8::Local<v8::Value> elem = element(stackPos);
   2130             if (!elem->IsUndefined())
   2131                 array->Set(i, elem);
   2132         }
   2133         pop(length);
   2134         return true;
   2135     }
   2136 
   2137     virtual void pushObjectReference(const v8::Handle<v8::Value>& object)
   2138     {
   2139         m_objectPool.append(object);
   2140     }
   2141 
   2142     virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Value>* object)
   2143     {
   2144         if (!m_transferredMessagePorts)
   2145             return false;
   2146         if (index >= m_transferredMessagePorts->size())
   2147             return false;
   2148         *object = toV8(m_transferredMessagePorts->at(index).get(), v8::Handle<v8::Object>(), m_reader.getIsolate());
   2149         return true;
   2150     }
   2151 
   2152     virtual bool tryGetTransferredArrayBuffer(uint32_t index, v8::Handle<v8::Value>* object)
   2153     {
   2154         if (!m_arrayBufferContents)
   2155             return false;
   2156         if (index >= m_arrayBuffers.size())
   2157             return false;
   2158         v8::Handle<v8::Object> result = m_arrayBuffers.at(index);
   2159         if (result.IsEmpty()) {
   2160             RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(m_arrayBufferContents->at(index));
   2161             buffer->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instanceTemplate());
   2162             m_reader.isolate()->AdjustAmountOfExternalAllocatedMemory(buffer->byteLength());
   2163             result = toV8Object(buffer.get(), m_reader.getIsolate());
   2164             m_arrayBuffers[index] = result;
   2165         }
   2166         *object = result;
   2167         return true;
   2168     }
   2169 
   2170     virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle<v8::Value>* object)
   2171     {
   2172         if (reference >= m_objectPool.size())
   2173             return false;
   2174         *object = m_objectPool[reference];
   2175         return object;
   2176     }
   2177 
   2178     virtual uint32_t objectReferenceCount()
   2179     {
   2180         return m_objectPool.size();
   2181     }
   2182 
   2183 private:
   2184     bool initializeObject(v8::Handle<v8::Object> object, uint32_t numProperties, v8::Handle<v8::Value>* value)
   2185     {
   2186         unsigned length = 2 * numProperties;
   2187         if (length > stackDepth())
   2188             return false;
   2189         for (unsigned i = stackDepth() - length; i < stackDepth(); i += 2) {
   2190             v8::Local<v8::Value> propertyName = element(i);
   2191             v8::Local<v8::Value> propertyValue = element(i + 1);
   2192             object->Set(propertyName, propertyValue);
   2193         }
   2194         pop(length);
   2195         *value = object;
   2196         return true;
   2197     }
   2198 
   2199     bool doDeserialize()
   2200     {
   2201         v8::Local<v8::Value> value;
   2202         if (!m_reader.read(&value, *this))
   2203             return false;
   2204         if (!value.IsEmpty())
   2205             push(value);
   2206         return true;
   2207     }
   2208 
   2209     void push(v8::Local<v8::Value> value) { m_stack.append(value); }
   2210 
   2211     void pop(unsigned length)
   2212     {
   2213         ASSERT(length <= m_stack.size());
   2214         m_stack.shrink(m_stack.size() - length);
   2215     }
   2216 
   2217     unsigned stackDepth() const { return m_stack.size(); }
   2218 
   2219     v8::Local<v8::Value> element(unsigned index)
   2220     {
   2221         ASSERT_WITH_SECURITY_IMPLICATION(index < m_stack.size());
   2222         return m_stack[index];
   2223     }
   2224 
   2225     void openComposite(const v8::Local<v8::Value>& object)
   2226     {
   2227         uint32_t newObjectReference = m_objectPool.size();
   2228         m_openCompositeReferenceStack.append(newObjectReference);
   2229         m_objectPool.append(object);
   2230     }
   2231 
   2232     bool closeComposite(v8::Handle<v8::Value>* object)
   2233     {
   2234         if (!m_openCompositeReferenceStack.size())
   2235             return false;
   2236         uint32_t objectReference = m_openCompositeReferenceStack[m_openCompositeReferenceStack.size() - 1];
   2237         m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size() - 1);
   2238         if (objectReference >= m_objectPool.size())
   2239             return false;
   2240         *object = m_objectPool[objectReference];
   2241         return true;
   2242     }
   2243 
   2244     Reader& m_reader;
   2245     Vector<v8::Local<v8::Value> > m_stack;
   2246     Vector<v8::Handle<v8::Value> > m_objectPool;
   2247     Vector<uint32_t> m_openCompositeReferenceStack;
   2248     MessagePortArray* m_transferredMessagePorts;
   2249     ArrayBufferContentsArray* m_arrayBufferContents;
   2250     Vector<v8::Handle<v8::Object> > m_arrayBuffers;
   2251     uint32_t m_version;
   2252 };
   2253 
   2254 } // namespace
   2255 
   2256 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, bool& didThrow, v8::Isolate* isolate)
   2257 {
   2258     return adoptRef(new SerializedScriptValue(value, messagePorts, arrayBuffers, didThrow, isolate));
   2259 }
   2260 
   2261 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createAndSwallowExceptions(v8::Handle<v8::Value> value, v8::Isolate* isolate)
   2262 {
   2263     bool didThrow;
   2264     return adoptRef(new SerializedScriptValue(value, 0, 0, didThrow, isolate, DoNotThrowExceptions));
   2265 }
   2266 
   2267 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const ScriptValue& value, bool& didThrow, ScriptState* state)
   2268 {
   2269     ScriptScope scope(state);
   2270     return adoptRef(new SerializedScriptValue(value.v8Value(), 0, 0, didThrow, state->isolate()));
   2271 }
   2272 
   2273 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWire(const String& data)
   2274 {
   2275     return adoptRef(new SerializedScriptValue(data));
   2276 }
   2277 
   2278 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWireBytes(const Vector<uint8_t>& data)
   2279 {
   2280     // Decode wire data from big endian to host byte order.
   2281     ASSERT(!(data.size() % sizeof(UChar)));
   2282     size_t length = data.size() / sizeof(UChar);
   2283     StringBuffer<UChar> buffer(length);
   2284     const UChar* src = reinterpret_cast<const UChar*>(data.data());
   2285     UChar* dst = buffer.characters();
   2286     for (size_t i = 0; i < length; i++)
   2287         dst[i] = ntohs(src[i]);
   2288 
   2289     return createFromWire(String::adopt(buffer));
   2290 }
   2291 
   2292 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& data)
   2293 {
   2294     return create(data, v8::Isolate::GetCurrent());
   2295 }
   2296 
   2297 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& data, v8::Isolate* isolate)
   2298 {
   2299     Writer writer(isolate);
   2300     writer.writeWebCoreString(data);
   2301     String wireData = writer.takeWireString();
   2302     return adoptRef(new SerializedScriptValue(wireData));
   2303 }
   2304 
   2305 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create()
   2306 {
   2307     return adoptRef(new SerializedScriptValue());
   2308 }
   2309 
   2310 PassRefPtr<SerializedScriptValue> SerializedScriptValue::nullValue()
   2311 {
   2312     return nullValue(v8::Isolate::GetCurrent());
   2313 }
   2314 
   2315 PassRefPtr<SerializedScriptValue> SerializedScriptValue::nullValue(v8::Isolate* isolate)
   2316 {
   2317     Writer writer(isolate);
   2318     writer.writeNull();
   2319     String wireData = writer.takeWireString();
   2320     return adoptRef(new SerializedScriptValue(wireData));
   2321 }
   2322 
   2323 // Convert serialized string to big endian wire data.
   2324 void SerializedScriptValue::toWireBytes(Vector<char>& result) const
   2325 {
   2326     ASSERT(result.isEmpty());
   2327     size_t length = m_data.length();
   2328     result.resize(length * sizeof(UChar));
   2329     UChar* dst = reinterpret_cast<UChar*>(result.data());
   2330 
   2331     if (m_data.is8Bit()) {
   2332         const LChar* src = m_data.characters8();
   2333         for (size_t i = 0; i < length; i++)
   2334             dst[i] = htons(static_cast<UChar>(src[i]));
   2335     } else {
   2336         const UChar* src = m_data.characters16();
   2337         for (size_t i = 0; i < length; i++)
   2338             dst[i] = htons(src[i]);
   2339     }
   2340 }
   2341 
   2342 SerializedScriptValue::SerializedScriptValue()
   2343     : m_externallyAllocatedMemory(0)
   2344 {
   2345 }
   2346 
   2347 inline void neuterBinding(ArrayBuffer* object)
   2348 {
   2349     v8::Isolate* isolate = v8::Isolate::GetCurrent();
   2350     Vector<DOMDataStore*>& allStores = V8PerIsolateData::from(isolate)->allStores();
   2351     for (size_t i = 0; i < allStores.size(); i++) {
   2352         v8::Handle<v8::Object> wrapper = allStores[i]->get<V8ArrayBuffer>(object, isolate);
   2353         if (!wrapper.IsEmpty()) {
   2354             ASSERT(wrapper->IsArrayBuffer());
   2355             v8::Handle<v8::ArrayBuffer>::Cast(wrapper)->Neuter();
   2356         }
   2357     }
   2358 }
   2359 
   2360 inline void neuterBinding(ArrayBufferView* object)
   2361 {
   2362     v8::Isolate* isolate = v8::Isolate::GetCurrent();
   2363     Vector<DOMDataStore*>& allStores = V8PerIsolateData::from(isolate)->allStores();
   2364     for (size_t i = 0; i < allStores.size(); i++) {
   2365         v8::Handle<v8::Object> wrapper = allStores[i]->get<V8ArrayBufferView>(object, isolate);
   2366         if (!wrapper.IsEmpty())
   2367             wrapper->SetIndexedPropertiesToExternalArrayData(0, v8::kExternalByteArray, 0);
   2368     }
   2369 }
   2370 
   2371 PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValue::transferArrayBuffers(ArrayBufferArray& arrayBuffers, bool& didThrow, v8::Isolate* isolate)
   2372 {
   2373     ASSERT(arrayBuffers.size());
   2374 
   2375     for (size_t i = 0; i < arrayBuffers.size(); i++) {
   2376         if (arrayBuffers[i]->isNeutered()) {
   2377             setDOMException(InvalidStateError, isolate);
   2378             didThrow = true;
   2379             return nullptr;
   2380         }
   2381     }
   2382 
   2383     OwnPtr<ArrayBufferContentsArray> contents = adoptPtr(new ArrayBufferContentsArray(arrayBuffers.size()));
   2384 
   2385     HashSet<ArrayBuffer*> visited;
   2386     for (size_t i = 0; i < arrayBuffers.size(); i++) {
   2387         Vector<RefPtr<ArrayBufferView> > neuteredViews;
   2388 
   2389         if (visited.contains(arrayBuffers[i].get()))
   2390             continue;
   2391         visited.add(arrayBuffers[i].get());
   2392 
   2393         bool result = arrayBuffers[i]->transfer(contents->at(i), neuteredViews);
   2394         if (!result) {
   2395             setDOMException(InvalidStateError, isolate);
   2396             didThrow = true;
   2397             return nullptr;
   2398         }
   2399 
   2400         neuterBinding(arrayBuffers[i].get());
   2401         for (size_t j = 0; j < neuteredViews.size(); j++)
   2402             neuterBinding(neuteredViews[j].get());
   2403     }
   2404     return contents.release();
   2405 }
   2406 
   2407 SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, bool& didThrow, v8::Isolate* isolate, ExceptionPolicy policy)
   2408     : m_externallyAllocatedMemory(0)
   2409 {
   2410     didThrow = false;
   2411     Writer writer(isolate);
   2412     Serializer::Status status;
   2413     {
   2414         v8::TryCatch tryCatch;
   2415         Serializer serializer(writer, messagePorts, arrayBuffers, m_blobDataHandles, tryCatch, isolate);
   2416         status = serializer.serialize(value);
   2417         if (status == Serializer::JSException) {
   2418             didThrow = true;
   2419             // If there was a JS exception thrown, re-throw it.
   2420             if (policy == ThrowExceptions)
   2421                 tryCatch.ReThrow();
   2422             return;
   2423         }
   2424     }
   2425     switch (status) {
   2426     case Serializer::InputError:
   2427     case Serializer::DataCloneError:
   2428         // If there was an input error, throw a new exception outside
   2429         // of the TryCatch scope.
   2430         didThrow = true;
   2431         if (policy == ThrowExceptions)
   2432             setDOMException(DataCloneError, isolate);
   2433         return;
   2434     case Serializer::InvalidStateError:
   2435         didThrow = true;
   2436         if (policy == ThrowExceptions)
   2437             setDOMException(InvalidStateError, isolate);
   2438         return;
   2439     case Serializer::JSFailure:
   2440         // If there was a JS failure (but no exception), there's not
   2441         // much we can do except for unwinding the C++ stack by
   2442         // pretending there was a JS exception.
   2443         didThrow = true;
   2444         return;
   2445     case Serializer::Success:
   2446         m_data = writer.takeWireString();
   2447         ASSERT(m_data.impl()->hasOneRef());
   2448         if (arrayBuffers && arrayBuffers->size())
   2449             m_arrayBufferContentsArray = transferArrayBuffers(*arrayBuffers, didThrow, isolate);
   2450         return;
   2451     case Serializer::JSException:
   2452         // We should never get here because this case was handled above.
   2453         break;
   2454     }
   2455     ASSERT_NOT_REACHED();
   2456 }
   2457 
   2458 SerializedScriptValue::SerializedScriptValue(const String& wireData)
   2459     : m_externallyAllocatedMemory(0)
   2460 {
   2461     m_data = wireData.isolatedCopy();
   2462 }
   2463 
   2464 v8::Handle<v8::Value> SerializedScriptValue::deserialize(MessagePortArray* messagePorts)
   2465 {
   2466     return deserialize(v8::Isolate::GetCurrent(), messagePorts);
   2467 }
   2468 
   2469 v8::Handle<v8::Value> SerializedScriptValue::deserialize(v8::Isolate* isolate, MessagePortArray* messagePorts)
   2470 {
   2471     if (!m_data.impl())
   2472         return v8::Null(isolate);
   2473     COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
   2474     m_data.ensure16Bit();
   2475     // FIXME: SerializedScriptValue shouldn't use String for its underlying
   2476     // storage. Instead, it should use SharedBuffer or Vector<uint8_t>. The
   2477     // information stored in m_data isn't even encoded in UTF-16. Instead,
   2478     // unicode characters are encoded as UTF-8 with two code units per UChar.
   2479     Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->characters16()), 2 * m_data.length(), isolate, m_blobDataHandles);
   2480     Deserializer deserializer(reader, messagePorts, m_arrayBufferContentsArray.get());
   2481 
   2482     // deserialize() can run arbitrary script (e.g., setters), which could result in |this| being destroyed.
   2483     // Holding a RefPtr ensures we are alive (along with our internal data) throughout the operation.
   2484     RefPtr<SerializedScriptValue> protect(this);
   2485     return deserializer.deserialize();
   2486 }
   2487 
   2488 void SerializedScriptValue::registerMemoryAllocatedWithCurrentScriptContext()
   2489 {
   2490     if (m_externallyAllocatedMemory)
   2491         return;
   2492     m_externallyAllocatedMemory = static_cast<intptr_t>(m_data.length());
   2493     v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(m_externallyAllocatedMemory);
   2494 }
   2495 
   2496 SerializedScriptValue::~SerializedScriptValue()
   2497 {
   2498     // If the allocated memory was not registered before, then this class is likely
   2499     // used in a context other then Worker's onmessage environment and the presence of
   2500     // current v8 context is not guaranteed. Avoid calling v8 then.
   2501     if (m_externallyAllocatedMemory) {
   2502         ASSERT(v8::Isolate::GetCurrent());
   2503         v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-m_externallyAllocatedMemory);
   2504     }
   2505 }
   2506 
   2507 } // namespace WebCore
   2508