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 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 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 "CryptoKeyAES.h"
32#include "CryptoKeyDataOctetSequence.h"
33#include "CryptoKeyDataRSAComponents.h"
34#include "CryptoKeyHMAC.h"
35#include "CryptoKeyRSA.h"
36#include "ExceptionCode.h"
37#include "File.h"
38#include "FileList.h"
39#include "ImageData.h"
40#include "JSBlob.h"
41#include "JSCryptoKey.h"
42#include "JSDOMBinding.h"
43#include "JSDOMGlobalObject.h"
44#include "JSFile.h"
45#include "JSFileList.h"
46#include "JSImageData.h"
47#include "JSMessagePort.h"
48#include "JSNavigator.h"
49#include "ScriptExecutionContext.h"
50#include "SharedBuffer.h"
51#include "WebCoreJSClientData.h"
52#include <limits>
53#include <JavaScriptCore/APICast.h>
54#include <runtime/ArrayBuffer.h>
55#include <runtime/BooleanObject.h>
56#include <runtime/DateInstance.h>
57#include <runtime/Error.h>
58#include <runtime/ExceptionHelpers.h>
59#include <runtime/JSArrayBuffer.h>
60#include <runtime/JSArrayBufferView.h>
61#include <runtime/JSCInlines.h>
62#include <runtime/JSDataView.h>
63#include <runtime/JSMap.h>
64#include <runtime/JSSet.h>
65#include <runtime/JSTypedArrays.h>
66#include <runtime/MapData.h>
67#include <runtime/ObjectConstructor.h>
68#include <runtime/PropertyNameArray.h>
69#include <runtime/RegExp.h>
70#include <runtime/RegExpObject.h>
71#include <runtime/TypedArrayInlines.h>
72#include <runtime/TypedArrays.h>
73#include <wtf/HashTraits.h>
74#include <wtf/Vector.h>
75
76using namespace JSC;
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    MapDataStartVisitEntry, MapDataEndVisitKey, MapDataEndVisitValue };
91
92// These can't be reordered, and any new types must be added to the end of the list
93enum SerializationTag {
94    ArrayTag = 1,
95    ObjectTag = 2,
96    UndefinedTag = 3,
97    NullTag = 4,
98    IntTag = 5,
99    ZeroTag = 6,
100    OneTag = 7,
101    FalseTag = 8,
102    TrueTag = 9,
103    DoubleTag = 10,
104    DateTag = 11,
105    FileTag = 12,
106    FileListTag = 13,
107    ImageDataTag = 14,
108    BlobTag = 15,
109    StringTag = 16,
110    EmptyStringTag = 17,
111    RegExpTag = 18,
112    ObjectReferenceTag = 19,
113    MessagePortReferenceTag = 20,
114    ArrayBufferTag = 21,
115    ArrayBufferViewTag = 22,
116    ArrayBufferTransferTag = 23,
117    TrueObjectTag = 24,
118    FalseObjectTag = 25,
119    StringObjectTag = 26,
120    EmptyStringObjectTag = 27,
121    NumberObjectTag = 28,
122    SetObjectTag = 29,
123    MapObjectTag = 30,
124    NonMapPropertiesTag = 31,
125#if ENABLE(SUBTLE_CRYPTO)
126    CryptoKeyTag = 32,
127#endif
128    ErrorTag = 255
129};
130
131enum ArrayBufferViewSubtag {
132    DataViewTag = 0,
133    Int8ArrayTag = 1,
134    Uint8ArrayTag = 2,
135    Uint8ClampedArrayTag = 3,
136    Int16ArrayTag = 4,
137    Uint16ArrayTag = 5,
138    Int32ArrayTag = 6,
139    Uint32ArrayTag = 7,
140    Float32ArrayTag = 8,
141    Float64ArrayTag = 9
142};
143
144static unsigned typedArrayElementSize(ArrayBufferViewSubtag tag)
145{
146    switch (tag) {
147    case DataViewTag:
148    case Int8ArrayTag:
149    case Uint8ArrayTag:
150    case Uint8ClampedArrayTag:
151        return 1;
152    case Int16ArrayTag:
153    case Uint16ArrayTag:
154        return 2;
155    case Int32ArrayTag:
156    case Uint32ArrayTag:
157    case Float32ArrayTag:
158        return 4;
159    case Float64ArrayTag:
160        return 8;
161    default:
162        return 0;
163    }
164
165}
166
167#if ENABLE(SUBTLE_CRYPTO)
168
169const uint32_t currentKeyFormatVersion = 1;
170
171enum class CryptoKeyClassSubtag {
172    HMAC = 0,
173    AES = 1,
174    RSA = 2
175};
176const uint8_t cryptoKeyClassSubtagMaximumValue = 2;
177
178enum class CryptoKeyAsymmetricTypeSubtag {
179    Public = 0,
180    Private = 1
181};
182const uint8_t cryptoKeyAsymmetricTypeSubtagMaximumValue = 1;
183
184enum class CryptoKeyUsageTag {
185    Encrypt = 0,
186    Decrypt = 1,
187    Sign = 2,
188    Verify = 3,
189    DeriveKey = 4,
190    DeriveBits = 5,
191    WrapKey = 6,
192    UnwrapKey = 7
193};
194const uint8_t cryptoKeyUsageTagMaximumValue = 7;
195
196enum class CryptoAlgorithmIdentifierTag {
197    RSAES_PKCS1_v1_5 = 0,
198    RSASSA_PKCS1_v1_5 = 1,
199    RSA_PSS = 2,
200    RSA_OAEP = 3,
201    ECDSA = 4,
202    ECDH = 5,
203    AES_CTR = 6,
204    AES_CBC = 7,
205    AES_CMAC = 8,
206    AES_GCM = 9,
207    AES_CFB = 10,
208    AES_KW = 11,
209    HMAC = 12,
210    DH = 13,
211    SHA_1 = 14,
212    SHA_224 = 15,
213    SHA_256 = 16,
214    SHA_384 = 17,
215    SHA_512 = 18,
216    CONCAT = 19,
217    HKDF_CTR = 20,
218    PBKDF2 = 21,
219};
220const uint8_t cryptoAlgorithmIdentifierTagMaximumValue = 21;
221
222static unsigned countUsages(CryptoKeyUsage usages)
223{
224    // Fast bit count algorithm for sparse bit maps.
225    unsigned count = 0;
226    while (usages) {
227        usages = usages & (usages - 1);
228        ++count;
229    }
230    return count;
231}
232
233#endif
234
235/* CurrentVersion tracks the serialization version so that persistent stores
236 * are able to correctly bail out in the case of encountering newer formats.
237 *
238 * Initial version was 1.
239 * Version 2. added the ObjectReferenceTag and support for serialization of cyclic graphs.
240 * Version 3. added the FalseObjectTag, TrueObjectTag, NumberObjectTag, StringObjectTag
241 * and EmptyStringObjectTag for serialization of Boolean, Number and String objects.
242 * Version 4. added support for serializing non-index properties of arrays.
243 * Version 5. added support for Map and Set types.
244 */
245static const unsigned CurrentVersion = 5;
246static const unsigned TerminatorTag = 0xFFFFFFFF;
247static const unsigned StringPoolTag = 0xFFFFFFFE;
248static const unsigned NonIndexPropertiesTag = 0xFFFFFFFD;
249
250/*
251 * Object serialization is performed according to the following grammar, all tags
252 * are recorded as a single uint8_t.
253 *
254 * IndexType (used for the object pool and StringData's constant pool) is the
255 * minimum sized unsigned integer type required to represent the maximum index
256 * in the constant pool.
257 *
258 * SerializedValue :- <CurrentVersion:uint32_t> Value
259 * Value :- Array | Object | Map | Set | Terminal
260 *
261 * Array :-
262 *     ArrayTag <length:uint32_t>(<index:uint32_t><value:Value>)* TerminatorTag
263 *
264 * Object :-
265 *     ObjectTag (<name:StringData><value:Value>)* TerminatorTag
266 *
267 * Map :- MapObjectTag MapData
268 *
269 * Set :- SetObjectTag MapData
270 *
271 * MapData :- (<key:Value><value:Value>) NonMapPropertiesTag (<name:StringData><value:Value>)* TerminatorTag
272 *
273 * Terminal :-
274 *      UndefinedTag
275 *    | NullTag
276 *    | IntTag <value:int32_t>
277 *    | ZeroTag
278 *    | OneTag
279 *    | FalseTag
280 *    | TrueTag
281 *    | FalseObjectTag
282 *    | TrueObjectTag
283 *    | DoubleTag <value:double>
284 *    | NumberObjectTag <value:double>
285 *    | DateTag <value:double>
286 *    | String
287 *    | EmptyStringTag
288 *    | EmptyStringObjectTag
289 *    | File
290 *    | FileList
291 *    | ImageData
292 *    | Blob
293 *    | ObjectReference
294 *    | MessagePortReferenceTag <value:uint32_t>
295 *    | ArrayBuffer
296 *    | ArrayBufferViewTag ArrayBufferViewSubtag <byteOffset:uint32_t> <byteLength:uint32_t> (ArrayBuffer | ObjectReference)
297 *    | ArrayBufferTransferTag <value:uint32_t>
298 *    | CryptoKeyTag <wrappedKeyLength:uint32_t> <factor:byte{wrappedKeyLength}>
299 *
300 * Inside wrapped crypto key, data is serialized in this format:
301 *
302 * <keyFormatVersion:uint32_t> <extractable:int32_t> <usagesCount:uint32_t> <usages:byte{usagesCount}> CryptoKeyClassSubtag (CryptoKeyHMAC | CryptoKeyAES | CryptoKeyRSA)
303 *
304 * String :-
305 *      EmptyStringTag
306 *      StringTag StringData
307 *
308 * StringObject:
309 *      EmptyStringObjectTag
310 *      StringObjectTag StringData
311 *
312 * StringData :-
313 *      StringPoolTag <cpIndex:IndexType>
314 *      (not (TerminatorTag | StringPoolTag))<length:uint32_t><characters:UChar{length}> // Added to constant pool when seen, string length 0xFFFFFFFF is disallowed
315 *
316 * File :-
317 *    FileTag FileData
318 *
319 * FileData :-
320 *    <path:StringData> <url:StringData> <type:StringData> <name:StringData>
321 *
322 * FileList :-
323 *    FileListTag <length:uint32_t>(<file:FileData>){length}
324 *
325 * ImageData :-
326 *    ImageDataTag <width:int32_t><height:int32_t><length:uint32_t><data:uint8_t{length}>
327 *
328 * Blob :-
329 *    BlobTag <url:StringData><type:StringData><size:long long>
330 *
331 * RegExp :-
332 *    RegExpTag <pattern:StringData><flags:StringData>
333 *
334 * ObjectReference :-
335 *    ObjectReferenceTag <opIndex:IndexType>
336 *
337 * ArrayBuffer :-
338 *    ArrayBufferTag <length:uint32_t> <contents:byte{length}>
339 *
340 * CryptoKeyHMAC :-
341 *    <keySize:uint32_t> <keyData:byte{keySize}> CryptoAlgorithmIdentifierTag // Algorithm tag inner hash function.
342 *
343 * CryptoKeyAES :-
344 *    CryptoAlgorithmIdentifierTag <keySize:uint32_t> <keyData:byte{keySize}>
345 *
346 * CryptoKeyRSA :-
347 *    CryptoAlgorithmIdentifierTag <isRestrictedToHash:int32_t> CryptoAlgorithmIdentifierTag? CryptoKeyAsymmetricTypeSubtag CryptoKeyRSAPublicComponents CryptoKeyRSAPrivateComponents?
348 *
349 * CryptoKeyRSAPublicComponents :-
350 *    <modulusSize:uint32_t> <modulus:byte{modulusSize}> <exponentSize:uint32_t> <exponent:byte{exponentSize}>
351 *
352 * CryptoKeyRSAPrivateComponents :-
353 *    <privateExponentSize:uint32_t> <privateExponent:byte{privateExponentSize}> <primeCount:uint32_t> FirstPrimeInfo? PrimeInfo{primeCount - 1}
354 *
355 * // CRT data could be computed from prime factors. It is only serialized to reuse a code path that's needed for JWK.
356 * FirstPrimeInfo :-
357 *    <factorSize:uint32_t> <factor:byte{factorSize}> <crtExponentSize:uint32_t> <crtExponent:byte{crtExponentSize}>
358 *
359 * PrimeInfo :-
360 *    <factorSize:uint32_t> <factor:byte{factorSize}> <crtExponentSize:uint32_t> <crtExponent:byte{crtExponentSize}> <crtCoefficientSize:uint32_t> <crtCoefficient:byte{crtCoefficientSize}>
361 */
362
363typedef std::pair<JSC::JSValue, SerializationReturnCode> DeserializationResult;
364
365class CloneBase {
366protected:
367    CloneBase(ExecState* exec)
368        : m_exec(exec)
369        , m_failed(false)
370    {
371    }
372
373    bool shouldTerminate()
374    {
375        return m_exec->hadException();
376    }
377
378    void throwStackOverflow()
379    {
380        m_exec->vm().throwException(m_exec, createStackOverflowError(m_exec));
381    }
382
383    void fail()
384    {
385        m_failed = true;
386    }
387
388    ExecState* m_exec;
389    bool m_failed;
390    MarkedArgumentBuffer m_gcBuffer;
391};
392
393#if ENABLE(SUBTLE_CRYPTO)
394static bool wrapCryptoKey(ExecState* exec, const Vector<uint8_t>& key, Vector<uint8_t>& wrappedKey)
395{
396    ScriptExecutionContext* scriptExecutionContext = scriptExecutionContextFromExecState(exec);
397    if (!scriptExecutionContext)
398        return false;
399    return scriptExecutionContext->wrapCryptoKey(key, wrappedKey);
400}
401
402static bool unwrapCryptoKey(ExecState* exec, const Vector<uint8_t>& wrappedKey, Vector<uint8_t>& key)
403{
404    ScriptExecutionContext* scriptExecutionContext = scriptExecutionContextFromExecState(exec);
405    if (!scriptExecutionContext)
406        return false;
407    return scriptExecutionContext->unwrapCryptoKey(wrappedKey, key);
408}
409#endif
410
411#if ASSUME_LITTLE_ENDIAN
412template <typename T> static void writeLittleEndian(Vector<uint8_t>& buffer, T value)
413{
414    buffer.append(reinterpret_cast<uint8_t*>(&value), sizeof(value));
415}
416#else
417template <typename T> static void writeLittleEndian(Vector<uint8_t>& buffer, T value)
418{
419    for (unsigned i = 0; i < sizeof(T); i++) {
420        buffer.append(value & 0xFF);
421        value >>= 8;
422    }
423}
424#endif
425
426template <> void writeLittleEndian<uint8_t>(Vector<uint8_t>& buffer, uint8_t value)
427{
428    buffer.append(value);
429}
430
431template <typename T> static bool writeLittleEndian(Vector<uint8_t>& buffer, const T* values, uint32_t length)
432{
433    if (length > std::numeric_limits<uint32_t>::max() / sizeof(T))
434        return false;
435
436#if ASSUME_LITTLE_ENDIAN
437    buffer.append(reinterpret_cast<const uint8_t*>(values), length * sizeof(T));
438#else
439    for (unsigned i = 0; i < length; i++) {
440        T value = values[i];
441        for (unsigned j = 0; j < sizeof(T); j++) {
442            buffer.append(static_cast<uint8_t>(value & 0xFF));
443            value >>= 8;
444        }
445    }
446#endif
447    return true;
448}
449
450static bool writeLittleEndianUInt16(Vector<uint8_t>& buffer, const LChar* values, uint32_t length)
451{
452    if (length > std::numeric_limits<uint32_t>::max() / 2)
453        return false;
454
455    for (unsigned i = 0; i < length; ++i) {
456        buffer.append(values[i]);
457        buffer.append(0);
458    }
459
460    return true;
461}
462
463template <> bool writeLittleEndian<uint8_t>(Vector<uint8_t>& buffer, const uint8_t* values, uint32_t length)
464{
465    buffer.append(values, length);
466    return true;
467}
468
469class CloneSerializer : CloneBase {
470public:
471    static SerializationReturnCode serialize(ExecState* exec, JSValue value,
472                                             MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers,
473                                             Vector<String>& blobURLs, Vector<uint8_t>& out)
474    {
475        CloneSerializer serializer(exec, messagePorts, arrayBuffers, blobURLs, out);
476        return serializer.serialize(value);
477    }
478
479    static bool serialize(const String& s, Vector<uint8_t>& out)
480    {
481        writeLittleEndian(out, CurrentVersion);
482        if (s.isEmpty()) {
483            writeLittleEndian<uint8_t>(out, EmptyStringTag);
484            return true;
485        }
486        writeLittleEndian<uint8_t>(out, StringTag);
487        writeLittleEndian(out, s.length());
488        if (s.is8Bit())
489            return writeLittleEndianUInt16(out, s.characters8(), s.length());
490        return writeLittleEndian(out, s.characters16(), s.length());
491    }
492
493    static void serializeUndefined(Vector<uint8_t>& out)
494    {
495        writeLittleEndian(out, CurrentVersion);
496        writeLittleEndian<uint8_t>(out, UndefinedTag);
497    }
498
499    static void serializeBoolean(bool value, Vector<uint8_t>& out)
500    {
501        writeLittleEndian(out, CurrentVersion);
502        writeLittleEndian<uint8_t>(out, value ? TrueTag : FalseTag);
503    }
504
505    static void serializeNumber(double value, Vector<uint8_t>& out)
506    {
507        writeLittleEndian(out, CurrentVersion);
508        writeLittleEndian<uint8_t>(out, DoubleTag);
509        union {
510            double d;
511            int64_t i;
512        } u;
513        u.d = value;
514        writeLittleEndian(out, u.i);
515    }
516
517private:
518    typedef HashMap<JSObject*, uint32_t> ObjectPool;
519
520    CloneSerializer(ExecState* exec, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, Vector<String>& blobURLs, Vector<uint8_t>& out)
521        : CloneBase(exec)
522        , m_buffer(out)
523        , m_blobURLs(blobURLs)
524        , m_emptyIdentifier(exec, emptyString())
525    {
526        write(CurrentVersion);
527        fillTransferMap(messagePorts, m_transferredMessagePorts);
528        fillTransferMap(arrayBuffers, m_transferredArrayBuffers);
529    }
530
531    template <class T>
532    void fillTransferMap(Vector<RefPtr<T>, 1>* input, ObjectPool& result)
533    {
534        if (!input)
535            return;
536        JSDOMGlobalObject* globalObject = jsCast<JSDOMGlobalObject*>(m_exec->lexicalGlobalObject());
537        for (size_t i = 0; i < input->size(); i++) {
538            JSC::JSValue value = toJS(m_exec, globalObject, input->at(i).get());
539            JSC::JSObject* obj = value.getObject();
540            if (obj && !result.contains(obj))
541                result.add(obj, i);
542        }
543    }
544
545    SerializationReturnCode serialize(JSValue in);
546
547    bool isArray(JSValue value)
548    {
549        if (!value.isObject())
550            return false;
551        JSObject* object = asObject(value);
552        return isJSArray(object) || object->inherits(JSArray::info());
553    }
554
555    bool isMap(JSValue value)
556    {
557        if (!value.isObject())
558            return false;
559        JSObject* object = asObject(value);
560        return object->inherits(JSMap::info());
561    }
562    bool isSet(JSValue value)
563    {
564        if (!value.isObject())
565            return false;
566        JSObject* object = asObject(value);
567        return object->inherits(JSSet::info());
568    }
569
570    bool checkForDuplicate(JSObject* object)
571    {
572        // Record object for graph reconstruction
573        ObjectPool::const_iterator found = m_objectPool.find(object);
574
575        // Handle duplicate references
576        if (found != m_objectPool.end()) {
577            write(ObjectReferenceTag);
578            ASSERT(static_cast<int32_t>(found->value) < m_objectPool.size());
579            writeObjectIndex(found->value);
580            return true;
581        }
582
583        return false;
584    }
585
586    void recordObject(JSObject* object)
587    {
588        m_objectPool.add(object, m_objectPool.size());
589        m_gcBuffer.append(object);
590    }
591
592    bool startObjectInternal(JSObject* object)
593    {
594        if (checkForDuplicate(object))
595            return false;
596        recordObject(object);
597        return true;
598    }
599
600    bool startObject(JSObject* object)
601    {
602        if (!startObjectInternal(object))
603            return false;
604        write(ObjectTag);
605        return true;
606    }
607
608    bool startArray(JSArray* array)
609    {
610        if (!startObjectInternal(array))
611            return false;
612
613        unsigned length = array->length();
614        write(ArrayTag);
615        write(length);
616        return true;
617    }
618
619    bool startSet(JSSet* set)
620    {
621        if (!startObjectInternal(set))
622            return false;
623
624        write(SetObjectTag);
625        return true;
626    }
627
628    bool startMap(JSMap* map)
629    {
630        if (!startObjectInternal(map))
631            return false;
632
633        write(MapObjectTag);
634        return true;
635    }
636
637    void endObject()
638    {
639        write(TerminatorTag);
640    }
641
642    JSValue getProperty(JSObject* object, const Identifier& propertyName)
643    {
644        PropertySlot slot(object);
645        if (object->methodTable()->getOwnPropertySlot(object, m_exec, propertyName, slot))
646            return slot.getValue(m_exec, propertyName);
647        return JSValue();
648    }
649
650    void dumpImmediate(JSValue value)
651    {
652        if (value.isNull())
653            write(NullTag);
654        else if (value.isUndefined())
655            write(UndefinedTag);
656        else if (value.isNumber()) {
657            if (value.isInt32()) {
658                if (!value.asInt32())
659                    write(ZeroTag);
660                else if (value.asInt32() == 1)
661                    write(OneTag);
662                else {
663                    write(IntTag);
664                    write(static_cast<uint32_t>(value.asInt32()));
665                }
666            } else {
667                write(DoubleTag);
668                write(value.asDouble());
669            }
670        } else if (value.isBoolean()) {
671            if (value.isTrue())
672                write(TrueTag);
673            else
674                write(FalseTag);
675        }
676    }
677
678    void dumpString(String str)
679    {
680        if (str.isEmpty())
681            write(EmptyStringTag);
682        else {
683            write(StringTag);
684            write(str);
685        }
686    }
687
688    void dumpStringObject(String str)
689    {
690        if (str.isEmpty())
691            write(EmptyStringObjectTag);
692        else {
693            write(StringObjectTag);
694            write(str);
695        }
696    }
697
698    bool dumpArrayBufferView(JSObject* obj, SerializationReturnCode& code)
699    {
700        write(ArrayBufferViewTag);
701        if (obj->inherits(JSDataView::info()))
702            write(DataViewTag);
703        else if (obj->inherits(JSUint8ClampedArray::info()))
704            write(Uint8ClampedArrayTag);
705        else if (obj->inherits(JSInt8Array::info()))
706            write(Int8ArrayTag);
707        else if (obj->inherits(JSUint8Array::info()))
708            write(Uint8ArrayTag);
709        else if (obj->inherits(JSInt16Array::info()))
710            write(Int16ArrayTag);
711        else if (obj->inherits(JSUint16Array::info()))
712            write(Uint16ArrayTag);
713        else if (obj->inherits(JSInt32Array::info()))
714            write(Int32ArrayTag);
715        else if (obj->inherits(JSUint32Array::info()))
716            write(Uint32ArrayTag);
717        else if (obj->inherits(JSFloat32Array::info()))
718            write(Float32ArrayTag);
719        else if (obj->inherits(JSFloat64Array::info()))
720            write(Float64ArrayTag);
721        else
722            return false;
723
724        RefPtr<ArrayBufferView> arrayBufferView = toArrayBufferView(obj);
725        write(static_cast<uint32_t>(arrayBufferView->byteOffset()));
726        write(static_cast<uint32_t>(arrayBufferView->byteLength()));
727        RefPtr<ArrayBuffer> arrayBuffer = arrayBufferView->buffer();
728        if (!arrayBuffer) {
729            code = ValidationError;
730            return true;
731        }
732        JSValue bufferObj = toJS(m_exec, jsCast<JSDOMGlobalObject*>(m_exec->lexicalGlobalObject()), arrayBuffer.get());
733        return dumpIfTerminal(bufferObj, code);
734    }
735
736    bool dumpIfTerminal(JSValue value, SerializationReturnCode& code)
737    {
738        if (!value.isCell()) {
739            dumpImmediate(value);
740            return true;
741        }
742
743        if (value.isString()) {
744            String str = asString(value)->value(m_exec);
745            dumpString(str);
746            return true;
747        }
748
749        if (value.isNumber()) {
750            write(DoubleTag);
751            write(value.asNumber());
752            return true;
753        }
754
755        if (value.isObject() && asObject(value)->inherits(DateInstance::info())) {
756            write(DateTag);
757            write(asDateInstance(value)->internalNumber());
758            return true;
759        }
760
761        if (isArray(value))
762            return false;
763
764        if (value.isObject()) {
765            JSObject* obj = asObject(value);
766            if (obj->inherits(BooleanObject::info())) {
767                if (!startObjectInternal(obj)) // handle duplicates
768                    return true;
769                write(asBooleanObject(value)->internalValue().toBoolean(m_exec) ? TrueObjectTag : FalseObjectTag);
770                return true;
771            }
772            if (obj->inherits(StringObject::info())) {
773                if (!startObjectInternal(obj)) // handle duplicates
774                    return true;
775                String str = asString(asStringObject(value)->internalValue())->value(m_exec);
776                dumpStringObject(str);
777                return true;
778            }
779            if (obj->inherits(NumberObject::info())) {
780                if (!startObjectInternal(obj)) // handle duplicates
781                    return true;
782                write(NumberObjectTag);
783                NumberObject* obj = static_cast<NumberObject*>(asObject(value));
784                write(obj->internalValue().asNumber());
785                return true;
786            }
787            if (File* file = toFile(obj)) {
788                write(FileTag);
789                write(file);
790                return true;
791            }
792            if (FileList* list = toFileList(obj)) {
793                write(FileListTag);
794                unsigned length = list->length();
795                write(length);
796                for (unsigned i = 0; i < length; i++)
797                    write(list->item(i));
798                return true;
799            }
800            if (Blob* blob = toBlob(obj)) {
801                write(BlobTag);
802                m_blobURLs.append(blob->url());
803                write(blob->url());
804                write(blob->type());
805                write(blob->size());
806                return true;
807            }
808            if (ImageData* data = toImageData(obj)) {
809                write(ImageDataTag);
810                write(data->width());
811                write(data->height());
812                write(data->data()->length());
813                write(data->data()->data(), data->data()->length());
814                return true;
815            }
816            if (obj->inherits(RegExpObject::info())) {
817                RegExpObject* regExp = asRegExpObject(obj);
818                char flags[3];
819                int flagCount = 0;
820                if (regExp->regExp()->global())
821                    flags[flagCount++] = 'g';
822                if (regExp->regExp()->ignoreCase())
823                    flags[flagCount++] = 'i';
824                if (regExp->regExp()->multiline())
825                    flags[flagCount++] = 'm';
826                write(RegExpTag);
827                write(regExp->regExp()->pattern());
828                write(String(flags, flagCount));
829                return true;
830            }
831            if (obj->inherits(JSMessagePort::info())) {
832                ObjectPool::iterator index = m_transferredMessagePorts.find(obj);
833                if (index != m_transferredMessagePorts.end()) {
834                    write(MessagePortReferenceTag);
835                    write(index->value);
836                    return true;
837                }
838                // MessagePort object could not be found in transferred message ports
839                code = ValidationError;
840                return true;
841            }
842            if (ArrayBuffer* arrayBuffer = toArrayBuffer(obj)) {
843                if (arrayBuffer->isNeutered()) {
844                    code = ValidationError;
845                    return true;
846                }
847                ObjectPool::iterator index = m_transferredArrayBuffers.find(obj);
848                if (index != m_transferredArrayBuffers.end()) {
849                    write(ArrayBufferTransferTag);
850                    write(index->value);
851                    return true;
852                }
853                if (!startObjectInternal(obj)) // handle duplicates
854                    return true;
855                write(ArrayBufferTag);
856                write(arrayBuffer->byteLength());
857                write(static_cast<const uint8_t*>(arrayBuffer->data()), arrayBuffer->byteLength());
858                return true;
859            }
860            if (obj->inherits(JSArrayBufferView::info())) {
861                if (checkForDuplicate(obj))
862                    return true;
863                bool success = dumpArrayBufferView(obj, code);
864                recordObject(obj);
865                return success;
866            }
867#if ENABLE(SUBTLE_CRYPTO)
868            if (CryptoKey* key = toCryptoKey(obj)) {
869                write(CryptoKeyTag);
870                Vector<uint8_t> serializedKey;
871                Vector<String> dummyBlobURLs;
872                CloneSerializer rawKeySerializer(m_exec, nullptr, nullptr, dummyBlobURLs, serializedKey);
873                rawKeySerializer.write(key);
874                Vector<uint8_t> wrappedKey;
875                if (!wrapCryptoKey(m_exec, serializedKey, wrappedKey))
876                    return false;
877                write(wrappedKey);
878                return true;
879            }
880#endif
881
882            return false;
883        }
884        // Any other types are expected to serialize as null.
885        write(NullTag);
886        return true;
887    }
888
889    void write(SerializationTag tag)
890    {
891        writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag));
892    }
893
894    void write(ArrayBufferViewSubtag tag)
895    {
896        writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag));
897    }
898
899#if ENABLE(SUBTLE_CRYPTO)
900    void write(CryptoKeyClassSubtag tag)
901    {
902        writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag));
903    }
904
905    void write(CryptoKeyAsymmetricTypeSubtag tag)
906    {
907        writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag));
908    }
909
910    void write(CryptoKeyUsageTag tag)
911    {
912        writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag));
913    }
914
915    void write(CryptoAlgorithmIdentifierTag tag)
916    {
917        writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag));
918    }
919#endif
920
921    void write(uint8_t c)
922    {
923        writeLittleEndian(m_buffer, c);
924    }
925
926    void write(uint32_t i)
927    {
928        writeLittleEndian(m_buffer, i);
929    }
930
931    void write(double d)
932    {
933        union {
934            double d;
935            int64_t i;
936        } u;
937        u.d = d;
938        writeLittleEndian(m_buffer, u.i);
939    }
940
941    void write(int32_t i)
942    {
943        writeLittleEndian(m_buffer, i);
944    }
945
946    void write(unsigned long long i)
947    {
948        writeLittleEndian(m_buffer, i);
949    }
950
951    void write(uint16_t ch)
952    {
953        writeLittleEndian(m_buffer, ch);
954    }
955
956    void writeStringIndex(unsigned i)
957    {
958        writeConstantPoolIndex(m_constantPool, i);
959    }
960
961    void writeObjectIndex(unsigned i)
962    {
963        writeConstantPoolIndex(m_objectPool, i);
964    }
965
966    template <class T> void writeConstantPoolIndex(const T& constantPool, unsigned i)
967    {
968        ASSERT(static_cast<int32_t>(i) < constantPool.size());
969        if (constantPool.size() <= 0xFF)
970            write(static_cast<uint8_t>(i));
971        else if (constantPool.size() <= 0xFFFF)
972            write(static_cast<uint16_t>(i));
973        else
974            write(static_cast<uint32_t>(i));
975    }
976
977    void write(const Identifier& ident)
978    {
979        const String& str = ident.string();
980        StringConstantPool::AddResult addResult = m_constantPool.add(str.impl(), m_constantPool.size());
981        if (!addResult.isNewEntry) {
982            write(StringPoolTag);
983            writeStringIndex(addResult.iterator->value);
984            return;
985        }
986
987        unsigned length = str.length();
988
989        // This condition is unlikely to happen as they would imply an ~8gb
990        // string but we should guard against it anyway
991        if (length >= StringPoolTag) {
992            fail();
993            return;
994        }
995
996        // Guard against overflow
997        if (length > (std::numeric_limits<uint32_t>::max() - sizeof(uint32_t)) / sizeof(UChar)) {
998            fail();
999            return;
1000        }
1001
1002        writeLittleEndian<uint32_t>(m_buffer, length);
1003        if (!length || str.is8Bit()) {
1004            if (!writeLittleEndianUInt16(m_buffer, str.characters8(), length))
1005                fail();
1006            return;
1007        }
1008        if (!writeLittleEndian(m_buffer, str.characters16(), length))
1009            fail();
1010    }
1011
1012    void write(const String& str)
1013    {
1014        if (str.isNull())
1015            write(m_emptyIdentifier);
1016        else
1017            write(Identifier(m_exec, str));
1018    }
1019
1020    void write(const Vector<uint8_t>& vector)
1021    {
1022        uint32_t size = vector.size();
1023        write(size);
1024        writeLittleEndian(m_buffer, vector.data(), size);
1025    }
1026
1027    void write(const File* file)
1028    {
1029        m_blobURLs.append(file->url());
1030        write(file->path());
1031        write(file->url());
1032        write(file->type());
1033        write(file->name());
1034    }
1035
1036#if ENABLE(SUBTLE_CRYPTO)
1037    void write(CryptoAlgorithmIdentifier algorithm)
1038    {
1039        switch (algorithm) {
1040        case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
1041            write(CryptoAlgorithmIdentifierTag::RSAES_PKCS1_v1_5);
1042            break;
1043        case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
1044            write(CryptoAlgorithmIdentifierTag::RSASSA_PKCS1_v1_5);
1045            break;
1046        case CryptoAlgorithmIdentifier::RSA_PSS:
1047            write(CryptoAlgorithmIdentifierTag::RSA_PSS);
1048            break;
1049        case CryptoAlgorithmIdentifier::RSA_OAEP:
1050            write(CryptoAlgorithmIdentifierTag::RSA_OAEP);
1051            break;
1052        case CryptoAlgorithmIdentifier::ECDSA:
1053            write(CryptoAlgorithmIdentifierTag::ECDSA);
1054            break;
1055        case CryptoAlgorithmIdentifier::ECDH:
1056            write(CryptoAlgorithmIdentifierTag::ECDH);
1057            break;
1058        case CryptoAlgorithmIdentifier::AES_CTR:
1059            write(CryptoAlgorithmIdentifierTag::AES_CTR);
1060            break;
1061        case CryptoAlgorithmIdentifier::AES_CBC:
1062            write(CryptoAlgorithmIdentifierTag::AES_CBC);
1063            break;
1064        case CryptoAlgorithmIdentifier::AES_CMAC:
1065            write(CryptoAlgorithmIdentifierTag::AES_CMAC);
1066            break;
1067        case CryptoAlgorithmIdentifier::AES_GCM:
1068            write(CryptoAlgorithmIdentifierTag::AES_GCM);
1069            break;
1070        case CryptoAlgorithmIdentifier::AES_CFB:
1071            write(CryptoAlgorithmIdentifierTag::AES_CFB);
1072            break;
1073        case CryptoAlgorithmIdentifier::AES_KW:
1074            write(CryptoAlgorithmIdentifierTag::AES_KW);
1075            break;
1076        case CryptoAlgorithmIdentifier::HMAC:
1077            write(CryptoAlgorithmIdentifierTag::HMAC);
1078            break;
1079        case CryptoAlgorithmIdentifier::DH:
1080            write(CryptoAlgorithmIdentifierTag::DH);
1081            break;
1082        case CryptoAlgorithmIdentifier::SHA_1:
1083            write(CryptoAlgorithmIdentifierTag::SHA_1);
1084            break;
1085        case CryptoAlgorithmIdentifier::SHA_224:
1086            write(CryptoAlgorithmIdentifierTag::SHA_224);
1087            break;
1088        case CryptoAlgorithmIdentifier::SHA_256:
1089            write(CryptoAlgorithmIdentifierTag::SHA_256);
1090            break;
1091        case CryptoAlgorithmIdentifier::SHA_384:
1092            write(CryptoAlgorithmIdentifierTag::SHA_384);
1093            break;
1094        case CryptoAlgorithmIdentifier::SHA_512:
1095            write(CryptoAlgorithmIdentifierTag::SHA_512);
1096            break;
1097        case CryptoAlgorithmIdentifier::CONCAT:
1098            write(CryptoAlgorithmIdentifierTag::CONCAT);
1099            break;
1100        case CryptoAlgorithmIdentifier::HKDF_CTR:
1101            write(CryptoAlgorithmIdentifierTag::HKDF_CTR);
1102            break;
1103        case CryptoAlgorithmIdentifier::PBKDF2:
1104            write(CryptoAlgorithmIdentifierTag::PBKDF2);
1105            break;
1106        }
1107    }
1108
1109    void write(CryptoKeyDataRSAComponents::Type type)
1110    {
1111        switch (type) {
1112        case CryptoKeyDataRSAComponents::Type::Public:
1113            write(CryptoKeyAsymmetricTypeSubtag::Public);
1114            return;
1115        case CryptoKeyDataRSAComponents::Type::Private:
1116            write(CryptoKeyAsymmetricTypeSubtag::Private);
1117            return;
1118        }
1119    }
1120
1121    void write(const CryptoKeyDataRSAComponents& key)
1122    {
1123        write(key.type());
1124        write(key.modulus());
1125        write(key.exponent());
1126        if (key.type() == CryptoKeyDataRSAComponents::Type::Public)
1127            return;
1128
1129        write(key.privateExponent());
1130
1131        unsigned primeCount = key.hasAdditionalPrivateKeyParameters() ? key.otherPrimeInfos().size() + 2 : 0;
1132        write(primeCount);
1133        if (!primeCount)
1134            return;
1135
1136        write(key.firstPrimeInfo().primeFactor);
1137        write(key.firstPrimeInfo().factorCRTExponent);
1138        write(key.secondPrimeInfo().primeFactor);
1139        write(key.secondPrimeInfo().factorCRTExponent);
1140        write(key.secondPrimeInfo().factorCRTCoefficient);
1141        for (unsigned i = 2; i < primeCount; ++i) {
1142            write(key.otherPrimeInfos()[i].primeFactor);
1143            write(key.otherPrimeInfos()[i].factorCRTExponent);
1144            write(key.otherPrimeInfos()[i].factorCRTCoefficient);
1145        }
1146    }
1147
1148    void write(const CryptoKey* key)
1149    {
1150        write(currentKeyFormatVersion);
1151
1152        write(key->extractable());
1153
1154        CryptoKeyUsage usages = key->usagesBitmap();
1155        write(countUsages(usages));
1156        if (usages & CryptoKeyUsageEncrypt)
1157            write(CryptoKeyUsageTag::Encrypt);
1158        if (usages & CryptoKeyUsageDecrypt)
1159            write(CryptoKeyUsageTag::Decrypt);
1160        if (usages & CryptoKeyUsageSign)
1161            write(CryptoKeyUsageTag::Sign);
1162        if (usages & CryptoKeyUsageVerify)
1163            write(CryptoKeyUsageTag::Verify);
1164        if (usages & CryptoKeyUsageDeriveKey)
1165            write(CryptoKeyUsageTag::DeriveKey);
1166        if (usages & CryptoKeyUsageDeriveBits)
1167            write(CryptoKeyUsageTag::DeriveBits);
1168        if (usages & CryptoKeyUsageWrapKey)
1169            write(CryptoKeyUsageTag::WrapKey);
1170        if (usages & CryptoKeyUsageUnwrapKey)
1171            write(CryptoKeyUsageTag::UnwrapKey);
1172
1173        switch (key->keyClass()) {
1174        case CryptoKeyClass::HMAC:
1175            write(CryptoKeyClassSubtag::HMAC);
1176            write(toCryptoKeyHMAC(key)->key());
1177            write(toCryptoKeyHMAC(key)->hashAlgorithmIdentifier());
1178            break;
1179        case CryptoKeyClass::AES:
1180            write(CryptoKeyClassSubtag::AES);
1181            write(key->algorithmIdentifier());
1182            write(toCryptoKeyAES(key)->key());
1183            break;
1184        case CryptoKeyClass::RSA:
1185            write(CryptoKeyClassSubtag::RSA);
1186            write(key->algorithmIdentifier());
1187            CryptoAlgorithmIdentifier hash;
1188            bool isRestrictedToHash = toCryptoKeyRSA(key)->isRestrictedToHash(hash);
1189            write(isRestrictedToHash);
1190            if (isRestrictedToHash)
1191                write(hash);
1192            write(toCryptoKeyDataRSAComponents(*key->exportData()));
1193            break;
1194        }
1195    }
1196#endif
1197
1198    void write(const uint8_t* data, unsigned length)
1199    {
1200        m_buffer.append(data, length);
1201    }
1202
1203    Vector<uint8_t>& m_buffer;
1204    Vector<String>& m_blobURLs;
1205    ObjectPool m_objectPool;
1206    ObjectPool m_transferredMessagePorts;
1207    ObjectPool m_transferredArrayBuffers;
1208    typedef HashMap<RefPtr<StringImpl>, uint32_t, IdentifierRepHash> StringConstantPool;
1209    StringConstantPool m_constantPool;
1210    Identifier m_emptyIdentifier;
1211};
1212
1213SerializationReturnCode CloneSerializer::serialize(JSValue in)
1214{
1215    Vector<uint32_t, 16> indexStack;
1216    Vector<uint32_t, 16> lengthStack;
1217    Vector<PropertyNameArray, 16> propertyStack;
1218    Vector<JSObject*, 32> inputObjectStack;
1219    Vector<MapData*, 4> mapDataStack;
1220    Vector<MapData::const_iterator, 4> iteratorStack;
1221    Vector<WalkerState, 16> stateStack;
1222    WalkerState state = StateUnknown;
1223    JSValue inValue = in;
1224    while (1) {
1225        switch (state) {
1226            arrayStartState:
1227            case ArrayStartState: {
1228                ASSERT(isArray(inValue));
1229                if (inputObjectStack.size() > maximumFilterRecursion)
1230                    return StackOverflowError;
1231
1232                JSArray* inArray = asArray(inValue);
1233                unsigned length = inArray->length();
1234                if (!startArray(inArray))
1235                    break;
1236                inputObjectStack.append(inArray);
1237                indexStack.append(0);
1238                lengthStack.append(length);
1239            }
1240            arrayStartVisitMember:
1241            FALLTHROUGH;
1242            case ArrayStartVisitMember: {
1243                JSObject* array = inputObjectStack.last();
1244                uint32_t index = indexStack.last();
1245                if (index == lengthStack.last()) {
1246                    indexStack.removeLast();
1247                    lengthStack.removeLast();
1248
1249                    propertyStack.append(PropertyNameArray(m_exec));
1250                    array->methodTable()->getOwnNonIndexPropertyNames(array, m_exec, propertyStack.last(), ExcludeDontEnumProperties);
1251                    if (propertyStack.last().size()) {
1252                        write(NonIndexPropertiesTag);
1253                        indexStack.append(0);
1254                        goto objectStartVisitMember;
1255                    }
1256                    propertyStack.removeLast();
1257
1258                    endObject();
1259                    inputObjectStack.removeLast();
1260                    break;
1261                }
1262                inValue = array->getDirectIndex(m_exec, index);
1263                if (!inValue) {
1264                    indexStack.last()++;
1265                    goto arrayStartVisitMember;
1266                }
1267
1268                write(index);
1269                SerializationReturnCode terminalCode = SuccessfullyCompleted;
1270                if (dumpIfTerminal(inValue, terminalCode)) {
1271                    if (terminalCode != SuccessfullyCompleted)
1272                        return terminalCode;
1273                    indexStack.last()++;
1274                    goto arrayStartVisitMember;
1275                }
1276                stateStack.append(ArrayEndVisitMember);
1277                goto stateUnknown;
1278            }
1279            case ArrayEndVisitMember: {
1280                indexStack.last()++;
1281                goto arrayStartVisitMember;
1282            }
1283            objectStartState:
1284            case ObjectStartState: {
1285                ASSERT(inValue.isObject());
1286                if (inputObjectStack.size() > maximumFilterRecursion)
1287                    return StackOverflowError;
1288                JSObject* inObject = asObject(inValue);
1289                if (!startObject(inObject))
1290                    break;
1291                // At this point, all supported objects other than Object
1292                // objects have been handled. If we reach this point and
1293                // the input is not an Object object then we should throw
1294                // a DataCloneError.
1295                if (inObject->classInfo() != JSFinalObject::info())
1296                    return DataCloneError;
1297                inputObjectStack.append(inObject);
1298                indexStack.append(0);
1299                propertyStack.append(PropertyNameArray(m_exec));
1300                inObject->methodTable()->getOwnPropertyNames(inObject, m_exec, propertyStack.last(), ExcludeDontEnumProperties);
1301            }
1302            objectStartVisitMember:
1303            FALLTHROUGH;
1304            case ObjectStartVisitMember: {
1305                JSObject* object = inputObjectStack.last();
1306                uint32_t index = indexStack.last();
1307                PropertyNameArray& properties = propertyStack.last();
1308                if (index == properties.size()) {
1309                    endObject();
1310                    inputObjectStack.removeLast();
1311                    indexStack.removeLast();
1312                    propertyStack.removeLast();
1313                    break;
1314                }
1315                inValue = getProperty(object, properties[index]);
1316                if (shouldTerminate())
1317                    return ExistingExceptionError;
1318
1319                if (!inValue) {
1320                    // Property was removed during serialisation
1321                    indexStack.last()++;
1322                    goto objectStartVisitMember;
1323                }
1324                write(properties[index]);
1325
1326                if (shouldTerminate())
1327                    return ExistingExceptionError;
1328
1329                SerializationReturnCode terminalCode = SuccessfullyCompleted;
1330                if (!dumpIfTerminal(inValue, terminalCode)) {
1331                    stateStack.append(ObjectEndVisitMember);
1332                    goto stateUnknown;
1333                }
1334                if (terminalCode != SuccessfullyCompleted)
1335                    return terminalCode;
1336                FALLTHROUGH;
1337            }
1338            case ObjectEndVisitMember: {
1339                if (shouldTerminate())
1340                    return ExistingExceptionError;
1341
1342                indexStack.last()++;
1343                goto objectStartVisitMember;
1344            }
1345            mapStartState: {
1346                ASSERT(inValue.isObject());
1347                if (inputObjectStack.size() > maximumFilterRecursion)
1348                    return StackOverflowError;
1349                JSMap* inMap = jsCast<JSMap*>(inValue);
1350                if (!startMap(inMap))
1351                    break;
1352                MapData* mapData = inMap->mapData();
1353                m_gcBuffer.append(mapData);
1354                mapDataStack.append(mapData);
1355                iteratorStack.append(mapData->begin());
1356                inputObjectStack.append(inMap);
1357                goto mapDataStartVisitEntry;
1358            }
1359            setStartState: {
1360                ASSERT(inValue.isObject());
1361                if (inputObjectStack.size() > maximumFilterRecursion)
1362                    return StackOverflowError;
1363                JSSet* inSet = jsCast<JSSet*>(inValue);
1364                if (!startSet(inSet))
1365                    break;
1366                MapData* mapData = inSet->mapData();
1367                m_gcBuffer.append(mapData);
1368                mapDataStack.append(mapData);
1369                iteratorStack.append(mapData->begin());
1370                inputObjectStack.append(inSet);
1371                goto mapDataStartVisitEntry;
1372            }
1373            mapDataStartVisitEntry:
1374            case MapDataStartVisitEntry: {
1375                MapData::const_iterator& ptr = iteratorStack.last();
1376                MapData* mapData = mapDataStack.last();
1377                if (ptr == mapData->end()) {
1378                    iteratorStack.removeLast();
1379                    mapDataStack.removeLast();
1380                    JSObject* object = inputObjectStack.last();
1381                    ASSERT(jsDynamicCast<JSSet*>(object) || jsDynamicCast<JSMap*>(object));
1382                    propertyStack.append(PropertyNameArray(m_exec));
1383                    object->methodTable()->getOwnPropertyNames(object, m_exec, propertyStack.last(), ExcludeDontEnumProperties);
1384                    write(NonMapPropertiesTag);
1385                    indexStack.append(0);
1386                    goto objectStartVisitMember;
1387                }
1388                inValue = ptr.key();
1389                stateStack.append(MapDataEndVisitKey);
1390                goto stateUnknown;
1391            }
1392            case MapDataEndVisitKey: {
1393                inValue = iteratorStack.last().value();
1394                stateStack.append(MapDataEndVisitValue);
1395                goto stateUnknown;
1396            }
1397            case MapDataEndVisitValue: {
1398                ++iteratorStack.last();
1399                goto mapDataStartVisitEntry;
1400            }
1401
1402            stateUnknown:
1403            case StateUnknown: {
1404                SerializationReturnCode terminalCode = SuccessfullyCompleted;
1405                if (dumpIfTerminal(inValue, terminalCode)) {
1406                    if (terminalCode != SuccessfullyCompleted)
1407                        return terminalCode;
1408                    break;
1409                }
1410
1411                if (isArray(inValue))
1412                    goto arrayStartState;
1413                if (isMap(inValue))
1414                    goto mapStartState;
1415                if (isSet(inValue))
1416                    goto setStartState;
1417                goto objectStartState;
1418            }
1419        }
1420        if (stateStack.isEmpty())
1421            break;
1422
1423        state = stateStack.last();
1424        stateStack.removeLast();
1425    }
1426    if (m_failed)
1427        return UnspecifiedError;
1428
1429    return SuccessfullyCompleted;
1430}
1431
1432typedef Vector<JSC::ArrayBufferContents> ArrayBufferContentsArray;
1433
1434class CloneDeserializer : CloneBase {
1435public:
1436    static String deserializeString(const Vector<uint8_t>& buffer)
1437    {
1438        if (buffer.isEmpty())
1439            return String();
1440        const uint8_t* ptr = buffer.begin();
1441        const uint8_t* end = buffer.end();
1442        uint32_t version;
1443        if (!readLittleEndian(ptr, end, version) || version > CurrentVersion)
1444            return String();
1445        uint8_t tag;
1446        if (!readLittleEndian(ptr, end, tag) || tag != StringTag)
1447            return String();
1448        uint32_t length;
1449        if (!readLittleEndian(ptr, end, length) || length >= StringPoolTag)
1450            return String();
1451        String str;
1452        if (!readString(ptr, end, str, length))
1453            return String();
1454        return String(str.impl());
1455    }
1456
1457    static DeserializationResult deserialize(ExecState* exec, JSGlobalObject* globalObject,
1458                                             MessagePortArray* messagePorts, ArrayBufferContentsArray* arrayBufferContentsArray,
1459                                             const Vector<uint8_t>& buffer)
1460    {
1461        if (!buffer.size())
1462            return std::make_pair(jsNull(), UnspecifiedError);
1463        CloneDeserializer deserializer(exec, globalObject, messagePorts, arrayBufferContentsArray, buffer);
1464        if (!deserializer.isValid())
1465            return std::make_pair(JSValue(), ValidationError);
1466        return deserializer.deserialize();
1467    }
1468
1469private:
1470    struct CachedString {
1471        CachedString(const String& string)
1472            : m_string(string)
1473        {
1474        }
1475
1476        JSValue jsString(ExecState* exec)
1477        {
1478            if (!m_jsString)
1479                m_jsString = JSC::jsString(exec, m_string);
1480            return m_jsString;
1481        }
1482        const String& string() { return m_string; }
1483
1484    private:
1485        String m_string;
1486        JSValue m_jsString;
1487    };
1488
1489    struct CachedStringRef {
1490        CachedStringRef()
1491            : m_base(0)
1492            , m_index(0)
1493        {
1494        }
1495        CachedStringRef(Vector<CachedString>* base, size_t index)
1496            : m_base(base)
1497            , m_index(index)
1498        {
1499        }
1500
1501        CachedString* operator->() { ASSERT(m_base); return &m_base->at(m_index); }
1502
1503    private:
1504        Vector<CachedString>* m_base;
1505        size_t m_index;
1506    };
1507
1508    CloneDeserializer(ExecState* exec, JSGlobalObject* globalObject,
1509                      MessagePortArray* messagePorts, ArrayBufferContentsArray* arrayBufferContents,
1510                      const Vector<uint8_t>& buffer)
1511        : CloneBase(exec)
1512        , m_globalObject(globalObject)
1513        , m_isDOMGlobalObject(globalObject->inherits(JSDOMGlobalObject::info()))
1514        , m_ptr(buffer.data())
1515        , m_end(buffer.data() + buffer.size())
1516        , m_version(0xFFFFFFFF)
1517        , m_messagePorts(messagePorts)
1518        , m_arrayBufferContents(arrayBufferContents)
1519        , m_arrayBuffers(arrayBufferContents ? arrayBufferContents->size() : 0)
1520    {
1521        if (!read(m_version))
1522            m_version = 0xFFFFFFFF;
1523    }
1524
1525    DeserializationResult deserialize();
1526
1527    void throwValidationError()
1528    {
1529        m_exec->vm().throwException(m_exec, createTypeError(m_exec, "Unable to deserialize data."));
1530    }
1531
1532    bool isValid() const { return m_version <= CurrentVersion; }
1533
1534    template <typename T> bool readLittleEndian(T& value)
1535    {
1536        if (m_failed || !readLittleEndian(m_ptr, m_end, value)) {
1537            fail();
1538            return false;
1539        }
1540        return true;
1541    }
1542#if ASSUME_LITTLE_ENDIAN
1543    template <typename T> static bool readLittleEndian(const uint8_t*& ptr, const uint8_t* end, T& value)
1544    {
1545        if (ptr > end - sizeof(value))
1546            return false;
1547
1548        if (sizeof(T) == 1)
1549            value = *ptr++;
1550        else {
1551            value = *reinterpret_cast<const T*>(ptr);
1552            ptr += sizeof(T);
1553        }
1554        return true;
1555    }
1556#else
1557    template <typename T> static bool readLittleEndian(const uint8_t*& ptr, const uint8_t* end, T& value)
1558    {
1559        if (ptr > end - sizeof(value))
1560            return false;
1561
1562        if (sizeof(T) == 1)
1563            value = *ptr++;
1564        else {
1565            value = 0;
1566            for (unsigned i = 0; i < sizeof(T); i++)
1567                value += ((T)*ptr++) << (i * 8);
1568        }
1569        return true;
1570    }
1571#endif
1572
1573    bool read(uint32_t& i)
1574    {
1575        return readLittleEndian(i);
1576    }
1577
1578    bool read(int32_t& i)
1579    {
1580        return readLittleEndian(*reinterpret_cast<uint32_t*>(&i));
1581    }
1582
1583    bool read(uint16_t& i)
1584    {
1585        return readLittleEndian(i);
1586    }
1587
1588    bool read(uint8_t& i)
1589    {
1590        return readLittleEndian(i);
1591    }
1592
1593    bool read(double& d)
1594    {
1595        union {
1596            double d;
1597            uint64_t i64;
1598        } u;
1599        if (!readLittleEndian(u.i64))
1600            return false;
1601        d = u.d;
1602        return true;
1603    }
1604
1605    bool read(unsigned long long& i)
1606    {
1607        return readLittleEndian(i);
1608    }
1609
1610    bool readStringIndex(uint32_t& i)
1611    {
1612        return readConstantPoolIndex(m_constantPool, i);
1613    }
1614
1615    template <class T> bool readConstantPoolIndex(const T& constantPool, uint32_t& i)
1616    {
1617        if (constantPool.size() <= 0xFF) {
1618            uint8_t i8;
1619            if (!read(i8))
1620                return false;
1621            i = i8;
1622            return true;
1623        }
1624        if (constantPool.size() <= 0xFFFF) {
1625            uint16_t i16;
1626            if (!read(i16))
1627                return false;
1628            i = i16;
1629            return true;
1630        }
1631        return read(i);
1632    }
1633
1634    static bool readString(const uint8_t*& ptr, const uint8_t* end, String& str, unsigned length)
1635    {
1636        if (length >= std::numeric_limits<int32_t>::max() / sizeof(UChar))
1637            return false;
1638
1639        unsigned size = length * sizeof(UChar);
1640        if ((end - ptr) < static_cast<int>(size))
1641            return false;
1642
1643#if ASSUME_LITTLE_ENDIAN
1644        str = String(reinterpret_cast<const UChar*>(ptr), length);
1645        ptr += length * sizeof(UChar);
1646#else
1647        Vector<UChar> buffer;
1648        buffer.reserveCapacity(length);
1649        for (unsigned i = 0; i < length; i++) {
1650            uint16_t ch;
1651            readLittleEndian(ptr, end, ch);
1652            buffer.append(ch);
1653        }
1654        str = String::adopt(buffer);
1655#endif
1656        return true;
1657    }
1658
1659    bool readStringData(CachedStringRef& cachedString)
1660    {
1661        bool scratch;
1662        return readStringData(cachedString, scratch);
1663    }
1664
1665    bool readStringData(CachedStringRef& cachedString, bool& wasTerminator)
1666    {
1667        if (m_failed)
1668            return false;
1669        uint32_t length = 0;
1670        if (!read(length))
1671            return false;
1672        if (length == TerminatorTag) {
1673            wasTerminator = true;
1674            return false;
1675        }
1676        if (length == StringPoolTag) {
1677            unsigned index = 0;
1678            if (!readStringIndex(index)) {
1679                fail();
1680                return false;
1681            }
1682            if (index >= m_constantPool.size()) {
1683                fail();
1684                return false;
1685            }
1686            cachedString = CachedStringRef(&m_constantPool, index);
1687            return true;
1688        }
1689        String str;
1690        if (!readString(m_ptr, m_end, str, length)) {
1691            fail();
1692            return false;
1693        }
1694        m_constantPool.append(str);
1695        cachedString = CachedStringRef(&m_constantPool, m_constantPool.size() - 1);
1696        return true;
1697    }
1698
1699    SerializationTag readTag()
1700    {
1701        if (m_ptr >= m_end)
1702            return ErrorTag;
1703        return static_cast<SerializationTag>(*m_ptr++);
1704    }
1705
1706    bool readArrayBufferViewSubtag(ArrayBufferViewSubtag& tag)
1707    {
1708        if (m_ptr >= m_end)
1709            return false;
1710        tag = static_cast<ArrayBufferViewSubtag>(*m_ptr++);
1711        return true;
1712    }
1713
1714    void putProperty(JSObject* object, unsigned index, JSValue value)
1715    {
1716        object->putDirectIndex(m_exec, index, value);
1717    }
1718
1719    void putProperty(JSObject* object, const Identifier& property, JSValue value)
1720    {
1721        object->putDirectMayBeIndex(m_exec, property, value);
1722    }
1723
1724    bool readFile(RefPtr<File>& file)
1725    {
1726        CachedStringRef path;
1727        if (!readStringData(path))
1728            return 0;
1729        CachedStringRef url;
1730        if (!readStringData(url))
1731            return 0;
1732        CachedStringRef type;
1733        if (!readStringData(type))
1734            return 0;
1735        CachedStringRef name;
1736        if (!readStringData(name))
1737            return 0;
1738        if (m_isDOMGlobalObject)
1739            file = File::deserialize(path->string(), URL(URL(), url->string()), type->string(), name->string());
1740        return true;
1741    }
1742
1743    bool readArrayBuffer(RefPtr<ArrayBuffer>& arrayBuffer)
1744    {
1745        uint32_t length;
1746        if (!read(length))
1747            return false;
1748        if (m_ptr + length > m_end)
1749            return false;
1750        arrayBuffer = ArrayBuffer::create(m_ptr, length);
1751        m_ptr += length;
1752        return true;
1753    }
1754
1755    bool readArrayBufferView(JSValue& arrayBufferView)
1756    {
1757        ArrayBufferViewSubtag arrayBufferViewSubtag;
1758        if (!readArrayBufferViewSubtag(arrayBufferViewSubtag))
1759            return false;
1760        uint32_t byteOffset;
1761        if (!read(byteOffset))
1762            return false;
1763        uint32_t byteLength;
1764        if (!read(byteLength))
1765            return false;
1766        JSObject* arrayBufferObj = asObject(readTerminal());
1767        if (!arrayBufferObj || !arrayBufferObj->inherits(JSArrayBuffer::info()))
1768            return false;
1769
1770        unsigned elementSize = typedArrayElementSize(arrayBufferViewSubtag);
1771        if (!elementSize)
1772            return false;
1773        unsigned length = byteLength / elementSize;
1774        if (length * elementSize != byteLength)
1775            return false;
1776
1777        RefPtr<ArrayBuffer> arrayBuffer = toArrayBuffer(arrayBufferObj);
1778        switch (arrayBufferViewSubtag) {
1779        case DataViewTag:
1780            arrayBufferView = getJSValue(DataView::create(arrayBuffer, byteOffset, length).get());
1781            return true;
1782        case Int8ArrayTag:
1783            arrayBufferView = getJSValue(Int8Array::create(arrayBuffer, byteOffset, length).get());
1784            return true;
1785        case Uint8ArrayTag:
1786            arrayBufferView = getJSValue(Uint8Array::create(arrayBuffer, byteOffset, length).get());
1787            return true;
1788        case Uint8ClampedArrayTag:
1789            arrayBufferView = getJSValue(Uint8ClampedArray::create(arrayBuffer, byteOffset, length).get());
1790            return true;
1791        case Int16ArrayTag:
1792            arrayBufferView = getJSValue(Int16Array::create(arrayBuffer, byteOffset, length).get());
1793            return true;
1794        case Uint16ArrayTag:
1795            arrayBufferView = getJSValue(Uint16Array::create(arrayBuffer, byteOffset, length).get());
1796            return true;
1797        case Int32ArrayTag:
1798            arrayBufferView = getJSValue(Int32Array::create(arrayBuffer, byteOffset, length).get());
1799            return true;
1800        case Uint32ArrayTag:
1801            arrayBufferView = getJSValue(Uint32Array::create(arrayBuffer, byteOffset, length).get());
1802            return true;
1803        case Float32ArrayTag:
1804            arrayBufferView = getJSValue(Float32Array::create(arrayBuffer, byteOffset, length).get());
1805            return true;
1806        case Float64ArrayTag:
1807            arrayBufferView = getJSValue(Float64Array::create(arrayBuffer, byteOffset, length).get());
1808            return true;
1809        default:
1810            return false;
1811        }
1812    }
1813
1814    bool read(Vector<uint8_t>& result)
1815    {
1816        ASSERT(result.isEmpty());
1817        uint32_t size;
1818        if (!read(size))
1819            return false;
1820        if (m_ptr + size > m_end)
1821            return false;
1822        result.append(m_ptr, size);
1823        m_ptr += size;
1824        return true;
1825    }
1826
1827#if ENABLE(SUBTLE_CRYPTO)
1828    bool read(CryptoAlgorithmIdentifier& result)
1829    {
1830        uint8_t algorithmTag;
1831        if (!read(algorithmTag))
1832            return false;
1833        if (algorithmTag > cryptoAlgorithmIdentifierTagMaximumValue)
1834            return false;
1835        switch (static_cast<CryptoAlgorithmIdentifierTag>(algorithmTag)) {
1836        case CryptoAlgorithmIdentifierTag::RSAES_PKCS1_v1_5:
1837            result = CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5;
1838            break;
1839        case CryptoAlgorithmIdentifierTag::RSASSA_PKCS1_v1_5:
1840            result = CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5;
1841            break;
1842        case CryptoAlgorithmIdentifierTag::RSA_PSS:
1843            result = CryptoAlgorithmIdentifier::RSA_PSS;
1844            break;
1845        case CryptoAlgorithmIdentifierTag::RSA_OAEP:
1846            result = CryptoAlgorithmIdentifier::RSA_OAEP;
1847            break;
1848        case CryptoAlgorithmIdentifierTag::ECDSA:
1849            result = CryptoAlgorithmIdentifier::ECDSA;
1850            break;
1851        case CryptoAlgorithmIdentifierTag::ECDH:
1852            result = CryptoAlgorithmIdentifier::ECDH;
1853            break;
1854        case CryptoAlgorithmIdentifierTag::AES_CTR:
1855            result = CryptoAlgorithmIdentifier::AES_CTR;
1856            break;
1857        case CryptoAlgorithmIdentifierTag::AES_CBC:
1858            result = CryptoAlgorithmIdentifier::AES_CBC;
1859            break;
1860        case CryptoAlgorithmIdentifierTag::AES_CMAC:
1861            result = CryptoAlgorithmIdentifier::AES_CMAC;
1862            break;
1863        case CryptoAlgorithmIdentifierTag::AES_GCM:
1864            result = CryptoAlgorithmIdentifier::AES_GCM;
1865            break;
1866        case CryptoAlgorithmIdentifierTag::AES_CFB:
1867            result = CryptoAlgorithmIdentifier::AES_CFB;
1868            break;
1869        case CryptoAlgorithmIdentifierTag::AES_KW:
1870            result = CryptoAlgorithmIdentifier::AES_KW;
1871            break;
1872        case CryptoAlgorithmIdentifierTag::HMAC:
1873            result = CryptoAlgorithmIdentifier::HMAC;
1874            break;
1875        case CryptoAlgorithmIdentifierTag::DH:
1876            result = CryptoAlgorithmIdentifier::DH;
1877            break;
1878        case CryptoAlgorithmIdentifierTag::SHA_1:
1879            result = CryptoAlgorithmIdentifier::SHA_1;
1880            break;
1881        case CryptoAlgorithmIdentifierTag::SHA_224:
1882            result = CryptoAlgorithmIdentifier::SHA_224;
1883            break;
1884        case CryptoAlgorithmIdentifierTag::SHA_256:
1885            result = CryptoAlgorithmIdentifier::SHA_256;
1886            break;
1887        case CryptoAlgorithmIdentifierTag::SHA_384:
1888            result = CryptoAlgorithmIdentifier::SHA_384;
1889            break;
1890        case CryptoAlgorithmIdentifierTag::SHA_512:
1891            result = CryptoAlgorithmIdentifier::SHA_512;
1892            break;
1893        case CryptoAlgorithmIdentifierTag::CONCAT:
1894            result = CryptoAlgorithmIdentifier::CONCAT;
1895            break;
1896        case CryptoAlgorithmIdentifierTag::HKDF_CTR:
1897            result = CryptoAlgorithmIdentifier::HKDF_CTR;
1898            break;
1899        case CryptoAlgorithmIdentifierTag::PBKDF2:
1900            result = CryptoAlgorithmIdentifier::PBKDF2;
1901            break;
1902        }
1903        return true;
1904    }
1905
1906    bool read(CryptoKeyClassSubtag& result)
1907    {
1908        uint8_t tag;
1909        if (!read(tag))
1910            return false;
1911        if (tag > cryptoKeyClassSubtagMaximumValue)
1912            return false;
1913        result = static_cast<CryptoKeyClassSubtag>(tag);
1914        return true;
1915    }
1916
1917    bool read(CryptoKeyUsageTag& result)
1918    {
1919        uint8_t tag;
1920        if (!read(tag))
1921            return false;
1922        if (tag > cryptoKeyUsageTagMaximumValue)
1923            return false;
1924        result = static_cast<CryptoKeyUsageTag>(tag);
1925        return true;
1926    }
1927
1928    bool read(CryptoKeyAsymmetricTypeSubtag& result)
1929    {
1930        uint8_t tag;
1931        if (!read(tag))
1932            return false;
1933        if (tag > cryptoKeyAsymmetricTypeSubtagMaximumValue)
1934            return false;
1935        result = static_cast<CryptoKeyAsymmetricTypeSubtag>(tag);
1936        return true;
1937    }
1938
1939    bool readHMACKey(bool extractable, CryptoKeyUsage usages, RefPtr<CryptoKey>& result)
1940    {
1941        Vector<uint8_t> keyData;
1942        if (!read(keyData))
1943            return false;
1944        CryptoAlgorithmIdentifier hash;
1945        if (!read(hash))
1946            return false;
1947        result = CryptoKeyHMAC::create(keyData, hash, extractable, usages);
1948        return true;
1949    }
1950
1951    bool readAESKey(bool extractable, CryptoKeyUsage usages, RefPtr<CryptoKey>& result)
1952    {
1953        CryptoAlgorithmIdentifier algorithm;
1954        if (!read(algorithm))
1955            return false;
1956        if (!CryptoKeyAES::isValidAESAlgorithm(algorithm))
1957            return false;
1958        Vector<uint8_t> keyData;
1959        if (!read(keyData))
1960            return false;
1961        result = CryptoKeyAES::create(algorithm, keyData, extractable, usages);
1962        return true;
1963    }
1964
1965    bool readRSAKey(bool extractable, CryptoKeyUsage usages, RefPtr<CryptoKey>& result)
1966    {
1967        CryptoAlgorithmIdentifier algorithm;
1968        if (!read(algorithm))
1969            return false;
1970
1971        int32_t isRestrictedToHash;
1972        CryptoAlgorithmIdentifier hash;
1973        if (!read(isRestrictedToHash))
1974            return false;
1975        if (isRestrictedToHash && !read(hash))
1976            return false;
1977
1978        CryptoKeyAsymmetricTypeSubtag type;
1979        if (!read(type))
1980            return false;
1981
1982        Vector<uint8_t> modulus;
1983        if (!read(modulus))
1984            return false;
1985        Vector<uint8_t> exponent;
1986        if (!read(exponent))
1987            return false;
1988
1989        if (type == CryptoKeyAsymmetricTypeSubtag::Public) {
1990            auto keyData = CryptoKeyDataRSAComponents::createPublic(modulus, exponent);
1991            auto key = CryptoKeyRSA::create(algorithm, *keyData, extractable, usages);
1992            if (isRestrictedToHash)
1993                key->restrictToHash(hash);
1994            result = WTF::move(key);
1995            return true;
1996        }
1997
1998        Vector<uint8_t> privateExponent;
1999        if (!read(privateExponent))
2000            return false;
2001
2002        uint32_t primeCount;
2003        if (!read(primeCount))
2004            return false;
2005
2006        if (!primeCount) {
2007            auto keyData = CryptoKeyDataRSAComponents::createPrivate(modulus, exponent, privateExponent);
2008            auto key = CryptoKeyRSA::create(algorithm, *keyData, extractable, usages);
2009            if (isRestrictedToHash)
2010                key->restrictToHash(hash);
2011            result = WTF::move(key);
2012            return true;
2013        }
2014
2015        if (primeCount < 2)
2016            return false;
2017
2018        CryptoKeyDataRSAComponents::PrimeInfo firstPrimeInfo;
2019        CryptoKeyDataRSAComponents::PrimeInfo secondPrimeInfo;
2020        Vector<CryptoKeyDataRSAComponents::PrimeInfo> otherPrimeInfos(primeCount - 2);
2021
2022        if (!read(firstPrimeInfo.primeFactor))
2023            return false;
2024        if (!read(firstPrimeInfo.factorCRTExponent))
2025            return false;
2026        if (!read(secondPrimeInfo.primeFactor))
2027            return false;
2028        if (!read(secondPrimeInfo.factorCRTExponent))
2029            return false;
2030        if (!read(secondPrimeInfo.factorCRTCoefficient))
2031            return false;
2032        for (unsigned i = 2; i < primeCount; ++i) {
2033            if (!read(otherPrimeInfos[i].primeFactor))
2034                return false;
2035            if (!read(otherPrimeInfos[i].factorCRTExponent))
2036                return false;
2037            if (!read(otherPrimeInfos[i].factorCRTCoefficient))
2038                return false;
2039        }
2040
2041        auto keyData = CryptoKeyDataRSAComponents::createPrivateWithAdditionalData(modulus, exponent, privateExponent, firstPrimeInfo, secondPrimeInfo, otherPrimeInfos);
2042        auto key = CryptoKeyRSA::create(algorithm, *keyData, extractable, usages);
2043        if (isRestrictedToHash)
2044            key->restrictToHash(hash);
2045        result = WTF::move(key);
2046        return true;
2047    }
2048
2049    bool readCryptoKey(JSValue& cryptoKey)
2050    {
2051        uint32_t keyFormatVersion;
2052        if (!read(keyFormatVersion) || keyFormatVersion > currentKeyFormatVersion)
2053            return false;
2054
2055        int32_t extractable;
2056        if (!read(extractable))
2057            return false;
2058
2059        uint32_t usagesCount;
2060        if (!read(usagesCount))
2061            return false;
2062
2063        CryptoKeyUsage usages = 0;
2064        for (uint32_t i = 0; i < usagesCount; ++i) {
2065            CryptoKeyUsageTag usage;
2066            if (!read(usage))
2067                return false;
2068            switch (usage) {
2069            case CryptoKeyUsageTag::Encrypt:
2070                usages |= CryptoKeyUsageEncrypt;
2071                break;
2072            case CryptoKeyUsageTag::Decrypt:
2073                usages |= CryptoKeyUsageDecrypt;
2074                break;
2075            case CryptoKeyUsageTag::Sign:
2076                usages |= CryptoKeyUsageSign;
2077                break;
2078            case CryptoKeyUsageTag::Verify:
2079                usages |= CryptoKeyUsageVerify;
2080                break;
2081            case CryptoKeyUsageTag::DeriveKey:
2082                usages |= CryptoKeyUsageDeriveKey;
2083                break;
2084            case CryptoKeyUsageTag::DeriveBits:
2085                usages |= CryptoKeyUsageDeriveBits;
2086                break;
2087            case CryptoKeyUsageTag::WrapKey:
2088                usages |= CryptoKeyUsageWrapKey;
2089                break;
2090            case CryptoKeyUsageTag::UnwrapKey:
2091                usages |= CryptoKeyUsageUnwrapKey;
2092                break;
2093            }
2094        }
2095
2096        CryptoKeyClassSubtag cryptoKeyClass;
2097        if (!read(cryptoKeyClass))
2098            return false;
2099        RefPtr<CryptoKey> result;
2100        switch (cryptoKeyClass) {
2101        case CryptoKeyClassSubtag::HMAC:
2102            if (!readHMACKey(extractable, usages, result))
2103                return false;
2104            break;
2105        case CryptoKeyClassSubtag::AES:
2106            if (!readAESKey(extractable, usages, result))
2107                return false;
2108            break;
2109        case CryptoKeyClassSubtag::RSA:
2110            if (!readRSAKey(extractable, usages, result))
2111                return false;
2112            break;
2113        }
2114        cryptoKey = getJSValue(result.get());
2115        return true;
2116    }
2117#endif
2118
2119    template<class T>
2120    JSValue getJSValue(T* nativeObj)
2121    {
2122        return toJS(m_exec, jsCast<JSDOMGlobalObject*>(m_globalObject), nativeObj);
2123    }
2124
2125    JSValue readTerminal()
2126    {
2127        SerializationTag tag = readTag();
2128        switch (tag) {
2129        case UndefinedTag:
2130            return jsUndefined();
2131        case NullTag:
2132            return jsNull();
2133        case IntTag: {
2134            int32_t i;
2135            if (!read(i))
2136                return JSValue();
2137            return jsNumber(i);
2138        }
2139        case ZeroTag:
2140            return jsNumber(0);
2141        case OneTag:
2142            return jsNumber(1);
2143        case FalseTag:
2144            return jsBoolean(false);
2145        case TrueTag:
2146            return jsBoolean(true);
2147        case FalseObjectTag: {
2148            BooleanObject* obj = BooleanObject::create(m_exec->vm(), m_globalObject->booleanObjectStructure());
2149            obj->setInternalValue(m_exec->vm(), jsBoolean(false));
2150            m_gcBuffer.append(obj);
2151            return obj;
2152        }
2153        case TrueObjectTag: {
2154            BooleanObject* obj = BooleanObject::create(m_exec->vm(), m_globalObject->booleanObjectStructure());
2155            obj->setInternalValue(m_exec->vm(), jsBoolean(true));
2156             m_gcBuffer.append(obj);
2157            return obj;
2158        }
2159        case DoubleTag: {
2160            double d;
2161            if (!read(d))
2162                return JSValue();
2163            return jsNumber(d);
2164        }
2165        case NumberObjectTag: {
2166            double d;
2167            if (!read(d))
2168                return JSValue();
2169            NumberObject* obj = constructNumber(m_exec, m_globalObject, jsNumber(d));
2170            m_gcBuffer.append(obj);
2171            return obj;
2172        }
2173        case DateTag: {
2174            double d;
2175            if (!read(d))
2176                return JSValue();
2177            return DateInstance::create(m_exec->vm(), m_globalObject->dateStructure(), d);
2178        }
2179        case FileTag: {
2180            RefPtr<File> file;
2181            if (!readFile(file))
2182                return JSValue();
2183            if (!m_isDOMGlobalObject)
2184                return jsNull();
2185            return toJS(m_exec, jsCast<JSDOMGlobalObject*>(m_globalObject), file.get());
2186        }
2187        case FileListTag: {
2188            unsigned length = 0;
2189            if (!read(length))
2190                return JSValue();
2191            Vector<RefPtr<File>> files;
2192            for (unsigned i = 0; i < length; i++) {
2193                RefPtr<File> file;
2194                if (!readFile(file))
2195                    return JSValue();
2196                if (m_isDOMGlobalObject)
2197                    files.append(WTF::move(file));
2198            }
2199            if (!m_isDOMGlobalObject)
2200                return jsNull();
2201            return getJSValue(FileList::create(WTF::move(files)).get());
2202        }
2203        case ImageDataTag: {
2204            int32_t width;
2205            if (!read(width))
2206                return JSValue();
2207            int32_t height;
2208            if (!read(height))
2209                return JSValue();
2210            uint32_t length;
2211            if (!read(length))
2212                return JSValue();
2213            if (m_end < ((uint8_t*)0) + length || m_ptr > m_end - length) {
2214                fail();
2215                return JSValue();
2216            }
2217            if (!m_isDOMGlobalObject) {
2218                m_ptr += length;
2219                return jsNull();
2220            }
2221            RefPtr<ImageData> result = ImageData::create(IntSize(width, height));
2222            memcpy(result->data()->data(), m_ptr, length);
2223            m_ptr += length;
2224            return getJSValue(result.get());
2225        }
2226        case BlobTag: {
2227            CachedStringRef url;
2228            if (!readStringData(url))
2229                return JSValue();
2230            CachedStringRef type;
2231            if (!readStringData(type))
2232                return JSValue();
2233            unsigned long long size = 0;
2234            if (!read(size))
2235                return JSValue();
2236            if (!m_isDOMGlobalObject)
2237                return jsNull();
2238            return getJSValue(Blob::deserialize(URL(URL(), url->string()), type->string(), size).get());
2239        }
2240        case StringTag: {
2241            CachedStringRef cachedString;
2242            if (!readStringData(cachedString))
2243                return JSValue();
2244            return cachedString->jsString(m_exec);
2245        }
2246        case EmptyStringTag:
2247            return jsEmptyString(&m_exec->vm());
2248        case StringObjectTag: {
2249            CachedStringRef cachedString;
2250            if (!readStringData(cachedString))
2251                return JSValue();
2252            StringObject* obj = constructString(m_exec->vm(), m_globalObject, cachedString->jsString(m_exec));
2253            m_gcBuffer.append(obj);
2254            return obj;
2255        }
2256        case EmptyStringObjectTag: {
2257            VM& vm = m_exec->vm();
2258            StringObject* obj = constructString(vm, m_globalObject, jsEmptyString(&vm));
2259            m_gcBuffer.append(obj);
2260            return obj;
2261        }
2262        case RegExpTag: {
2263            CachedStringRef pattern;
2264            if (!readStringData(pattern))
2265                return JSValue();
2266            CachedStringRef flags;
2267            if (!readStringData(flags))
2268                return JSValue();
2269            RegExpFlags reFlags = regExpFlags(flags->string());
2270            ASSERT(reFlags != InvalidFlags);
2271            VM& vm = m_exec->vm();
2272            RegExp* regExp = RegExp::create(vm, pattern->string(), reFlags);
2273            return RegExpObject::create(vm, m_globalObject->regExpStructure(), regExp);
2274        }
2275        case ObjectReferenceTag: {
2276            unsigned index = 0;
2277            if (!readConstantPoolIndex(m_gcBuffer, index)) {
2278                fail();
2279                return JSValue();
2280            }
2281            return m_gcBuffer.at(index);
2282        }
2283        case MessagePortReferenceTag: {
2284            uint32_t index;
2285            bool indexSuccessfullyRead = read(index);
2286            if (!indexSuccessfullyRead || !m_messagePorts || index >= m_messagePorts->size()) {
2287                fail();
2288                return JSValue();
2289            }
2290            return getJSValue(m_messagePorts->at(index).get());
2291        }
2292        case ArrayBufferTag: {
2293            RefPtr<ArrayBuffer> arrayBuffer;
2294            if (!readArrayBuffer(arrayBuffer)) {
2295                fail();
2296                return JSValue();
2297            }
2298            JSValue result = getJSValue(arrayBuffer.get());
2299            m_gcBuffer.append(result);
2300            return result;
2301        }
2302        case ArrayBufferTransferTag: {
2303            uint32_t index;
2304            bool indexSuccessfullyRead = read(index);
2305            if (!indexSuccessfullyRead || index >= m_arrayBuffers.size()) {
2306                fail();
2307                return JSValue();
2308            }
2309
2310            if (!m_arrayBuffers[index])
2311                m_arrayBuffers[index] = ArrayBuffer::create(m_arrayBufferContents->at(index));
2312
2313            return getJSValue(m_arrayBuffers[index].get());
2314        }
2315        case ArrayBufferViewTag: {
2316            JSValue arrayBufferView;
2317            if (!readArrayBufferView(arrayBufferView)) {
2318                fail();
2319                return JSValue();
2320            }
2321            m_gcBuffer.append(arrayBufferView);
2322            return arrayBufferView;
2323        }
2324#if ENABLE(SUBTLE_CRYPTO)
2325        case CryptoKeyTag: {
2326            Vector<uint8_t> wrappedKey;
2327            if (!read(wrappedKey)) {
2328                fail();
2329                return JSValue();
2330            }
2331            Vector<uint8_t> serializedKey;
2332            if (!unwrapCryptoKey(m_exec, wrappedKey, serializedKey)) {
2333                fail();
2334                return JSValue();
2335            }
2336            JSValue cryptoKey;
2337            CloneDeserializer rawKeyDeserializer(m_exec, m_globalObject, nullptr, nullptr, serializedKey);
2338            if (!rawKeyDeserializer.readCryptoKey(cryptoKey)) {
2339                fail();
2340                return JSValue();
2341            }
2342            m_gcBuffer.append(cryptoKey);
2343            return cryptoKey;
2344        }
2345#endif
2346        default:
2347            m_ptr--; // Push the tag back
2348            return JSValue();
2349        }
2350    }
2351
2352    bool consumeMapDataTerminationIfPossible()
2353    {
2354        if (readTag() == NonMapPropertiesTag)
2355            return true;
2356        m_ptr--;
2357        return false;
2358    }
2359
2360    JSGlobalObject* m_globalObject;
2361    bool m_isDOMGlobalObject;
2362    const uint8_t* m_ptr;
2363    const uint8_t* m_end;
2364    unsigned m_version;
2365    Vector<CachedString> m_constantPool;
2366    MessagePortArray* m_messagePorts;
2367    ArrayBufferContentsArray* m_arrayBufferContents;
2368    ArrayBufferArray m_arrayBuffers;
2369};
2370
2371DeserializationResult CloneDeserializer::deserialize()
2372{
2373    Vector<uint32_t, 16> indexStack;
2374    Vector<Identifier, 16> propertyNameStack;
2375    Vector<JSObject*, 32> outputObjectStack;
2376    Vector<JSValue, 4> keyStack;
2377    Vector<MapData*, 4> mapDataStack;
2378    Vector<WalkerState, 16> stateStack;
2379    WalkerState state = StateUnknown;
2380    JSValue outValue;
2381
2382    while (1) {
2383        switch (state) {
2384        arrayStartState:
2385        case ArrayStartState: {
2386            uint32_t length;
2387            if (!read(length)) {
2388                fail();
2389                goto error;
2390            }
2391            JSArray* outArray = constructEmptyArray(m_exec, 0, m_globalObject, length);
2392            m_gcBuffer.append(outArray);
2393            outputObjectStack.append(outArray);
2394        }
2395        arrayStartVisitMember:
2396        FALLTHROUGH;
2397        case ArrayStartVisitMember: {
2398            uint32_t index;
2399            if (!read(index)) {
2400                fail();
2401                goto error;
2402            }
2403            if (index == TerminatorTag) {
2404                JSObject* outArray = outputObjectStack.last();
2405                outValue = outArray;
2406                outputObjectStack.removeLast();
2407                break;
2408            } else if (index == NonIndexPropertiesTag) {
2409                goto objectStartVisitMember;
2410            }
2411
2412            if (JSValue terminal = readTerminal()) {
2413                putProperty(outputObjectStack.last(), index, terminal);
2414                goto arrayStartVisitMember;
2415            }
2416            if (m_failed)
2417                goto error;
2418            indexStack.append(index);
2419            stateStack.append(ArrayEndVisitMember);
2420            goto stateUnknown;
2421        }
2422        case ArrayEndVisitMember: {
2423            JSObject* outArray = outputObjectStack.last();
2424            putProperty(outArray, indexStack.last(), outValue);
2425            indexStack.removeLast();
2426            goto arrayStartVisitMember;
2427        }
2428        objectStartState:
2429        case ObjectStartState: {
2430            if (outputObjectStack.size() > maximumFilterRecursion)
2431                return std::make_pair(JSValue(), StackOverflowError);
2432            JSObject* outObject = constructEmptyObject(m_exec, m_globalObject->objectPrototype());
2433            m_gcBuffer.append(outObject);
2434            outputObjectStack.append(outObject);
2435        }
2436        objectStartVisitMember:
2437        FALLTHROUGH;
2438        case ObjectStartVisitMember: {
2439            CachedStringRef cachedString;
2440            bool wasTerminator = false;
2441            if (!readStringData(cachedString, wasTerminator)) {
2442                if (!wasTerminator)
2443                    goto error;
2444
2445                JSObject* outObject = outputObjectStack.last();
2446                outValue = outObject;
2447                outputObjectStack.removeLast();
2448                break;
2449            }
2450
2451            if (JSValue terminal = readTerminal()) {
2452                putProperty(outputObjectStack.last(), Identifier(m_exec, cachedString->string()), terminal);
2453                goto objectStartVisitMember;
2454            }
2455            stateStack.append(ObjectEndVisitMember);
2456            propertyNameStack.append(Identifier(m_exec, cachedString->string()));
2457            goto stateUnknown;
2458        }
2459        case ObjectEndVisitMember: {
2460            putProperty(outputObjectStack.last(), propertyNameStack.last(), outValue);
2461            propertyNameStack.removeLast();
2462            goto objectStartVisitMember;
2463        }
2464        mapObjectStartState: {
2465            if (outputObjectStack.size() > maximumFilterRecursion)
2466                return std::make_pair(JSValue(), StackOverflowError);
2467            JSMap* map = JSMap::create(m_exec->vm(), m_globalObject->mapStructure());
2468            m_gcBuffer.append(map);
2469            outputObjectStack.append(map);
2470            MapData* mapData = map->mapData();
2471            mapDataStack.append(mapData);
2472            goto mapDataStartVisitEntry;
2473        }
2474        setObjectStartState: {
2475            if (outputObjectStack.size() > maximumFilterRecursion)
2476                return std::make_pair(JSValue(), StackOverflowError);
2477            JSSet* set = JSSet::create(m_exec->vm(), m_globalObject->setStructure());
2478            m_gcBuffer.append(set);
2479            outputObjectStack.append(set);
2480            MapData* mapData = set->mapData();
2481            mapDataStack.append(mapData);
2482            goto mapDataStartVisitEntry;
2483        }
2484        mapDataStartVisitEntry:
2485        case MapDataStartVisitEntry: {
2486            if (consumeMapDataTerminationIfPossible()) {
2487                mapDataStack.removeLast();
2488                goto objectStartVisitMember;
2489            }
2490            stateStack.append(MapDataEndVisitKey);
2491            goto stateUnknown;
2492        }
2493
2494        case MapDataEndVisitKey: {
2495            keyStack.append(outValue);
2496            stateStack.append(MapDataEndVisitValue);
2497            goto stateUnknown;
2498        }
2499
2500        case MapDataEndVisitValue: {
2501            mapDataStack.last()->set(m_exec, keyStack.last(), outValue);
2502            keyStack.removeLast();
2503            goto mapDataStartVisitEntry;
2504        }
2505        stateUnknown:
2506        case StateUnknown:
2507            if (JSValue terminal = readTerminal()) {
2508                outValue = terminal;
2509                break;
2510            }
2511            SerializationTag tag = readTag();
2512            if (tag == ArrayTag)
2513                goto arrayStartState;
2514            if (tag == ObjectTag)
2515                goto objectStartState;
2516            if (tag == MapObjectTag)
2517                goto mapObjectStartState;
2518            if (tag == SetObjectTag)
2519                goto setObjectStartState;
2520            goto error;
2521        }
2522        if (stateStack.isEmpty())
2523            break;
2524
2525        state = stateStack.last();
2526        stateStack.removeLast();
2527    }
2528    ASSERT(outValue);
2529    ASSERT(!m_failed);
2530    return std::make_pair(outValue, SuccessfullyCompleted);
2531error:
2532    fail();
2533    return std::make_pair(JSValue(), ValidationError);
2534}
2535
2536void SerializedScriptValue::addBlobURL(const String& string)
2537{
2538    m_blobURLs.append(Vector<uint16_t>());
2539    m_blobURLs.last().reserveCapacity(string.length());
2540    for (size_t i = 0; i < string.length(); i++)
2541        m_blobURLs.last().append(string.characterAt(i));
2542    m_blobURLs.last().resize(m_blobURLs.last().size());
2543}
2544
2545SerializedScriptValue::~SerializedScriptValue()
2546{
2547}
2548
2549SerializedScriptValue::SerializedScriptValue(const Vector<uint8_t>& buffer)
2550    : m_data(buffer)
2551{
2552}
2553
2554SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer)
2555{
2556    m_data.swap(buffer);
2557}
2558
2559SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer, Vector<String>& blobURLs)
2560{
2561    m_data.swap(buffer);
2562    for (auto& string : blobURLs)
2563        addBlobURL(string);
2564}
2565
2566SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer, Vector<String>& blobURLs, PassOwnPtr<ArrayBufferContentsArray> arrayBufferContentsArray)
2567    : m_arrayBufferContentsArray(arrayBufferContentsArray)
2568{
2569    m_data.swap(buffer);
2570    for (auto& string : blobURLs)
2571        addBlobURL(string);
2572}
2573
2574PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValue::transferArrayBuffers(
2575    ExecState* exec, ArrayBufferArray& arrayBuffers, SerializationReturnCode& code)
2576{
2577    for (size_t i = 0; i < arrayBuffers.size(); i++) {
2578        if (arrayBuffers[i]->isNeutered()) {
2579            code = ValidationError;
2580            return nullptr;
2581        }
2582    }
2583
2584    OwnPtr<ArrayBufferContentsArray> contents = adoptPtr(new ArrayBufferContentsArray(arrayBuffers.size()));
2585    Vector<Ref<DOMWrapperWorld>> worlds;
2586    static_cast<WebCoreJSClientData*>(exec->vm().clientData)->getAllWorlds(worlds);
2587
2588    HashSet<JSC::ArrayBuffer*> visited;
2589    for (size_t arrayBufferIndex = 0; arrayBufferIndex < arrayBuffers.size(); arrayBufferIndex++) {
2590        if (visited.contains(arrayBuffers[arrayBufferIndex].get()))
2591            continue;
2592        visited.add(arrayBuffers[arrayBufferIndex].get());
2593
2594        bool result = arrayBuffers[arrayBufferIndex]->transfer(contents->at(arrayBufferIndex));
2595        if (!result) {
2596            code = ValidationError;
2597            return nullptr;
2598        }
2599    }
2600    return contents.release();
2601}
2602
2603
2604PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(ExecState* exec, JSValue value,
2605                                                                MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers,
2606                                                                SerializationErrorMode throwExceptions)
2607{
2608    Vector<uint8_t> buffer;
2609    Vector<String> blobURLs;
2610    SerializationReturnCode code = CloneSerializer::serialize(exec, value, messagePorts, arrayBuffers, blobURLs, buffer);
2611
2612    OwnPtr<ArrayBufferContentsArray> arrayBufferContentsArray;
2613
2614    if (arrayBuffers && serializationDidCompleteSuccessfully(code))
2615        arrayBufferContentsArray = transferArrayBuffers(exec, *arrayBuffers, code);
2616
2617    if (throwExceptions == Throwing)
2618        maybeThrowExceptionIfSerializationFailed(exec, code);
2619
2620    if (!serializationDidCompleteSuccessfully(code))
2621        return 0;
2622
2623    return adoptRef(new SerializedScriptValue(buffer, blobURLs, arrayBufferContentsArray.release()));
2624}
2625
2626PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& string)
2627{
2628    Vector<uint8_t> buffer;
2629    if (!CloneSerializer::serialize(string, buffer))
2630        return 0;
2631    return adoptRef(new SerializedScriptValue(buffer));
2632}
2633
2634#if ENABLE(INDEXED_DATABASE)
2635PassRefPtr<SerializedScriptValue> SerializedScriptValue::numberValue(double value)
2636{
2637    Vector<uint8_t> buffer;
2638    CloneSerializer::serializeNumber(value, buffer);
2639    return adoptRef(new SerializedScriptValue(buffer));
2640}
2641
2642PassRefPtr<SerializedScriptValue> SerializedScriptValue::undefinedValue()
2643{
2644    Vector<uint8_t> buffer;
2645    CloneSerializer::serializeUndefined(buffer);
2646    return adoptRef(new SerializedScriptValue(buffer));
2647}
2648#endif
2649
2650PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(JSContextRef originContext, JSValueRef apiValue, JSValueRef* exception)
2651{
2652    ExecState* exec = toJS(originContext);
2653    JSLockHolder locker(exec);
2654    JSValue value = toJS(exec, apiValue);
2655    RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::create(exec, value, nullptr, nullptr);
2656    if (exec->hadException()) {
2657        if (exception)
2658            *exception = toRef(exec, exec->exception());
2659        exec->clearException();
2660        return 0;
2661    }
2662    ASSERT(serializedValue);
2663    return serializedValue.release();
2664}
2665
2666String SerializedScriptValue::toString()
2667{
2668    return CloneDeserializer::deserializeString(m_data);
2669}
2670
2671JSValue SerializedScriptValue::deserialize(ExecState* exec, JSGlobalObject* globalObject,
2672                                           MessagePortArray* messagePorts, SerializationErrorMode throwExceptions)
2673{
2674    DeserializationResult result = CloneDeserializer::deserialize(exec, globalObject, messagePorts,
2675                                                                  m_arrayBufferContentsArray.get(), m_data);
2676    if (throwExceptions == Throwing)
2677        maybeThrowExceptionIfSerializationFailed(exec, result.second);
2678    return result.first ? result.first : jsNull();
2679}
2680
2681JSValueRef SerializedScriptValue::deserialize(JSContextRef destinationContext, JSValueRef* exception)
2682{
2683    ExecState* exec = toJS(destinationContext);
2684    JSLockHolder locker(exec);
2685    JSValue value = deserialize(exec, exec->lexicalGlobalObject(), nullptr);
2686    if (exec->hadException()) {
2687        if (exception)
2688            *exception = toRef(exec, exec->exception());
2689        exec->clearException();
2690        return nullptr;
2691    }
2692    ASSERT(value);
2693    return toRef(exec, value);
2694}
2695
2696PassRefPtr<SerializedScriptValue> SerializedScriptValue::nullValue()
2697{
2698    Vector<uint8_t> buffer;
2699    return adoptRef(new SerializedScriptValue(buffer));
2700}
2701
2702void SerializedScriptValue::maybeThrowExceptionIfSerializationFailed(ExecState* exec, SerializationReturnCode code)
2703{
2704    if (code == SuccessfullyCompleted)
2705        return;
2706
2707    switch (code) {
2708    case StackOverflowError:
2709        exec->vm().throwException(exec, createStackOverflowError(exec));
2710        break;
2711    case ValidationError:
2712        exec->vm().throwException(exec, createTypeError(exec, "Unable to deserialize data."));
2713        break;
2714    case DataCloneError:
2715        setDOMException(exec, DATA_CLONE_ERR);
2716        break;
2717    case ExistingExceptionError:
2718        break;
2719    case UnspecifiedError:
2720        break;
2721    default:
2722        ASSERT_NOT_REACHED();
2723    }
2724}
2725
2726bool SerializedScriptValue::serializationDidCompleteSuccessfully(SerializationReturnCode code)
2727{
2728    return (code == SuccessfullyCompleted);
2729}
2730
2731uint32_t SerializedScriptValue::wireFormatVersion()
2732{
2733    return CurrentVersion;
2734}
2735
2736}
2737