Generate Element casting helper functions
[WebKit.git] / Source / WebCore / bindings / js / SerializedScriptValue.cpp
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
76 using 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
84 namespace WebCore {
85
86 static const unsigned maximumFilterRecursion = 40000;
87
88 enum 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
93 enum 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
131 enum 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
144 static 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
169 const uint32_t currentKeyFormatVersion = 1;
170
171 enum class CryptoKeyClassSubtag {
172     HMAC = 0,
173     AES = 1,
174     RSA = 2
175 };
176 const uint8_t cryptoKeyClassSubtagMaximumValue = 2;
177
178 enum class CryptoKeyAsymmetricTypeSubtag {
179     Public = 0,
180     Private = 1
181 };
182 const uint8_t cryptoKeyAsymmetricTypeSubtagMaximumValue = 1;
183
184 enum 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 };
194 const uint8_t cryptoKeyUsageTagMaximumValue = 7;
195
196 enum 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 };
220 const uint8_t cryptoAlgorithmIdentifierTagMaximumValue = 21;
221
222 static 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  */
245 static const unsigned CurrentVersion = 5;
246 static const unsigned TerminatorTag = 0xFFFFFFFF;
247 static const unsigned StringPoolTag = 0xFFFFFFFE;
248 static 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
363 typedef std::pair<JSC::JSValue, SerializationReturnCode> DeserializationResult;
364
365 class CloneBase {
366 protected:
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)
394 static 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
402 static 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
412 template <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
417 template <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
426 template <> void writeLittleEndian<uint8_t>(Vector<uint8_t>& buffer, uint8_t value)
427 {
428     buffer.append(value);
429 }
430
431 template <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
450 static 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
463 template <> 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
469 class CloneSerializer : CloneBase {
470 public:
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
517 private:
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 = JSFile::toWrapped(obj)) {
788                 write(FileTag);
789                 write(file);
790                 return true;
791             }
792             if (FileList* list = JSFileList::toWrapped(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 = JSBlob::toWrapped(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 = JSImageData::toWrapped(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 = JSCryptoKey::toWrapped(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
1213 SerializationReturnCode 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
1432 typedef Vector<JSC::ArrayBufferContents> ArrayBufferContentsArray;
1433
1434 class CloneDeserializer : CloneBase {
1435 public:
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
1469 private:
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
2371 DeserializationResult 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);
2531 error:
2532     fail();
2533     return std::make_pair(JSValue(), ValidationError);
2534 }
2535
2536 void 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
2545 SerializedScriptValue::~SerializedScriptValue()
2546 {
2547 }
2548
2549 SerializedScriptValue::SerializedScriptValue(const Vector<uint8_t>& buffer)
2550     : m_data(buffer)
2551 {
2552 }
2553
2554 SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer)
2555 {
2556     m_data.swap(buffer);
2557 }
2558
2559 SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer, Vector<String>& blobURLs)
2560 {
2561     m_data.swap(buffer);
2562     for (auto& string : blobURLs)
2563         addBlobURL(string);
2564 }
2565
2566 SerializedScriptValue::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
2574 PassOwnPtr<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
2604 PassRefPtr<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
2626 PassRefPtr<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)
2635 PassRefPtr<SerializedScriptValue> SerializedScriptValue::numberValue(double value)
2636 {
2637     Vector<uint8_t> buffer;
2638     CloneSerializer::serializeNumber(value, buffer);
2639     return adoptRef(new SerializedScriptValue(buffer));
2640 }
2641
2642 PassRefPtr<SerializedScriptValue> SerializedScriptValue::undefinedValue()
2643 {
2644     Vector<uint8_t> buffer;
2645     CloneSerializer::serializeUndefined(buffer);
2646     return adoptRef(new SerializedScriptValue(buffer));
2647 }
2648 #endif
2649
2650 PassRefPtr<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
2666 String SerializedScriptValue::toString()
2667 {
2668     return CloneDeserializer::deserializeString(m_data);
2669 }
2670
2671 JSValue 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
2681 JSValueRef 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
2696 PassRefPtr<SerializedScriptValue> SerializedScriptValue::nullValue()
2697 {
2698     Vector<uint8_t> buffer;
2699     return adoptRef(new SerializedScriptValue(buffer));
2700 }
2701
2702 void 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
2726 bool SerializedScriptValue::serializationDidCompleteSuccessfully(SerializationReturnCode code)
2727 {
2728     return (code == SuccessfullyCompleted);
2729 }
2730
2731 uint32_t SerializedScriptValue::wireFormatVersion()
2732 {
2733     return CurrentVersion;
2734 }
2735
2736 }