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