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