1/*
2 * Copyright (C) 2009, 2013 Apple 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
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 */
26
27#include "config.h"
28#include "SerializedScriptValue.h"
29
30#include "Blob.h"
31#include "ExceptionCode.h"
32#include "File.h"
33#include "FileList.h"
34#include "ImageData.h"
35#include "JSArrayBuffer.h"
36#include "JSArrayBufferView.h"
37#include "JSBlob.h"
38#include "JSDataView.h"
39#include "JSDOMGlobalObject.h"
40#include "JSFile.h"
41#include "JSFileList.h"
42#include "JSFloat32Array.h"
43#include "JSFloat64Array.h"
44#include "JSImageData.h"
45#include "JSInt16Array.h"
46#include "JSInt32Array.h"
47#include "JSInt8Array.h"
48#include "JSMessagePort.h"
49#include "JSNavigator.h"
50#include "JSUint16Array.h"
51#include "JSUint32Array.h"
52#include "JSUint8Array.h"
53#include "JSUint8ClampedArray.h"
54#include "NotImplemented.h"
55#include "ScriptValue.h"
56#include "SharedBuffer.h"
57#include "WebCoreJSClientData.h"
58#include <limits>
59#include <JavaScriptCore/APICast.h>
60#include <JavaScriptCore/APIShims.h>
61#include <runtime/BooleanObject.h>
62#include <runtime/DateInstance.h>
63#include <runtime/Error.h>
64#include <runtime/ExceptionHelpers.h>
65#include <runtime/ObjectConstructor.h>
66#include <runtime/Operations.h>
67#include <runtime/PropertyNameArray.h>
68#include <runtime/RegExp.h>
69#include <runtime/RegExpObject.h>
70#include <wtf/ArrayBuffer.h>
71#include <wtf/HashTraits.h>
72#include <wtf/Uint8ClampedArray.h>
73#include <wtf/Vector.h>
74
75using namespace JSC;
76using namespace std;
77
78#if CPU(BIG_ENDIAN) || CPU(MIDDLE_ENDIAN) || CPU(NEEDS_ALIGNED_ACCESS)
79#define ASSUME_LITTLE_ENDIAN 0
80#else
81#define ASSUME_LITTLE_ENDIAN 1
82#endif
83
84namespace WebCore {
85
86static const unsigned maximumFilterRecursion = 40000;
87
88enum WalkerState { StateUnknown, ArrayStartState, ArrayStartVisitMember, ArrayEndVisitMember,
89    ObjectStartState, ObjectStartVisitMember, ObjectEndVisitMember };
90
91// These can't be reordered, and any new types must be added to the end of the list
92enum SerializationTag {
93    ArrayTag = 1,
94    ObjectTag = 2,
95    UndefinedTag = 3,
96    NullTag = 4,
97    IntTag = 5,
98    ZeroTag = 6,
99    OneTag = 7,
100    FalseTag = 8,
101    TrueTag = 9,
102    DoubleTag = 10,
103    DateTag = 11,
104    FileTag = 12,
105    FileListTag = 13,
106    ImageDataTag = 14,
107    BlobTag = 15,
108    StringTag = 16,
109    EmptyStringTag = 17,
110    RegExpTag = 18,
111    ObjectReferenceTag = 19,
112    MessagePortReferenceTag = 20,
113    ArrayBufferTag = 21,
114    ArrayBufferViewTag = 22,
115    ArrayBufferTransferTag = 23,
116    TrueObjectTag = 24,
117    FalseObjectTag = 25,
118    StringObjectTag = 26,
119    EmptyStringObjectTag = 27,
120    NumberObjectTag = 28,
121    ErrorTag = 255
122};
123
124enum ArrayBufferViewSubtag {
125    DataViewTag = 0,
126    Int8ArrayTag = 1,
127    Uint8ArrayTag = 2,
128    Uint8ClampedArrayTag = 3,
129    Int16ArrayTag = 4,
130    Uint16ArrayTag = 5,
131    Int32ArrayTag = 6,
132    Uint32ArrayTag = 7,
133    Float32ArrayTag = 8,
134    Float64ArrayTag = 9
135};
136
137static unsigned typedArrayElementSize(ArrayBufferViewSubtag tag)
138{
139    switch (tag) {
140    case DataViewTag:
141    case Int8ArrayTag:
142    case Uint8ArrayTag:
143    case Uint8ClampedArrayTag:
144        return 1;
145    case Int16ArrayTag:
146    case Uint16ArrayTag:
147        return 2;
148    case Int32ArrayTag:
149    case Uint32ArrayTag:
150    case Float32ArrayTag:
151        return 4;
152    case Float64ArrayTag:
153        return 8;
154    default:
155        return 0;
156    }
157
158}
159
160/* CurrentVersion tracks the serialization version so that persistant stores
161 * are able to correctly bail out in the case of encountering newer formats.
162 *
163 * Initial version was 1.
164 * Version 2. added the ObjectReferenceTag and support for serialization of cyclic graphs.
165 * Version 3. added the FalseObjectTag, TrueObjectTag, NumberObjectTag, StringObjectTag
166 * and EmptyStringObjectTag for serialization of Boolean, Number and String objects.
167 * Version 4. added support for serializing non-index properties of arrays.
168 */
169static const unsigned CurrentVersion = 4;
170static const unsigned TerminatorTag = 0xFFFFFFFF;
171static const unsigned StringPoolTag = 0xFFFFFFFE;
172static const unsigned NonIndexPropertiesTag = 0xFFFFFFFD;
173
174/*
175 * Object serialization is performed according to the following grammar, all tags
176 * are recorded as a single uint8_t.
177 *
178 * IndexType (used for the object pool and StringData's constant pool) is the
179 * minimum sized unsigned integer type required to represent the maximum index
180 * in the constant pool.
181 *
182 * SerializedValue :- <CurrentVersion:uint32_t> Value
183 * Value :- Array | Object | Terminal
184 *
185 * Array :-
186 *     ArrayTag <length:uint32_t>(<index:uint32_t><value:Value>)* TerminatorTag
187 *
188 * Object :-
189 *     ObjectTag (<name:StringData><value:Value>)* TerminatorTag
190 *
191 * Terminal :-
192 *      UndefinedTag
193 *    | NullTag
194 *    | IntTag <value:int32_t>
195 *    | ZeroTag
196 *    | OneTag
197 *    | FalseTag
198 *    | TrueTag
199 *    | FalseObjectTag
200 *    | TrueObjectTag
201 *    | DoubleTag <value:double>
202 *    | NumberObjectTag <value:double>
203 *    | DateTag <value:double>
204 *    | String
205 *    | EmptyStringTag
206 *    | EmptyStringObjectTag
207 *    | File
208 *    | FileList
209 *    | ImageData
210 *    | Blob
211 *    | ObjectReference
212 *    | MessagePortReferenceTag <value:uint32_t>
213 *    | ArrayBuffer
214 *    | ArrayBufferViewTag ArrayBufferViewSubtag <byteOffset:uint32_t> <byteLenght:uint32_t> (ArrayBuffer | ObjectReference)
215 *    | ArrayBufferTransferTag <value:uint32_t>
216 *
217 * String :-
218 *      EmptyStringTag
219 *      StringTag StringData
220 *
221 * StringObject:
222 *      EmptyStringObjectTag
223 *      StringObjectTag StringData
224 *
225 * StringData :-
226 *      StringPoolTag <cpIndex:IndexType>
227 *      (not (TerminatorTag | StringPoolTag))<length:uint32_t><characters:UChar{length}> // Added to constant pool when seen, string length 0xFFFFFFFF is disallowed
228 *
229 * File :-
230 *    FileTag FileData
231 *
232 * FileData :-
233 *    <path:StringData> <url:StringData> <type:StringData>
234 *
235 * FileList :-
236 *    FileListTag <length:uint32_t>(<file:FileData>){length}
237 *
238 * ImageData :-
239 *    ImageDataTag <width:int32_t><height:int32_t><length:uint32_t><data:uint8_t{length}>
240 *
241 * Blob :-
242 *    BlobTag <url:StringData><type:StringData><size:long long>
243 *
244 * RegExp :-
245 *    RegExpTag <pattern:StringData><flags:StringData>
246 *
247 * ObjectReference :-
248 *    ObjectReferenceTag <opIndex:IndexType>
249 *
250 * ArrayBuffer :-
251 *    ArrayBufferTag <length:uint32_t> <contents:byte{length}>
252 */
253
254typedef pair<JSC::JSValue, SerializationReturnCode> DeserializationResult;
255
256class CloneBase {
257protected:
258    CloneBase(ExecState* exec)
259        : m_exec(exec)
260        , m_failed(false)
261    {
262    }
263
264    bool shouldTerminate()
265    {
266        return m_exec->hadException();
267    }
268
269    void throwStackOverflow()
270    {
271        throwError(m_exec, createStackOverflowError(m_exec));
272    }
273
274    NO_RETURN_DUE_TO_ASSERT
275    void fail()
276    {
277        ASSERT_NOT_REACHED();
278        m_failed = true;
279    }
280
281    ExecState* m_exec;
282    bool m_failed;
283    MarkedArgumentBuffer m_gcBuffer;
284};
285
286#if ASSUME_LITTLE_ENDIAN
287template <typename T> static void writeLittleEndian(Vector<uint8_t>& buffer, T value)
288{
289    buffer.append(reinterpret_cast<uint8_t*>(&value), sizeof(value));
290}
291#else
292template <typename T> static void writeLittleEndian(Vector<uint8_t>& buffer, T value)
293{
294    for (unsigned i = 0; i < sizeof(T); i++) {
295        buffer.append(value & 0xFF);
296        value >>= 8;
297    }
298}
299#endif
300
301template <> void writeLittleEndian<uint8_t>(Vector<uint8_t>& buffer, uint8_t value)
302{
303    buffer.append(value);
304}
305
306template <typename T> static bool writeLittleEndian(Vector<uint8_t>& buffer, const T* values, uint32_t length)
307{
308    if (length > numeric_limits<uint32_t>::max() / sizeof(T))
309        return false;
310
311#if ASSUME_LITTLE_ENDIAN
312    buffer.append(reinterpret_cast<const uint8_t*>(values), length * sizeof(T));
313#else
314    for (unsigned i = 0; i < length; i++) {
315        T value = values[i];
316        for (unsigned j = 0; j < sizeof(T); j++) {
317            buffer.append(static_cast<uint8_t>(value & 0xFF));
318            value >>= 8;
319        }
320    }
321#endif
322    return true;
323}
324
325class CloneSerializer : CloneBase {
326public:
327    static SerializationReturnCode serialize(ExecState* exec, JSValue value,
328                                             MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers,
329                                             Vector<String>& blobURLs, Vector<uint8_t>& out)
330    {
331        CloneSerializer serializer(exec, messagePorts, arrayBuffers, blobURLs, out);
332        return serializer.serialize(value);
333    }
334
335    static bool serialize(const String& s, Vector<uint8_t>& out)
336    {
337        writeLittleEndian(out, CurrentVersion);
338        if (s.isEmpty()) {
339            writeLittleEndian<uint8_t>(out, EmptyStringTag);
340            return true;
341        }
342        writeLittleEndian<uint8_t>(out, StringTag);
343        writeLittleEndian(out, s.length());
344        return writeLittleEndian(out, s.impl()->characters(), s.length());
345    }
346
347    static void serializeUndefined(Vector<uint8_t>& out)
348    {
349        writeLittleEndian(out, CurrentVersion);
350        writeLittleEndian<uint8_t>(out, UndefinedTag);
351    }
352
353    static void serializeBoolean(bool value, Vector<uint8_t>& out)
354    {
355        writeLittleEndian(out, CurrentVersion);
356        writeLittleEndian<uint8_t>(out, value ? TrueTag : FalseTag);
357    }
358
359    static void serializeNumber(double value, Vector<uint8_t>& out)
360    {
361        writeLittleEndian(out, CurrentVersion);
362        writeLittleEndian<uint8_t>(out, DoubleTag);
363        union {
364            double d;
365            int64_t i;
366        } u;
367        u.d = value;
368        writeLittleEndian(out, u.i);
369    }
370
371private:
372    typedef HashMap<JSObject*, uint32_t> ObjectPool;
373
374    CloneSerializer(ExecState* exec, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, Vector<String>& blobURLs, Vector<uint8_t>& out)
375        : CloneBase(exec)
376        , m_buffer(out)
377        , m_blobURLs(blobURLs)
378        , m_emptyIdentifier(exec, emptyString())
379    {
380        write(CurrentVersion);
381        fillTransferMap(messagePorts, m_transferredMessagePorts);
382        fillTransferMap(arrayBuffers, m_transferredArrayBuffers);
383    }
384
385    template <class T>
386    void fillTransferMap(Vector<RefPtr<T>, 1>* input, ObjectPool& result)
387    {
388        if (!input)
389            return;
390        JSDOMGlobalObject* globalObject = jsCast<JSDOMGlobalObject*>(m_exec->lexicalGlobalObject());
391        for (size_t i = 0; i < input->size(); i++) {
392            JSC::JSValue value = toJS(m_exec, globalObject, input->at(i).get());
393            JSC::JSObject* obj = value.getObject();
394            if (obj && !result.contains(obj))
395                result.add(obj, i);
396        }
397    }
398
399    SerializationReturnCode serialize(JSValue in);
400
401    bool isArray(JSValue value)
402    {
403        if (!value.isObject())
404            return false;
405        JSObject* object = asObject(value);
406        return isJSArray(object) || object->inherits(&JSArray::s_info);
407    }
408
409    bool checkForDuplicate(JSObject* object)
410    {
411        // Record object for graph reconstruction
412        ObjectPool::const_iterator found = m_objectPool.find(object);
413
414        // Handle duplicate references
415        if (found != m_objectPool.end()) {
416            write(ObjectReferenceTag);
417            ASSERT(static_cast<int32_t>(found->value) < m_objectPool.size());
418            writeObjectIndex(found->value);
419            return true;
420        }
421
422        return false;
423    }
424
425    void recordObject(JSObject* object)
426    {
427        m_objectPool.add(object, m_objectPool.size());
428        m_gcBuffer.append(object);
429    }
430
431    bool startObjectInternal(JSObject* object)
432    {
433        if (checkForDuplicate(object))
434            return false;
435        recordObject(object);
436        return true;
437    }
438
439    bool startObject(JSObject* object)
440    {
441        if (!startObjectInternal(object))
442            return false;
443        write(ObjectTag);
444        return true;
445    }
446
447    bool startArray(JSArray* array)
448    {
449        if (!startObjectInternal(array))
450            return false;
451
452        unsigned length = array->length();
453        write(ArrayTag);
454        write(length);
455        return true;
456    }
457
458    void endObject()
459    {
460        write(TerminatorTag);
461    }
462
463    JSValue getProperty(JSObject* object, const Identifier& propertyName)
464    {
465        PropertySlot slot(object);
466        if (object->methodTable()->getOwnPropertySlot(object, m_exec, propertyName, slot))
467            return slot.getValue(m_exec, propertyName);
468        return JSValue();
469    }
470
471    void dumpImmediate(JSValue value)
472    {
473        if (value.isNull())
474            write(NullTag);
475        else if (value.isUndefined())
476            write(UndefinedTag);
477        else if (value.isNumber()) {
478            if (value.isInt32()) {
479                if (!value.asInt32())
480                    write(ZeroTag);
481                else if (value.asInt32() == 1)
482                    write(OneTag);
483                else {
484                    write(IntTag);
485                    write(static_cast<uint32_t>(value.asInt32()));
486                }
487            } else {
488                write(DoubleTag);
489                write(value.asDouble());
490            }
491        } else if (value.isBoolean()) {
492            if (value.isTrue())
493                write(TrueTag);
494            else
495                write(FalseTag);
496        }
497    }
498
499    void dumpString(String str)
500    {
501        if (str.isEmpty())
502            write(EmptyStringTag);
503        else {
504            write(StringTag);
505            write(str);
506        }
507    }
508
509    void dumpStringObject(String str)
510    {
511        if (str.isEmpty())
512            write(EmptyStringObjectTag);
513        else {
514            write(StringObjectTag);
515            write(str);
516        }
517    }
518
519    bool dumpArrayBufferView(JSObject* obj, SerializationReturnCode& code)
520    {
521        write(ArrayBufferViewTag);
522        if (obj->inherits(&JSDataView::s_info))
523            write(DataViewTag);
524        else if (obj->inherits(&JSUint8ClampedArray::s_info))
525            write(Uint8ClampedArrayTag);
526        else if (obj->inherits(&JSInt8Array::s_info))
527            write(Int8ArrayTag);
528        else if (obj->inherits(&JSUint8Array::s_info))
529            write(Uint8ArrayTag);
530        else if (obj->inherits(&JSInt16Array::s_info))
531            write(Int16ArrayTag);
532        else if (obj->inherits(&JSUint16Array::s_info))
533            write(Uint16ArrayTag);
534        else if (obj->inherits(&JSInt32Array::s_info))
535            write(Int32ArrayTag);
536        else if (obj->inherits(&JSUint32Array::s_info))
537            write(Uint32ArrayTag);
538        else if (obj->inherits(&JSFloat32Array::s_info))
539            write(Float32ArrayTag);
540        else if (obj->inherits(&JSFloat64Array::s_info))
541            write(Float64ArrayTag);
542        else
543            return false;
544
545        RefPtr<ArrayBufferView> arrayBufferView = toArrayBufferView(obj);
546        write(static_cast<uint32_t>(arrayBufferView->byteOffset()));
547        write(static_cast<uint32_t>(arrayBufferView->byteLength()));
548        RefPtr<ArrayBuffer> arrayBuffer = arrayBufferView->buffer();
549        if (!arrayBuffer) {
550            code = ValidationError;
551            return true;
552        }
553        JSValue bufferObj = toJS(m_exec, jsCast<JSDOMGlobalObject*>(m_exec->lexicalGlobalObject()), arrayBuffer.get());
554        return dumpIfTerminal(bufferObj, code);
555    }
556
557    bool dumpIfTerminal(JSValue value, SerializationReturnCode& code)
558    {
559        if (!value.isCell()) {
560            dumpImmediate(value);
561            return true;
562        }
563
564        if (value.isString()) {
565            String str = asString(value)->value(m_exec);
566            dumpString(str);
567            return true;
568        }
569
570        if (value.isNumber()) {
571            write(DoubleTag);
572            write(value.asNumber());
573            return true;
574        }
575
576        if (value.isObject() && asObject(value)->inherits(&DateInstance::s_info)) {
577            write(DateTag);
578            write(asDateInstance(value)->internalNumber());
579            return true;
580        }
581
582        if (isArray(value))
583            return false;
584
585        if (value.isObject()) {
586            JSObject* obj = asObject(value);
587            if (obj->inherits(&BooleanObject::s_info)) {
588                if (!startObjectInternal(obj)) // handle duplicates
589                    return true;
590                write(asBooleanObject(value)->internalValue().toBoolean(m_exec) ? TrueObjectTag : FalseObjectTag);
591                return true;
592            }
593            if (obj->inherits(&StringObject::s_info)) {
594                if (!startObjectInternal(obj)) // handle duplicates
595                    return true;
596                String str = asString(asStringObject(value)->internalValue())->value(m_exec);
597                dumpStringObject(str);
598                return true;
599            }
600            if (obj->inherits(&NumberObject::s_info)) {
601                if (!startObjectInternal(obj)) // handle duplicates
602                    return true;
603                write(NumberObjectTag);
604                NumberObject* obj = static_cast<NumberObject*>(asObject(value));
605                write(obj->internalValue().asNumber());
606                return true;
607            }
608            if (obj->inherits(&JSFile::s_info)) {
609                write(FileTag);
610                write(toFile(obj));
611                return true;
612            }
613            if (obj->inherits(&JSFileList::s_info)) {
614                FileList* list = toFileList(obj);
615                write(FileListTag);
616                unsigned length = list->length();
617                write(length);
618                for (unsigned i = 0; i < length; i++)
619                    write(list->item(i));
620                return true;
621            }
622            if (obj->inherits(&JSBlob::s_info)) {
623                write(BlobTag);
624                Blob* blob = toBlob(obj);
625                m_blobURLs.append(blob->url());
626                write(blob->url());
627                write(blob->type());
628                write(blob->size());
629                return true;
630            }
631            if (obj->inherits(&JSImageData::s_info)) {
632                ImageData* data = toImageData(obj);
633                write(ImageDataTag);
634                write(data->width());
635                write(data->height());
636                write(data->data()->length());
637                write(data->data()->data(), data->data()->length());
638                return true;
639            }
640            if (obj->inherits(&RegExpObject::s_info)) {
641                RegExpObject* regExp = asRegExpObject(obj);
642                char flags[3];
643                int flagCount = 0;
644                if (regExp->regExp()->global())
645                    flags[flagCount++] = 'g';
646                if (regExp->regExp()->ignoreCase())
647                    flags[flagCount++] = 'i';
648                if (regExp->regExp()->multiline())
649                    flags[flagCount++] = 'm';
650                write(RegExpTag);
651                write(regExp->regExp()->pattern());
652                write(String(flags, flagCount));
653                return true;
654            }
655            if (obj->inherits(&JSMessagePort::s_info)) {
656                ObjectPool::iterator index = m_transferredMessagePorts.find(obj);
657                if (index != m_transferredMessagePorts.end()) {
658                    write(MessagePortReferenceTag);
659                    write(index->value);
660                    return true;
661                }
662                // MessagePort object could not be found in transferred message ports
663                code = ValidationError;
664                return true;
665            }
666            if (obj->inherits(&JSArrayBuffer::s_info)) {
667                RefPtr<ArrayBuffer> arrayBuffer = toArrayBuffer(obj);
668                if (arrayBuffer->isNeutered()) {
669                    code = ValidationError;
670                    return true;
671                }
672                ObjectPool::iterator index = m_transferredArrayBuffers.find(obj);
673                if (index != m_transferredArrayBuffers.end()) {
674                    write(ArrayBufferTransferTag);
675                    write(index->value);
676                    return true;
677                }
678                if (!startObjectInternal(obj)) // handle duplicates
679                    return true;
680                write(ArrayBufferTag);
681                write(arrayBuffer->byteLength());
682                write(static_cast<const uint8_t *>(arrayBuffer->data()), arrayBuffer->byteLength());
683                return true;
684            }
685            if (obj->inherits(&JSArrayBufferView::s_info)) {
686                if (checkForDuplicate(obj))
687                    return true;
688                bool success = dumpArrayBufferView(obj, code);
689                recordObject(obj);
690                return success;
691            }
692
693            return false;
694        }
695        // Any other types are expected to serialize as null.
696        write(NullTag);
697        return true;
698    }
699
700    void write(SerializationTag tag)
701    {
702        writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag));
703    }
704
705    void write(ArrayBufferViewSubtag tag)
706    {
707        writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag));
708    }
709
710    void write(uint8_t c)
711    {
712        writeLittleEndian(m_buffer, c);
713    }
714
715    void write(uint32_t i)
716    {
717        writeLittleEndian(m_buffer, i);
718    }
719
720    void write(double d)
721    {
722        union {
723            double d;
724            int64_t i;
725        } u;
726        u.d = d;
727        writeLittleEndian(m_buffer, u.i);
728    }
729
730    void write(int32_t i)
731    {
732        writeLittleEndian(m_buffer, i);
733    }
734
735    void write(unsigned long long i)
736    {
737        writeLittleEndian(m_buffer, i);
738    }
739
740    void write(uint16_t ch)
741    {
742        writeLittleEndian(m_buffer, ch);
743    }
744
745    void writeStringIndex(unsigned i)
746    {
747        writeConstantPoolIndex(m_constantPool, i);
748    }
749
750    void writeObjectIndex(unsigned i)
751    {
752        writeConstantPoolIndex(m_objectPool, i);
753    }
754
755    template <class T> void writeConstantPoolIndex(const T& constantPool, unsigned i)
756    {
757        ASSERT(static_cast<int32_t>(i) < constantPool.size());
758        if (constantPool.size() <= 0xFF)
759            write(static_cast<uint8_t>(i));
760        else if (constantPool.size() <= 0xFFFF)
761            write(static_cast<uint16_t>(i));
762        else
763            write(static_cast<uint32_t>(i));
764    }
765
766    void write(const Identifier& ident)
767    {
768        const String& str = ident.string();
769        StringConstantPool::AddResult addResult = m_constantPool.add(str.impl(), m_constantPool.size());
770        if (!addResult.isNewEntry) {
771            write(StringPoolTag);
772            writeStringIndex(addResult.iterator->value);
773            return;
774        }
775
776        // This condition is unlikely to happen as they would imply an ~8gb
777        // string but we should guard against it anyway
778        if (str.length() >= StringPoolTag) {
779            fail();
780            return;
781        }
782
783        // Guard against overflow
784        if (str.length() > (numeric_limits<uint32_t>::max() - sizeof(uint32_t)) / sizeof(UChar)) {
785            fail();
786            return;
787        }
788
789        writeLittleEndian<uint32_t>(m_buffer, str.length());
790        if (!writeLittleEndian<uint16_t>(m_buffer, reinterpret_cast<const uint16_t*>(str.characters()), str.length()))
791            fail();
792    }
793
794    void write(const String& str)
795    {
796        if (str.isNull())
797            write(m_emptyIdentifier);
798        else
799            write(Identifier(m_exec, str));
800    }
801
802    void write(const File* file)
803    {
804        m_blobURLs.append(file->url());
805        write(file->path());
806        write(file->url());
807        write(file->type());
808    }
809
810    void write(const uint8_t* data, unsigned length)
811    {
812        m_buffer.append(data, length);
813    }
814
815    Vector<uint8_t>& m_buffer;
816    Vector<String>& m_blobURLs;
817    ObjectPool m_objectPool;
818    ObjectPool m_transferredMessagePorts;
819    ObjectPool m_transferredArrayBuffers;
820    typedef HashMap<RefPtr<StringImpl>, uint32_t, IdentifierRepHash> StringConstantPool;
821    StringConstantPool m_constantPool;
822    Identifier m_emptyIdentifier;
823};
824
825SerializationReturnCode CloneSerializer::serialize(JSValue in)
826{
827    Vector<uint32_t, 16> indexStack;
828    Vector<uint32_t, 16> lengthStack;
829    Vector<PropertyNameArray, 16> propertyStack;
830    Vector<JSObject*, 32> inputObjectStack;
831    Vector<WalkerState, 16> stateStack;
832    WalkerState state = StateUnknown;
833    JSValue inValue = in;
834    while (1) {
835        switch (state) {
836            arrayStartState:
837            case ArrayStartState: {
838                ASSERT(isArray(inValue));
839                if (inputObjectStack.size() > maximumFilterRecursion)
840                    return StackOverflowError;
841
842                JSArray* inArray = asArray(inValue);
843                unsigned length = inArray->length();
844                if (!startArray(inArray))
845                    break;
846                inputObjectStack.append(inArray);
847                indexStack.append(0);
848                lengthStack.append(length);
849                // fallthrough
850            }
851            arrayStartVisitMember:
852            case ArrayStartVisitMember: {
853                JSObject* array = inputObjectStack.last();
854                uint32_t index = indexStack.last();
855                if (index == lengthStack.last()) {
856                    indexStack.removeLast();
857                    lengthStack.removeLast();
858
859                    propertyStack.append(PropertyNameArray(m_exec));
860                    array->methodTable()->getOwnNonIndexPropertyNames(array, m_exec, propertyStack.last(), ExcludeDontEnumProperties);
861                    if (propertyStack.last().size()) {
862                        write(NonIndexPropertiesTag);
863                        indexStack.append(0);
864                        goto objectStartVisitMember;
865                    }
866                    propertyStack.removeLast();
867
868                    endObject();
869                    inputObjectStack.removeLast();
870                    break;
871                }
872                inValue = array->getDirectIndex(m_exec, index);
873                if (!inValue) {
874                    indexStack.last()++;
875                    goto arrayStartVisitMember;
876                }
877
878                write(index);
879                SerializationReturnCode terminalCode = SuccessfullyCompleted;
880                if (dumpIfTerminal(inValue, terminalCode)) {
881                    if (terminalCode != SuccessfullyCompleted)
882                        return terminalCode;
883                    indexStack.last()++;
884                    goto arrayStartVisitMember;
885                }
886                stateStack.append(ArrayEndVisitMember);
887                goto stateUnknown;
888            }
889            case ArrayEndVisitMember: {
890                indexStack.last()++;
891                goto arrayStartVisitMember;
892            }
893            objectStartState:
894            case ObjectStartState: {
895                ASSERT(inValue.isObject());
896                if (inputObjectStack.size() > maximumFilterRecursion)
897                    return StackOverflowError;
898                JSObject* inObject = asObject(inValue);
899                if (!startObject(inObject))
900                    break;
901                // At this point, all supported objects other than Object
902                // objects have been handled. If we reach this point and
903                // the input is not an Object object then we should throw
904                // a DataCloneError.
905                if (inObject->classInfo() != &JSFinalObject::s_info)
906                    return DataCloneError;
907                inputObjectStack.append(inObject);
908                indexStack.append(0);
909                propertyStack.append(PropertyNameArray(m_exec));
910                inObject->methodTable()->getOwnPropertyNames(inObject, m_exec, propertyStack.last(), ExcludeDontEnumProperties);
911                // fallthrough
912            }
913            objectStartVisitMember:
914            case ObjectStartVisitMember: {
915                JSObject* object = inputObjectStack.last();
916                uint32_t index = indexStack.last();
917                PropertyNameArray& properties = propertyStack.last();
918                if (index == properties.size()) {
919                    endObject();
920                    inputObjectStack.removeLast();
921                    indexStack.removeLast();
922                    propertyStack.removeLast();
923                    break;
924                }
925                inValue = getProperty(object, properties[index]);
926                if (shouldTerminate())
927                    return ExistingExceptionError;
928
929                if (!inValue) {
930                    // Property was removed during serialisation
931                    indexStack.last()++;
932                    goto objectStartVisitMember;
933                }
934                write(properties[index]);
935
936                if (shouldTerminate())
937                    return ExistingExceptionError;
938
939                SerializationReturnCode terminalCode = SuccessfullyCompleted;
940                if (!dumpIfTerminal(inValue, terminalCode)) {
941                    stateStack.append(ObjectEndVisitMember);
942                    goto stateUnknown;
943                }
944                if (terminalCode != SuccessfullyCompleted)
945                    return terminalCode;
946                // fallthrough
947            }
948            case ObjectEndVisitMember: {
949                if (shouldTerminate())
950                    return ExistingExceptionError;
951
952                indexStack.last()++;
953                goto objectStartVisitMember;
954            }
955            stateUnknown:
956            case StateUnknown: {
957                SerializationReturnCode terminalCode = SuccessfullyCompleted;
958                if (dumpIfTerminal(inValue, terminalCode)) {
959                    if (terminalCode != SuccessfullyCompleted)
960                        return terminalCode;
961                    break;
962                }
963
964                if (isArray(inValue))
965                    goto arrayStartState;
966                goto objectStartState;
967            }
968        }
969        if (stateStack.isEmpty())
970            break;
971
972        state = stateStack.last();
973        stateStack.removeLast();
974    }
975    if (m_failed)
976        return UnspecifiedError;
977
978    return SuccessfullyCompleted;
979}
980
981typedef Vector<WTF::ArrayBufferContents> ArrayBufferContentsArray;
982
983class CloneDeserializer : CloneBase {
984public:
985    static String deserializeString(const Vector<uint8_t>& buffer)
986    {
987        if (buffer.isEmpty())
988            return String();
989        const uint8_t* ptr = buffer.begin();
990        const uint8_t* end = buffer.end();
991        uint32_t version;
992        if (!readLittleEndian(ptr, end, version) || version > CurrentVersion)
993            return String();
994        uint8_t tag;
995        if (!readLittleEndian(ptr, end, tag) || tag != StringTag)
996            return String();
997        uint32_t length;
998        if (!readLittleEndian(ptr, end, length) || length >= StringPoolTag)
999            return String();
1000        String str;
1001        if (!readString(ptr, end, str, length))
1002            return String();
1003        return String(str.impl());
1004    }
1005
1006    static DeserializationResult deserialize(ExecState* exec, JSGlobalObject* globalObject,
1007                                             MessagePortArray* messagePorts, ArrayBufferContentsArray* arrayBufferContentsArray,
1008                                             const Vector<uint8_t>& buffer)
1009    {
1010        if (!buffer.size())
1011            return make_pair(jsNull(), UnspecifiedError);
1012        CloneDeserializer deserializer(exec, globalObject, messagePorts, arrayBufferContentsArray, buffer);
1013        if (!deserializer.isValid())
1014            return make_pair(JSValue(), ValidationError);
1015        return deserializer.deserialize();
1016    }
1017
1018private:
1019    struct CachedString {
1020        CachedString(const String& string)
1021            : m_string(string)
1022        {
1023        }
1024
1025        JSValue jsString(ExecState* exec)
1026        {
1027            if (!m_jsString)
1028                m_jsString = JSC::jsString(exec, m_string);
1029            return m_jsString;
1030        }
1031        const String& string() { return m_string; }
1032
1033    private:
1034        String m_string;
1035        JSValue m_jsString;
1036    };
1037
1038    struct CachedStringRef {
1039        CachedStringRef()
1040            : m_base(0)
1041            , m_index(0)
1042        {
1043        }
1044        CachedStringRef(Vector<CachedString>* base, size_t index)
1045            : m_base(base)
1046            , m_index(index)
1047        {
1048        }
1049
1050        CachedString* operator->() { ASSERT(m_base); return &m_base->at(m_index); }
1051
1052    private:
1053        Vector<CachedString>* m_base;
1054        size_t m_index;
1055    };
1056
1057    CloneDeserializer(ExecState* exec, JSGlobalObject* globalObject,
1058                      MessagePortArray* messagePorts, ArrayBufferContentsArray* arrayBufferContents,
1059                      const Vector<uint8_t>& buffer)
1060        : CloneBase(exec)
1061        , m_globalObject(globalObject)
1062        , m_isDOMGlobalObject(globalObject->inherits(&JSDOMGlobalObject::s_info))
1063        , m_ptr(buffer.data())
1064        , m_end(buffer.data() + buffer.size())
1065        , m_version(0xFFFFFFFF)
1066        , m_messagePorts(messagePorts)
1067        , m_arrayBufferContents(arrayBufferContents)
1068        , m_arrayBuffers(arrayBufferContents ? arrayBufferContents->size() : 0)
1069    {
1070        if (!read(m_version))
1071            m_version = 0xFFFFFFFF;
1072    }
1073
1074    DeserializationResult deserialize();
1075
1076    void throwValidationError()
1077    {
1078        throwError(m_exec, createTypeError(m_exec, "Unable to deserialize data."));
1079    }
1080
1081    bool isValid() const { return m_version <= CurrentVersion; }
1082
1083    template <typename T> bool readLittleEndian(T& value)
1084    {
1085        if (m_failed || !readLittleEndian(m_ptr, m_end, value)) {
1086            fail();
1087            return false;
1088        }
1089        return true;
1090    }
1091#if ASSUME_LITTLE_ENDIAN
1092    template <typename T> static bool readLittleEndian(const uint8_t*& ptr, const uint8_t* end, T& value)
1093    {
1094        if (ptr > end - sizeof(value))
1095            return false;
1096
1097        if (sizeof(T) == 1)
1098            value = *ptr++;
1099        else {
1100            value = *reinterpret_cast<const T*>(ptr);
1101            ptr += sizeof(T);
1102        }
1103        return true;
1104    }
1105#else
1106    template <typename T> static bool readLittleEndian(const uint8_t*& ptr, const uint8_t* end, T& value)
1107    {
1108        if (ptr > end - sizeof(value))
1109            return false;
1110
1111        if (sizeof(T) == 1)
1112            value = *ptr++;
1113        else {
1114            value = 0;
1115            for (unsigned i = 0; i < sizeof(T); i++)
1116                value += ((T)*ptr++) << (i * 8);
1117        }
1118        return true;
1119    }
1120#endif
1121
1122    bool read(uint32_t& i)
1123    {
1124        return readLittleEndian(i);
1125    }
1126
1127    bool read(int32_t& i)
1128    {
1129        return readLittleEndian(*reinterpret_cast<uint32_t*>(&i));
1130    }
1131
1132    bool read(uint16_t& i)
1133    {
1134        return readLittleEndian(i);
1135    }
1136
1137    bool read(uint8_t& i)
1138    {
1139        return readLittleEndian(i);
1140    }
1141
1142    bool read(double& d)
1143    {
1144        union {
1145            double d;
1146            uint64_t i64;
1147        } u;
1148        if (!readLittleEndian(u.i64))
1149            return false;
1150        d = u.d;
1151        return true;
1152    }
1153
1154    bool read(unsigned long long& i)
1155    {
1156        return readLittleEndian(i);
1157    }
1158
1159    bool readStringIndex(uint32_t& i)
1160    {
1161        return readConstantPoolIndex(m_constantPool, i);
1162    }
1163
1164    template <class T> bool readConstantPoolIndex(const T& constantPool, uint32_t& i)
1165    {
1166        if (constantPool.size() <= 0xFF) {
1167            uint8_t i8;
1168            if (!read(i8))
1169                return false;
1170            i = i8;
1171            return true;
1172        }
1173        if (constantPool.size() <= 0xFFFF) {
1174            uint16_t i16;
1175            if (!read(i16))
1176                return false;
1177            i = i16;
1178            return true;
1179        }
1180        return read(i);
1181    }
1182
1183    static bool readString(const uint8_t*& ptr, const uint8_t* end, String& str, unsigned length)
1184    {
1185        if (length >= numeric_limits<int32_t>::max() / sizeof(UChar))
1186            return false;
1187
1188        unsigned size = length * sizeof(UChar);
1189        if ((end - ptr) < static_cast<int>(size))
1190            return false;
1191
1192#if ASSUME_LITTLE_ENDIAN
1193        str = String(reinterpret_cast<const UChar*>(ptr), length);
1194        ptr += length * sizeof(UChar);
1195#else
1196        Vector<UChar> buffer;
1197        buffer.reserveCapacity(length);
1198        for (unsigned i = 0; i < length; i++) {
1199            uint16_t ch;
1200            readLittleEndian(ptr, end, ch);
1201            buffer.append(ch);
1202        }
1203        str = String::adopt(buffer);
1204#endif
1205        return true;
1206    }
1207
1208    bool readStringData(CachedStringRef& cachedString)
1209    {
1210        bool scratch;
1211        return readStringData(cachedString, scratch);
1212    }
1213
1214    bool readStringData(CachedStringRef& cachedString, bool& wasTerminator)
1215    {
1216        if (m_failed)
1217            return false;
1218        uint32_t length = 0;
1219        if (!read(length))
1220            return false;
1221        if (length == TerminatorTag) {
1222            wasTerminator = true;
1223            return false;
1224        }
1225        if (length == StringPoolTag) {
1226            unsigned index = 0;
1227            if (!readStringIndex(index)) {
1228                fail();
1229                return false;
1230            }
1231            if (index >= m_constantPool.size()) {
1232                fail();
1233                return false;
1234            }
1235            cachedString = CachedStringRef(&m_constantPool, index);
1236            return true;
1237        }
1238        String str;
1239        if (!readString(m_ptr, m_end, str, length)) {
1240            fail();
1241            return false;
1242        }
1243        m_constantPool.append(str);
1244        cachedString = CachedStringRef(&m_constantPool, m_constantPool.size() - 1);
1245        return true;
1246    }
1247
1248    SerializationTag readTag()
1249    {
1250        if (m_ptr >= m_end)
1251            return ErrorTag;
1252        return static_cast<SerializationTag>(*m_ptr++);
1253    }
1254
1255    bool readArrayBufferViewSubtag(ArrayBufferViewSubtag& tag)
1256    {
1257        if (m_ptr >= m_end)
1258            return false;
1259        tag = static_cast<ArrayBufferViewSubtag>(*m_ptr++);
1260        return true;
1261    }
1262
1263    void putProperty(JSObject* object, unsigned index, JSValue value)
1264    {
1265        object->putDirectIndex(m_exec, index, value);
1266    }
1267
1268    void putProperty(JSObject* object, const Identifier& property, JSValue value)
1269    {
1270        object->putDirectMayBeIndex(m_exec, property, value);
1271    }
1272
1273    bool readFile(RefPtr<File>& file)
1274    {
1275        CachedStringRef path;
1276        if (!readStringData(path))
1277            return 0;
1278        CachedStringRef url;
1279        if (!readStringData(url))
1280            return 0;
1281        CachedStringRef type;
1282        if (!readStringData(type))
1283            return 0;
1284        if (m_isDOMGlobalObject)
1285            file = File::create(path->string(), KURL(KURL(), url->string()), type->string());
1286        return true;
1287    }
1288
1289    bool readArrayBuffer(RefPtr<ArrayBuffer>& arrayBuffer)
1290    {
1291        uint32_t length;
1292        if (!read(length))
1293            return false;
1294        if (m_ptr + length > m_end)
1295            return false;
1296        arrayBuffer = ArrayBuffer::create(m_ptr, length);
1297        m_ptr += length;
1298        return true;
1299    }
1300
1301    bool readArrayBufferView(JSValue& arrayBufferView)
1302    {
1303        ArrayBufferViewSubtag arrayBufferViewSubtag;
1304        if (!readArrayBufferViewSubtag(arrayBufferViewSubtag))
1305            return false;
1306        uint32_t byteOffset;
1307        if (!read(byteOffset))
1308            return false;
1309        uint32_t byteLength;
1310        if (!read(byteLength))
1311            return false;
1312        JSObject* arrayBufferObj = asObject(readTerminal());
1313        if (!arrayBufferObj || !arrayBufferObj->inherits(&JSArrayBuffer::s_info))
1314            return false;
1315
1316        unsigned elementSize = typedArrayElementSize(arrayBufferViewSubtag);
1317        if (!elementSize)
1318            return false;
1319        unsigned length = byteLength / elementSize;
1320        if (length * elementSize != byteLength)
1321            return false;
1322
1323        RefPtr<ArrayBuffer> arrayBuffer = toArrayBuffer(arrayBufferObj);
1324        switch (arrayBufferViewSubtag) {
1325        case DataViewTag:
1326            arrayBufferView = getJSValue(DataView::create(arrayBuffer, byteOffset, length).get());
1327            return true;
1328        case Int8ArrayTag:
1329            arrayBufferView = getJSValue(Int8Array::create(arrayBuffer, byteOffset, length).get());
1330            return true;
1331        case Uint8ArrayTag:
1332            arrayBufferView = getJSValue(Uint8Array::create(arrayBuffer, byteOffset, length).get());
1333            return true;
1334        case Uint8ClampedArrayTag:
1335            arrayBufferView = getJSValue(Uint8ClampedArray::create(arrayBuffer, byteOffset, length).get());
1336            return true;
1337        case Int16ArrayTag:
1338            arrayBufferView = getJSValue(Int16Array::create(arrayBuffer, byteOffset, length).get());
1339            return true;
1340        case Uint16ArrayTag:
1341            arrayBufferView = getJSValue(Uint16Array::create(arrayBuffer, byteOffset, length).get());
1342            return true;
1343        case Int32ArrayTag:
1344            arrayBufferView = getJSValue(Int32Array::create(arrayBuffer, byteOffset, length).get());
1345            return true;
1346        case Uint32ArrayTag:
1347            arrayBufferView = getJSValue(Uint32Array::create(arrayBuffer, byteOffset, length).get());
1348            return true;
1349        case Float32ArrayTag:
1350            arrayBufferView = getJSValue(Float32Array::create(arrayBuffer, byteOffset, length).get());
1351            return true;
1352        case Float64ArrayTag:
1353            arrayBufferView = getJSValue(Float64Array::create(arrayBuffer, byteOffset, length).get());
1354            return true;
1355        default:
1356            return false;
1357        }
1358    }
1359
1360    template<class T>
1361    JSValue getJSValue(T* nativeObj)
1362    {
1363        return toJS(m_exec, jsCast<JSDOMGlobalObject*>(m_globalObject), nativeObj);
1364    }
1365
1366    JSValue readTerminal()
1367    {
1368        SerializationTag tag = readTag();
1369        switch (tag) {
1370        case UndefinedTag:
1371            return jsUndefined();
1372        case NullTag:
1373            return jsNull();
1374        case IntTag: {
1375            int32_t i;
1376            if (!read(i))
1377                return JSValue();
1378            return jsNumber(i);
1379        }
1380        case ZeroTag:
1381            return jsNumber(0);
1382        case OneTag:
1383            return jsNumber(1);
1384        case FalseTag:
1385            return jsBoolean(false);
1386        case TrueTag:
1387            return jsBoolean(true);
1388        case FalseObjectTag: {
1389            BooleanObject* obj = BooleanObject::create(m_exec->vm(), m_globalObject->booleanObjectStructure());
1390            obj->setInternalValue(m_exec->vm(), jsBoolean(false));
1391            m_gcBuffer.append(obj);
1392            return obj;
1393        }
1394        case TrueObjectTag: {
1395            BooleanObject* obj = BooleanObject::create(m_exec->vm(), m_globalObject->booleanObjectStructure());
1396            obj->setInternalValue(m_exec->vm(), jsBoolean(true));
1397             m_gcBuffer.append(obj);
1398            return obj;
1399        }
1400        case DoubleTag: {
1401            double d;
1402            if (!read(d))
1403                return JSValue();
1404            return jsNumber(d);
1405        }
1406        case NumberObjectTag: {
1407            double d;
1408            if (!read(d))
1409                return JSValue();
1410            NumberObject* obj = constructNumber(m_exec, m_globalObject, jsNumber(d));
1411            m_gcBuffer.append(obj);
1412            return obj;
1413        }
1414        case DateTag: {
1415            double d;
1416            if (!read(d))
1417                return JSValue();
1418            return DateInstance::create(m_exec, m_globalObject->dateStructure(), d);
1419        }
1420        case FileTag: {
1421            RefPtr<File> file;
1422            if (!readFile(file))
1423                return JSValue();
1424            if (!m_isDOMGlobalObject)
1425                return jsNull();
1426            return toJS(m_exec, jsCast<JSDOMGlobalObject*>(m_globalObject), file.get());
1427        }
1428        case FileListTag: {
1429            unsigned length = 0;
1430            if (!read(length))
1431                return JSValue();
1432            RefPtr<FileList> result = FileList::create();
1433            for (unsigned i = 0; i < length; i++) {
1434                RefPtr<File> file;
1435                if (!readFile(file))
1436                    return JSValue();
1437                if (m_isDOMGlobalObject)
1438                    result->append(file.get());
1439            }
1440            if (!m_isDOMGlobalObject)
1441                return jsNull();
1442            return getJSValue(result.get());
1443        }
1444        case ImageDataTag: {
1445            int32_t width;
1446            if (!read(width))
1447                return JSValue();
1448            int32_t height;
1449            if (!read(height))
1450                return JSValue();
1451            uint32_t length;
1452            if (!read(length))
1453                return JSValue();
1454            if (m_end < ((uint8_t*)0) + length || m_ptr > m_end - length) {
1455                fail();
1456                return JSValue();
1457            }
1458            if (!m_isDOMGlobalObject) {
1459                m_ptr += length;
1460                return jsNull();
1461            }
1462            RefPtr<ImageData> result = ImageData::create(IntSize(width, height));
1463            memcpy(result->data()->data(), m_ptr, length);
1464            m_ptr += length;
1465            return getJSValue(result.get());
1466        }
1467        case BlobTag: {
1468            CachedStringRef url;
1469            if (!readStringData(url))
1470                return JSValue();
1471            CachedStringRef type;
1472            if (!readStringData(type))
1473                return JSValue();
1474            unsigned long long size = 0;
1475            if (!read(size))
1476                return JSValue();
1477            if (!m_isDOMGlobalObject)
1478                return jsNull();
1479            return getJSValue(Blob::create(KURL(KURL(), url->string()), type->string(), size).get());
1480        }
1481        case StringTag: {
1482            CachedStringRef cachedString;
1483            if (!readStringData(cachedString))
1484                return JSValue();
1485            return cachedString->jsString(m_exec);
1486        }
1487        case EmptyStringTag:
1488            return jsEmptyString(&m_exec->vm());
1489        case StringObjectTag: {
1490            CachedStringRef cachedString;
1491            if (!readStringData(cachedString))
1492                return JSValue();
1493            StringObject* obj = constructString(m_exec, m_globalObject, cachedString->jsString(m_exec));
1494            m_gcBuffer.append(obj);
1495            return obj;
1496        }
1497        case EmptyStringObjectTag: {
1498            StringObject* obj = constructString(m_exec, m_globalObject, jsEmptyString(&m_exec->vm()));
1499            m_gcBuffer.append(obj);
1500            return obj;
1501        }
1502        case RegExpTag: {
1503            CachedStringRef pattern;
1504            if (!readStringData(pattern))
1505                return JSValue();
1506            CachedStringRef flags;
1507            if (!readStringData(flags))
1508                return JSValue();
1509            RegExpFlags reFlags = regExpFlags(flags->string());
1510            ASSERT(reFlags != InvalidFlags);
1511            RegExp* regExp = RegExp::create(m_exec->vm(), pattern->string(), reFlags);
1512            return RegExpObject::create(m_exec, m_exec->lexicalGlobalObject(), m_globalObject->regExpStructure(), regExp);
1513        }
1514        case ObjectReferenceTag: {
1515            unsigned index = 0;
1516            if (!readConstantPoolIndex(m_gcBuffer, index)) {
1517                fail();
1518                return JSValue();
1519            }
1520            return m_gcBuffer.at(index);
1521        }
1522        case MessagePortReferenceTag: {
1523            uint32_t index;
1524            bool indexSuccessfullyRead = read(index);
1525            if (!indexSuccessfullyRead || !m_messagePorts || index >= m_messagePorts->size()) {
1526                fail();
1527                return JSValue();
1528            }
1529            return getJSValue(m_messagePorts->at(index).get());
1530        }
1531        case ArrayBufferTag: {
1532            RefPtr<ArrayBuffer> arrayBuffer;
1533            if (!readArrayBuffer(arrayBuffer)) {
1534                fail();
1535                return JSValue();
1536            }
1537            JSValue result = getJSValue(arrayBuffer.get());
1538            m_gcBuffer.append(result);
1539            return result;
1540        }
1541        case ArrayBufferTransferTag: {
1542            uint32_t index;
1543            bool indexSuccessfullyRead = read(index);
1544            if (!indexSuccessfullyRead || index >= m_arrayBuffers.size()) {
1545                fail();
1546                return JSValue();
1547            }
1548
1549            if (!m_arrayBuffers[index])
1550                m_arrayBuffers[index] = ArrayBuffer::create(m_arrayBufferContents->at(index));
1551
1552            return getJSValue(m_arrayBuffers[index].get());
1553        }
1554        case ArrayBufferViewTag: {
1555            JSValue arrayBufferView;
1556            if (!readArrayBufferView(arrayBufferView)) {
1557                fail();
1558                return JSValue();
1559            }
1560            m_gcBuffer.append(arrayBufferView);
1561            return arrayBufferView;
1562        }
1563        default:
1564            m_ptr--; // Push the tag back
1565            return JSValue();
1566        }
1567    }
1568
1569    JSGlobalObject* m_globalObject;
1570    bool m_isDOMGlobalObject;
1571    const uint8_t* m_ptr;
1572    const uint8_t* m_end;
1573    unsigned m_version;
1574    Vector<CachedString> m_constantPool;
1575    MessagePortArray* m_messagePorts;
1576    ArrayBufferContentsArray* m_arrayBufferContents;
1577    ArrayBufferArray m_arrayBuffers;
1578};
1579
1580DeserializationResult CloneDeserializer::deserialize()
1581{
1582    Vector<uint32_t, 16> indexStack;
1583    Vector<Identifier, 16> propertyNameStack;
1584    Vector<JSObject*, 32> outputObjectStack;
1585    Vector<WalkerState, 16> stateStack;
1586    WalkerState state = StateUnknown;
1587    JSValue outValue;
1588
1589    while (1) {
1590        switch (state) {
1591        arrayStartState:
1592        case ArrayStartState: {
1593            uint32_t length;
1594            if (!read(length)) {
1595                fail();
1596                goto error;
1597            }
1598            JSArray* outArray = constructEmptyArray(m_exec, 0, m_globalObject, length);
1599            m_gcBuffer.append(outArray);
1600            outputObjectStack.append(outArray);
1601            // fallthrough
1602        }
1603        arrayStartVisitMember:
1604        case ArrayStartVisitMember: {
1605            uint32_t index;
1606            if (!read(index)) {
1607                fail();
1608                goto error;
1609            }
1610            if (index == TerminatorTag) {
1611                JSObject* outArray = outputObjectStack.last();
1612                outValue = outArray;
1613                outputObjectStack.removeLast();
1614                break;
1615            } else if (index == NonIndexPropertiesTag) {
1616                goto objectStartVisitMember;
1617            }
1618
1619            if (JSValue terminal = readTerminal()) {
1620                putProperty(outputObjectStack.last(), index, terminal);
1621                goto arrayStartVisitMember;
1622            }
1623            if (m_failed)
1624                goto error;
1625            indexStack.append(index);
1626            stateStack.append(ArrayEndVisitMember);
1627            goto stateUnknown;
1628        }
1629        case ArrayEndVisitMember: {
1630            JSObject* outArray = outputObjectStack.last();
1631            putProperty(outArray, indexStack.last(), outValue);
1632            indexStack.removeLast();
1633            goto arrayStartVisitMember;
1634        }
1635        objectStartState:
1636        case ObjectStartState: {
1637            if (outputObjectStack.size() > maximumFilterRecursion)
1638                return make_pair(JSValue(), StackOverflowError);
1639            JSObject* outObject = constructEmptyObject(m_exec, m_globalObject->objectPrototype());
1640            m_gcBuffer.append(outObject);
1641            outputObjectStack.append(outObject);
1642            // fallthrough
1643        }
1644        objectStartVisitMember:
1645        case ObjectStartVisitMember: {
1646            CachedStringRef cachedString;
1647            bool wasTerminator = false;
1648            if (!readStringData(cachedString, wasTerminator)) {
1649                if (!wasTerminator)
1650                    goto error;
1651
1652                JSObject* outObject = outputObjectStack.last();
1653                outValue = outObject;
1654                outputObjectStack.removeLast();
1655                break;
1656            }
1657
1658            if (JSValue terminal = readTerminal()) {
1659                putProperty(outputObjectStack.last(), Identifier(m_exec, cachedString->string()), terminal);
1660                goto objectStartVisitMember;
1661            }
1662            stateStack.append(ObjectEndVisitMember);
1663            propertyNameStack.append(Identifier(m_exec, cachedString->string()));
1664            goto stateUnknown;
1665        }
1666        case ObjectEndVisitMember: {
1667            putProperty(outputObjectStack.last(), propertyNameStack.last(), outValue);
1668            propertyNameStack.removeLast();
1669            goto objectStartVisitMember;
1670        }
1671        stateUnknown:
1672        case StateUnknown:
1673            if (JSValue terminal = readTerminal()) {
1674                outValue = terminal;
1675                break;
1676            }
1677            SerializationTag tag = readTag();
1678            if (tag == ArrayTag)
1679                goto arrayStartState;
1680            if (tag == ObjectTag)
1681                goto objectStartState;
1682            goto error;
1683        }
1684        if (stateStack.isEmpty())
1685            break;
1686
1687        state = stateStack.last();
1688        stateStack.removeLast();
1689    }
1690    ASSERT(outValue);
1691    ASSERT(!m_failed);
1692    return make_pair(outValue, SuccessfullyCompleted);
1693error:
1694    fail();
1695    return make_pair(JSValue(), ValidationError);
1696}
1697
1698void SerializedScriptValue::addBlobURL(const String& string)
1699{
1700    m_blobURLs.append(Vector<uint16_t>());
1701    m_blobURLs.last().reserveCapacity(string.length());
1702    for (size_t i = 0; i < string.length(); i++)
1703        m_blobURLs.last().append(string.characterAt(i));
1704    m_blobURLs.last().resize(m_blobURLs.last().size());
1705}
1706
1707SerializedScriptValue::~SerializedScriptValue()
1708{
1709}
1710
1711SerializedScriptValue::SerializedScriptValue(const Vector<uint8_t>& buffer)
1712    : m_data(buffer)
1713{
1714}
1715
1716SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer)
1717{
1718    m_data.swap(buffer);
1719}
1720
1721SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer, Vector<String>& blobURLs)
1722{
1723    m_data.swap(buffer);
1724    for (auto blobIter = blobURLs.begin(); blobIter != blobURLs.end(); ++blobIter)
1725        addBlobURL(*blobIter);
1726}
1727
1728SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer, Vector<String>& blobURLs, PassOwnPtr<ArrayBufferContentsArray> arrayBufferContentsArray)
1729    : m_arrayBufferContentsArray(arrayBufferContentsArray)
1730{
1731    m_data.swap(buffer);
1732   for (auto blobIter = blobURLs.begin(); blobIter != blobURLs.end(); ++blobIter)
1733       addBlobURL(*blobIter);
1734}
1735
1736static void neuterView(JSCell* jsView)
1737{
1738    if (!jsView)
1739        return;
1740
1741    switch (jsView->classInfo()->typedArrayStorageType) {
1742    case TypedArrayNone:
1743        // This could be a DataView, for example. Assume that there are views that the
1744        // DFG doesn't care about.
1745        return;
1746    case TypedArrayInt8:
1747        jsCast<JSInt8Array*>(jsView)->m_storageLength = 0;
1748        return;
1749    case TypedArrayInt16:
1750        jsCast<JSInt16Array*>(jsView)->m_storageLength = 0;
1751        return;
1752    case TypedArrayInt32:
1753        jsCast<JSInt32Array*>(jsView)->m_storageLength = 0;
1754        return;
1755    case TypedArrayUint8:
1756        jsCast<JSUint8Array*>(jsView)->m_storageLength = 0;
1757        return;
1758    case TypedArrayUint8Clamped:
1759        jsCast<JSUint8ClampedArray*>(jsView)->m_storageLength = 0;
1760        return;
1761    case TypedArrayUint16:
1762        jsCast<JSUint16Array*>(jsView)->m_storageLength = 0;
1763        return;
1764    case TypedArrayUint32:
1765        jsCast<JSUint32Array*>(jsView)->m_storageLength = 0;
1766        return;
1767    case TypedArrayFloat32:
1768        jsCast<JSFloat32Array*>(jsView)->m_storageLength = 0;
1769        return;
1770    case TypedArrayFloat64:
1771        jsCast<JSFloat64Array*>(jsView)->m_storageLength = 0;
1772        return;
1773    }
1774    RELEASE_ASSERT_NOT_REACHED();
1775}
1776
1777PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValue::transferArrayBuffers(
1778    ExecState* exec, ArrayBufferArray& arrayBuffers, SerializationReturnCode& code)
1779{
1780    for (size_t i = 0; i < arrayBuffers.size(); i++) {
1781        if (arrayBuffers[i]->isNeutered()) {
1782            code = ValidationError;
1783            return nullptr;
1784        }
1785    }
1786
1787    OwnPtr<ArrayBufferContentsArray> contents = adoptPtr(new ArrayBufferContentsArray(arrayBuffers.size()));
1788    Vector<RefPtr<DOMWrapperWorld> > worlds;
1789    static_cast<WebCoreJSClientData*>(exec->vm().clientData)->getAllWorlds(worlds);
1790
1791    HashSet<WTF::ArrayBuffer*> visited;
1792    for (size_t arrayBufferIndex = 0; arrayBufferIndex < arrayBuffers.size(); arrayBufferIndex++) {
1793        Vector<RefPtr<ArrayBufferView> > neuteredViews;
1794
1795        if (visited.contains(arrayBuffers[arrayBufferIndex].get()))
1796            continue;
1797        visited.add(arrayBuffers[arrayBufferIndex].get());
1798
1799        bool result = arrayBuffers[arrayBufferIndex]->transfer(contents->at(arrayBufferIndex), neuteredViews);
1800        if (!result) {
1801            code = ValidationError;
1802            return nullptr;
1803        }
1804
1805        // The views may have been neutered, but their wrappers also need to be neutered, too.
1806        for (size_t viewIndex = neuteredViews.size(); viewIndex--;) {
1807            ArrayBufferView* view = neuteredViews[viewIndex].get();
1808            for (size_t worldIndex = worlds.size(); worldIndex--;) {
1809                DOMWrapperWorld* world = worlds[worldIndex].get();
1810                neuterView(getCachedWrapper(world, view));
1811            }
1812        }
1813    }
1814    return contents.release();
1815}
1816
1817
1818PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(ExecState* exec, JSValue value,
1819                                                                MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers,
1820                                                                SerializationErrorMode throwExceptions)
1821{
1822    Vector<uint8_t> buffer;
1823    Vector<String> blobURLs;
1824    SerializationReturnCode code = CloneSerializer::serialize(exec, value, messagePorts, arrayBuffers, blobURLs, buffer);
1825
1826    OwnPtr<ArrayBufferContentsArray> arrayBufferContentsArray;
1827
1828    if (arrayBuffers && serializationDidCompleteSuccessfully(code))
1829        arrayBufferContentsArray = transferArrayBuffers(exec, *arrayBuffers, code);
1830
1831    if (throwExceptions == Throwing)
1832        maybeThrowExceptionIfSerializationFailed(exec, code);
1833
1834    if (!serializationDidCompleteSuccessfully(code))
1835        return 0;
1836
1837    return adoptRef(new SerializedScriptValue(buffer, blobURLs, arrayBufferContentsArray.release()));
1838}
1839
1840PassRefPtr<SerializedScriptValue> SerializedScriptValue::create()
1841{
1842    Vector<uint8_t> buffer;
1843    return adoptRef(new SerializedScriptValue(buffer));
1844}
1845
1846PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& string)
1847{
1848    Vector<uint8_t> buffer;
1849    if (!CloneSerializer::serialize(string, buffer))
1850        return 0;
1851    return adoptRef(new SerializedScriptValue(buffer));
1852}
1853
1854#if ENABLE(INDEXED_DATABASE)
1855PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(JSC::ExecState* exec, JSC::JSValue value)
1856{
1857    return SerializedScriptValue::create(exec, value, 0, 0);
1858}
1859
1860PassRefPtr<SerializedScriptValue> SerializedScriptValue::numberValue(double value)
1861{
1862    Vector<uint8_t> buffer;
1863    CloneSerializer::serializeNumber(value, buffer);
1864    return adoptRef(new SerializedScriptValue(buffer));
1865}
1866
1867JSValue SerializedScriptValue::deserialize(JSC::ExecState* exec, JSC::JSGlobalObject* globalObject)
1868{
1869    return deserialize(exec, globalObject, 0);
1870}
1871#endif
1872
1873PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(JSContextRef originContext, JSValueRef apiValue,
1874                                                                MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers,
1875                                                                JSValueRef* exception)
1876{
1877    ExecState* exec = toJS(originContext);
1878    APIEntryShim entryShim(exec);
1879    JSValue value = toJS(exec, apiValue);
1880    RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::create(exec, value, messagePorts, arrayBuffers);
1881    if (exec->hadException()) {
1882        if (exception)
1883            *exception = toRef(exec, exec->exception());
1884        exec->clearException();
1885        return 0;
1886    }
1887    ASSERT(serializedValue);
1888    return serializedValue.release();
1889}
1890
1891PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(JSContextRef originContext, JSValueRef apiValue,
1892                                                                JSValueRef* exception)
1893{
1894    return create(originContext, apiValue, 0, 0, exception);
1895}
1896
1897String SerializedScriptValue::toString()
1898{
1899    return CloneDeserializer::deserializeString(m_data);
1900}
1901
1902JSValue SerializedScriptValue::deserialize(ExecState* exec, JSGlobalObject* globalObject,
1903                                           MessagePortArray* messagePorts, SerializationErrorMode throwExceptions)
1904{
1905    DeserializationResult result = CloneDeserializer::deserialize(exec, globalObject, messagePorts,
1906                                                                  m_arrayBufferContentsArray.get(), m_data);
1907    if (throwExceptions == Throwing)
1908        maybeThrowExceptionIfSerializationFailed(exec, result.second);
1909    return result.first;
1910}
1911
1912#if ENABLE(INSPECTOR)
1913ScriptValue SerializedScriptValue::deserializeForInspector(ScriptState* scriptState)
1914{
1915    JSValue value = deserialize(scriptState, scriptState->lexicalGlobalObject(), 0);
1916    return ScriptValue(scriptState->vm(), value);
1917}
1918#endif
1919
1920JSValueRef SerializedScriptValue::deserialize(JSContextRef destinationContext, JSValueRef* exception, MessagePortArray* messagePorts)
1921{
1922    ExecState* exec = toJS(destinationContext);
1923    APIEntryShim entryShim(exec);
1924    JSValue value = deserialize(exec, exec->lexicalGlobalObject(), messagePorts);
1925    if (exec->hadException()) {
1926        if (exception)
1927            *exception = toRef(exec, exec->exception());
1928        exec->clearException();
1929        return 0;
1930    }
1931    ASSERT(value);
1932    return toRef(exec, value);
1933}
1934
1935
1936JSValueRef SerializedScriptValue::deserialize(JSContextRef destinationContext, JSValueRef* exception)
1937{
1938    return deserialize(destinationContext, exception, 0);
1939}
1940
1941PassRefPtr<SerializedScriptValue> SerializedScriptValue::nullValue()
1942{
1943    return SerializedScriptValue::create();
1944}
1945
1946PassRefPtr<SerializedScriptValue> SerializedScriptValue::undefinedValue()
1947{
1948    Vector<uint8_t> buffer;
1949    CloneSerializer::serializeUndefined(buffer);
1950    return adoptRef(new SerializedScriptValue(buffer));
1951}
1952
1953PassRefPtr<SerializedScriptValue> SerializedScriptValue::booleanValue(bool value)
1954{
1955    Vector<uint8_t> buffer;
1956    CloneSerializer::serializeBoolean(value, buffer);
1957    return adoptRef(new SerializedScriptValue(buffer));
1958}
1959
1960void SerializedScriptValue::maybeThrowExceptionIfSerializationFailed(ExecState* exec, SerializationReturnCode code)
1961{
1962    if (code == SuccessfullyCompleted)
1963        return;
1964
1965    switch (code) {
1966    case StackOverflowError:
1967        throwError(exec, createStackOverflowError(exec));
1968        break;
1969    case ValidationError:
1970        throwError(exec, createTypeError(exec, "Unable to deserialize data."));
1971        break;
1972    case DataCloneError:
1973        setDOMException(exec, DATA_CLONE_ERR);
1974        break;
1975    case ExistingExceptionError:
1976        break;
1977    case UnspecifiedError:
1978        break;
1979    default:
1980        ASSERT_NOT_REACHED();
1981    }
1982}
1983
1984bool SerializedScriptValue::serializationDidCompleteSuccessfully(SerializationReturnCode code)
1985{
1986    return (code == SuccessfullyCompleted);
1987}
1988
1989uint32_t SerializedScriptValue::wireFormatVersion()
1990{
1991    return CurrentVersion;
1992}
1993
1994}
1995