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/core/v8/SerializedScriptValue.h"
     33 
     34 #include "bindings/core/v8/ExceptionState.h"
     35 #include "bindings/core/v8/V8Binding.h"
     36 #include "bindings/core/v8/V8Blob.h"
     37 #include "bindings/core/v8/V8File.h"
     38 #include "bindings/core/v8/V8FileList.h"
     39 #include "bindings/core/v8/V8ImageData.h"
     40 #include "bindings/core/v8/V8MessagePort.h"
     41 #include "bindings/core/v8/WorkerScriptController.h"
     42 #include "bindings/core/v8/custom/V8ArrayBufferCustom.h"
     43 #include "bindings/core/v8/custom/V8ArrayBufferViewCustom.h"
     44 #include "bindings/core/v8/custom/V8DataViewCustom.h"
     45 #include "bindings/core/v8/custom/V8Float32ArrayCustom.h"
     46 #include "bindings/core/v8/custom/V8Float64ArrayCustom.h"
     47 #include "bindings/core/v8/custom/V8Int16ArrayCustom.h"
     48 #include "bindings/core/v8/custom/V8Int32ArrayCustom.h"
     49 #include "bindings/core/v8/custom/V8Int8ArrayCustom.h"
     50 #include "bindings/core/v8/custom/V8Uint16ArrayCustom.h"
     51 #include "bindings/core/v8/custom/V8Uint32ArrayCustom.h"
     52 #include "bindings/core/v8/custom/V8Uint8ArrayCustom.h"
     53 #include "bindings/core/v8/custom/V8Uint8ClampedArrayCustom.h"
     54 #include "bindings/modules/v8/V8CryptoKey.h"
     55 #include "bindings/modules/v8/V8DOMFileSystem.h"
     56 #include "core/dom/ExceptionCode.h"
     57 #include "core/dom/MessagePort.h"
     58 #include "core/fileapi/Blob.h"
     59 #include "core/fileapi/File.h"
     60 #include "core/fileapi/FileList.h"
     61 #include "core/html/ImageData.h"
     62 #include "core/html/canvas/DataView.h"
     63 #include "platform/SharedBuffer.h"
     64 #include "platform/heap/Handle.h"
     65 #include "public/platform/Platform.h"
     66 #include "public/platform/WebBlobInfo.h"
     67 #include "public/platform/WebCrypto.h"
     68 #include "public/platform/WebCryptoKey.h"
     69 #include "public/platform/WebCryptoKeyAlgorithm.h"
     70 #include "wtf/ArrayBuffer.h"
     71 #include "wtf/ArrayBufferContents.h"
     72 #include "wtf/ArrayBufferView.h"
     73 #include "wtf/Assertions.h"
     74 #include "wtf/ByteOrder.h"
     75 #include "wtf/Float32Array.h"
     76 #include "wtf/Float64Array.h"
     77 #include "wtf/Int16Array.h"
     78 #include "wtf/Int32Array.h"
     79 #include "wtf/Int8Array.h"
     80 #include "wtf/RefCounted.h"
     81 #include "wtf/Uint16Array.h"
     82 #include "wtf/Uint32Array.h"
     83 #include "wtf/Uint8Array.h"
     84 #include "wtf/Uint8ClampedArray.h"
     85 #include "wtf/Vector.h"
     86 #include "wtf/text/StringBuffer.h"
     87 #include "wtf/text/StringUTF8Adaptor.h"
     88 
     89 // FIXME: consider crashing in debug mode on deserialization errors
     90 // NOTE: be sure to change wireFormatVersion as necessary!
     91 
     92 namespace blink {
     93 
     94 namespace {
     95 
     96 // This code implements the HTML5 Structured Clone algorithm:
     97 // http://www.whatwg.org/specs/web-apps/current-work/multipage/urls.html#safe-passing-of-structured-data
     98 
     99 // V8ObjectMap is a map from V8 objects to arbitrary values of type T.
    100 // V8 objects (or handles to V8 objects) cannot be used as keys in ordinary wtf::HashMaps;
    101 // this class should be used instead. GCObject must be a subtype of v8::Object.
    102 // Suggested usage:
    103 //     V8ObjectMap<v8::Object, int> map;
    104 //     v8::Handle<v8::Object> obj = ...;
    105 //     map.set(obj, 42);
    106 template<typename GCObject, typename T>
    107 class V8ObjectMap {
    108 public:
    109     bool contains(const v8::Handle<GCObject>& handle)
    110     {
    111         return m_map.contains(*handle);
    112     }
    113 
    114     bool tryGet(const v8::Handle<GCObject>& handle, T* valueOut)
    115     {
    116         typename HandleToT::iterator result = m_map.find(*handle);
    117         if (result != m_map.end()) {
    118             *valueOut = result->value;
    119             return true;
    120         }
    121         return false;
    122     }
    123 
    124     void set(const v8::Handle<GCObject>& handle, const T& value)
    125     {
    126         m_map.set(*handle, value);
    127     }
    128 
    129 private:
    130     // This implementation uses GetIdentityHash(), which sets a hidden property on the object containing
    131     // a random integer (or returns the one that had been previously set). This ensures that the table
    132     // never needs to be rebuilt across garbage collections at the expense of doing additional allocation
    133     // and making more round trips into V8. Note that since GetIdentityHash() is defined only on
    134     // v8::Objects, this V8ObjectMap cannot be used to map v8::Strings to T (because the public V8 API
    135     // considers a v8::String to be a v8::Primitive).
    136 
    137     // If V8 exposes a way to get at the address of the object held by a handle, then we can produce
    138     // an alternate implementation that does not need to do any V8-side allocation; however, it will
    139     // need to rehash after every garbage collection because a key object may have been moved.
    140     template<typename G>
    141     struct V8HandlePtrHash {
    142         static v8::Handle<G> unsafeHandleFromRawValue(const G* value)
    143         {
    144             const v8::Handle<G>* handle = reinterpret_cast<const v8::Handle<G>*>(&value);
    145             return *handle;
    146         }
    147 
    148         static unsigned hash(const G* key)
    149         {
    150             return static_cast<unsigned>(unsafeHandleFromRawValue(key)->GetIdentityHash());
    151         }
    152         static bool equal(const G* a, const G* b)
    153         {
    154             return unsafeHandleFromRawValue(a) == unsafeHandleFromRawValue(b);
    155         }
    156         // For HashArg.
    157         static const bool safeToCompareToEmptyOrDeleted = false;
    158     };
    159 
    160     typedef WTF::HashMap<GCObject*, T, V8HandlePtrHash<GCObject> > HandleToT;
    161     HandleToT m_map;
    162 };
    163 
    164 typedef UChar BufferValueType;
    165 
    166 // Serialization format is a sequence of tags followed by zero or more data arguments.
    167 // Tags always take exactly one byte. A serialized stream first begins with
    168 // a complete VersionTag. If the stream does not begin with a VersionTag, we assume that
    169 // the stream is in format 0.
    170 
    171 // This format is private to the implementation of SerializedScriptValue. Do not rely on it
    172 // externally. It is safe to persist a SerializedScriptValue as a binary blob, but this
    173 // code should always be used to interpret it.
    174 
    175 // WebCoreStrings are read as (length:uint32_t, string:UTF8[length]).
    176 // RawStrings are read as (length:uint32_t, string:UTF8[length]).
    177 // RawUCharStrings are read as (length:uint32_t, string:UChar[length/sizeof(UChar)]).
    178 // RawFiles are read as (path:WebCoreString, url:WebCoreStrng, type:WebCoreString).
    179 // There is a reference table that maps object references (uint32_t) to v8::Values.
    180 // Tokens marked with (ref) are inserted into the reference table and given the next object reference ID after decoding.
    181 // All tags except InvalidTag, PaddingTag, ReferenceCountTag, VersionTag, GenerateFreshObjectTag
    182 //     and GenerateFreshArrayTag push their results to the deserialization stack.
    183 // There is also an 'open' stack that is used to resolve circular references. Objects or arrays may
    184 //     contain self-references. Before we begin to deserialize the contents of these values, they
    185 //     are first given object reference IDs (by GenerateFreshObjectTag/GenerateFreshArrayTag);
    186 //     these reference IDs are then used with ObjectReferenceTag to tie the recursive knot.
    187 enum SerializationTag {
    188     InvalidTag = '!', // Causes deserialization to fail.
    189     PaddingTag = '\0', // Is ignored (but consumed).
    190     UndefinedTag = '_', // -> <undefined>
    191     NullTag = '0', // -> <null>
    192     TrueTag = 'T', // -> <true>
    193     FalseTag = 'F', // -> <false>
    194     StringTag = 'S', // string:RawString -> string
    195     StringUCharTag = 'c', // string:RawUCharString -> string
    196     Int32Tag = 'I', // value:ZigZag-encoded int32 -> Integer
    197     Uint32Tag = 'U', // value:uint32_t -> Integer
    198     DateTag = 'D', // value:double -> Date (ref)
    199     MessagePortTag = 'M', // index:int -> MessagePort. Fills the result with transferred MessagePort.
    200     NumberTag = 'N', // value:double -> Number
    201     BlobTag = 'b', // uuid:WebCoreString, type:WebCoreString, size:uint64_t -> Blob (ref)
    202     BlobIndexTag = 'i', // index:int32_t -> Blob (ref)
    203     FileTag = 'f', // file:RawFile -> File (ref)
    204     FileIndexTag = 'e', // index:int32_t -> File (ref)
    205     DOMFileSystemTag = 'd', // type:int32_t, name:WebCoreString, uuid:WebCoreString -> FileSystem (ref)
    206     FileListTag = 'l', // length:uint32_t, files:RawFile[length] -> FileList (ref)
    207     FileListIndexTag = 'L', // length:uint32_t, files:int32_t[length] -> FileList (ref)
    208     ImageDataTag = '#', // width:uint32_t, height:uint32_t, pixelDataLength:uint32_t, data:byte[pixelDataLength] -> ImageData (ref)
    209     ObjectTag = '{', // numProperties:uint32_t -> pops the last object from the open stack;
    210                      //                           fills it with the last numProperties name,value pairs pushed onto the deserialization stack
    211     SparseArrayTag = '@', // numProperties:uint32_t, length:uint32_t -> pops the last object from the open stack;
    212                           //                                            fills it with the last numProperties name,value pairs pushed onto the deserialization stack
    213     DenseArrayTag = '$', // numProperties:uint32_t, length:uint32_t -> pops the last object from the open stack;
    214                          //                                            fills it with the last length elements and numProperties name,value pairs pushed onto deserialization stack
    215     RegExpTag = 'R', // pattern:RawString, flags:uint32_t -> RegExp (ref)
    216     ArrayBufferTag = 'B', // byteLength:uint32_t, data:byte[byteLength] -> ArrayBuffer (ref)
    217     ArrayBufferTransferTag = 't', // index:uint32_t -> ArrayBuffer. For ArrayBuffer transfer
    218     ArrayBufferViewTag = 'V', // subtag:byte, byteOffset:uint32_t, byteLength:uint32_t -> ArrayBufferView (ref). Consumes an ArrayBuffer from the top of the deserialization stack.
    219     CryptoKeyTag = 'K', // subtag:byte, props, usages:uint32_t, keyDataLength:uint32_t, keyData:byte[keyDataLength]
    220                         //   If subtag=AesKeyTag:
    221                         //       props = keyLengthBytes:uint32_t, algorithmId:uint32_t
    222                         //   If subtag=HmacKeyTag:
    223                         //       props = keyLengthBytes:uint32_t, hashId:uint32_t
    224                         //   If subtag=RsaHashedKeyTag:
    225                         //       props = algorithmId:uint32_t, type:uint32_t, modulusLengthBits:uint32_t, publicExponentLength:uint32_t, publicExponent:byte[publicExponentLength], hashId:uint32_t
    226     ObjectReferenceTag = '^', // ref:uint32_t -> reference table[ref]
    227     GenerateFreshObjectTag = 'o', // -> empty object allocated an object ID and pushed onto the open stack (ref)
    228     GenerateFreshSparseArrayTag = 'a', // length:uint32_t -> empty array[length] allocated an object ID and pushed onto the open stack (ref)
    229     GenerateFreshDenseArrayTag = 'A', // length:uint32_t -> empty array[length] allocated an object ID and pushed onto the open stack (ref)
    230     ReferenceCountTag = '?', // refTableSize:uint32_t -> If the reference table is not refTableSize big, fails.
    231     StringObjectTag = 's', //  string:RawString -> new String(string) (ref)
    232     NumberObjectTag = 'n', // value:double -> new Number(value) (ref)
    233     TrueObjectTag = 'y', // new Boolean(true) (ref)
    234     FalseObjectTag = 'x', // new Boolean(false) (ref)
    235     VersionTag = 0xFF // version:uint32_t -> Uses this as the file version.
    236 };
    237 
    238 enum ArrayBufferViewSubTag {
    239     ByteArrayTag = 'b',
    240     UnsignedByteArrayTag = 'B',
    241     UnsignedByteClampedArrayTag = 'C',
    242     ShortArrayTag = 'w',
    243     UnsignedShortArrayTag = 'W',
    244     IntArrayTag = 'd',
    245     UnsignedIntArrayTag = 'D',
    246     FloatArrayTag = 'f',
    247     DoubleArrayTag = 'F',
    248     DataViewTag = '?'
    249 };
    250 
    251 enum CryptoKeySubTag {
    252     AesKeyTag = 1,
    253     HmacKeyTag = 2,
    254     // ID 3 was used by RsaKeyTag, while still behind experimental flag.
    255     RsaHashedKeyTag = 4,
    256     // Maximum allowed value is 255
    257 };
    258 
    259 enum AssymetricCryptoKeyType {
    260     PublicKeyType = 1,
    261     PrivateKeyType = 2,
    262     // Maximum allowed value is 2^32-1
    263 };
    264 
    265 enum CryptoKeyAlgorithmTag {
    266     AesCbcTag = 1,
    267     HmacTag = 2,
    268     RsaSsaPkcs1v1_5Tag = 3,
    269     // ID 4 was used by RsaEs, while still behind experimental flag.
    270     Sha1Tag = 5,
    271     Sha256Tag = 6,
    272     Sha384Tag = 7,
    273     Sha512Tag = 8,
    274     AesGcmTag = 9,
    275     RsaOaepTag = 10,
    276     AesCtrTag = 11,
    277     AesKwTag = 12,
    278     // Maximum allowed value is 2^32-1
    279 };
    280 
    281 enum CryptoKeyUsage {
    282     // Extractability is not a "usage" in the WebCryptoKeyUsages sense, however
    283     // it fits conveniently into this bitfield.
    284     ExtractableUsage = 1 << 0,
    285 
    286     EncryptUsage = 1 << 1,
    287     DecryptUsage = 1 << 2,
    288     SignUsage = 1 << 3,
    289     VerifyUsage = 1 << 4,
    290     DeriveKeyUsage = 1 << 5,
    291     WrapKeyUsage = 1 << 6,
    292     UnwrapKeyUsage = 1 << 7,
    293     DeriveBitsUsage = 1 << 8,
    294     // Maximum allowed value is 1 << 31
    295 };
    296 
    297 static bool shouldCheckForCycles(int depth)
    298 {
    299     ASSERT(depth >= 0);
    300     // Since we are not required to spot the cycle as soon as it
    301     // happens we can check for cycles only when the current depth
    302     // is a power of two.
    303     return !(depth & (depth - 1));
    304 }
    305 
    306 static const int maxDepth = 20000;
    307 
    308 // VarInt encoding constants.
    309 static const int varIntShift = 7;
    310 static const int varIntMask = (1 << varIntShift) - 1;
    311 
    312 // ZigZag encoding helps VarInt encoding stay small for negative
    313 // numbers with small absolute values.
    314 class ZigZag {
    315 public:
    316     static uint32_t encode(uint32_t value)
    317     {
    318         if (value & (1U << 31))
    319             value = ((~value) << 1) + 1;
    320         else
    321             value <<= 1;
    322         return value;
    323     }
    324 
    325     static uint32_t decode(uint32_t value)
    326     {
    327         if (value & 1)
    328             value = ~(value >> 1);
    329         else
    330             value >>= 1;
    331         return value;
    332     }
    333 
    334 private:
    335     ZigZag();
    336 };
    337 
    338 // Writer is responsible for serializing primitive types and storing
    339 // information used to reconstruct composite types.
    340 class Writer {
    341     WTF_MAKE_NONCOPYABLE(Writer);
    342 public:
    343     Writer()
    344         : m_position(0)
    345     {
    346     }
    347 
    348     // Write functions for primitive types.
    349 
    350     void writeUndefined() { append(UndefinedTag); }
    351 
    352     void writeNull() { append(NullTag); }
    353 
    354     void writeTrue() { append(TrueTag); }
    355 
    356     void writeFalse() { append(FalseTag); }
    357 
    358     void writeBooleanObject(bool value)
    359     {
    360         append(value ? TrueObjectTag : FalseObjectTag);
    361     }
    362 
    363     void writeOneByteString(v8::Handle<v8::String>& string)
    364     {
    365         int stringLength = string->Length();
    366         int utf8Length = string->Utf8Length();
    367         ASSERT(stringLength >= 0 && utf8Length >= 0);
    368 
    369         append(StringTag);
    370         doWriteUint32(static_cast<uint32_t>(utf8Length));
    371         ensureSpace(utf8Length);
    372 
    373         // ASCII fast path.
    374         if (stringLength == utf8Length) {
    375             string->WriteOneByte(byteAt(m_position), 0, utf8Length, v8StringWriteOptions());
    376         } else {
    377             char* buffer = reinterpret_cast<char*>(byteAt(m_position));
    378             string->WriteUtf8(buffer, utf8Length, 0, v8StringWriteOptions());
    379         }
    380         m_position += utf8Length;
    381     }
    382 
    383     void writeUCharString(v8::Handle<v8::String>& string)
    384     {
    385         int length = string->Length();
    386         ASSERT(length >= 0);
    387 
    388         int size = length * sizeof(UChar);
    389         int bytes = bytesNeededToWireEncode(static_cast<uint32_t>(size));
    390         if ((m_position + 1 + bytes) & 1)
    391             append(PaddingTag);
    392 
    393         append(StringUCharTag);
    394         doWriteUint32(static_cast<uint32_t>(size));
    395         ensureSpace(size);
    396 
    397         ASSERT(!(m_position & 1));
    398         uint16_t* buffer = reinterpret_cast<uint16_t*>(byteAt(m_position));
    399         string->Write(buffer, 0, length, v8StringWriteOptions());
    400         m_position += size;
    401     }
    402 
    403     void writeStringObject(const char* data, int length)
    404     {
    405         ASSERT(length >= 0);
    406         append(StringObjectTag);
    407         doWriteString(data, length);
    408     }
    409 
    410     void writeWebCoreString(const String& string)
    411     {
    412         // Uses UTF8 encoding so we can read it back as either V8 or
    413         // WebCore string.
    414         append(StringTag);
    415         doWriteWebCoreString(string);
    416     }
    417 
    418     void writeVersion()
    419     {
    420         append(VersionTag);
    421         doWriteUint32(SerializedScriptValue::wireFormatVersion);
    422     }
    423 
    424     void writeInt32(int32_t value)
    425     {
    426         append(Int32Tag);
    427         doWriteUint32(ZigZag::encode(static_cast<uint32_t>(value)));
    428     }
    429 
    430     void writeUint32(uint32_t value)
    431     {
    432         append(Uint32Tag);
    433         doWriteUint32(value);
    434     }
    435 
    436     void writeDate(double numberValue)
    437     {
    438         append(DateTag);
    439         doWriteNumber(numberValue);
    440     }
    441 
    442     void writeNumber(double number)
    443     {
    444         append(NumberTag);
    445         doWriteNumber(number);
    446     }
    447 
    448     void writeNumberObject(double number)
    449     {
    450         append(NumberObjectTag);
    451         doWriteNumber(number);
    452     }
    453 
    454     void writeBlob(const String& uuid, const String& type, unsigned long long size)
    455     {
    456         append(BlobTag);
    457         doWriteWebCoreString(uuid);
    458         doWriteWebCoreString(type);
    459         doWriteUint64(size);
    460     }
    461 
    462     void writeBlobIndex(int blobIndex)
    463     {
    464         ASSERT(blobIndex >= 0);
    465         append(BlobIndexTag);
    466         doWriteUint32(blobIndex);
    467     }
    468 
    469     void writeDOMFileSystem(int type, const String& name, const String& url)
    470     {
    471         append(DOMFileSystemTag);
    472         doWriteUint32(type);
    473         doWriteWebCoreString(name);
    474         doWriteWebCoreString(url);
    475     }
    476 
    477     void writeFile(const File& file)
    478     {
    479         append(FileTag);
    480         doWriteFile(file);
    481     }
    482 
    483     void writeFileIndex(int blobIndex)
    484     {
    485         append(FileIndexTag);
    486         doWriteUint32(blobIndex);
    487     }
    488 
    489     void writeFileList(const FileList& fileList)
    490     {
    491         append(FileListTag);
    492         uint32_t length = fileList.length();
    493         doWriteUint32(length);
    494         for (unsigned i = 0; i < length; ++i)
    495             doWriteFile(*fileList.item(i));
    496     }
    497 
    498     void writeFileListIndex(const Vector<int>& blobIndices)
    499     {
    500         append(FileListIndexTag);
    501         uint32_t length = blobIndices.size();
    502         doWriteUint32(length);
    503         for (unsigned i = 0; i < length; ++i)
    504             doWriteUint32(blobIndices[i]);
    505     }
    506 
    507     bool writeCryptoKey(const blink::WebCryptoKey& key)
    508     {
    509         append(static_cast<uint8_t>(CryptoKeyTag));
    510 
    511         switch (key.algorithm().paramsType()) {
    512         case blink::WebCryptoKeyAlgorithmParamsTypeAes:
    513             doWriteAesKey(key);
    514             break;
    515         case blink::WebCryptoKeyAlgorithmParamsTypeHmac:
    516             doWriteHmacKey(key);
    517             break;
    518         case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed:
    519             doWriteRsaHashedKey(key);
    520             break;
    521         case blink::WebCryptoKeyAlgorithmParamsTypeNone:
    522             ASSERT_NOT_REACHED();
    523             return false;
    524         }
    525 
    526         doWriteKeyUsages(key.usages(), key.extractable());
    527 
    528         blink::WebVector<uint8_t> keyData;
    529         if (!blink::Platform::current()->crypto()->serializeKeyForClone(key, keyData))
    530             return false;
    531 
    532         doWriteUint32(keyData.size());
    533         append(keyData.data(), keyData.size());
    534         return true;
    535     }
    536 
    537     void writeArrayBuffer(const ArrayBuffer& arrayBuffer)
    538     {
    539         append(ArrayBufferTag);
    540         doWriteArrayBuffer(arrayBuffer);
    541     }
    542 
    543     void writeArrayBufferView(const ArrayBufferView& arrayBufferView)
    544     {
    545         append(ArrayBufferViewTag);
    546 #if ENABLE(ASSERT)
    547         const ArrayBuffer& arrayBuffer = *arrayBufferView.buffer();
    548         ASSERT(static_cast<const uint8_t*>(arrayBuffer.data()) + arrayBufferView.byteOffset() ==
    549                static_cast<const uint8_t*>(arrayBufferView.baseAddress()));
    550 #endif
    551         ArrayBufferView::ViewType type = arrayBufferView.type();
    552 
    553         if (type == ArrayBufferView::TypeInt8)
    554             append(ByteArrayTag);
    555         else if (type == ArrayBufferView::TypeUint8Clamped)
    556             append(UnsignedByteClampedArrayTag);
    557         else if (type == ArrayBufferView::TypeUint8)
    558             append(UnsignedByteArrayTag);
    559         else if (type == ArrayBufferView::TypeInt16)
    560             append(ShortArrayTag);
    561         else if (type == ArrayBufferView::TypeUint16)
    562             append(UnsignedShortArrayTag);
    563         else if (type == ArrayBufferView::TypeInt32)
    564             append(IntArrayTag);
    565         else if (type == ArrayBufferView::TypeUint32)
    566             append(UnsignedIntArrayTag);
    567         else if (type == ArrayBufferView::TypeFloat32)
    568             append(FloatArrayTag);
    569         else if (type == ArrayBufferView::TypeFloat64)
    570             append(DoubleArrayTag);
    571         else if (type == ArrayBufferView::TypeDataView)
    572             append(DataViewTag);
    573         else
    574             ASSERT_NOT_REACHED();
    575         doWriteUint32(arrayBufferView.byteOffset());
    576         doWriteUint32(arrayBufferView.byteLength());
    577     }
    578 
    579     void writeImageData(uint32_t width, uint32_t height, const uint8_t* pixelData, uint32_t pixelDataLength)
    580     {
    581         append(ImageDataTag);
    582         doWriteUint32(width);
    583         doWriteUint32(height);
    584         doWriteUint32(pixelDataLength);
    585         append(pixelData, pixelDataLength);
    586     }
    587 
    588     void writeRegExp(v8::Local<v8::String> pattern, v8::RegExp::Flags flags)
    589     {
    590         append(RegExpTag);
    591         v8::String::Utf8Value patternUtf8Value(pattern);
    592         doWriteString(*patternUtf8Value, patternUtf8Value.length());
    593         doWriteUint32(static_cast<uint32_t>(flags));
    594     }
    595 
    596     void writeTransferredMessagePort(uint32_t index)
    597     {
    598         append(MessagePortTag);
    599         doWriteUint32(index);
    600     }
    601 
    602     void writeTransferredArrayBuffer(uint32_t index)
    603     {
    604         append(ArrayBufferTransferTag);
    605         doWriteUint32(index);
    606     }
    607 
    608     void writeObjectReference(uint32_t reference)
    609     {
    610         append(ObjectReferenceTag);
    611         doWriteUint32(reference);
    612     }
    613 
    614     void writeObject(uint32_t numProperties)
    615     {
    616         append(ObjectTag);
    617         doWriteUint32(numProperties);
    618     }
    619 
    620     void writeSparseArray(uint32_t numProperties, uint32_t length)
    621     {
    622         append(SparseArrayTag);
    623         doWriteUint32(numProperties);
    624         doWriteUint32(length);
    625     }
    626 
    627     void writeDenseArray(uint32_t numProperties, uint32_t length)
    628     {
    629         append(DenseArrayTag);
    630         doWriteUint32(numProperties);
    631         doWriteUint32(length);
    632     }
    633 
    634     String takeWireString()
    635     {
    636         COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
    637         fillHole();
    638         String data = String(m_buffer.data(), m_buffer.size());
    639         data.impl()->truncateAssumingIsolated((m_position + 1) / sizeof(BufferValueType));
    640         return data;
    641     }
    642 
    643     void writeReferenceCount(uint32_t numberOfReferences)
    644     {
    645         append(ReferenceCountTag);
    646         doWriteUint32(numberOfReferences);
    647     }
    648 
    649     void writeGenerateFreshObject()
    650     {
    651         append(GenerateFreshObjectTag);
    652     }
    653 
    654     void writeGenerateFreshSparseArray(uint32_t length)
    655     {
    656         append(GenerateFreshSparseArrayTag);
    657         doWriteUint32(length);
    658     }
    659 
    660     void writeGenerateFreshDenseArray(uint32_t length)
    661     {
    662         append(GenerateFreshDenseArrayTag);
    663         doWriteUint32(length);
    664     }
    665 
    666 private:
    667     void doWriteFile(const File& file)
    668     {
    669         doWriteWebCoreString(file.hasBackingFile() ? file.path() : "");
    670         doWriteWebCoreString(file.name());
    671         doWriteWebCoreString(file.webkitRelativePath());
    672         doWriteWebCoreString(file.uuid());
    673         doWriteWebCoreString(file.type());
    674 
    675         // FIXME don't use 1 byte to encode a flag.
    676         if (file.hasValidSnapshotMetadata()) {
    677             doWriteUint32(static_cast<uint8_t>(1));
    678 
    679             long long size;
    680             double lastModified;
    681             file.captureSnapshot(size, lastModified);
    682             doWriteUint64(static_cast<uint64_t>(size));
    683             doWriteNumber(lastModified);
    684         } else {
    685             doWriteUint32(static_cast<uint8_t>(0));
    686         }
    687 
    688         doWriteUint32(static_cast<uint8_t>((file.userVisibility() == File::IsUserVisible) ? 1 : 0));
    689     }
    690 
    691     void doWriteArrayBuffer(const ArrayBuffer& arrayBuffer)
    692     {
    693         uint32_t byteLength = arrayBuffer.byteLength();
    694         doWriteUint32(byteLength);
    695         append(static_cast<const uint8_t*>(arrayBuffer.data()), byteLength);
    696     }
    697 
    698     void doWriteString(const char* data, int length)
    699     {
    700         doWriteUint32(static_cast<uint32_t>(length));
    701         append(reinterpret_cast<const uint8_t*>(data), length);
    702     }
    703 
    704     void doWriteWebCoreString(const String& string)
    705     {
    706         StringUTF8Adaptor stringUTF8(string);
    707         doWriteString(stringUTF8.data(), stringUTF8.length());
    708     }
    709 
    710     void doWriteHmacKey(const blink::WebCryptoKey& key)
    711     {
    712         ASSERT(key.algorithm().paramsType() == blink::WebCryptoKeyAlgorithmParamsTypeHmac);
    713 
    714         append(static_cast<uint8_t>(HmacKeyTag));
    715         ASSERT(!(key.algorithm().hmacParams()->lengthBits() % 8));
    716         doWriteUint32(key.algorithm().hmacParams()->lengthBits() / 8);
    717         doWriteAlgorithmId(key.algorithm().hmacParams()->hash().id());
    718     }
    719 
    720     void doWriteAesKey(const blink::WebCryptoKey& key)
    721     {
    722         ASSERT(key.algorithm().paramsType() == blink::WebCryptoKeyAlgorithmParamsTypeAes);
    723 
    724         append(static_cast<uint8_t>(AesKeyTag));
    725         doWriteAlgorithmId(key.algorithm().id());
    726         // Converting the key length from bits to bytes is lossless and makes
    727         // it fit in 1 byte.
    728         ASSERT(!(key.algorithm().aesParams()->lengthBits() % 8));
    729         doWriteUint32(key.algorithm().aesParams()->lengthBits() / 8);
    730     }
    731 
    732     void doWriteRsaHashedKey(const blink::WebCryptoKey& key)
    733     {
    734         ASSERT(key.algorithm().rsaHashedParams());
    735         append(static_cast<uint8_t>(RsaHashedKeyTag));
    736 
    737         doWriteAlgorithmId(key.algorithm().id());
    738 
    739         switch (key.type()) {
    740         case blink::WebCryptoKeyTypePublic:
    741             doWriteUint32(PublicKeyType);
    742             break;
    743         case blink::WebCryptoKeyTypePrivate:
    744             doWriteUint32(PrivateKeyType);
    745             break;
    746         case blink::WebCryptoKeyTypeSecret:
    747             ASSERT_NOT_REACHED();
    748         }
    749 
    750         const blink::WebCryptoRsaHashedKeyAlgorithmParams* params = key.algorithm().rsaHashedParams();
    751         doWriteUint32(params->modulusLengthBits());
    752         doWriteUint32(params->publicExponent().size());
    753         append(params->publicExponent().data(), params->publicExponent().size());
    754         doWriteAlgorithmId(key.algorithm().rsaHashedParams()->hash().id());
    755     }
    756 
    757     void doWriteAlgorithmId(blink::WebCryptoAlgorithmId id)
    758     {
    759         switch (id) {
    760         case blink::WebCryptoAlgorithmIdAesCbc:
    761             return doWriteUint32(AesCbcTag);
    762         case blink::WebCryptoAlgorithmIdHmac:
    763             return doWriteUint32(HmacTag);
    764         case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5:
    765             return doWriteUint32(RsaSsaPkcs1v1_5Tag);
    766         case blink::WebCryptoAlgorithmIdSha1:
    767             return doWriteUint32(Sha1Tag);
    768         case blink::WebCryptoAlgorithmIdSha256:
    769             return doWriteUint32(Sha256Tag);
    770         case blink::WebCryptoAlgorithmIdSha384:
    771             return doWriteUint32(Sha384Tag);
    772         case blink::WebCryptoAlgorithmIdSha512:
    773             return doWriteUint32(Sha512Tag);
    774         case blink::WebCryptoAlgorithmIdAesGcm:
    775             return doWriteUint32(AesGcmTag);
    776         case blink::WebCryptoAlgorithmIdRsaOaep:
    777             return doWriteUint32(RsaOaepTag);
    778         case blink::WebCryptoAlgorithmIdAesCtr:
    779             return doWriteUint32(AesCtrTag);
    780         case blink::WebCryptoAlgorithmIdAesKw:
    781             return doWriteUint32(AesKwTag);
    782         }
    783         ASSERT_NOT_REACHED();
    784     }
    785 
    786     void doWriteKeyUsages(const blink::WebCryptoKeyUsageMask usages, bool extractable)
    787     {
    788         // Reminder to update this when adding new key usages.
    789         COMPILE_ASSERT(blink::EndOfWebCryptoKeyUsage == (1 << 7) + 1, UpdateMe);
    790 
    791         uint32_t value = 0;
    792 
    793         if (extractable)
    794             value |= ExtractableUsage;
    795 
    796         if (usages & blink::WebCryptoKeyUsageEncrypt)
    797             value |= EncryptUsage;
    798         if (usages & blink::WebCryptoKeyUsageDecrypt)
    799             value |= DecryptUsage;
    800         if (usages & blink::WebCryptoKeyUsageSign)
    801             value |= SignUsage;
    802         if (usages & blink::WebCryptoKeyUsageVerify)
    803             value |= VerifyUsage;
    804         if (usages & blink::WebCryptoKeyUsageDeriveKey)
    805             value |= DeriveKeyUsage;
    806         if (usages & blink::WebCryptoKeyUsageWrapKey)
    807             value |= WrapKeyUsage;
    808         if (usages & blink::WebCryptoKeyUsageUnwrapKey)
    809             value |= UnwrapKeyUsage;
    810         if (usages & blink::WebCryptoKeyUsageDeriveBits)
    811             value |= DeriveBitsUsage;
    812 
    813         doWriteUint32(value);
    814     }
    815 
    816     int bytesNeededToWireEncode(uint32_t value)
    817     {
    818         int bytes = 1;
    819         while (true) {
    820             value >>= varIntShift;
    821             if (!value)
    822                 break;
    823             ++bytes;
    824         }
    825 
    826         return bytes;
    827     }
    828 
    829     template<class T>
    830     void doWriteUintHelper(T value)
    831     {
    832         while (true) {
    833             uint8_t b = (value & varIntMask);
    834             value >>= varIntShift;
    835             if (!value) {
    836                 append(b);
    837                 break;
    838             }
    839             append(b | (1 << varIntShift));
    840         }
    841     }
    842 
    843     void doWriteUint32(uint32_t value)
    844     {
    845         doWriteUintHelper(value);
    846     }
    847 
    848     void doWriteUint64(uint64_t value)
    849     {
    850         doWriteUintHelper(value);
    851     }
    852 
    853     void doWriteNumber(double number)
    854     {
    855         append(reinterpret_cast<uint8_t*>(&number), sizeof(number));
    856     }
    857 
    858     void append(SerializationTag tag)
    859     {
    860         append(static_cast<uint8_t>(tag));
    861     }
    862 
    863     void append(uint8_t b)
    864     {
    865         ensureSpace(1);
    866         *byteAt(m_position++) = b;
    867     }
    868 
    869     void append(const uint8_t* data, int length)
    870     {
    871         ensureSpace(length);
    872         memcpy(byteAt(m_position), data, length);
    873         m_position += length;
    874     }
    875 
    876     void ensureSpace(unsigned extra)
    877     {
    878         COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
    879         m_buffer.resize((m_position + extra + 1) / sizeof(BufferValueType)); // "+ 1" to round up.
    880     }
    881 
    882     void fillHole()
    883     {
    884         COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
    885         // If the writer is at odd position in the buffer, then one of
    886         // the bytes in the last UChar is not initialized.
    887         if (m_position % 2)
    888             *byteAt(m_position) = static_cast<uint8_t>(PaddingTag);
    889     }
    890 
    891     uint8_t* byteAt(int position)
    892     {
    893         return reinterpret_cast<uint8_t*>(m_buffer.data()) + position;
    894     }
    895 
    896     int v8StringWriteOptions()
    897     {
    898         return v8::String::NO_NULL_TERMINATION;
    899     }
    900 
    901     Vector<BufferValueType> m_buffer;
    902     unsigned m_position;
    903 };
    904 
    905 static v8::Handle<v8::Object> toV8Object(MessagePort* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
    906 {
    907     if (!impl)
    908         return v8::Handle<v8::Object>();
    909     v8::Handle<v8::Value> wrapper = toV8(impl, creationContext, isolate);
    910     ASSERT(wrapper->IsObject());
    911     return wrapper.As<v8::Object>();
    912 }
    913 
    914 static v8::Handle<v8::ArrayBuffer> toV8Object(ArrayBuffer* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
    915 {
    916     if (!impl)
    917         return v8::Handle<v8::ArrayBuffer>();
    918     v8::Handle<v8::Value> wrapper = toV8(impl, creationContext, isolate);
    919     ASSERT(wrapper->IsArrayBuffer());
    920     return wrapper.As<v8::ArrayBuffer>();
    921 }
    922 
    923 class Serializer {
    924     class StateBase;
    925 public:
    926     enum Status {
    927         Success,
    928         InputError,
    929         DataCloneError,
    930         JSException
    931     };
    932 
    933     Serializer(Writer& writer, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, WebBlobInfoArray* blobInfo, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, ScriptState* scriptState)
    934         : m_scriptState(scriptState)
    935         , m_writer(writer)
    936         , m_tryCatch(tryCatch)
    937         , m_depth(0)
    938         , m_status(Success)
    939         , m_nextObjectReference(0)
    940         , m_blobInfo(blobInfo)
    941         , m_blobDataHandles(blobDataHandles)
    942     {
    943         ASSERT(!tryCatch.HasCaught());
    944         v8::Handle<v8::Object> creationContext = m_scriptState->context()->Global();
    945         if (messagePorts) {
    946             for (size_t i = 0; i < messagePorts->size(); i++)
    947                 m_transferredMessagePorts.set(toV8Object(messagePorts->at(i).get(), creationContext, isolate()), i);
    948         }
    949         if (arrayBuffers) {
    950             for (size_t i = 0; i < arrayBuffers->size(); i++)  {
    951                 v8::Handle<v8::Object> v8ArrayBuffer = toV8Object(arrayBuffers->at(i).get(), creationContext, isolate());
    952                 // Coalesce multiple occurences of the same buffer to the first index.
    953                 if (!m_transferredArrayBuffers.contains(v8ArrayBuffer))
    954                     m_transferredArrayBuffers.set(v8ArrayBuffer, i);
    955             }
    956         }
    957     }
    958 
    959     v8::Isolate* isolate() { return m_scriptState->isolate(); }
    960 
    961     Status serialize(v8::Handle<v8::Value> value)
    962     {
    963         v8::HandleScope scope(isolate());
    964         m_writer.writeVersion();
    965         StateBase* state = doSerialize(value, 0);
    966         while (state)
    967             state = state->advance(*this);
    968         return m_status;
    969     }
    970 
    971     String errorMessage() { return m_errorMessage; }
    972 
    973     // Functions used by serialization states.
    974     StateBase* doSerialize(v8::Handle<v8::Value>, StateBase* next);
    975 
    976     StateBase* doSerializeArrayBuffer(v8::Handle<v8::Value> arrayBuffer, StateBase* next)
    977     {
    978         return doSerialize(arrayBuffer, next);
    979     }
    980 
    981     StateBase* checkException(StateBase* state)
    982     {
    983         return m_tryCatch.HasCaught() ? handleError(JSException, "", state) : 0;
    984     }
    985 
    986     StateBase* writeObject(uint32_t numProperties, StateBase* state)
    987     {
    988         m_writer.writeObject(numProperties);
    989         return pop(state);
    990     }
    991 
    992     StateBase* writeSparseArray(uint32_t numProperties, uint32_t length, StateBase* state)
    993     {
    994         m_writer.writeSparseArray(numProperties, length);
    995         return pop(state);
    996     }
    997 
    998     StateBase* writeDenseArray(uint32_t numProperties, uint32_t length, StateBase* state)
    999     {
   1000         m_writer.writeDenseArray(numProperties, length);
   1001         return pop(state);
   1002     }
   1003 
   1004 
   1005 private:
   1006     class StateBase {
   1007         WTF_MAKE_NONCOPYABLE(StateBase);
   1008     public:
   1009         virtual ~StateBase() { }
   1010 
   1011         // Link to the next state to form a stack.
   1012         StateBase* nextState() { return m_next; }
   1013 
   1014         // Composite object we're processing in this state.
   1015         v8::Handle<v8::Value> composite() { return m_composite; }
   1016 
   1017         // Serializes (a part of) the current composite and returns
   1018         // the next state to process or null when this is the final
   1019         // state.
   1020         virtual StateBase* advance(Serializer&) = 0;
   1021 
   1022     protected:
   1023         StateBase(v8::Handle<v8::Value> composite, StateBase* next)
   1024             : m_composite(composite)
   1025             , m_next(next)
   1026         {
   1027         }
   1028 
   1029     private:
   1030         v8::Handle<v8::Value> m_composite;
   1031         StateBase* m_next;
   1032     };
   1033 
   1034     // Dummy state that is used to signal serialization errors.
   1035     class ErrorState FINAL : public StateBase {
   1036     public:
   1037         ErrorState()
   1038             : StateBase(v8Undefined(), 0)
   1039         {
   1040         }
   1041 
   1042         virtual StateBase* advance(Serializer&) OVERRIDE
   1043         {
   1044             delete this;
   1045             return 0;
   1046         }
   1047     };
   1048 
   1049     template <typename T>
   1050     class State : public StateBase {
   1051     public:
   1052         v8::Handle<T> composite() { return v8::Handle<T>::Cast(StateBase::composite()); }
   1053 
   1054     protected:
   1055         State(v8::Handle<T> composite, StateBase* next)
   1056             : StateBase(composite, next)
   1057         {
   1058         }
   1059     };
   1060 
   1061     class AbstractObjectState : public State<v8::Object> {
   1062     public:
   1063         AbstractObjectState(v8::Handle<v8::Object> object, StateBase* next)
   1064             : State<v8::Object>(object, next)
   1065             , m_index(0)
   1066             , m_numSerializedProperties(0)
   1067             , m_nameDone(false)
   1068         {
   1069         }
   1070 
   1071     protected:
   1072         virtual StateBase* objectDone(unsigned numProperties, Serializer&) = 0;
   1073 
   1074         StateBase* serializeProperties(bool ignoreIndexed, Serializer& serializer)
   1075         {
   1076             while (m_index < m_propertyNames->Length()) {
   1077                 if (!m_nameDone) {
   1078                     v8::Local<v8::Value> propertyName = m_propertyNames->Get(m_index);
   1079                     if (StateBase* newState = serializer.checkException(this))
   1080                         return newState;
   1081                     if (propertyName.IsEmpty())
   1082                         return serializer.handleError(InputError, "Empty property names cannot be cloned.", this);
   1083                     bool hasStringProperty = propertyName->IsString() && composite()->HasRealNamedProperty(propertyName.As<v8::String>());
   1084                     if (StateBase* newState = serializer.checkException(this))
   1085                         return newState;
   1086                     bool hasIndexedProperty = !hasStringProperty && propertyName->IsUint32() && composite()->HasRealIndexedProperty(propertyName->Uint32Value());
   1087                     if (StateBase* newState = serializer.checkException(this))
   1088                         return newState;
   1089                     if (hasStringProperty || (hasIndexedProperty && !ignoreIndexed)) {
   1090                         m_propertyName = propertyName;
   1091                     } else {
   1092                         ++m_index;
   1093                         continue;
   1094                     }
   1095                 }
   1096                 ASSERT(!m_propertyName.IsEmpty());
   1097                 if (!m_nameDone) {
   1098                     m_nameDone = true;
   1099                     if (StateBase* newState = serializer.doSerialize(m_propertyName, this))
   1100                         return newState;
   1101                 }
   1102                 v8::Local<v8::Value> value = composite()->Get(m_propertyName);
   1103                 if (StateBase* newState = serializer.checkException(this))
   1104                     return newState;
   1105                 m_nameDone = false;
   1106                 m_propertyName.Clear();
   1107                 ++m_index;
   1108                 ++m_numSerializedProperties;
   1109                 // If we return early here, it's either because we have pushed a new state onto the
   1110                 // serialization state stack or because we have encountered an error (and in both cases
   1111                 // we are unwinding the native stack).
   1112                 if (StateBase* newState = serializer.doSerialize(value, this))
   1113                     return newState;
   1114             }
   1115             return objectDone(m_numSerializedProperties, serializer);
   1116         }
   1117 
   1118         v8::Local<v8::Array> m_propertyNames;
   1119 
   1120     private:
   1121         v8::Local<v8::Value> m_propertyName;
   1122         unsigned m_index;
   1123         unsigned m_numSerializedProperties;
   1124         bool m_nameDone;
   1125     };
   1126 
   1127     class ObjectState FINAL : public AbstractObjectState {
   1128     public:
   1129         ObjectState(v8::Handle<v8::Object> object, StateBase* next)
   1130             : AbstractObjectState(object, next)
   1131         {
   1132         }
   1133 
   1134         virtual StateBase* advance(Serializer& serializer) OVERRIDE
   1135         {
   1136             if (m_propertyNames.IsEmpty()) {
   1137                 m_propertyNames = composite()->GetPropertyNames();
   1138                 if (StateBase* newState = serializer.checkException(this))
   1139                     return newState;
   1140                 if (m_propertyNames.IsEmpty())
   1141                     return serializer.handleError(InputError, "Empty property names cannot be cloned.", nextState());
   1142             }
   1143             return serializeProperties(false, serializer);
   1144         }
   1145 
   1146     protected:
   1147         virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) OVERRIDE
   1148         {
   1149             return serializer.writeObject(numProperties, this);
   1150         }
   1151     };
   1152 
   1153     class DenseArrayState FINAL : public AbstractObjectState {
   1154     public:
   1155         DenseArrayState(v8::Handle<v8::Array> array, v8::Handle<v8::Array> propertyNames, StateBase* next, v8::Isolate* isolate)
   1156             : AbstractObjectState(array, next)
   1157             , m_arrayIndex(0)
   1158             , m_arrayLength(array->Length())
   1159         {
   1160             m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames);
   1161         }
   1162 
   1163         virtual StateBase* advance(Serializer& serializer) OVERRIDE
   1164         {
   1165             while (m_arrayIndex < m_arrayLength) {
   1166                 v8::Handle<v8::Value> value = composite().As<v8::Array>()->Get(m_arrayIndex);
   1167                 m_arrayIndex++;
   1168                 if (StateBase* newState = serializer.checkException(this))
   1169                     return newState;
   1170                 if (StateBase* newState = serializer.doSerialize(value, this))
   1171                     return newState;
   1172             }
   1173             return serializeProperties(true, serializer);
   1174         }
   1175 
   1176     protected:
   1177         virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) OVERRIDE
   1178         {
   1179             return serializer.writeDenseArray(numProperties, m_arrayLength, this);
   1180         }
   1181 
   1182     private:
   1183         uint32_t m_arrayIndex;
   1184         uint32_t m_arrayLength;
   1185     };
   1186 
   1187     class SparseArrayState FINAL : public AbstractObjectState {
   1188     public:
   1189         SparseArrayState(v8::Handle<v8::Array> array, v8::Handle<v8::Array> propertyNames, StateBase* next, v8::Isolate* isolate)
   1190             : AbstractObjectState(array, next)
   1191         {
   1192             m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames);
   1193         }
   1194 
   1195         virtual StateBase* advance(Serializer& serializer) OVERRIDE
   1196         {
   1197             return serializeProperties(false, serializer);
   1198         }
   1199 
   1200     protected:
   1201         virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) OVERRIDE
   1202         {
   1203             return serializer.writeSparseArray(numProperties, composite().As<v8::Array>()->Length(), this);
   1204         }
   1205     };
   1206 
   1207     StateBase* push(StateBase* state)
   1208     {
   1209         ASSERT(state);
   1210         ++m_depth;
   1211         return checkComposite(state) ? state : handleError(InputError, "Value being cloned is either cyclic or too deeply nested.", state);
   1212     }
   1213 
   1214     StateBase* pop(StateBase* state)
   1215     {
   1216         ASSERT(state);
   1217         --m_depth;
   1218         StateBase* next = state->nextState();
   1219         delete state;
   1220         return next;
   1221     }
   1222 
   1223     StateBase* handleError(Status errorStatus, const String& message, StateBase* state)
   1224     {
   1225         ASSERT(errorStatus != Success);
   1226         m_status = errorStatus;
   1227         m_errorMessage = message;
   1228         while (state) {
   1229             StateBase* tmp = state->nextState();
   1230             delete state;
   1231             state = tmp;
   1232         }
   1233         return new ErrorState;
   1234     }
   1235 
   1236     bool checkComposite(StateBase* top)
   1237     {
   1238         ASSERT(top);
   1239         if (m_depth > maxDepth)
   1240             return false;
   1241         if (!shouldCheckForCycles(m_depth))
   1242             return true;
   1243         v8::Handle<v8::Value> composite = top->composite();
   1244         for (StateBase* state = top->nextState(); state; state = state->nextState()) {
   1245             if (state->composite() == composite)
   1246                 return false;
   1247         }
   1248         return true;
   1249     }
   1250 
   1251     void writeString(v8::Handle<v8::Value> value)
   1252     {
   1253         v8::Handle<v8::String> string = value.As<v8::String>();
   1254         if (!string->Length() || string->IsOneByte())
   1255             m_writer.writeOneByteString(string);
   1256         else
   1257             m_writer.writeUCharString(string);
   1258     }
   1259 
   1260     void writeStringObject(v8::Handle<v8::Value> value)
   1261     {
   1262         v8::Handle<v8::StringObject> stringObject = value.As<v8::StringObject>();
   1263         v8::String::Utf8Value stringValue(stringObject->ValueOf());
   1264         m_writer.writeStringObject(*stringValue, stringValue.length());
   1265     }
   1266 
   1267     void writeNumberObject(v8::Handle<v8::Value> value)
   1268     {
   1269         v8::Handle<v8::NumberObject> numberObject = value.As<v8::NumberObject>();
   1270         m_writer.writeNumberObject(numberObject->ValueOf());
   1271     }
   1272 
   1273     void writeBooleanObject(v8::Handle<v8::Value> value)
   1274     {
   1275         v8::Handle<v8::BooleanObject> booleanObject = value.As<v8::BooleanObject>();
   1276         m_writer.writeBooleanObject(booleanObject->ValueOf());
   1277     }
   1278 
   1279     StateBase* writeBlob(v8::Handle<v8::Value> value, StateBase* next)
   1280     {
   1281         Blob* blob = V8Blob::toImpl(value.As<v8::Object>());
   1282         if (!blob)
   1283             return 0;
   1284         if (blob->hasBeenClosed())
   1285             return handleError(DataCloneError, "A Blob object has been closed, and could therefore not be cloned.", next);
   1286         int blobIndex = -1;
   1287         m_blobDataHandles.set(blob->uuid(), blob->blobDataHandle());
   1288         if (appendBlobInfo(blob->uuid(), blob->type(), blob->size(), &blobIndex))
   1289             m_writer.writeBlobIndex(blobIndex);
   1290         else
   1291             m_writer.writeBlob(blob->uuid(), blob->type(), blob->size());
   1292         return 0;
   1293     }
   1294 
   1295     StateBase* writeDOMFileSystem(v8::Handle<v8::Value> value, StateBase* next)
   1296     {
   1297         DOMFileSystem* fs = V8DOMFileSystem::toImpl(value.As<v8::Object>());
   1298         if (!fs)
   1299             return 0;
   1300         if (!fs->clonable())
   1301             return handleError(DataCloneError, "A FileSystem object could not be cloned.", next);
   1302         m_writer.writeDOMFileSystem(fs->type(), fs->name(), fs->rootURL().string());
   1303         return 0;
   1304     }
   1305 
   1306     StateBase* writeFile(v8::Handle<v8::Value> value, StateBase* next)
   1307     {
   1308         File* file = V8File::toImpl(value.As<v8::Object>());
   1309         if (!file)
   1310             return 0;
   1311         if (file->hasBeenClosed())
   1312             return handleError(DataCloneError, "A File object has been closed, and could therefore not be cloned.", next);
   1313         int blobIndex = -1;
   1314         m_blobDataHandles.set(file->uuid(), file->blobDataHandle());
   1315         if (appendFileInfo(file, &blobIndex)) {
   1316             ASSERT(blobIndex >= 0);
   1317             m_writer.writeFileIndex(blobIndex);
   1318         } else {
   1319             m_writer.writeFile(*file);
   1320         }
   1321         return 0;
   1322     }
   1323 
   1324     StateBase* writeFileList(v8::Handle<v8::Value> value, StateBase* next)
   1325     {
   1326         FileList* fileList = V8FileList::toImpl(value.As<v8::Object>());
   1327         if (!fileList)
   1328             return 0;
   1329         unsigned length = fileList->length();
   1330         Vector<int> blobIndices;
   1331         for (unsigned i = 0; i < length; ++i) {
   1332             int blobIndex = -1;
   1333             const File* file = fileList->item(i);
   1334             if (file->hasBeenClosed())
   1335                 return handleError(DataCloneError, "A File object has been closed, and could therefore not be cloned.", next);
   1336             m_blobDataHandles.set(file->uuid(), file->blobDataHandle());
   1337             if (appendFileInfo(file, &blobIndex)) {
   1338                 ASSERT(!i || blobIndex > 0);
   1339                 ASSERT(blobIndex >= 0);
   1340                 blobIndices.append(blobIndex);
   1341             }
   1342         }
   1343         if (!blobIndices.isEmpty())
   1344             m_writer.writeFileListIndex(blobIndices);
   1345         else
   1346             m_writer.writeFileList(*fileList);
   1347         return 0;
   1348     }
   1349 
   1350     bool writeCryptoKey(v8::Handle<v8::Value> value)
   1351     {
   1352         CryptoKey* key = V8CryptoKey::toImpl(value.As<v8::Object>());
   1353         if (!key)
   1354             return false;
   1355         return m_writer.writeCryptoKey(key->key());
   1356     }
   1357 
   1358     void writeImageData(v8::Handle<v8::Value> value)
   1359     {
   1360         ImageData* imageData = V8ImageData::toImpl(value.As<v8::Object>());
   1361         if (!imageData)
   1362             return;
   1363         Uint8ClampedArray* pixelArray = imageData->data();
   1364         m_writer.writeImageData(imageData->width(), imageData->height(), pixelArray->data(), pixelArray->length());
   1365     }
   1366 
   1367     void writeRegExp(v8::Handle<v8::Value> value)
   1368     {
   1369         v8::Handle<v8::RegExp> regExp = value.As<v8::RegExp>();
   1370         m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags());
   1371     }
   1372 
   1373     StateBase* writeAndGreyArrayBufferView(v8::Handle<v8::Object> object, StateBase* next)
   1374     {
   1375         ASSERT(!object.IsEmpty());
   1376         ArrayBufferView* arrayBufferView = V8ArrayBufferView::toImpl(object);
   1377         if (!arrayBufferView)
   1378             return 0;
   1379         if (!arrayBufferView->buffer())
   1380             return handleError(DataCloneError, "An ArrayBuffer could not be cloned.", next);
   1381         v8::Handle<v8::Value> underlyingBuffer = toV8(arrayBufferView->buffer(), m_scriptState->context()->Global(), isolate());
   1382         if (underlyingBuffer.IsEmpty())
   1383             return handleError(DataCloneError, "An ArrayBuffer could not be cloned.", next);
   1384         StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next);
   1385         if (stateOut)
   1386             return stateOut;
   1387         m_writer.writeArrayBufferView(*arrayBufferView);
   1388         // This should be safe: we serialize something that we know to be a wrapper (see
   1389         // the toV8 call above), so the call to doSerializeArrayBuffer should neither
   1390         // cause the system stack to overflow nor should it have potential to reach
   1391         // this ArrayBufferView again.
   1392         //
   1393         // We do need to grey the underlying buffer before we grey its view, however;
   1394         // ArrayBuffers may be shared, so they need to be given reference IDs, and an
   1395         // ArrayBufferView cannot be constructed without a corresponding ArrayBuffer
   1396         // (or without an additional tag that would allow us to do two-stage construction
   1397         // like we do for Objects and Arrays).
   1398         greyObject(object);
   1399         return 0;
   1400     }
   1401 
   1402     StateBase* writeArrayBuffer(v8::Handle<v8::Value> value, StateBase* next)
   1403     {
   1404         ArrayBuffer* arrayBuffer = V8ArrayBuffer::toImpl(value.As<v8::Object>());
   1405         if (!arrayBuffer)
   1406             return 0;
   1407         if (arrayBuffer->isNeutered())
   1408             return handleError(DataCloneError, "An ArrayBuffer is neutered and could not be cloned.", next);
   1409         ASSERT(!m_transferredArrayBuffers.contains(value.As<v8::Object>()));
   1410         m_writer.writeArrayBuffer(*arrayBuffer);
   1411         return 0;
   1412     }
   1413 
   1414     StateBase* writeTransferredArrayBuffer(v8::Handle<v8::Value> value, uint32_t index, StateBase* next)
   1415     {
   1416         ArrayBuffer* arrayBuffer = V8ArrayBuffer::toImpl(value.As<v8::Object>());
   1417         if (!arrayBuffer)
   1418             return 0;
   1419         if (arrayBuffer->isNeutered())
   1420             return handleError(DataCloneError, "An ArrayBuffer is neutered and could not be cloned.", next);
   1421         m_writer.writeTransferredArrayBuffer(index);
   1422         return 0;
   1423     }
   1424 
   1425     static bool shouldSerializeDensely(uint32_t length, uint32_t propertyCount)
   1426     {
   1427         // Let K be the cost of serializing all property values that are there
   1428         // Cost of serializing sparsely: 5*propertyCount + K (5 bytes per uint32_t key)
   1429         // Cost of serializing densely: K + 1*(length - propertyCount) (1 byte for all properties that are not there)
   1430         // so densely is better than sparsly whenever 6*propertyCount > length
   1431         return 6 * propertyCount >= length;
   1432     }
   1433 
   1434     StateBase* startArrayState(v8::Handle<v8::Array> array, StateBase* next)
   1435     {
   1436         v8::Handle<v8::Array> propertyNames = array->GetPropertyNames();
   1437         if (StateBase* newState = checkException(next))
   1438             return newState;
   1439         uint32_t length = array->Length();
   1440 
   1441         if (shouldSerializeDensely(length, propertyNames->Length())) {
   1442             m_writer.writeGenerateFreshDenseArray(length);
   1443             return push(new DenseArrayState(array, propertyNames, next, isolate()));
   1444         }
   1445 
   1446         m_writer.writeGenerateFreshSparseArray(length);
   1447         return push(new SparseArrayState(array, propertyNames, next, isolate()));
   1448     }
   1449 
   1450     StateBase* startObjectState(v8::Handle<v8::Object> object, StateBase* next)
   1451     {
   1452         m_writer.writeGenerateFreshObject();
   1453         // FIXME: check not a wrapper
   1454         return push(new ObjectState(object, next));
   1455     }
   1456 
   1457     // Marks object as having been visited by the serializer and assigns it a unique object reference ID.
   1458     // An object may only be greyed once.
   1459     void greyObject(const v8::Handle<v8::Object>& object)
   1460     {
   1461         ASSERT(!m_objectPool.contains(object));
   1462         uint32_t objectReference = m_nextObjectReference++;
   1463         m_objectPool.set(object, objectReference);
   1464     }
   1465 
   1466     bool appendBlobInfo(const String& uuid, const String& type, unsigned long long size, int* index)
   1467     {
   1468         if (!m_blobInfo)
   1469             return false;
   1470         *index = m_blobInfo->size();
   1471         m_blobInfo->append(WebBlobInfo(uuid, type, size));
   1472         return true;
   1473     }
   1474 
   1475     bool appendFileInfo(const File* file, int* index)
   1476     {
   1477         if (!m_blobInfo)
   1478             return false;
   1479 
   1480         long long size = -1;
   1481         double lastModified = invalidFileTime();
   1482         file->captureSnapshot(size, lastModified);
   1483         *index = m_blobInfo->size();
   1484         m_blobInfo->append(WebBlobInfo(file->uuid(), file->path(), file->name(), file->type(), lastModified, size));
   1485         return true;
   1486     }
   1487 
   1488     RefPtr<ScriptState> m_scriptState;
   1489     Writer& m_writer;
   1490     v8::TryCatch& m_tryCatch;
   1491     int m_depth;
   1492     Status m_status;
   1493     String m_errorMessage;
   1494     typedef V8ObjectMap<v8::Object, uint32_t> ObjectPool;
   1495     ObjectPool m_objectPool;
   1496     ObjectPool m_transferredMessagePorts;
   1497     ObjectPool m_transferredArrayBuffers;
   1498     uint32_t m_nextObjectReference;
   1499     WebBlobInfoArray* m_blobInfo;
   1500     BlobDataHandleMap& m_blobDataHandles;
   1501 };
   1502 
   1503 // Returns true if the provided object is to be considered a 'host object', as used in the
   1504 // HTML5 structured clone algorithm.
   1505 static bool isHostObject(v8::Handle<v8::Object> object)
   1506 {
   1507     // If the object has any internal fields, then we won't be able to serialize or deserialize
   1508     // them; conveniently, this is also a quick way to detect DOM wrapper objects, because
   1509     // the mechanism for these relies on data stored in these fields. We should
   1510     // catch external array data as a special case.
   1511     return object->InternalFieldCount() || object->HasIndexedPropertiesInExternalArrayData();
   1512 }
   1513 
   1514 Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, StateBase* next)
   1515 {
   1516     m_writer.writeReferenceCount(m_nextObjectReference);
   1517     uint32_t objectReference;
   1518     uint32_t arrayBufferIndex;
   1519     if ((value->IsObject() || value->IsDate() || value->IsRegExp())
   1520         && m_objectPool.tryGet(value.As<v8::Object>(), &objectReference)) {
   1521         // Note that IsObject() also detects wrappers (eg, it will catch the things
   1522         // that we grey and write below).
   1523         ASSERT(!value->IsString());
   1524         m_writer.writeObjectReference(objectReference);
   1525     } else if (value.IsEmpty()) {
   1526         return handleError(InputError, "The empty property name cannot be cloned.", next);
   1527     } else if (value->IsUndefined()) {
   1528         m_writer.writeUndefined();
   1529     } else if (value->IsNull()) {
   1530         m_writer.writeNull();
   1531     } else if (value->IsTrue()) {
   1532         m_writer.writeTrue();
   1533     } else if (value->IsFalse()) {
   1534         m_writer.writeFalse();
   1535     } else if (value->IsInt32()) {
   1536         m_writer.writeInt32(value->Int32Value());
   1537     } else if (value->IsUint32()) {
   1538         m_writer.writeUint32(value->Uint32Value());
   1539     } else if (value->IsNumber()) {
   1540         m_writer.writeNumber(value.As<v8::Number>()->Value());
   1541     } else if (V8ArrayBufferView::hasInstance(value, isolate())) {
   1542         return writeAndGreyArrayBufferView(value.As<v8::Object>(), next);
   1543     } else if (value->IsString()) {
   1544         writeString(value);
   1545     } else if (V8MessagePort::hasInstance(value, isolate())) {
   1546         uint32_t messagePortIndex;
   1547         if (m_transferredMessagePorts.tryGet(value.As<v8::Object>(), &messagePortIndex)) {
   1548             m_writer.writeTransferredMessagePort(messagePortIndex);
   1549         } else {
   1550             return handleError(DataCloneError, "A MessagePort could not be cloned.", next);
   1551         }
   1552     } else if (V8ArrayBuffer::hasInstance(value, isolate()) && m_transferredArrayBuffers.tryGet(value.As<v8::Object>(), &arrayBufferIndex)) {
   1553         return writeTransferredArrayBuffer(value, arrayBufferIndex, next);
   1554     } else {
   1555         v8::Handle<v8::Object> jsObject = value.As<v8::Object>();
   1556         if (jsObject.IsEmpty())
   1557             return handleError(DataCloneError, "An object could not be cloned.", next);
   1558         greyObject(jsObject);
   1559         if (value->IsDate()) {
   1560             m_writer.writeDate(value->NumberValue());
   1561         } else if (value->IsStringObject()) {
   1562             writeStringObject(value);
   1563         } else if (value->IsNumberObject()) {
   1564             writeNumberObject(value);
   1565         } else if (value->IsBooleanObject()) {
   1566             writeBooleanObject(value);
   1567         } else if (value->IsArray()) {
   1568             return startArrayState(value.As<v8::Array>(), next);
   1569         } else if (V8File::hasInstance(value, isolate())) {
   1570             return writeFile(value, next);
   1571         } else if (V8Blob::hasInstance(value, isolate())) {
   1572             return writeBlob(value, next);
   1573         } else if (V8DOMFileSystem::hasInstance(value, isolate())) {
   1574             return writeDOMFileSystem(value, next);
   1575         } else if (V8FileList::hasInstance(value, isolate())) {
   1576             return writeFileList(value, next);
   1577         } else if (V8CryptoKey::hasInstance(value, isolate())) {
   1578             if (!writeCryptoKey(value))
   1579                 return handleError(DataCloneError, "Couldn't serialize key data", next);
   1580         } else if (V8ImageData::hasInstance(value, isolate())) {
   1581             writeImageData(value);
   1582         } else if (value->IsRegExp()) {
   1583             writeRegExp(value);
   1584         } else if (V8ArrayBuffer::hasInstance(value, isolate())) {
   1585             return writeArrayBuffer(value, next);
   1586         } else if (value->IsObject()) {
   1587             if (isHostObject(jsObject) || jsObject->IsCallable() || value->IsNativeError())
   1588                 return handleError(DataCloneError, "An object could not be cloned.", next);
   1589             return startObjectState(jsObject, next);
   1590         } else {
   1591             return handleError(DataCloneError, "A value could not be cloned.", next);
   1592         }
   1593     }
   1594     return 0;
   1595 }
   1596 
   1597 // Interface used by Reader to create objects of composite types.
   1598 class CompositeCreator {
   1599     STACK_ALLOCATED();
   1600 public:
   1601     virtual ~CompositeCreator() { }
   1602 
   1603     virtual bool consumeTopOfStack(v8::Handle<v8::Value>*) = 0;
   1604     virtual uint32_t objectReferenceCount() = 0;
   1605     virtual void pushObjectReference(const v8::Handle<v8::Value>&) = 0;
   1606     virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle<v8::Value>*) = 0;
   1607     virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Value>*) = 0;
   1608     virtual bool tryGetTransferredArrayBuffer(uint32_t index, v8::Handle<v8::Value>*) = 0;
   1609     virtual bool newSparseArray(uint32_t length) = 0;
   1610     virtual bool newDenseArray(uint32_t length) = 0;
   1611     virtual bool newObject() = 0;
   1612     virtual bool completeObject(uint32_t numProperties, v8::Handle<v8::Value>*) = 0;
   1613     virtual bool completeSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>*) = 0;
   1614     virtual bool completeDenseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>*) = 0;
   1615 };
   1616 
   1617 // Reader is responsible for deserializing primitive types and
   1618 // restoring information about saved objects of composite types.
   1619 class Reader {
   1620 public:
   1621     Reader(const uint8_t* buffer, int length, const WebBlobInfoArray* blobInfo, BlobDataHandleMap& blobDataHandles, ScriptState* scriptState)
   1622         : m_scriptState(scriptState)
   1623         , m_buffer(buffer)
   1624         , m_length(length)
   1625         , m_position(0)
   1626         , m_version(0)
   1627         , m_blobInfo(blobInfo)
   1628         , m_blobDataHandles(blobDataHandles)
   1629     {
   1630         ASSERT(!(reinterpret_cast<size_t>(buffer) & 1));
   1631         ASSERT(length >= 0);
   1632     }
   1633 
   1634     bool isEof() const { return m_position >= m_length; }
   1635 
   1636     ScriptState* scriptState() const { return m_scriptState.get(); }
   1637 
   1638 private:
   1639     v8::Isolate* isolate() const { return m_scriptState->isolate(); }
   1640 
   1641 public:
   1642     bool read(v8::Handle<v8::Value>* value, CompositeCreator& creator)
   1643     {
   1644         SerializationTag tag;
   1645         if (!readTag(&tag))
   1646             return false;
   1647         switch (tag) {
   1648         case ReferenceCountTag: {
   1649             if (!m_version)
   1650                 return false;
   1651             uint32_t referenceTableSize;
   1652             if (!doReadUint32(&referenceTableSize))
   1653                 return false;
   1654             // If this test fails, then the serializer and deserializer disagree about the assignment
   1655             // of object reference IDs. On the deserialization side, this means there are too many or too few
   1656             // calls to pushObjectReference.
   1657             if (referenceTableSize != creator.objectReferenceCount())
   1658                 return false;
   1659             return true;
   1660         }
   1661         case InvalidTag:
   1662             return false;
   1663         case PaddingTag:
   1664             return true;
   1665         case UndefinedTag:
   1666             *value = v8::Undefined(isolate());
   1667             break;
   1668         case NullTag:
   1669             *value = v8::Null(isolate());
   1670             break;
   1671         case TrueTag:
   1672             *value = v8Boolean(true, isolate());
   1673             break;
   1674         case FalseTag:
   1675             *value = v8Boolean(false, isolate());
   1676             break;
   1677         case TrueObjectTag:
   1678             *value = v8::BooleanObject::New(true);
   1679             creator.pushObjectReference(*value);
   1680             break;
   1681         case FalseObjectTag:
   1682             *value = v8::BooleanObject::New(false);
   1683             creator.pushObjectReference(*value);
   1684             break;
   1685         case StringTag:
   1686             if (!readString(value))
   1687                 return false;
   1688             break;
   1689         case StringUCharTag:
   1690             if (!readUCharString(value))
   1691                 return false;
   1692             break;
   1693         case StringObjectTag:
   1694             if (!readStringObject(value))
   1695                 return false;
   1696             creator.pushObjectReference(*value);
   1697             break;
   1698         case Int32Tag:
   1699             if (!readInt32(value))
   1700                 return false;
   1701             break;
   1702         case Uint32Tag:
   1703             if (!readUint32(value))
   1704                 return false;
   1705             break;
   1706         case DateTag:
   1707             if (!readDate(value))
   1708                 return false;
   1709             creator.pushObjectReference(*value);
   1710             break;
   1711         case NumberTag:
   1712             if (!readNumber(value))
   1713                 return false;
   1714             break;
   1715         case NumberObjectTag:
   1716             if (!readNumberObject(value))
   1717                 return false;
   1718             creator.pushObjectReference(*value);
   1719             break;
   1720         case BlobTag:
   1721         case BlobIndexTag:
   1722             if (!readBlob(value, tag == BlobIndexTag))
   1723                 return false;
   1724             creator.pushObjectReference(*value);
   1725             break;
   1726         case FileTag:
   1727         case FileIndexTag:
   1728             if (!readFile(value, tag == FileIndexTag))
   1729                 return false;
   1730             creator.pushObjectReference(*value);
   1731             break;
   1732         case DOMFileSystemTag:
   1733             if (!readDOMFileSystem(value))
   1734                 return false;
   1735             creator.pushObjectReference(*value);
   1736             break;
   1737         case FileListTag:
   1738         case FileListIndexTag:
   1739             if (!readFileList(value, tag == FileListIndexTag))
   1740                 return false;
   1741             creator.pushObjectReference(*value);
   1742             break;
   1743         case CryptoKeyTag:
   1744             if (!readCryptoKey(value))
   1745                 return false;
   1746             creator.pushObjectReference(*value);
   1747             break;
   1748         case ImageDataTag:
   1749             if (!readImageData(value))
   1750                 return false;
   1751             creator.pushObjectReference(*value);
   1752             break;
   1753 
   1754         case RegExpTag:
   1755             if (!readRegExp(value))
   1756                 return false;
   1757             creator.pushObjectReference(*value);
   1758             break;
   1759         case ObjectTag: {
   1760             uint32_t numProperties;
   1761             if (!doReadUint32(&numProperties))
   1762                 return false;
   1763             if (!creator.completeObject(numProperties, value))
   1764                 return false;
   1765             break;
   1766         }
   1767         case SparseArrayTag: {
   1768             uint32_t numProperties;
   1769             uint32_t length;
   1770             if (!doReadUint32(&numProperties))
   1771                 return false;
   1772             if (!doReadUint32(&length))
   1773                 return false;
   1774             if (!creator.completeSparseArray(numProperties, length, value))
   1775                 return false;
   1776             break;
   1777         }
   1778         case DenseArrayTag: {
   1779             uint32_t numProperties;
   1780             uint32_t length;
   1781             if (!doReadUint32(&numProperties))
   1782                 return false;
   1783             if (!doReadUint32(&length))
   1784                 return false;
   1785             if (!creator.completeDenseArray(numProperties, length, value))
   1786                 return false;
   1787             break;
   1788         }
   1789         case ArrayBufferViewTag: {
   1790             if (!m_version)
   1791                 return false;
   1792             if (!readArrayBufferView(value, creator))
   1793                 return false;
   1794             creator.pushObjectReference(*value);
   1795             break;
   1796         }
   1797         case ArrayBufferTag: {
   1798             if (!m_version)
   1799                 return false;
   1800             if (!readArrayBuffer(value))
   1801                 return false;
   1802             creator.pushObjectReference(*value);
   1803             break;
   1804         }
   1805         case GenerateFreshObjectTag: {
   1806             if (!m_version)
   1807                 return false;
   1808             if (!creator.newObject())
   1809                 return false;
   1810             return true;
   1811         }
   1812         case GenerateFreshSparseArrayTag: {
   1813             if (!m_version)
   1814                 return false;
   1815             uint32_t length;
   1816             if (!doReadUint32(&length))
   1817                 return false;
   1818             if (!creator.newSparseArray(length))
   1819                 return false;
   1820             return true;
   1821         }
   1822         case GenerateFreshDenseArrayTag: {
   1823             if (!m_version)
   1824                 return false;
   1825             uint32_t length;
   1826             if (!doReadUint32(&length))
   1827                 return false;
   1828             if (!creator.newDenseArray(length))
   1829                 return false;
   1830             return true;
   1831         }
   1832         case MessagePortTag: {
   1833             if (!m_version)
   1834                 return false;
   1835             uint32_t index;
   1836             if (!doReadUint32(&index))
   1837                 return false;
   1838             if (!creator.tryGetTransferredMessagePort(index, value))
   1839                 return false;
   1840             break;
   1841         }
   1842         case ArrayBufferTransferTag: {
   1843             if (!m_version)
   1844                 return false;
   1845             uint32_t index;
   1846             if (!doReadUint32(&index))
   1847                 return false;
   1848             if (!creator.tryGetTransferredArrayBuffer(index, value))
   1849                 return false;
   1850             break;
   1851         }
   1852         case ObjectReferenceTag: {
   1853             if (!m_version)
   1854                 return false;
   1855             uint32_t reference;
   1856             if (!doReadUint32(&reference))
   1857                 return false;
   1858             if (!creator.tryGetObjectFromObjectReference(reference, value))
   1859                 return false;
   1860             break;
   1861         }
   1862         default:
   1863             return false;
   1864         }
   1865         return !value->IsEmpty();
   1866     }
   1867 
   1868     bool readVersion(uint32_t& version)
   1869     {
   1870         SerializationTag tag;
   1871         if (!readTag(&tag)) {
   1872             // This is a nullary buffer. We're still version 0.
   1873             version = 0;
   1874             return true;
   1875         }
   1876         if (tag != VersionTag) {
   1877             // Versions of the format past 0 start with the version tag.
   1878             version = 0;
   1879             // Put back the tag.
   1880             undoReadTag();
   1881             return true;
   1882         }
   1883         // Version-bearing messages are obligated to finish the version tag.
   1884         return doReadUint32(&version);
   1885     }
   1886 
   1887     void setVersion(uint32_t version)
   1888     {
   1889         m_version = version;
   1890     }
   1891 
   1892 private:
   1893     bool readTag(SerializationTag* tag)
   1894     {
   1895         if (m_position >= m_length)
   1896             return false;
   1897         *tag = static_cast<SerializationTag>(m_buffer[m_position++]);
   1898         return true;
   1899     }
   1900 
   1901     void undoReadTag()
   1902     {
   1903         if (m_position > 0)
   1904             --m_position;
   1905     }
   1906 
   1907     bool readArrayBufferViewSubTag(ArrayBufferViewSubTag* tag)
   1908     {
   1909         if (m_position >= m_length)
   1910             return false;
   1911         *tag = static_cast<ArrayBufferViewSubTag>(m_buffer[m_position++]);
   1912         return true;
   1913     }
   1914 
   1915     bool readString(v8::Handle<v8::Value>* value)
   1916     {
   1917         uint32_t length;
   1918         if (!doReadUint32(&length))
   1919             return false;
   1920         if (m_position + length > m_length)
   1921             return false;
   1922         *value = v8::String::NewFromUtf8(isolate(), reinterpret_cast<const char*>(m_buffer + m_position), v8::String::kNormalString, length);
   1923         m_position += length;
   1924         return true;
   1925     }
   1926 
   1927     bool readUCharString(v8::Handle<v8::Value>* value)
   1928     {
   1929         uint32_t length;
   1930         if (!doReadUint32(&length) || (length & 1))
   1931             return false;
   1932         if (m_position + length > m_length)
   1933             return false;
   1934         ASSERT(!(m_position & 1));
   1935         *value = v8::String::NewFromTwoByte(isolate(), reinterpret_cast<const uint16_t*>(m_buffer + m_position), v8::String::kNormalString, length / sizeof(UChar));
   1936         m_position += length;
   1937         return true;
   1938     }
   1939 
   1940     bool readStringObject(v8::Handle<v8::Value>* value)
   1941     {
   1942         v8::Handle<v8::Value> stringValue;
   1943         if (!readString(&stringValue) || !stringValue->IsString())
   1944             return false;
   1945         *value = v8::StringObject::New(stringValue.As<v8::String>());
   1946         return true;
   1947     }
   1948 
   1949     bool readWebCoreString(String* string)
   1950     {
   1951         uint32_t length;
   1952         if (!doReadUint32(&length))
   1953             return false;
   1954         if (m_position + length > m_length)
   1955             return false;
   1956         *string = String::fromUTF8(reinterpret_cast<const char*>(m_buffer + m_position), length);
   1957         m_position += length;
   1958         return true;
   1959     }
   1960 
   1961     bool readInt32(v8::Handle<v8::Value>* value)
   1962     {
   1963         uint32_t rawValue;
   1964         if (!doReadUint32(&rawValue))
   1965             return false;
   1966         *value = v8::Integer::New(isolate(), static_cast<int32_t>(ZigZag::decode(rawValue)));
   1967         return true;
   1968     }
   1969 
   1970     bool readUint32(v8::Handle<v8::Value>* value)
   1971     {
   1972         uint32_t rawValue;
   1973         if (!doReadUint32(&rawValue))
   1974             return false;
   1975         *value = v8::Integer::NewFromUnsigned(isolate(), rawValue);
   1976         return true;
   1977     }
   1978 
   1979     bool readDate(v8::Handle<v8::Value>* value)
   1980     {
   1981         double numberValue;
   1982         if (!doReadNumber(&numberValue))
   1983             return false;
   1984         *value = v8DateOrNaN(numberValue, isolate());
   1985         return true;
   1986     }
   1987 
   1988     bool readNumber(v8::Handle<v8::Value>* value)
   1989     {
   1990         double number;
   1991         if (!doReadNumber(&number))
   1992             return false;
   1993         *value = v8::Number::New(isolate(), number);
   1994         return true;
   1995     }
   1996 
   1997     bool readNumberObject(v8::Handle<v8::Value>* value)
   1998     {
   1999         double number;
   2000         if (!doReadNumber(&number))
   2001             return false;
   2002         *value = v8::NumberObject::New(isolate(), number);
   2003         return true;
   2004     }
   2005 
   2006     bool readImageData(v8::Handle<v8::Value>* value)
   2007     {
   2008         uint32_t width;
   2009         uint32_t height;
   2010         uint32_t pixelDataLength;
   2011         if (!doReadUint32(&width))
   2012             return false;
   2013         if (!doReadUint32(&height))
   2014             return false;
   2015         if (!doReadUint32(&pixelDataLength))
   2016             return false;
   2017         if (m_position + pixelDataLength > m_length)
   2018             return false;
   2019         RefPtrWillBeRawPtr<ImageData> imageData = ImageData::create(IntSize(width, height));
   2020         Uint8ClampedArray* pixelArray = imageData->data();
   2021         ASSERT(pixelArray);
   2022         ASSERT(pixelArray->length() >= pixelDataLength);
   2023         memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength);
   2024         m_position += pixelDataLength;
   2025         *value = toV8(imageData.release(), m_scriptState->context()->Global(), isolate());
   2026         return true;
   2027     }
   2028 
   2029     PassRefPtr<ArrayBuffer> doReadArrayBuffer()
   2030     {
   2031         uint32_t byteLength;
   2032         if (!doReadUint32(&byteLength))
   2033             return nullptr;
   2034         if (m_position + byteLength > m_length)
   2035             return nullptr;
   2036         const void* bufferStart = m_buffer + m_position;
   2037         RefPtr<ArrayBuffer> arrayBuffer = ArrayBuffer::create(bufferStart, byteLength);
   2038         arrayBuffer->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instanceTemplate());
   2039         m_position += byteLength;
   2040         return arrayBuffer.release();
   2041     }
   2042 
   2043     bool readArrayBuffer(v8::Handle<v8::Value>* value)
   2044     {
   2045         RefPtr<ArrayBuffer> arrayBuffer = doReadArrayBuffer();
   2046         if (!arrayBuffer)
   2047             return false;
   2048         *value = toV8(arrayBuffer.release(), m_scriptState->context()->Global(), isolate());
   2049         return true;
   2050     }
   2051 
   2052     bool readArrayBufferView(v8::Handle<v8::Value>* value, CompositeCreator& creator)
   2053     {
   2054         ArrayBufferViewSubTag subTag;
   2055         uint32_t byteOffset;
   2056         uint32_t byteLength;
   2057         RefPtr<ArrayBuffer> arrayBuffer;
   2058         v8::Handle<v8::Value> arrayBufferV8Value;
   2059         if (!readArrayBufferViewSubTag(&subTag))
   2060             return false;
   2061         if (!doReadUint32(&byteOffset))
   2062             return false;
   2063         if (!doReadUint32(&byteLength))
   2064             return false;
   2065         if (!creator.consumeTopOfStack(&arrayBufferV8Value))
   2066             return false;
   2067         if (arrayBufferV8Value.IsEmpty())
   2068             return false;
   2069         arrayBuffer = V8ArrayBuffer::toImpl(arrayBufferV8Value.As<v8::Object>());
   2070         if (!arrayBuffer)
   2071             return false;
   2072 
   2073         v8::Handle<v8::Object> creationContext = m_scriptState->context()->Global();
   2074         switch (subTag) {
   2075         case ByteArrayTag:
   2076             *value = toV8(Int8Array::create(arrayBuffer.release(), byteOffset, byteLength), creationContext, isolate());
   2077             break;
   2078         case UnsignedByteArrayTag:
   2079             *value = toV8(Uint8Array::create(arrayBuffer.release(), byteOffset, byteLength), creationContext,  isolate());
   2080             break;
   2081         case UnsignedByteClampedArrayTag:
   2082             *value = toV8(Uint8ClampedArray::create(arrayBuffer.release(), byteOffset, byteLength), creationContext, isolate());
   2083             break;
   2084         case ShortArrayTag: {
   2085             uint32_t shortLength = byteLength / sizeof(int16_t);
   2086             if (shortLength * sizeof(int16_t) != byteLength)
   2087                 return false;
   2088             *value = toV8(Int16Array::create(arrayBuffer.release(), byteOffset, shortLength), creationContext, isolate());
   2089             break;
   2090         }
   2091         case UnsignedShortArrayTag: {
   2092             uint32_t shortLength = byteLength / sizeof(uint16_t);
   2093             if (shortLength * sizeof(uint16_t) != byteLength)
   2094                 return false;
   2095             *value = toV8(Uint16Array::create(arrayBuffer.release(), byteOffset, shortLength), creationContext, isolate());
   2096             break;
   2097         }
   2098         case IntArrayTag: {
   2099             uint32_t intLength = byteLength / sizeof(int32_t);
   2100             if (intLength * sizeof(int32_t) != byteLength)
   2101                 return false;
   2102             *value = toV8(Int32Array::create(arrayBuffer.release(), byteOffset, intLength), creationContext, isolate());
   2103             break;
   2104         }
   2105         case UnsignedIntArrayTag: {
   2106             uint32_t intLength = byteLength / sizeof(uint32_t);
   2107             if (intLength * sizeof(uint32_t) != byteLength)
   2108                 return false;
   2109             *value = toV8(Uint32Array::create(arrayBuffer.release(), byteOffset, intLength), creationContext, isolate());
   2110             break;
   2111         }
   2112         case FloatArrayTag: {
   2113             uint32_t floatLength = byteLength / sizeof(float);
   2114             if (floatLength * sizeof(float) != byteLength)
   2115                 return false;
   2116             *value = toV8(Float32Array::create(arrayBuffer.release(), byteOffset, floatLength), creationContext, isolate());
   2117             break;
   2118         }
   2119         case DoubleArrayTag: {
   2120             uint32_t floatLength = byteLength / sizeof(double);
   2121             if (floatLength * sizeof(double) != byteLength)
   2122                 return false;
   2123             *value = toV8(Float64Array::create(arrayBuffer.release(), byteOffset, floatLength), creationContext, isolate());
   2124             break;
   2125         }
   2126         case DataViewTag:
   2127             *value = toV8(DataView::create(arrayBuffer.release(), byteOffset, byteLength), creationContext, isolate());
   2128             break;
   2129         default:
   2130             return false;
   2131         }
   2132         // The various *Array::create() methods will return null if the range the view expects is
   2133         // mismatched with the range the buffer can provide or if the byte offset is not aligned
   2134         // to the size of the element type.
   2135         return !value->IsEmpty();
   2136     }
   2137 
   2138     bool readRegExp(v8::Handle<v8::Value>* value)
   2139     {
   2140         v8::Handle<v8::Value> pattern;
   2141         if (!readString(&pattern))
   2142             return false;
   2143         uint32_t flags;
   2144         if (!doReadUint32(&flags))
   2145             return false;
   2146         *value = v8::RegExp::New(pattern.As<v8::String>(), static_cast<v8::RegExp::Flags>(flags));
   2147         return true;
   2148     }
   2149 
   2150     bool readBlob(v8::Handle<v8::Value>* value, bool isIndexed)
   2151     {
   2152         if (m_version < 3)
   2153             return false;
   2154         RefPtrWillBeRawPtr<Blob> blob;
   2155         if (isIndexed) {
   2156             if (m_version < 6)
   2157                 return false;
   2158             ASSERT(m_blobInfo);
   2159             uint32_t index;
   2160             if (!doReadUint32(&index) || index >= m_blobInfo->size())
   2161                 return false;
   2162             const blink::WebBlobInfo& info = (*m_blobInfo)[index];
   2163             blob = Blob::create(getOrCreateBlobDataHandle(info.uuid(), info.type(), info.size()));
   2164         } else {
   2165             ASSERT(!m_blobInfo);
   2166             String uuid;
   2167             String type;
   2168             uint64_t size;
   2169             ASSERT(!m_blobInfo);
   2170             if (!readWebCoreString(&uuid))
   2171                 return false;
   2172             if (!readWebCoreString(&type))
   2173                 return false;
   2174             if (!doReadUint64(&size))
   2175                 return false;
   2176             blob = Blob::create(getOrCreateBlobDataHandle(uuid, type, size));
   2177         }
   2178         *value = toV8(blob.release(), m_scriptState->context()->Global(), isolate());
   2179         return true;
   2180     }
   2181 
   2182     bool readDOMFileSystem(v8::Handle<v8::Value>* value)
   2183     {
   2184         uint32_t type;
   2185         String name;
   2186         String url;
   2187         if (!doReadUint32(&type))
   2188             return false;
   2189         if (!readWebCoreString(&name))
   2190             return false;
   2191         if (!readWebCoreString(&url))
   2192             return false;
   2193         DOMFileSystem* fs = DOMFileSystem::create(m_scriptState->executionContext(), name, static_cast<blink::FileSystemType>(type), KURL(ParsedURLString, url));
   2194         *value = toV8(fs, m_scriptState->context()->Global(), isolate());
   2195         return true;
   2196     }
   2197 
   2198     bool readFile(v8::Handle<v8::Value>* value, bool isIndexed)
   2199     {
   2200         RefPtrWillBeRawPtr<File> file;
   2201         if (isIndexed) {
   2202             if (m_version < 6)
   2203                 return false;
   2204             file = readFileIndexHelper();
   2205         } else {
   2206             file = readFileHelper();
   2207         }
   2208         if (!file)
   2209             return false;
   2210         *value = toV8(file.release(), m_scriptState->context()->Global(), isolate());
   2211         return true;
   2212     }
   2213 
   2214     bool readFileList(v8::Handle<v8::Value>* value, bool isIndexed)
   2215     {
   2216         if (m_version < 3)
   2217             return false;
   2218         uint32_t length;
   2219         if (!doReadUint32(&length))
   2220             return false;
   2221         RefPtrWillBeRawPtr<FileList> fileList = FileList::create();
   2222         for (unsigned i = 0; i < length; ++i) {
   2223             RefPtrWillBeRawPtr<File> file;
   2224             if (isIndexed) {
   2225                 if (m_version < 6)
   2226                     return false;
   2227                 file = readFileIndexHelper();
   2228             } else {
   2229                 file = readFileHelper();
   2230             }
   2231             if (!file)
   2232                 return false;
   2233             fileList->append(file.release());
   2234         }
   2235         *value = toV8(fileList.release(), m_scriptState->context()->Global(), isolate());
   2236         return true;
   2237     }
   2238 
   2239     bool readCryptoKey(v8::Handle<v8::Value>* value)
   2240     {
   2241         uint32_t rawKeyType;
   2242         if (!doReadUint32(&rawKeyType))
   2243             return false;
   2244 
   2245         blink::WebCryptoKeyAlgorithm algorithm;
   2246         blink::WebCryptoKeyType type = blink::WebCryptoKeyTypeSecret;
   2247 
   2248         switch (static_cast<CryptoKeySubTag>(rawKeyType)) {
   2249         case AesKeyTag:
   2250             if (!doReadAesKey(algorithm, type))
   2251                 return false;
   2252             break;
   2253         case HmacKeyTag:
   2254             if (!doReadHmacKey(algorithm, type))
   2255                 return false;
   2256             break;
   2257         case RsaHashedKeyTag:
   2258             if (!doReadRsaHashedKey(algorithm, type))
   2259                 return false;
   2260             break;
   2261         default:
   2262             return false;
   2263         }
   2264 
   2265         blink::WebCryptoKeyUsageMask usages;
   2266         bool extractable;
   2267         if (!doReadKeyUsages(usages, extractable))
   2268             return false;
   2269 
   2270         uint32_t keyDataLength;
   2271         if (!doReadUint32(&keyDataLength))
   2272             return false;
   2273 
   2274         if (m_position + keyDataLength > m_length)
   2275             return false;
   2276 
   2277         const uint8_t* keyData = m_buffer + m_position;
   2278         m_position += keyDataLength;
   2279 
   2280         blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
   2281         if (!blink::Platform::current()->crypto()->deserializeKeyForClone(
   2282             algorithm, type, extractable, usages, keyData, keyDataLength, key)) {
   2283             return false;
   2284         }
   2285 
   2286         *value = toV8(CryptoKey::create(key), m_scriptState->context()->Global(), isolate());
   2287         return true;
   2288     }
   2289 
   2290     PassRefPtrWillBeRawPtr<File> readFileHelper()
   2291     {
   2292         if (m_version < 3)
   2293             return nullptr;
   2294         ASSERT(!m_blobInfo);
   2295         String path;
   2296         String name;
   2297         String relativePath;
   2298         String uuid;
   2299         String type;
   2300         uint32_t hasSnapshot = 0;
   2301         uint64_t size = 0;
   2302         double lastModified = 0;
   2303         if (!readWebCoreString(&path))
   2304             return nullptr;
   2305         if (m_version >= 4 && !readWebCoreString(&name))
   2306             return nullptr;
   2307         if (m_version >= 4 && !readWebCoreString(&relativePath))
   2308             return nullptr;
   2309         if (!readWebCoreString(&uuid))
   2310             return nullptr;
   2311         if (!readWebCoreString(&type))
   2312             return nullptr;
   2313         if (m_version >= 4 && !doReadUint32(&hasSnapshot))
   2314             return nullptr;
   2315         if (hasSnapshot) {
   2316             if (!doReadUint64(&size))
   2317                 return nullptr;
   2318             if (!doReadNumber(&lastModified))
   2319                 return nullptr;
   2320         }
   2321         uint32_t isUserVisible = 1;
   2322         if (m_version >= 7 && !doReadUint32(&isUserVisible))
   2323             return nullptr;
   2324         const File::UserVisibility userVisibility = (isUserVisible > 0) ? File::IsUserVisible : File::IsNotUserVisible;
   2325         return File::createFromSerialization(path, name, relativePath, userVisibility, hasSnapshot > 0, size, lastModified, getOrCreateBlobDataHandle(uuid, type));
   2326     }
   2327 
   2328     PassRefPtrWillBeRawPtr<File> readFileIndexHelper()
   2329     {
   2330         if (m_version < 3)
   2331             return nullptr;
   2332         ASSERT(m_blobInfo);
   2333         uint32_t index;
   2334         if (!doReadUint32(&index) || index >= m_blobInfo->size())
   2335             return nullptr;
   2336         const WebBlobInfo& info = (*m_blobInfo)[index];
   2337         return File::createFromIndexedSerialization(info.filePath(), info.fileName(), info.size(), info.lastModified(), getOrCreateBlobDataHandle(info.uuid(), info.type(), info.size()));
   2338     }
   2339 
   2340     template<class T>
   2341     bool doReadUintHelper(T* value)
   2342     {
   2343         *value = 0;
   2344         uint8_t currentByte;
   2345         int shift = 0;
   2346         do {
   2347             if (m_position >= m_length)
   2348                 return false;
   2349             currentByte = m_buffer[m_position++];
   2350             *value |= ((currentByte & varIntMask) << shift);
   2351             shift += varIntShift;
   2352         } while (currentByte & (1 << varIntShift));
   2353         return true;
   2354     }
   2355 
   2356     bool doReadUint32(uint32_t* value)
   2357     {
   2358         return doReadUintHelper(value);
   2359     }
   2360 
   2361     bool doReadUint64(uint64_t* value)
   2362     {
   2363         return doReadUintHelper(value);
   2364     }
   2365 
   2366     bool doReadNumber(double* number)
   2367     {
   2368         if (m_position + sizeof(double) > m_length)
   2369             return false;
   2370         uint8_t* numberAsByteArray = reinterpret_cast<uint8_t*>(number);
   2371         for (unsigned i = 0; i < sizeof(double); ++i)
   2372             numberAsByteArray[i] = m_buffer[m_position++];
   2373         return true;
   2374     }
   2375 
   2376     PassRefPtr<BlobDataHandle> getOrCreateBlobDataHandle(const String& uuid, const String& type, long long size = -1)
   2377     {
   2378         // The containing ssv may have a BDH for this uuid if this ssv is just being
   2379         // passed from main to worker thread (for example). We use those values when creating
   2380         // the new blob instead of cons'ing up a new BDH.
   2381         //
   2382         // FIXME: Maybe we should require that it work that way where the ssv must have a BDH for any
   2383         // blobs it comes across during deserialization. Would require callers to explicitly populate
   2384         // the collection of BDH's for blobs to work, which would encourage lifetimes to be considered
   2385         // when passing ssv's around cross process. At present, we get 'lucky' in some cases because
   2386         // the blob in the src process happens to still exist at the time the dest process is deserializing.
   2387         // For example in sharedWorker.postMessage(...).
   2388         BlobDataHandleMap::const_iterator it = m_blobDataHandles.find(uuid);
   2389         if (it != m_blobDataHandles.end()) {
   2390             // make assertions about type and size?
   2391             return it->value;
   2392         }
   2393         return BlobDataHandle::create(uuid, type, size);
   2394     }
   2395 
   2396     bool doReadHmacKey(blink::WebCryptoKeyAlgorithm& algorithm, blink::WebCryptoKeyType& type)
   2397     {
   2398         uint32_t lengthBytes;
   2399         if (!doReadUint32(&lengthBytes))
   2400             return false;
   2401         blink::WebCryptoAlgorithmId hash;
   2402         if (!doReadAlgorithmId(hash))
   2403             return false;
   2404         algorithm = blink::WebCryptoKeyAlgorithm::createHmac(hash, lengthBytes * 8);
   2405         type = blink::WebCryptoKeyTypeSecret;
   2406         return !algorithm.isNull();
   2407     }
   2408 
   2409     bool doReadAesKey(blink::WebCryptoKeyAlgorithm& algorithm, blink::WebCryptoKeyType& type)
   2410     {
   2411         blink::WebCryptoAlgorithmId id;
   2412         if (!doReadAlgorithmId(id))
   2413             return false;
   2414         uint32_t lengthBytes;
   2415         if (!doReadUint32(&lengthBytes))
   2416             return false;
   2417         algorithm = blink::WebCryptoKeyAlgorithm::createAes(id, lengthBytes * 8);
   2418         type = blink::WebCryptoKeyTypeSecret;
   2419         return !algorithm.isNull();
   2420     }
   2421 
   2422     bool doReadRsaHashedKey(blink::WebCryptoKeyAlgorithm& algorithm, blink::WebCryptoKeyType& type)
   2423     {
   2424         blink::WebCryptoAlgorithmId id;
   2425         if (!doReadAlgorithmId(id))
   2426             return false;
   2427 
   2428         uint32_t rawType;
   2429         if (!doReadUint32(&rawType))
   2430             return false;
   2431 
   2432         switch (static_cast<AssymetricCryptoKeyType>(rawType)) {
   2433         case PublicKeyType:
   2434             type = blink::WebCryptoKeyTypePublic;
   2435             break;
   2436         case PrivateKeyType:
   2437             type = blink::WebCryptoKeyTypePrivate;
   2438             break;
   2439         default:
   2440             return false;
   2441         }
   2442 
   2443         uint32_t modulusLengthBits;
   2444         if (!doReadUint32(&modulusLengthBits))
   2445             return false;
   2446 
   2447         uint32_t publicExponentSize;
   2448         if (!doReadUint32(&publicExponentSize))
   2449             return false;
   2450 
   2451         if (m_position + publicExponentSize > m_length)
   2452             return false;
   2453 
   2454         const uint8_t* publicExponent = m_buffer + m_position;
   2455         m_position += publicExponentSize;
   2456 
   2457         blink::WebCryptoAlgorithmId hash;
   2458         if (!doReadAlgorithmId(hash))
   2459             return false;
   2460         algorithm = blink::WebCryptoKeyAlgorithm::createRsaHashed(id, modulusLengthBits, publicExponent, publicExponentSize, hash);
   2461 
   2462         return !algorithm.isNull();
   2463     }
   2464 
   2465     bool doReadAlgorithmId(blink::WebCryptoAlgorithmId& id)
   2466     {
   2467         uint32_t rawId;
   2468         if (!doReadUint32(&rawId))
   2469             return false;
   2470 
   2471         switch (static_cast<CryptoKeyAlgorithmTag>(rawId)) {
   2472         case AesCbcTag:
   2473             id = blink::WebCryptoAlgorithmIdAesCbc;
   2474             return true;
   2475         case HmacTag:
   2476             id = blink::WebCryptoAlgorithmIdHmac;
   2477             return true;
   2478         case RsaSsaPkcs1v1_5Tag:
   2479             id = blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5;
   2480             return true;
   2481         case Sha1Tag:
   2482             id = blink::WebCryptoAlgorithmIdSha1;
   2483             return true;
   2484         case Sha256Tag:
   2485             id = blink::WebCryptoAlgorithmIdSha256;
   2486             return true;
   2487         case Sha384Tag:
   2488             id = blink::WebCryptoAlgorithmIdSha384;
   2489             return true;
   2490         case Sha512Tag:
   2491             id = blink::WebCryptoAlgorithmIdSha512;
   2492             return true;
   2493         case AesGcmTag:
   2494             id = blink::WebCryptoAlgorithmIdAesGcm;
   2495             return true;
   2496         case RsaOaepTag:
   2497             id = blink::WebCryptoAlgorithmIdRsaOaep;
   2498             return true;
   2499         case AesCtrTag:
   2500             id = blink::WebCryptoAlgorithmIdAesCtr;
   2501             return true;
   2502         case AesKwTag:
   2503             id = blink::WebCryptoAlgorithmIdAesKw;
   2504             return true;
   2505         }
   2506 
   2507         return false;
   2508     }
   2509 
   2510     bool doReadKeyUsages(blink::WebCryptoKeyUsageMask& usages, bool& extractable)
   2511     {
   2512         // Reminder to update this when adding new key usages.
   2513         COMPILE_ASSERT(blink::EndOfWebCryptoKeyUsage == (1 << 7) + 1, UpdateMe);
   2514         const uint32_t allPossibleUsages = ExtractableUsage | EncryptUsage | DecryptUsage | SignUsage | VerifyUsage | DeriveKeyUsage | WrapKeyUsage | UnwrapKeyUsage | DeriveBitsUsage;
   2515 
   2516         uint32_t rawUsages;
   2517         if (!doReadUint32(&rawUsages))
   2518             return false;
   2519 
   2520         // Make sure it doesn't contain an unrecognized usage value.
   2521         if (rawUsages & ~allPossibleUsages)
   2522             return false;
   2523 
   2524         usages = 0;
   2525 
   2526         extractable = rawUsages & ExtractableUsage;
   2527 
   2528         if (rawUsages & EncryptUsage)
   2529             usages |= blink::WebCryptoKeyUsageEncrypt;
   2530         if (rawUsages & DecryptUsage)
   2531             usages |= blink::WebCryptoKeyUsageDecrypt;
   2532         if (rawUsages & SignUsage)
   2533             usages |= blink::WebCryptoKeyUsageSign;
   2534         if (rawUsages & VerifyUsage)
   2535             usages |= blink::WebCryptoKeyUsageVerify;
   2536         if (rawUsages & DeriveKeyUsage)
   2537             usages |= blink::WebCryptoKeyUsageDeriveKey;
   2538         if (rawUsages & WrapKeyUsage)
   2539             usages |= blink::WebCryptoKeyUsageWrapKey;
   2540         if (rawUsages & UnwrapKeyUsage)
   2541             usages |= blink::WebCryptoKeyUsageUnwrapKey;
   2542         if (rawUsages & DeriveBitsUsage)
   2543             usages |= blink::WebCryptoKeyUsageDeriveBits;
   2544 
   2545         return true;
   2546     }
   2547 
   2548     RefPtr<ScriptState> m_scriptState;
   2549     const uint8_t* m_buffer;
   2550     const unsigned m_length;
   2551     unsigned m_position;
   2552     uint32_t m_version;
   2553     const WebBlobInfoArray* m_blobInfo;
   2554     const BlobDataHandleMap& m_blobDataHandles;
   2555 };
   2556 
   2557 
   2558 typedef Vector<WTF::ArrayBufferContents, 1> ArrayBufferContentsArray;
   2559 
   2560 class Deserializer FINAL : public CompositeCreator {
   2561 public:
   2562     Deserializer(Reader& reader, MessagePortArray* messagePorts, ArrayBufferContentsArray* arrayBufferContents)
   2563         : m_reader(reader)
   2564         , m_transferredMessagePorts(messagePorts)
   2565         , m_arrayBufferContents(arrayBufferContents)
   2566         , m_arrayBuffers(arrayBufferContents ? arrayBufferContents->size() : 0)
   2567         , m_version(0)
   2568     {
   2569     }
   2570 
   2571     v8::Handle<v8::Value> deserialize()
   2572     {
   2573         v8::Isolate* isolate = m_reader.scriptState()->isolate();
   2574         if (!m_reader.readVersion(m_version) || m_version > SerializedScriptValue::wireFormatVersion)
   2575             return v8::Null(isolate);
   2576         m_reader.setVersion(m_version);
   2577         v8::EscapableHandleScope scope(isolate);
   2578         while (!m_reader.isEof()) {
   2579             if (!doDeserialize())
   2580                 return v8::Null(isolate);
   2581         }
   2582         if (stackDepth() != 1 || m_openCompositeReferenceStack.size())
   2583             return v8::Null(isolate);
   2584         v8::Handle<v8::Value> result = scope.Escape(element(0));
   2585         return result;
   2586     }
   2587 
   2588     virtual bool newSparseArray(uint32_t) OVERRIDE
   2589     {
   2590         v8::Local<v8::Array> array = v8::Array::New(m_reader.scriptState()->isolate(), 0);
   2591         openComposite(array);
   2592         return true;
   2593     }
   2594 
   2595     virtual bool newDenseArray(uint32_t length) OVERRIDE
   2596     {
   2597         v8::Local<v8::Array> array = v8::Array::New(m_reader.scriptState()->isolate(), length);
   2598         openComposite(array);
   2599         return true;
   2600     }
   2601 
   2602     virtual bool consumeTopOfStack(v8::Handle<v8::Value>* object) OVERRIDE
   2603     {
   2604         if (stackDepth() < 1)
   2605             return false;
   2606         *object = element(stackDepth() - 1);
   2607         pop(1);
   2608         return true;
   2609     }
   2610 
   2611     virtual bool newObject() OVERRIDE
   2612     {
   2613         v8::Local<v8::Object> object = v8::Object::New(m_reader.scriptState()->isolate());
   2614         if (object.IsEmpty())
   2615             return false;
   2616         openComposite(object);
   2617         return true;
   2618     }
   2619 
   2620     virtual bool completeObject(uint32_t numProperties, v8::Handle<v8::Value>* value) OVERRIDE
   2621     {
   2622         v8::Local<v8::Object> object;
   2623         if (m_version > 0) {
   2624             v8::Local<v8::Value> composite;
   2625             if (!closeComposite(&composite))
   2626                 return false;
   2627             object = composite.As<v8::Object>();
   2628         } else {
   2629             object = v8::Object::New(m_reader.scriptState()->isolate());
   2630         }
   2631         if (object.IsEmpty())
   2632             return false;
   2633         return initializeObject(object, numProperties, value);
   2634     }
   2635 
   2636     virtual bool completeSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) OVERRIDE
   2637     {
   2638         v8::Local<v8::Array> array;
   2639         if (m_version > 0) {
   2640             v8::Local<v8::Value> composite;
   2641             if (!closeComposite(&composite))
   2642                 return false;
   2643             array = composite.As<v8::Array>();
   2644         } else {
   2645             array = v8::Array::New(m_reader.scriptState()->isolate());
   2646         }
   2647         if (array.IsEmpty())
   2648             return false;
   2649         return initializeObject(array, numProperties, value);
   2650     }
   2651 
   2652     virtual bool completeDenseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) OVERRIDE
   2653     {
   2654         v8::Local<v8::Array> array;
   2655         if (m_version > 0) {
   2656             v8::Local<v8::Value> composite;
   2657             if (!closeComposite(&composite))
   2658                 return false;
   2659             array = composite.As<v8::Array>();
   2660         }
   2661         if (array.IsEmpty())
   2662             return false;
   2663         if (!initializeObject(array, numProperties, value))
   2664             return false;
   2665         if (length > stackDepth())
   2666             return false;
   2667         for (unsigned i = 0, stackPos = stackDepth() - length; i < length; i++, stackPos++) {
   2668             v8::Local<v8::Value> elem = element(stackPos);
   2669             if (!elem->IsUndefined())
   2670                 array->Set(i, elem);
   2671         }
   2672         pop(length);
   2673         return true;
   2674     }
   2675 
   2676     virtual void pushObjectReference(const v8::Handle<v8::Value>& object) OVERRIDE
   2677     {
   2678         m_objectPool.append(object);
   2679     }
   2680 
   2681     virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Value>* object) OVERRIDE
   2682     {
   2683         if (!m_transferredMessagePorts)
   2684             return false;
   2685         if (index >= m_transferredMessagePorts->size())
   2686             return false;
   2687         v8::Handle<v8::Object> creationContext = m_reader.scriptState()->context()->Global();
   2688         *object = toV8(m_transferredMessagePorts->at(index).get(), creationContext, m_reader.scriptState()->isolate());
   2689         return true;
   2690     }
   2691 
   2692     virtual bool tryGetTransferredArrayBuffer(uint32_t index, v8::Handle<v8::Value>* object) OVERRIDE
   2693     {
   2694         if (!m_arrayBufferContents)
   2695             return false;
   2696         if (index >= m_arrayBuffers.size())
   2697             return false;
   2698         v8::Handle<v8::Object> result = m_arrayBuffers.at(index);
   2699         if (result.IsEmpty()) {
   2700             RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(m_arrayBufferContents->at(index));
   2701             buffer->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instanceTemplate());
   2702             v8::Isolate* isolate = m_reader.scriptState()->isolate();
   2703             v8::Handle<v8::Object> creationContext = m_reader.scriptState()->context()->Global();
   2704             isolate->AdjustAmountOfExternalAllocatedMemory(buffer->byteLength());
   2705             result = toV8Object(buffer.get(), creationContext, isolate);
   2706             m_arrayBuffers[index] = result;
   2707         }
   2708         *object = result;
   2709         return true;
   2710     }
   2711 
   2712     virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle<v8::Value>* object) OVERRIDE
   2713     {
   2714         if (reference >= m_objectPool.size())
   2715             return false;
   2716         *object = m_objectPool[reference];
   2717         return object;
   2718     }
   2719 
   2720     virtual uint32_t objectReferenceCount() OVERRIDE
   2721     {
   2722         return m_objectPool.size();
   2723     }
   2724 
   2725 private:
   2726     bool initializeObject(v8::Handle<v8::Object> object, uint32_t numProperties, v8::Handle<v8::Value>* value)
   2727     {
   2728         unsigned length = 2 * numProperties;
   2729         if (length > stackDepth())
   2730             return false;
   2731         for (unsigned i = stackDepth() - length; i < stackDepth(); i += 2) {
   2732             v8::Local<v8::Value> propertyName = element(i);
   2733             v8::Local<v8::Value> propertyValue = element(i + 1);
   2734             object->Set(propertyName, propertyValue);
   2735         }
   2736         pop(length);
   2737         *value = object;
   2738         return true;
   2739     }
   2740 
   2741     bool doDeserialize()
   2742     {
   2743         v8::Local<v8::Value> value;
   2744         if (!m_reader.read(&value, *this))
   2745             return false;
   2746         if (!value.IsEmpty())
   2747             push(value);
   2748         return true;
   2749     }
   2750 
   2751     void push(v8::Local<v8::Value> value) { m_stack.append(value); }
   2752 
   2753     void pop(unsigned length)
   2754     {
   2755         ASSERT(length <= m_stack.size());
   2756         m_stack.shrink(m_stack.size() - length);
   2757     }
   2758 
   2759     unsigned stackDepth() const { return m_stack.size(); }
   2760 
   2761     v8::Local<v8::Value> element(unsigned index)
   2762     {
   2763         ASSERT_WITH_SECURITY_IMPLICATION(index < m_stack.size());
   2764         return m_stack[index];
   2765     }
   2766 
   2767     void openComposite(const v8::Local<v8::Value>& object)
   2768     {
   2769         uint32_t newObjectReference = m_objectPool.size();
   2770         m_openCompositeReferenceStack.append(newObjectReference);
   2771         m_objectPool.append(object);
   2772     }
   2773 
   2774     bool closeComposite(v8::Handle<v8::Value>* object)
   2775     {
   2776         if (!m_openCompositeReferenceStack.size())
   2777             return false;
   2778         uint32_t objectReference = m_openCompositeReferenceStack[m_openCompositeReferenceStack.size() - 1];
   2779         m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size() - 1);
   2780         if (objectReference >= m_objectPool.size())
   2781             return false;
   2782         *object = m_objectPool[objectReference];
   2783         return true;
   2784     }
   2785 
   2786     Reader& m_reader;
   2787     Vector<v8::Local<v8::Value> > m_stack;
   2788     Vector<v8::Handle<v8::Value> > m_objectPool;
   2789     Vector<uint32_t> m_openCompositeReferenceStack;
   2790     RawPtrWillBeMember<MessagePortArray> m_transferredMessagePorts;
   2791     ArrayBufferContentsArray* m_arrayBufferContents;
   2792     Vector<v8::Handle<v8::Object> > m_arrayBuffers;
   2793     uint32_t m_version;
   2794 };
   2795 
   2796 } // namespace
   2797 
   2798 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, ExceptionState& exceptionState, v8::Isolate* isolate)
   2799 {
   2800     return adoptRef(new SerializedScriptValue(value, messagePorts, arrayBuffers, 0, exceptionState, isolate));
   2801 }
   2802 
   2803 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createAndSwallowExceptions(v8::Handle<v8::Value> value, v8::Isolate* isolate)
   2804 {
   2805     TrackExceptionState exceptionState;
   2806     return adoptRef(new SerializedScriptValue(value, 0, 0, 0, exceptionState, isolate));
   2807 }
   2808 
   2809 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const ScriptValue& value, WebBlobInfoArray* blobInfo, ExceptionState& exceptionState, v8::Isolate* isolate)
   2810 {
   2811     ASSERT(isolate->InContext());
   2812     return adoptRef(new SerializedScriptValue(value.v8Value(), 0, 0, blobInfo, exceptionState, isolate));
   2813 }
   2814 
   2815 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWire(const String& data)
   2816 {
   2817     return adoptRef(new SerializedScriptValue(data));
   2818 }
   2819 
   2820 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWireBytes(const Vector<uint8_t>& data)
   2821 {
   2822     // Decode wire data from big endian to host byte order.
   2823     ASSERT(!(data.size() % sizeof(UChar)));
   2824     size_t length = data.size() / sizeof(UChar);
   2825     StringBuffer<UChar> buffer(length);
   2826     const UChar* src = reinterpret_cast<const UChar*>(data.data());
   2827     UChar* dst = buffer.characters();
   2828     for (size_t i = 0; i < length; i++)
   2829         dst[i] = ntohs(src[i]);
   2830 
   2831     return createFromWire(String::adopt(buffer));
   2832 }
   2833 
   2834 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& data)
   2835 {
   2836     return create(data, v8::Isolate::GetCurrent());
   2837 }
   2838 
   2839 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& data, v8::Isolate* isolate)
   2840 {
   2841     Writer writer;
   2842     writer.writeWebCoreString(data);
   2843     String wireData = writer.takeWireString();
   2844     return adoptRef(new SerializedScriptValue(wireData));
   2845 }
   2846 
   2847 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create()
   2848 {
   2849     return adoptRef(new SerializedScriptValue());
   2850 }
   2851 
   2852 PassRefPtr<SerializedScriptValue> SerializedScriptValue::nullValue()
   2853 {
   2854     Writer writer;
   2855     writer.writeNull();
   2856     String wireData = writer.takeWireString();
   2857     return adoptRef(new SerializedScriptValue(wireData));
   2858 }
   2859 
   2860 // Convert serialized string to big endian wire data.
   2861 void SerializedScriptValue::toWireBytes(Vector<char>& result) const
   2862 {
   2863     ASSERT(result.isEmpty());
   2864     size_t length = m_data.length();
   2865     result.resize(length * sizeof(UChar));
   2866     UChar* dst = reinterpret_cast<UChar*>(result.data());
   2867 
   2868     if (m_data.is8Bit()) {
   2869         const LChar* src = m_data.characters8();
   2870         for (size_t i = 0; i < length; i++)
   2871             dst[i] = htons(static_cast<UChar>(src[i]));
   2872     } else {
   2873         const UChar* src = m_data.characters16();
   2874         for (size_t i = 0; i < length; i++)
   2875             dst[i] = htons(src[i]);
   2876     }
   2877 }
   2878 
   2879 SerializedScriptValue::SerializedScriptValue()
   2880     : m_externallyAllocatedMemory(0)
   2881 {
   2882 }
   2883 
   2884 static void neuterArrayBufferInAllWorlds(ArrayBuffer* object)
   2885 {
   2886     v8::Isolate* isolate = v8::Isolate::GetCurrent();
   2887     if (isMainThread()) {
   2888         Vector<RefPtr<DOMWrapperWorld> > worlds;
   2889         DOMWrapperWorld::allWorldsInMainThread(worlds);
   2890         for (size_t i = 0; i < worlds.size(); i++) {
   2891             v8::Handle<v8::Object> wrapper = worlds[i]->domDataStore().get<V8ArrayBuffer>(object, isolate);
   2892             if (!wrapper.IsEmpty()) {
   2893                 ASSERT(wrapper->IsArrayBuffer());
   2894                 v8::Handle<v8::ArrayBuffer>::Cast(wrapper)->Neuter();
   2895             }
   2896         }
   2897     } else {
   2898         v8::Handle<v8::Object> wrapper = DOMWrapperWorld::current(isolate).domDataStore().get<V8ArrayBuffer>(object, isolate);
   2899         if (!wrapper.IsEmpty()) {
   2900             ASSERT(wrapper->IsArrayBuffer());
   2901             v8::Handle<v8::ArrayBuffer>::Cast(wrapper)->Neuter();
   2902         }
   2903     }
   2904 }
   2905 
   2906 PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValue::transferArrayBuffers(ArrayBufferArray& arrayBuffers, ExceptionState& exceptionState, v8::Isolate* isolate)
   2907 {
   2908     ASSERT(arrayBuffers.size());
   2909 
   2910     for (size_t i = 0; i < arrayBuffers.size(); i++) {
   2911         if (arrayBuffers[i]->isNeutered()) {
   2912             exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at index " + String::number(i) + " is already neutered.");
   2913             return nullptr;
   2914         }
   2915     }
   2916 
   2917     OwnPtr<ArrayBufferContentsArray> contents = adoptPtr(new ArrayBufferContentsArray(arrayBuffers.size()));
   2918 
   2919     HashSet<ArrayBuffer*> visited;
   2920     for (size_t i = 0; i < arrayBuffers.size(); i++) {
   2921         if (visited.contains(arrayBuffers[i].get()))
   2922             continue;
   2923         visited.add(arrayBuffers[i].get());
   2924 
   2925         bool result = arrayBuffers[i]->transfer(contents->at(i));
   2926         if (!result) {
   2927             exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at index " + String::number(i) + " could not be transferred.");
   2928             return nullptr;
   2929         }
   2930 
   2931         neuterArrayBufferInAllWorlds(arrayBuffers[i].get());
   2932     }
   2933     return contents.release();
   2934 }
   2935 
   2936 SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, WebBlobInfoArray* blobInfo, ExceptionState& exceptionState, v8::Isolate* isolate)
   2937     : m_externallyAllocatedMemory(0)
   2938 {
   2939     Writer writer;
   2940     Serializer::Status status;
   2941     String errorMessage;
   2942     {
   2943         v8::TryCatch tryCatch;
   2944         Serializer serializer(writer, messagePorts, arrayBuffers, blobInfo, m_blobDataHandles, tryCatch, ScriptState::current(isolate));
   2945         status = serializer.serialize(value);
   2946         if (status == Serializer::JSException) {
   2947             // If there was a JS exception thrown, re-throw it.
   2948             exceptionState.rethrowV8Exception(tryCatch.Exception());
   2949             return;
   2950         }
   2951         errorMessage = serializer.errorMessage();
   2952     }
   2953     switch (status) {
   2954     case Serializer::InputError:
   2955     case Serializer::DataCloneError:
   2956         exceptionState.throwDOMException(DataCloneError, errorMessage);
   2957         return;
   2958     case Serializer::Success:
   2959         m_data = writer.takeWireString();
   2960         ASSERT(m_data.impl()->hasOneRef());
   2961         if (arrayBuffers && arrayBuffers->size())
   2962             m_arrayBufferContentsArray = transferArrayBuffers(*arrayBuffers, exceptionState, isolate);
   2963         return;
   2964     case Serializer::JSException:
   2965         ASSERT_NOT_REACHED();
   2966         break;
   2967     }
   2968     ASSERT_NOT_REACHED();
   2969 }
   2970 
   2971 SerializedScriptValue::SerializedScriptValue(const String& wireData)
   2972     : m_externallyAllocatedMemory(0)
   2973 {
   2974     m_data = wireData.isolatedCopy();
   2975 }
   2976 
   2977 v8::Handle<v8::Value> SerializedScriptValue::deserialize(MessagePortArray* messagePorts)
   2978 {
   2979     return deserialize(v8::Isolate::GetCurrent(), messagePorts, 0);
   2980 }
   2981 
   2982 v8::Handle<v8::Value> SerializedScriptValue::deserialize(v8::Isolate* isolate, MessagePortArray* messagePorts, const WebBlobInfoArray* blobInfo)
   2983 {
   2984     if (!m_data.impl())
   2985         return v8::Null(isolate);
   2986     COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
   2987     m_data.ensure16Bit();
   2988     // FIXME: SerializedScriptValue shouldn't use String for its underlying
   2989     // storage. Instead, it should use SharedBuffer or Vector<uint8_t>. The
   2990     // information stored in m_data isn't even encoded in UTF-16. Instead,
   2991     // unicode characters are encoded as UTF-8 with two code units per UChar.
   2992     Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->characters16()), 2 * m_data.length(), blobInfo, m_blobDataHandles, ScriptState::current(isolate));
   2993     Deserializer deserializer(reader, messagePorts, m_arrayBufferContentsArray.get());
   2994 
   2995     // deserialize() can run arbitrary script (e.g., setters), which could result in |this| being destroyed.
   2996     // Holding a RefPtr ensures we are alive (along with our internal data) throughout the operation.
   2997     RefPtr<SerializedScriptValue> protect(this);
   2998     return deserializer.deserialize();
   2999 }
   3000 
   3001 bool SerializedScriptValue::extractTransferables(v8::Local<v8::Value> value, int argumentIndex, MessagePortArray& ports, ArrayBufferArray& arrayBuffers, ExceptionState& exceptionState, v8::Isolate* isolate)
   3002 {
   3003     if (isUndefinedOrNull(value)) {
   3004         ports.resize(0);
   3005         arrayBuffers.resize(0);
   3006         return true;
   3007     }
   3008 
   3009     uint32_t length = 0;
   3010     if (value->IsArray()) {
   3011         v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(value);
   3012         length = array->Length();
   3013     } else if (!toV8Sequence(value, length, isolate, exceptionState)) {
   3014         if (!exceptionState.hadException())
   3015             exceptionState.throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex + 1));
   3016         return false;
   3017     }
   3018 
   3019     v8::Local<v8::Object> transferrables = v8::Local<v8::Object>::Cast(value);
   3020 
   3021     // Validate the passed array of transferrables.
   3022     for (unsigned i = 0; i < length; ++i) {
   3023         v8::Local<v8::Value> transferrable = transferrables->Get(i);
   3024         // Validation of non-null objects, per HTML5 spec 10.3.3.
   3025         if (isUndefinedOrNull(transferrable)) {
   3026             exceptionState.throwDOMException(DataCloneError, "Value at index " + String::number(i) + " is an untransferable " + (transferrable->IsUndefined() ? "'undefined'" : "'null'") + " value.");
   3027             return false;
   3028         }
   3029         // Validation of Objects implementing an interface, per WebIDL spec 4.1.15.
   3030         if (V8MessagePort::hasInstance(transferrable, isolate)) {
   3031             RefPtrWillBeRawPtr<MessagePort> port = V8MessagePort::toImpl(v8::Handle<v8::Object>::Cast(transferrable));
   3032             // Check for duplicate MessagePorts.
   3033             if (ports.contains(port)) {
   3034                 exceptionState.throwDOMException(DataCloneError, "Message port at index " + String::number(i) + " is a duplicate of an earlier port.");
   3035                 return false;
   3036             }
   3037             ports.append(port.release());
   3038         } else if (V8ArrayBuffer::hasInstance(transferrable, isolate)) {
   3039             RefPtr<ArrayBuffer> arrayBuffer = V8ArrayBuffer::toImpl(v8::Handle<v8::Object>::Cast(transferrable));
   3040             if (arrayBuffers.contains(arrayBuffer)) {
   3041                 exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at index " + String::number(i) + " is a duplicate of an earlier ArrayBuffer.");
   3042                 return false;
   3043             }
   3044             arrayBuffers.append(arrayBuffer.release());
   3045         } else {
   3046             exceptionState.throwDOMException(DataCloneError, "Value at index " + String::number(i) + " does not have a transferable type.");
   3047             return false;
   3048         }
   3049     }
   3050     return true;
   3051 }
   3052 
   3053 void SerializedScriptValue::registerMemoryAllocatedWithCurrentScriptContext()
   3054 {
   3055     if (m_externallyAllocatedMemory)
   3056         return;
   3057     m_externallyAllocatedMemory = static_cast<intptr_t>(m_data.length());
   3058     v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(m_externallyAllocatedMemory);
   3059 }
   3060 
   3061 SerializedScriptValue::~SerializedScriptValue()
   3062 {
   3063     // If the allocated memory was not registered before, then this class is likely
   3064     // used in a context other then Worker's onmessage environment and the presence of
   3065     // current v8 context is not guaranteed. Avoid calling v8 then.
   3066     if (m_externallyAllocatedMemory) {
   3067         ASSERT(v8::Isolate::GetCurrent());
   3068         v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-m_externallyAllocatedMemory);
   3069     }
   3070 }
   3071 
   3072 } // namespace blink
   3073