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