Replace WTF::move with WTFMove
[WebKit-https.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/Exception.h>
59 #include <runtime/ExceptionHelpers.h>
60 #include <runtime/JSArrayBuffer.h>
61 #include <runtime/JSArrayBufferView.h>
62 #include <runtime/JSCInlines.h>
63 #include <runtime/JSDataView.h>
64 #include <runtime/JSMap.h>
65 #include <runtime/JSMapIterator.h>
66 #include <runtime/JSSet.h>
67 #include <runtime/JSSetIterator.h>
68 #include <runtime/JSTypedArrays.h>
69 #include <runtime/MapData.h>
70 #include <runtime/MapDataInlines.h>
71 #include <runtime/ObjectConstructor.h>
72 #include <runtime/PropertyNameArray.h>
73 #include <runtime/RegExp.h>
74 #include <runtime/RegExpObject.h>
75 #include <runtime/TypedArrayInlines.h>
76 #include <runtime/TypedArrays.h>
77 #include <wtf/HashTraits.h>
78 #include <wtf/Vector.h>
79
80 using namespace JSC;
81
82 #if CPU(BIG_ENDIAN) || CPU(MIDDLE_ENDIAN) || CPU(NEEDS_ALIGNED_ACCESS)
83 #define ASSUME_LITTLE_ENDIAN 0
84 #else
85 #define ASSUME_LITTLE_ENDIAN 1
86 #endif
87
88 namespace WebCore {
89
90 static const unsigned maximumFilterRecursion = 40000;
91
92 enum WalkerState { StateUnknown, ArrayStartState, ArrayStartVisitMember, ArrayEndVisitMember,
93     ObjectStartState, ObjectStartVisitMember, ObjectEndVisitMember,
94     MapDataStartVisitEntry, MapDataEndVisitKey, MapDataEndVisitValue,
95     SetDataStartVisitEntry, SetDataEndVisitKey };
96
97 // These can't be reordered, and any new types must be added to the end of the list
98 enum SerializationTag {
99     ArrayTag = 1,
100     ObjectTag = 2,
101     UndefinedTag = 3,
102     NullTag = 4,
103     IntTag = 5,
104     ZeroTag = 6,
105     OneTag = 7,
106     FalseTag = 8,
107     TrueTag = 9,
108     DoubleTag = 10,
109     DateTag = 11,
110     FileTag = 12,
111     FileListTag = 13,
112     ImageDataTag = 14,
113     BlobTag = 15,
114     StringTag = 16,
115     EmptyStringTag = 17,
116     RegExpTag = 18,
117     ObjectReferenceTag = 19,
118     MessagePortReferenceTag = 20,
119     ArrayBufferTag = 21,
120     ArrayBufferViewTag = 22,
121     ArrayBufferTransferTag = 23,
122     TrueObjectTag = 24,
123     FalseObjectTag = 25,
124     StringObjectTag = 26,
125     EmptyStringObjectTag = 27,
126     NumberObjectTag = 28,
127     SetObjectTag = 29,
128     MapObjectTag = 30,
129     NonMapPropertiesTag = 31,
130     NonSetPropertiesTag = 32,
131 #if ENABLE(SUBTLE_CRYPTO)
132     CryptoKeyTag = 33,
133 #endif
134     ErrorTag = 255
135 };
136
137 enum ArrayBufferViewSubtag {
138     DataViewTag = 0,
139     Int8ArrayTag = 1,
140     Uint8ArrayTag = 2,
141     Uint8ClampedArrayTag = 3,
142     Int16ArrayTag = 4,
143     Uint16ArrayTag = 5,
144     Int32ArrayTag = 6,
145     Uint32ArrayTag = 7,
146     Float32ArrayTag = 8,
147     Float64ArrayTag = 9
148 };
149
150 static unsigned typedArrayElementSize(ArrayBufferViewSubtag tag)
151 {
152     switch (tag) {
153     case DataViewTag:
154     case Int8ArrayTag:
155     case Uint8ArrayTag:
156     case Uint8ClampedArrayTag:
157         return 1;
158     case Int16ArrayTag:
159     case Uint16ArrayTag:
160         return 2;
161     case Int32ArrayTag:
162     case Uint32ArrayTag:
163     case Float32ArrayTag:
164         return 4;
165     case Float64ArrayTag:
166         return 8;
167     default:
168         return 0;
169     }
170
171 }
172
173 #if ENABLE(SUBTLE_CRYPTO)
174
175 const uint32_t currentKeyFormatVersion = 1;
176
177 enum class CryptoKeyClassSubtag {
178     HMAC = 0,
179     AES = 1,
180     RSA = 2
181 };
182 const uint8_t cryptoKeyClassSubtagMaximumValue = 2;
183
184 enum class CryptoKeyAsymmetricTypeSubtag {
185     Public = 0,
186     Private = 1
187 };
188 const uint8_t cryptoKeyAsymmetricTypeSubtagMaximumValue = 1;
189
190 enum class CryptoKeyUsageTag {
191     Encrypt = 0,
192     Decrypt = 1,
193     Sign = 2,
194     Verify = 3,
195     DeriveKey = 4,
196     DeriveBits = 5,
197     WrapKey = 6,
198     UnwrapKey = 7
199 };
200 const uint8_t cryptoKeyUsageTagMaximumValue = 7;
201
202 enum class CryptoAlgorithmIdentifierTag {
203     RSAES_PKCS1_v1_5 = 0,
204     RSASSA_PKCS1_v1_5 = 1,
205     RSA_PSS = 2,
206     RSA_OAEP = 3,
207     ECDSA = 4,
208     ECDH = 5,
209     AES_CTR = 6,
210     AES_CBC = 7,
211     AES_CMAC = 8,
212     AES_GCM = 9,
213     AES_CFB = 10,
214     AES_KW = 11,
215     HMAC = 12,
216     DH = 13,
217     SHA_1 = 14,
218     SHA_224 = 15,
219     SHA_256 = 16,
220     SHA_384 = 17,
221     SHA_512 = 18,
222     CONCAT = 19,
223     HKDF_CTR = 20,
224     PBKDF2 = 21,
225 };
226 const uint8_t cryptoAlgorithmIdentifierTagMaximumValue = 21;
227
228 static unsigned countUsages(CryptoKeyUsage usages)
229 {
230     // Fast bit count algorithm for sparse bit maps.
231     unsigned count = 0;
232     while (usages) {
233         usages = usages & (usages - 1);
234         ++count;
235     }
236     return count;
237 }
238
239 #endif
240
241 /* CurrentVersion tracks the serialization version so that persistent stores
242  * are able to correctly bail out in the case of encountering newer formats.
243  *
244  * Initial version was 1.
245  * Version 2. added the ObjectReferenceTag and support for serialization of cyclic graphs.
246  * Version 3. added the FalseObjectTag, TrueObjectTag, NumberObjectTag, StringObjectTag
247  * and EmptyStringObjectTag for serialization of Boolean, Number and String objects.
248  * Version 4. added support for serializing non-index properties of arrays.
249  * Version 5. added support for Map and Set types.
250  * Version 6. added support for 8-bit strings.
251  */
252 static const unsigned CurrentVersion = 6;
253 static const unsigned TerminatorTag = 0xFFFFFFFF;
254 static const unsigned StringPoolTag = 0xFFFFFFFE;
255 static const unsigned NonIndexPropertiesTag = 0xFFFFFFFD;
256
257 // The high bit of a StringData's length determines the character size.
258 static const unsigned StringDataIs8BitFlag = 0x80000000;
259
260 /*
261  * Object serialization is performed according to the following grammar, all tags
262  * are recorded as a single uint8_t.
263  *
264  * IndexType (used for the object pool and StringData's constant pool) is the
265  * minimum sized unsigned integer type required to represent the maximum index
266  * in the constant pool.
267  *
268  * SerializedValue :- <CurrentVersion:uint32_t> Value
269  * Value :- Array | Object | Map | Set | Terminal
270  *
271  * Array :-
272  *     ArrayTag <length:uint32_t>(<index:uint32_t><value:Value>)* TerminatorTag
273  *
274  * Object :-
275  *     ObjectTag (<name:StringData><value:Value>)* TerminatorTag
276  *
277  * Map :- MapObjectTag MapData
278  *
279  * Set :- SetObjectTag SetData
280  *
281  * MapData :- (<key:Value><value:Value>)* NonMapPropertiesTag (<name:StringData><value:Value>)* TerminatorTag
282  * SetData :- (<key:Value>)* NonSetPropertiesTag (<name:StringData><value:Value>)* TerminatorTag
283  *
284  * Terminal :-
285  *      UndefinedTag
286  *    | NullTag
287  *    | IntTag <value:int32_t>
288  *    | ZeroTag
289  *    | OneTag
290  *    | FalseTag
291  *    | TrueTag
292  *    | FalseObjectTag
293  *    | TrueObjectTag
294  *    | DoubleTag <value:double>
295  *    | NumberObjectTag <value:double>
296  *    | DateTag <value:double>
297  *    | String
298  *    | EmptyStringTag
299  *    | EmptyStringObjectTag
300  *    | File
301  *    | FileList
302  *    | ImageData
303  *    | Blob
304  *    | ObjectReference
305  *    | MessagePortReferenceTag <value:uint32_t>
306  *    | ArrayBuffer
307  *    | ArrayBufferViewTag ArrayBufferViewSubtag <byteOffset:uint32_t> <byteLength:uint32_t> (ArrayBuffer | ObjectReference)
308  *    | ArrayBufferTransferTag <value:uint32_t>
309  *    | CryptoKeyTag <wrappedKeyLength:uint32_t> <factor:byte{wrappedKeyLength}>
310  *
311  * Inside wrapped crypto key, data is serialized in this format:
312  *
313  * <keyFormatVersion:uint32_t> <extractable:int32_t> <usagesCount:uint32_t> <usages:byte{usagesCount}> CryptoKeyClassSubtag (CryptoKeyHMAC | CryptoKeyAES | CryptoKeyRSA)
314  *
315  * String :-
316  *      EmptyStringTag
317  *      StringTag StringData
318  *
319  * StringObject:
320  *      EmptyStringObjectTag
321  *      StringObjectTag StringData
322  *
323  * StringData :-
324  *      StringPoolTag <cpIndex:IndexType>
325  *      (not (TerminatorTag | StringPoolTag))<is8Bit:uint32_t:1><length:uint32_t:31><characters:CharType{length}> // Added to constant pool when seen, string length 0xFFFFFFFF is disallowed
326  *
327  * File :-
328  *    FileTag FileData
329  *
330  * FileData :-
331  *    <path:StringData> <url:StringData> <type:StringData> <name:StringData>
332  *
333  * FileList :-
334  *    FileListTag <length:uint32_t>(<file:FileData>){length}
335  *
336  * ImageData :-
337  *    ImageDataTag <width:int32_t><height:int32_t><length:uint32_t><data:uint8_t{length}>
338  *
339  * Blob :-
340  *    BlobTag <url:StringData><type:StringData><size:long long>
341  *
342  * RegExp :-
343  *    RegExpTag <pattern:StringData><flags:StringData>
344  *
345  * ObjectReference :-
346  *    ObjectReferenceTag <opIndex:IndexType>
347  *
348  * ArrayBuffer :-
349  *    ArrayBufferTag <length:uint32_t> <contents:byte{length}>
350  *
351  * CryptoKeyHMAC :-
352  *    <keySize:uint32_t> <keyData:byte{keySize}> CryptoAlgorithmIdentifierTag // Algorithm tag inner hash function.
353  *
354  * CryptoKeyAES :-
355  *    CryptoAlgorithmIdentifierTag <keySize:uint32_t> <keyData:byte{keySize}>
356  *
357  * CryptoKeyRSA :-
358  *    CryptoAlgorithmIdentifierTag <isRestrictedToHash:int32_t> CryptoAlgorithmIdentifierTag? CryptoKeyAsymmetricTypeSubtag CryptoKeyRSAPublicComponents CryptoKeyRSAPrivateComponents?
359  *
360  * CryptoKeyRSAPublicComponents :-
361  *    <modulusSize:uint32_t> <modulus:byte{modulusSize}> <exponentSize:uint32_t> <exponent:byte{exponentSize}>
362  *
363  * CryptoKeyRSAPrivateComponents :-
364  *    <privateExponentSize:uint32_t> <privateExponent:byte{privateExponentSize}> <primeCount:uint32_t> FirstPrimeInfo? PrimeInfo{primeCount - 1}
365  *
366  * // CRT data could be computed from prime factors. It is only serialized to reuse a code path that's needed for JWK.
367  * FirstPrimeInfo :-
368  *    <factorSize:uint32_t> <factor:byte{factorSize}> <crtExponentSize:uint32_t> <crtExponent:byte{crtExponentSize}>
369  *
370  * PrimeInfo :-
371  *    <factorSize:uint32_t> <factor:byte{factorSize}> <crtExponentSize:uint32_t> <crtExponent:byte{crtExponentSize}> <crtCoefficientSize:uint32_t> <crtCoefficient:byte{crtCoefficientSize}>
372  */
373
374 typedef std::pair<JSC::JSValue, SerializationReturnCode> DeserializationResult;
375
376 class CloneBase {
377 protected:
378     CloneBase(ExecState* exec)
379         : m_exec(exec)
380         , m_failed(false)
381     {
382     }
383
384     bool shouldTerminate()
385     {
386         return m_exec->hadException();
387     }
388
389     void throwStackOverflow()
390     {
391         m_exec->vm().throwException(m_exec, createStackOverflowError(m_exec));
392     }
393
394     void fail()
395     {
396         m_failed = true;
397     }
398
399     ExecState* m_exec;
400     bool m_failed;
401     MarkedArgumentBuffer m_gcBuffer;
402 };
403
404 #if ENABLE(SUBTLE_CRYPTO)
405 static bool wrapCryptoKey(ExecState* exec, const Vector<uint8_t>& key, Vector<uint8_t>& wrappedKey)
406 {
407     ScriptExecutionContext* scriptExecutionContext = scriptExecutionContextFromExecState(exec);
408     if (!scriptExecutionContext)
409         return false;
410     return scriptExecutionContext->wrapCryptoKey(key, wrappedKey);
411 }
412
413 static bool unwrapCryptoKey(ExecState* exec, const Vector<uint8_t>& wrappedKey, Vector<uint8_t>& key)
414 {
415     ScriptExecutionContext* scriptExecutionContext = scriptExecutionContextFromExecState(exec);
416     if (!scriptExecutionContext)
417         return false;
418     return scriptExecutionContext->unwrapCryptoKey(wrappedKey, key);
419 }
420 #endif
421
422 #if ASSUME_LITTLE_ENDIAN
423 template <typename T> static void writeLittleEndian(Vector<uint8_t>& buffer, T value)
424 {
425     buffer.append(reinterpret_cast<uint8_t*>(&value), sizeof(value));
426 }
427 #else
428 template <typename T> static void writeLittleEndian(Vector<uint8_t>& buffer, T value)
429 {
430     for (unsigned i = 0; i < sizeof(T); i++) {
431         buffer.append(value & 0xFF);
432         value >>= 8;
433     }
434 }
435 #endif
436
437 template <> void writeLittleEndian<uint8_t>(Vector<uint8_t>& buffer, uint8_t value)
438 {
439     buffer.append(value);
440 }
441
442 template <typename T> static bool writeLittleEndian(Vector<uint8_t>& buffer, const T* values, uint32_t length)
443 {
444     if (length > std::numeric_limits<uint32_t>::max() / sizeof(T))
445         return false;
446
447 #if ASSUME_LITTLE_ENDIAN
448     buffer.append(reinterpret_cast<const uint8_t*>(values), length * sizeof(T));
449 #else
450     for (unsigned i = 0; i < length; i++) {
451         T value = values[i];
452         for (unsigned j = 0; j < sizeof(T); j++) {
453             buffer.append(static_cast<uint8_t>(value & 0xFF));
454             value >>= 8;
455         }
456     }
457 #endif
458     return true;
459 }
460
461 template <> bool writeLittleEndian<uint8_t>(Vector<uint8_t>& buffer, const uint8_t* values, uint32_t length)
462 {
463     buffer.append(values, length);
464     return true;
465 }
466
467 class CloneSerializer : CloneBase {
468 public:
469     static SerializationReturnCode serialize(ExecState* exec, JSValue value,
470                                              MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers,
471                                              Vector<String>& blobURLs, Vector<uint8_t>& out)
472     {
473         CloneSerializer serializer(exec, messagePorts, arrayBuffers, blobURLs, out);
474         return serializer.serialize(value);
475     }
476
477     static bool serialize(const String& s, Vector<uint8_t>& out)
478     {
479         writeLittleEndian(out, CurrentVersion);
480         if (s.isEmpty()) {
481             writeLittleEndian<uint8_t>(out, EmptyStringTag);
482             return true;
483         }
484         writeLittleEndian<uint8_t>(out, StringTag);
485         if (s.is8Bit()) {
486             writeLittleEndian(out, s.length() | StringDataIs8BitFlag);
487             return writeLittleEndian(out, s.characters8(), s.length());
488         }
489         writeLittleEndian(out, 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(Identifier::fromString(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(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(const String& string)
679     {
680         if (string.isEmpty())
681             write(EmptyStringTag);
682         else {
683             write(StringTag);
684             write(string);
685         }
686     }
687
688     void dumpStringObject(const String& string)
689     {
690         if (string.isEmpty())
691             write(EmptyStringObjectTag);
692         else {
693             write(StringObjectTag);
694             write(string);
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(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(ident.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         // Guard against overflow
990         if (length > (std::numeric_limits<uint32_t>::max() - sizeof(uint32_t)) / sizeof(UChar)) {
991             fail();
992             return;
993         }
994
995         if (str.is8Bit())
996             writeLittleEndian<uint32_t>(m_buffer, length | StringDataIs8BitFlag);
997         else
998             writeLittleEndian<uint32_t>(m_buffer, length);
999
1000         if (!length)
1001             return;
1002         if (str.is8Bit()) {
1003             if (!writeLittleEndian(m_buffer, str.characters8(), length))
1004                 fail();
1005             return;
1006         }
1007         if (!writeLittleEndian(m_buffer, str.characters16(), length))
1008             fail();
1009     }
1010
1011     void write(const String& str)
1012     {
1013         if (str.isNull())
1014             write(m_emptyIdentifier);
1015         else
1016             write(Identifier::fromString(m_exec, str));
1017     }
1018
1019     void write(const Vector<uint8_t>& vector)
1020     {
1021         uint32_t size = vector.size();
1022         write(size);
1023         writeLittleEndian(m_buffer, vector.data(), size);
1024     }
1025
1026     void write(const File* file)
1027     {
1028         m_blobURLs.append(file->url());
1029         write(file->path());
1030         write(file->url());
1031         write(file->type());
1032         write(file->name());
1033     }
1034
1035 #if ENABLE(SUBTLE_CRYPTO)
1036     void write(CryptoAlgorithmIdentifier algorithm)
1037     {
1038         switch (algorithm) {
1039         case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
1040             write(CryptoAlgorithmIdentifierTag::RSAES_PKCS1_v1_5);
1041             break;
1042         case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
1043             write(CryptoAlgorithmIdentifierTag::RSASSA_PKCS1_v1_5);
1044             break;
1045         case CryptoAlgorithmIdentifier::RSA_PSS:
1046             write(CryptoAlgorithmIdentifierTag::RSA_PSS);
1047             break;
1048         case CryptoAlgorithmIdentifier::RSA_OAEP:
1049             write(CryptoAlgorithmIdentifierTag::RSA_OAEP);
1050             break;
1051         case CryptoAlgorithmIdentifier::ECDSA:
1052             write(CryptoAlgorithmIdentifierTag::ECDSA);
1053             break;
1054         case CryptoAlgorithmIdentifier::ECDH:
1055             write(CryptoAlgorithmIdentifierTag::ECDH);
1056             break;
1057         case CryptoAlgorithmIdentifier::AES_CTR:
1058             write(CryptoAlgorithmIdentifierTag::AES_CTR);
1059             break;
1060         case CryptoAlgorithmIdentifier::AES_CBC:
1061             write(CryptoAlgorithmIdentifierTag::AES_CBC);
1062             break;
1063         case CryptoAlgorithmIdentifier::AES_CMAC:
1064             write(CryptoAlgorithmIdentifierTag::AES_CMAC);
1065             break;
1066         case CryptoAlgorithmIdentifier::AES_GCM:
1067             write(CryptoAlgorithmIdentifierTag::AES_GCM);
1068             break;
1069         case CryptoAlgorithmIdentifier::AES_CFB:
1070             write(CryptoAlgorithmIdentifierTag::AES_CFB);
1071             break;
1072         case CryptoAlgorithmIdentifier::AES_KW:
1073             write(CryptoAlgorithmIdentifierTag::AES_KW);
1074             break;
1075         case CryptoAlgorithmIdentifier::HMAC:
1076             write(CryptoAlgorithmIdentifierTag::HMAC);
1077             break;
1078         case CryptoAlgorithmIdentifier::DH:
1079             write(CryptoAlgorithmIdentifierTag::DH);
1080             break;
1081         case CryptoAlgorithmIdentifier::SHA_1:
1082             write(CryptoAlgorithmIdentifierTag::SHA_1);
1083             break;
1084         case CryptoAlgorithmIdentifier::SHA_224:
1085             write(CryptoAlgorithmIdentifierTag::SHA_224);
1086             break;
1087         case CryptoAlgorithmIdentifier::SHA_256:
1088             write(CryptoAlgorithmIdentifierTag::SHA_256);
1089             break;
1090         case CryptoAlgorithmIdentifier::SHA_384:
1091             write(CryptoAlgorithmIdentifierTag::SHA_384);
1092             break;
1093         case CryptoAlgorithmIdentifier::SHA_512:
1094             write(CryptoAlgorithmIdentifierTag::SHA_512);
1095             break;
1096         case CryptoAlgorithmIdentifier::CONCAT:
1097             write(CryptoAlgorithmIdentifierTag::CONCAT);
1098             break;
1099         case CryptoAlgorithmIdentifier::HKDF_CTR:
1100             write(CryptoAlgorithmIdentifierTag::HKDF_CTR);
1101             break;
1102         case CryptoAlgorithmIdentifier::PBKDF2:
1103             write(CryptoAlgorithmIdentifierTag::PBKDF2);
1104             break;
1105         }
1106     }
1107
1108     void write(CryptoKeyDataRSAComponents::Type type)
1109     {
1110         switch (type) {
1111         case CryptoKeyDataRSAComponents::Type::Public:
1112             write(CryptoKeyAsymmetricTypeSubtag::Public);
1113             return;
1114         case CryptoKeyDataRSAComponents::Type::Private:
1115             write(CryptoKeyAsymmetricTypeSubtag::Private);
1116             return;
1117         }
1118     }
1119
1120     void write(const CryptoKeyDataRSAComponents& key)
1121     {
1122         write(key.type());
1123         write(key.modulus());
1124         write(key.exponent());
1125         if (key.type() == CryptoKeyDataRSAComponents::Type::Public)
1126             return;
1127
1128         write(key.privateExponent());
1129
1130         unsigned primeCount = key.hasAdditionalPrivateKeyParameters() ? key.otherPrimeInfos().size() + 2 : 0;
1131         write(primeCount);
1132         if (!primeCount)
1133             return;
1134
1135         write(key.firstPrimeInfo().primeFactor);
1136         write(key.firstPrimeInfo().factorCRTExponent);
1137         write(key.secondPrimeInfo().primeFactor);
1138         write(key.secondPrimeInfo().factorCRTExponent);
1139         write(key.secondPrimeInfo().factorCRTCoefficient);
1140         for (unsigned i = 2; i < primeCount; ++i) {
1141             write(key.otherPrimeInfos()[i].primeFactor);
1142             write(key.otherPrimeInfos()[i].factorCRTExponent);
1143             write(key.otherPrimeInfos()[i].factorCRTCoefficient);
1144         }
1145     }
1146
1147     void write(const CryptoKey* key)
1148     {
1149         write(currentKeyFormatVersion);
1150
1151         write(key->extractable());
1152
1153         CryptoKeyUsage usages = key->usagesBitmap();
1154         write(countUsages(usages));
1155         if (usages & CryptoKeyUsageEncrypt)
1156             write(CryptoKeyUsageTag::Encrypt);
1157         if (usages & CryptoKeyUsageDecrypt)
1158             write(CryptoKeyUsageTag::Decrypt);
1159         if (usages & CryptoKeyUsageSign)
1160             write(CryptoKeyUsageTag::Sign);
1161         if (usages & CryptoKeyUsageVerify)
1162             write(CryptoKeyUsageTag::Verify);
1163         if (usages & CryptoKeyUsageDeriveKey)
1164             write(CryptoKeyUsageTag::DeriveKey);
1165         if (usages & CryptoKeyUsageDeriveBits)
1166             write(CryptoKeyUsageTag::DeriveBits);
1167         if (usages & CryptoKeyUsageWrapKey)
1168             write(CryptoKeyUsageTag::WrapKey);
1169         if (usages & CryptoKeyUsageUnwrapKey)
1170             write(CryptoKeyUsageTag::UnwrapKey);
1171
1172         switch (key->keyClass()) {
1173         case CryptoKeyClass::HMAC:
1174             write(CryptoKeyClassSubtag::HMAC);
1175             write(downcast<CryptoKeyHMAC>(*key).key());
1176             write(downcast<CryptoKeyHMAC>(*key).hashAlgorithmIdentifier());
1177             break;
1178         case CryptoKeyClass::AES:
1179             write(CryptoKeyClassSubtag::AES);
1180             write(key->algorithmIdentifier());
1181             write(downcast<CryptoKeyAES>(*key).key());
1182             break;
1183         case CryptoKeyClass::RSA:
1184             write(CryptoKeyClassSubtag::RSA);
1185             write(key->algorithmIdentifier());
1186             CryptoAlgorithmIdentifier hash;
1187             bool isRestrictedToHash = downcast<CryptoKeyRSA>(*key).isRestrictedToHash(hash);
1188             write(isRestrictedToHash);
1189             if (isRestrictedToHash)
1190                 write(hash);
1191             write(downcast<CryptoKeyDataRSAComponents>(*key->exportData()));
1192             break;
1193         }
1194     }
1195 #endif
1196
1197     void write(const uint8_t* data, unsigned length)
1198     {
1199         m_buffer.append(data, length);
1200     }
1201
1202     Vector<uint8_t>& m_buffer;
1203     Vector<String>& m_blobURLs;
1204     ObjectPool m_objectPool;
1205     ObjectPool m_transferredMessagePorts;
1206     ObjectPool m_transferredArrayBuffers;
1207     typedef HashMap<RefPtr<UniquedStringImpl>, uint32_t, IdentifierRepHash> StringConstantPool;
1208     StringConstantPool m_constantPool;
1209     Identifier m_emptyIdentifier;
1210 };
1211
1212 SerializationReturnCode CloneSerializer::serialize(JSValue in)
1213 {
1214     Vector<uint32_t, 16> indexStack;
1215     Vector<uint32_t, 16> lengthStack;
1216     Vector<PropertyNameArray, 16> propertyStack;
1217     Vector<JSObject*, 32> inputObjectStack;
1218     Vector<JSMapIterator*, 4> mapIteratorStack;
1219     Vector<JSSetIterator*, 4> setIteratorStack;
1220     Vector<JSValue, 4> mapIteratorValueStack;
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, PropertyNameMode::Strings));
1250                     array->methodTable()->getOwnNonIndexPropertyNames(array, m_exec, propertyStack.last(), EnumerationMode());
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, PropertyNameMode::Strings));
1300                 inObject->methodTable()->getOwnPropertyNames(inObject, m_exec, propertyStack.last(), EnumerationMode());
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                 JSMapIterator* iterator = JSMapIterator::create(m_exec->vm(), m_exec->lexicalGlobalObject()->mapIteratorStructure(), inMap, MapIterateKeyValue);
1353                 m_gcBuffer.append(inMap);
1354                 m_gcBuffer.append(iterator);
1355                 mapIteratorStack.append(iterator);
1356                 inputObjectStack.append(inMap);
1357                 goto mapDataStartVisitEntry;
1358             }
1359             mapDataStartVisitEntry:
1360             case MapDataStartVisitEntry: {
1361                 JSMapIterator* iterator = mapIteratorStack.last();
1362                 JSValue key, value;
1363                 if (!iterator->nextKeyValue(key, value)) {
1364                     mapIteratorStack.removeLast();
1365                     JSObject* object = inputObjectStack.last();
1366                     ASSERT(jsDynamicCast<JSMap*>(object));
1367                     propertyStack.append(PropertyNameArray(m_exec, PropertyNameMode::Strings));
1368                     object->methodTable()->getOwnPropertyNames(object, m_exec, propertyStack.last(), EnumerationMode());
1369                     write(NonMapPropertiesTag);
1370                     indexStack.append(0);
1371                     goto objectStartVisitMember;
1372                 }
1373                 inValue = key;
1374                 m_gcBuffer.append(value);
1375                 mapIteratorValueStack.append(value);
1376                 stateStack.append(MapDataEndVisitKey);
1377                 goto stateUnknown;
1378             }
1379             case MapDataEndVisitKey: {
1380                 inValue = mapIteratorValueStack.last();
1381                 mapIteratorValueStack.removeLast();
1382                 stateStack.append(MapDataEndVisitValue);
1383                 goto stateUnknown;
1384             }
1385             case MapDataEndVisitValue: {
1386                 goto mapDataStartVisitEntry;
1387             }
1388
1389             setStartState: {
1390                 ASSERT(inValue.isObject());
1391                 if (inputObjectStack.size() > maximumFilterRecursion)
1392                     return StackOverflowError;
1393                 JSSet* inSet = jsCast<JSSet*>(inValue);
1394                 if (!startSet(inSet))
1395                     break;
1396                 JSSetIterator* iterator = JSSetIterator::create(m_exec->vm(), m_exec->lexicalGlobalObject()->setIteratorStructure(), inSet, SetIterateKey);
1397                 m_gcBuffer.append(inSet);
1398                 m_gcBuffer.append(iterator);
1399                 setIteratorStack.append(iterator);
1400                 inputObjectStack.append(inSet);
1401                 goto setDataStartVisitEntry;
1402             }
1403             setDataStartVisitEntry:
1404             case SetDataStartVisitEntry: {
1405                 JSSetIterator* iterator = setIteratorStack.last();
1406                 JSValue key;
1407                 if (!iterator->next(m_exec, key)) {
1408                     setIteratorStack.removeLast();
1409                     JSObject* object = inputObjectStack.last();
1410                     ASSERT(jsDynamicCast<JSSet*>(object));
1411                     propertyStack.append(PropertyNameArray(m_exec, PropertyNameMode::Strings));
1412                     object->methodTable()->getOwnPropertyNames(object, m_exec, propertyStack.last(), EnumerationMode());
1413                     write(NonSetPropertiesTag);
1414                     indexStack.append(0);
1415                     goto objectStartVisitMember;
1416                 }
1417                 inValue = key;
1418                 stateStack.append(SetDataEndVisitKey);
1419                 goto stateUnknown;
1420             }
1421             case SetDataEndVisitKey: {
1422                 goto setDataStartVisitEntry;
1423             }
1424
1425             stateUnknown:
1426             case StateUnknown: {
1427                 SerializationReturnCode terminalCode = SuccessfullyCompleted;
1428                 if (dumpIfTerminal(inValue, terminalCode)) {
1429                     if (terminalCode != SuccessfullyCompleted)
1430                         return terminalCode;
1431                     break;
1432                 }
1433
1434                 if (isArray(inValue))
1435                     goto arrayStartState;
1436                 if (isMap(inValue))
1437                     goto mapStartState;
1438                 if (isSet(inValue))
1439                     goto setStartState;
1440                 goto objectStartState;
1441             }
1442         }
1443         if (stateStack.isEmpty())
1444             break;
1445
1446         state = stateStack.last();
1447         stateStack.removeLast();
1448     }
1449     if (m_failed)
1450         return UnspecifiedError;
1451
1452     return SuccessfullyCompleted;
1453 }
1454
1455 typedef Vector<JSC::ArrayBufferContents> ArrayBufferContentsArray;
1456
1457 class CloneDeserializer : CloneBase {
1458 public:
1459     static String deserializeString(const Vector<uint8_t>& buffer)
1460     {
1461         if (buffer.isEmpty())
1462             return String();
1463         const uint8_t* ptr = buffer.begin();
1464         const uint8_t* end = buffer.end();
1465         uint32_t version;
1466         if (!readLittleEndian(ptr, end, version) || version > CurrentVersion)
1467             return String();
1468         uint8_t tag;
1469         if (!readLittleEndian(ptr, end, tag) || tag != StringTag)
1470             return String();
1471         uint32_t length;
1472         if (!readLittleEndian(ptr, end, length))
1473             return String();
1474         bool is8Bit = length & StringDataIs8BitFlag;
1475         length &= ~StringDataIs8BitFlag;
1476         String str;
1477         if (!readString(ptr, end, str, length, is8Bit))
1478             return String();
1479         return str;
1480     }
1481
1482     static DeserializationResult deserialize(ExecState* exec, JSGlobalObject* globalObject,
1483                                              MessagePortArray* messagePorts, ArrayBufferContentsArray* arrayBufferContentsArray,
1484                                              const Vector<uint8_t>& buffer)
1485     {
1486         if (!buffer.size())
1487             return std::make_pair(jsNull(), UnspecifiedError);
1488         CloneDeserializer deserializer(exec, globalObject, messagePorts, arrayBufferContentsArray, buffer);
1489         if (!deserializer.isValid())
1490             return std::make_pair(JSValue(), ValidationError);
1491         return deserializer.deserialize();
1492     }
1493
1494 private:
1495     struct CachedString {
1496         CachedString(const String& string)
1497             : m_string(string)
1498         {
1499         }
1500
1501         JSValue jsString(ExecState* exec)
1502         {
1503             if (!m_jsString)
1504                 m_jsString = JSC::jsString(exec, m_string);
1505             return m_jsString;
1506         }
1507         const String& string() { return m_string; }
1508
1509     private:
1510         String m_string;
1511         JSValue m_jsString;
1512     };
1513
1514     struct CachedStringRef {
1515         CachedStringRef()
1516             : m_base(0)
1517             , m_index(0)
1518         {
1519         }
1520         CachedStringRef(Vector<CachedString>* base, size_t index)
1521             : m_base(base)
1522             , m_index(index)
1523         {
1524         }
1525         
1526         CachedString* operator->() { ASSERT(m_base); return &m_base->at(m_index); }
1527         
1528     private:
1529         Vector<CachedString>* m_base;
1530         size_t m_index;
1531     };
1532
1533     CloneDeserializer(ExecState* exec, JSGlobalObject* globalObject, 
1534                       MessagePortArray* messagePorts, ArrayBufferContentsArray* arrayBufferContents,
1535                       const Vector<uint8_t>& buffer)
1536         : CloneBase(exec)
1537         , m_globalObject(globalObject)
1538         , m_isDOMGlobalObject(globalObject->inherits(JSDOMGlobalObject::info()))
1539         , m_ptr(buffer.data())
1540         , m_end(buffer.data() + buffer.size())
1541         , m_version(0xFFFFFFFF)
1542         , m_messagePorts(messagePorts)
1543         , m_arrayBufferContents(arrayBufferContents)
1544         , m_arrayBuffers(arrayBufferContents ? arrayBufferContents->size() : 0)
1545     {
1546         if (!read(m_version))
1547             m_version = 0xFFFFFFFF;
1548     }
1549
1550     DeserializationResult deserialize();
1551
1552     void throwValidationError()
1553     {
1554         m_exec->vm().throwException(m_exec, createTypeError(m_exec, "Unable to deserialize data."));
1555     }
1556
1557     bool isValid() const { return m_version <= CurrentVersion; }
1558
1559     template <typename T> bool readLittleEndian(T& value)
1560     {
1561         if (m_failed || !readLittleEndian(m_ptr, m_end, value)) {
1562             fail();
1563             return false;
1564         }
1565         return true;
1566     }
1567 #if ASSUME_LITTLE_ENDIAN
1568     template <typename T> static bool readLittleEndian(const uint8_t*& ptr, const uint8_t* end, T& value)
1569     {
1570         if (ptr > end - sizeof(value))
1571             return false;
1572
1573         if (sizeof(T) == 1)
1574             value = *ptr++;
1575         else {
1576             value = *reinterpret_cast<const T*>(ptr);
1577             ptr += sizeof(T);
1578         }
1579         return true;
1580     }
1581 #else
1582     template <typename T> static bool readLittleEndian(const uint8_t*& ptr, const uint8_t* end, T& value)
1583     {
1584         if (ptr > end - sizeof(value))
1585             return false;
1586
1587         if (sizeof(T) == 1)
1588             value = *ptr++;
1589         else {
1590             value = 0;
1591             for (unsigned i = 0; i < sizeof(T); i++)
1592                 value += ((T)*ptr++) << (i * 8);
1593         }
1594         return true;
1595     }
1596 #endif
1597
1598     bool read(uint32_t& i)
1599     {
1600         return readLittleEndian(i);
1601     }
1602
1603     bool read(int32_t& i)
1604     {
1605         return readLittleEndian(*reinterpret_cast<uint32_t*>(&i));
1606     }
1607
1608     bool read(uint16_t& i)
1609     {
1610         return readLittleEndian(i);
1611     }
1612
1613     bool read(uint8_t& i)
1614     {
1615         return readLittleEndian(i);
1616     }
1617
1618     bool read(double& d)
1619     {
1620         union {
1621             double d;
1622             uint64_t i64;
1623         } u;
1624         if (!readLittleEndian(u.i64))
1625             return false;
1626         d = u.d;
1627         return true;
1628     }
1629
1630     bool read(unsigned long long& i)
1631     {
1632         return readLittleEndian(i);
1633     }
1634
1635     bool readStringIndex(uint32_t& i)
1636     {
1637         return readConstantPoolIndex(m_constantPool, i);
1638     }
1639
1640     template <class T> bool readConstantPoolIndex(const T& constantPool, uint32_t& i)
1641     {
1642         if (constantPool.size() <= 0xFF) {
1643             uint8_t i8;
1644             if (!read(i8))
1645                 return false;
1646             i = i8;
1647             return true;
1648         }
1649         if (constantPool.size() <= 0xFFFF) {
1650             uint16_t i16;
1651             if (!read(i16))
1652                 return false;
1653             i = i16;
1654             return true;
1655         }
1656         return read(i);
1657     }
1658
1659     static bool readString(const uint8_t*& ptr, const uint8_t* end, String& str, unsigned length, bool is8Bit)
1660     {
1661         if (length >= std::numeric_limits<int32_t>::max() / sizeof(UChar))
1662             return false;
1663
1664         if (is8Bit) {
1665             if ((end - ptr) < static_cast<int>(length))
1666                 return false;
1667             str = String(reinterpret_cast<const LChar*>(ptr), length);
1668             ptr += length;
1669             return true;
1670         }
1671
1672         unsigned size = length * sizeof(UChar);
1673         if ((end - ptr) < static_cast<int>(size))
1674             return false;
1675
1676 #if ASSUME_LITTLE_ENDIAN
1677         str = String(reinterpret_cast<const UChar*>(ptr), length);
1678         ptr += length * sizeof(UChar);
1679 #else
1680         Vector<UChar> buffer;
1681         buffer.reserveCapacity(length);
1682         for (unsigned i = 0; i < length; i++) {
1683             uint16_t ch;
1684             readLittleEndian(ptr, end, ch);
1685             buffer.append(ch);
1686         }
1687         str = String::adopt(buffer);
1688 #endif
1689         return true;
1690     }
1691
1692     bool readStringData(CachedStringRef& cachedString)
1693     {
1694         bool scratch;
1695         return readStringData(cachedString, scratch);
1696     }
1697
1698     bool readStringData(CachedStringRef& cachedString, bool& wasTerminator)
1699     {
1700         if (m_failed)
1701             return false;
1702         uint32_t length = 0;
1703         if (!read(length))
1704             return false;
1705         if (length == TerminatorTag) {
1706             wasTerminator = true;
1707             return false;
1708         }
1709         if (length == StringPoolTag) {
1710             unsigned index = 0;
1711             if (!readStringIndex(index)) {
1712                 fail();
1713                 return false;
1714             }
1715             if (index >= m_constantPool.size()) {
1716                 fail();
1717                 return false;
1718             }
1719             cachedString = CachedStringRef(&m_constantPool, index);
1720             return true;
1721         }
1722         bool is8Bit = length & StringDataIs8BitFlag;
1723         length &= ~StringDataIs8BitFlag;
1724         String str;
1725         if (!readString(m_ptr, m_end, str, length, is8Bit)) {
1726             fail();
1727             return false;
1728         }
1729         m_constantPool.append(str);
1730         cachedString = CachedStringRef(&m_constantPool, m_constantPool.size() - 1);
1731         return true;
1732     }
1733
1734     SerializationTag readTag()
1735     {
1736         if (m_ptr >= m_end)
1737             return ErrorTag;
1738         return static_cast<SerializationTag>(*m_ptr++);
1739     }
1740
1741     bool readArrayBufferViewSubtag(ArrayBufferViewSubtag& tag)
1742     {
1743         if (m_ptr >= m_end)
1744             return false;
1745         tag = static_cast<ArrayBufferViewSubtag>(*m_ptr++);
1746         return true;
1747     }
1748
1749     void putProperty(JSObject* object, unsigned index, JSValue value)
1750     {
1751         object->putDirectIndex(m_exec, index, value);
1752     }
1753
1754     void putProperty(JSObject* object, const Identifier& property, JSValue value)
1755     {
1756         object->putDirectMayBeIndex(m_exec, property, value);
1757     }
1758
1759     bool readFile(RefPtr<File>& file)
1760     {
1761         CachedStringRef path;
1762         if (!readStringData(path))
1763             return 0;
1764         CachedStringRef url;
1765         if (!readStringData(url))
1766             return 0;
1767         CachedStringRef type;
1768         if (!readStringData(type))
1769             return 0;
1770         CachedStringRef name;
1771         if (!readStringData(name))
1772             return 0;
1773         if (m_isDOMGlobalObject)
1774             file = File::deserialize(path->string(), URL(URL(), url->string()), type->string(), name->string());
1775         return true;
1776     }
1777
1778     bool readArrayBuffer(RefPtr<ArrayBuffer>& arrayBuffer)
1779     {
1780         uint32_t length;
1781         if (!read(length))
1782             return false;
1783         if (m_ptr + length > m_end)
1784             return false;
1785         arrayBuffer = ArrayBuffer::create(m_ptr, length);
1786         m_ptr += length;
1787         return true;
1788     }
1789
1790     bool readArrayBufferView(JSValue& arrayBufferView)
1791     {
1792         ArrayBufferViewSubtag arrayBufferViewSubtag;
1793         if (!readArrayBufferViewSubtag(arrayBufferViewSubtag))
1794             return false;
1795         uint32_t byteOffset;
1796         if (!read(byteOffset))
1797             return false;
1798         uint32_t byteLength;
1799         if (!read(byteLength))
1800             return false;
1801         JSObject* arrayBufferObj = asObject(readTerminal());
1802         if (!arrayBufferObj || !arrayBufferObj->inherits(JSArrayBuffer::info()))
1803             return false;
1804
1805         unsigned elementSize = typedArrayElementSize(arrayBufferViewSubtag);
1806         if (!elementSize)
1807             return false;
1808         unsigned length = byteLength / elementSize;
1809         if (length * elementSize != byteLength)
1810             return false;
1811
1812         RefPtr<ArrayBuffer> arrayBuffer = toArrayBuffer(arrayBufferObj);
1813         switch (arrayBufferViewSubtag) {
1814         case DataViewTag:
1815             arrayBufferView = getJSValue(DataView::create(arrayBuffer, byteOffset, length).get());
1816             return true;
1817         case Int8ArrayTag:
1818             arrayBufferView = getJSValue(Int8Array::create(arrayBuffer, byteOffset, length).get());
1819             return true;
1820         case Uint8ArrayTag:
1821             arrayBufferView = getJSValue(Uint8Array::create(arrayBuffer, byteOffset, length).get());
1822             return true;
1823         case Uint8ClampedArrayTag:
1824             arrayBufferView = getJSValue(Uint8ClampedArray::create(arrayBuffer, byteOffset, length).get());
1825             return true;
1826         case Int16ArrayTag:
1827             arrayBufferView = getJSValue(Int16Array::create(arrayBuffer, byteOffset, length).get());
1828             return true;
1829         case Uint16ArrayTag:
1830             arrayBufferView = getJSValue(Uint16Array::create(arrayBuffer, byteOffset, length).get());
1831             return true;
1832         case Int32ArrayTag:
1833             arrayBufferView = getJSValue(Int32Array::create(arrayBuffer, byteOffset, length).get());
1834             return true;
1835         case Uint32ArrayTag:
1836             arrayBufferView = getJSValue(Uint32Array::create(arrayBuffer, byteOffset, length).get());
1837             return true;
1838         case Float32ArrayTag:
1839             arrayBufferView = getJSValue(Float32Array::create(arrayBuffer, byteOffset, length).get());
1840             return true;
1841         case Float64ArrayTag:
1842             arrayBufferView = getJSValue(Float64Array::create(arrayBuffer, byteOffset, length).get());
1843             return true;
1844         default:
1845             return false;
1846         }
1847     }
1848
1849     bool read(Vector<uint8_t>& result)
1850     {
1851         ASSERT(result.isEmpty());
1852         uint32_t size;
1853         if (!read(size))
1854             return false;
1855         if (m_ptr + size > m_end)
1856             return false;
1857         result.append(m_ptr, size);
1858         m_ptr += size;
1859         return true;
1860     }
1861
1862 #if ENABLE(SUBTLE_CRYPTO)
1863     bool read(CryptoAlgorithmIdentifier& result)
1864     {
1865         uint8_t algorithmTag;
1866         if (!read(algorithmTag))
1867             return false;
1868         if (algorithmTag > cryptoAlgorithmIdentifierTagMaximumValue)
1869             return false;
1870         switch (static_cast<CryptoAlgorithmIdentifierTag>(algorithmTag)) {
1871         case CryptoAlgorithmIdentifierTag::RSAES_PKCS1_v1_5:
1872             result = CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5;
1873             break;
1874         case CryptoAlgorithmIdentifierTag::RSASSA_PKCS1_v1_5:
1875             result = CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5;
1876             break;
1877         case CryptoAlgorithmIdentifierTag::RSA_PSS:
1878             result = CryptoAlgorithmIdentifier::RSA_PSS;
1879             break;
1880         case CryptoAlgorithmIdentifierTag::RSA_OAEP:
1881             result = CryptoAlgorithmIdentifier::RSA_OAEP;
1882             break;
1883         case CryptoAlgorithmIdentifierTag::ECDSA:
1884             result = CryptoAlgorithmIdentifier::ECDSA;
1885             break;
1886         case CryptoAlgorithmIdentifierTag::ECDH:
1887             result = CryptoAlgorithmIdentifier::ECDH;
1888             break;
1889         case CryptoAlgorithmIdentifierTag::AES_CTR:
1890             result = CryptoAlgorithmIdentifier::AES_CTR;
1891             break;
1892         case CryptoAlgorithmIdentifierTag::AES_CBC:
1893             result = CryptoAlgorithmIdentifier::AES_CBC;
1894             break;
1895         case CryptoAlgorithmIdentifierTag::AES_CMAC:
1896             result = CryptoAlgorithmIdentifier::AES_CMAC;
1897             break;
1898         case CryptoAlgorithmIdentifierTag::AES_GCM:
1899             result = CryptoAlgorithmIdentifier::AES_GCM;
1900             break;
1901         case CryptoAlgorithmIdentifierTag::AES_CFB:
1902             result = CryptoAlgorithmIdentifier::AES_CFB;
1903             break;
1904         case CryptoAlgorithmIdentifierTag::AES_KW:
1905             result = CryptoAlgorithmIdentifier::AES_KW;
1906             break;
1907         case CryptoAlgorithmIdentifierTag::HMAC:
1908             result = CryptoAlgorithmIdentifier::HMAC;
1909             break;
1910         case CryptoAlgorithmIdentifierTag::DH:
1911             result = CryptoAlgorithmIdentifier::DH;
1912             break;
1913         case CryptoAlgorithmIdentifierTag::SHA_1:
1914             result = CryptoAlgorithmIdentifier::SHA_1;
1915             break;
1916         case CryptoAlgorithmIdentifierTag::SHA_224:
1917             result = CryptoAlgorithmIdentifier::SHA_224;
1918             break;
1919         case CryptoAlgorithmIdentifierTag::SHA_256:
1920             result = CryptoAlgorithmIdentifier::SHA_256;
1921             break;
1922         case CryptoAlgorithmIdentifierTag::SHA_384:
1923             result = CryptoAlgorithmIdentifier::SHA_384;
1924             break;
1925         case CryptoAlgorithmIdentifierTag::SHA_512:
1926             result = CryptoAlgorithmIdentifier::SHA_512;
1927             break;
1928         case CryptoAlgorithmIdentifierTag::CONCAT:
1929             result = CryptoAlgorithmIdentifier::CONCAT;
1930             break;
1931         case CryptoAlgorithmIdentifierTag::HKDF_CTR:
1932             result = CryptoAlgorithmIdentifier::HKDF_CTR;
1933             break;
1934         case CryptoAlgorithmIdentifierTag::PBKDF2:
1935             result = CryptoAlgorithmIdentifier::PBKDF2;
1936             break;
1937         }
1938         return true;
1939     }
1940
1941     bool read(CryptoKeyClassSubtag& result)
1942     {
1943         uint8_t tag;
1944         if (!read(tag))
1945             return false;
1946         if (tag > cryptoKeyClassSubtagMaximumValue)
1947             return false;
1948         result = static_cast<CryptoKeyClassSubtag>(tag);
1949         return true;
1950     }
1951
1952     bool read(CryptoKeyUsageTag& result)
1953     {
1954         uint8_t tag;
1955         if (!read(tag))
1956             return false;
1957         if (tag > cryptoKeyUsageTagMaximumValue)
1958             return false;
1959         result = static_cast<CryptoKeyUsageTag>(tag);
1960         return true;
1961     }
1962
1963     bool read(CryptoKeyAsymmetricTypeSubtag& result)
1964     {
1965         uint8_t tag;
1966         if (!read(tag))
1967             return false;
1968         if (tag > cryptoKeyAsymmetricTypeSubtagMaximumValue)
1969             return false;
1970         result = static_cast<CryptoKeyAsymmetricTypeSubtag>(tag);
1971         return true;
1972     }
1973
1974     bool readHMACKey(bool extractable, CryptoKeyUsage usages, RefPtr<CryptoKey>& result)
1975     {
1976         Vector<uint8_t> keyData;
1977         if (!read(keyData))
1978             return false;
1979         CryptoAlgorithmIdentifier hash;
1980         if (!read(hash))
1981             return false;
1982         result = CryptoKeyHMAC::create(keyData, hash, extractable, usages);
1983         return true;
1984     }
1985
1986     bool readAESKey(bool extractable, CryptoKeyUsage usages, RefPtr<CryptoKey>& result)
1987     {
1988         CryptoAlgorithmIdentifier algorithm;
1989         if (!read(algorithm))
1990             return false;
1991         if (!CryptoKeyAES::isValidAESAlgorithm(algorithm))
1992             return false;
1993         Vector<uint8_t> keyData;
1994         if (!read(keyData))
1995             return false;
1996         result = CryptoKeyAES::create(algorithm, keyData, extractable, usages);
1997         return true;
1998     }
1999
2000     bool readRSAKey(bool extractable, CryptoKeyUsage usages, RefPtr<CryptoKey>& result)
2001     {
2002         CryptoAlgorithmIdentifier algorithm;
2003         if (!read(algorithm))
2004             return false;
2005
2006         int32_t isRestrictedToHash;
2007         CryptoAlgorithmIdentifier hash;
2008         if (!read(isRestrictedToHash))
2009             return false;
2010         if (isRestrictedToHash && !read(hash))
2011             return false;
2012
2013         CryptoKeyAsymmetricTypeSubtag type;
2014         if (!read(type))
2015             return false;
2016
2017         Vector<uint8_t> modulus;
2018         if (!read(modulus))
2019             return false;
2020         Vector<uint8_t> exponent;
2021         if (!read(exponent))
2022             return false;
2023
2024         if (type == CryptoKeyAsymmetricTypeSubtag::Public) {
2025             auto keyData = CryptoKeyDataRSAComponents::createPublic(modulus, exponent);
2026             auto key = CryptoKeyRSA::create(algorithm, hash, isRestrictedToHash, *keyData, extractable, usages);
2027             result = WTFMove(key);
2028             return true;
2029         }
2030
2031         Vector<uint8_t> privateExponent;
2032         if (!read(privateExponent))
2033             return false;
2034
2035         uint32_t primeCount;
2036         if (!read(primeCount))
2037             return false;
2038
2039         if (!primeCount) {
2040             auto keyData = CryptoKeyDataRSAComponents::createPrivate(modulus, exponent, privateExponent);
2041             auto key = CryptoKeyRSA::create(algorithm, hash, isRestrictedToHash, *keyData, extractable, usages);
2042             result = WTFMove(key);
2043             return true;
2044         }
2045
2046         if (primeCount < 2)
2047             return false;
2048
2049         CryptoKeyDataRSAComponents::PrimeInfo firstPrimeInfo;
2050         CryptoKeyDataRSAComponents::PrimeInfo secondPrimeInfo;
2051         Vector<CryptoKeyDataRSAComponents::PrimeInfo> otherPrimeInfos(primeCount - 2);
2052
2053         if (!read(firstPrimeInfo.primeFactor))
2054             return false;
2055         if (!read(firstPrimeInfo.factorCRTExponent))
2056             return false;
2057         if (!read(secondPrimeInfo.primeFactor))
2058             return false;
2059         if (!read(secondPrimeInfo.factorCRTExponent))
2060             return false;
2061         if (!read(secondPrimeInfo.factorCRTCoefficient))
2062             return false;
2063         for (unsigned i = 2; i < primeCount; ++i) {
2064             if (!read(otherPrimeInfos[i].primeFactor))
2065                 return false;
2066             if (!read(otherPrimeInfos[i].factorCRTExponent))
2067                 return false;
2068             if (!read(otherPrimeInfos[i].factorCRTCoefficient))
2069                 return false;
2070         }
2071
2072         auto keyData = CryptoKeyDataRSAComponents::createPrivateWithAdditionalData(modulus, exponent, privateExponent, firstPrimeInfo, secondPrimeInfo, otherPrimeInfos);
2073         auto key = CryptoKeyRSA::create(algorithm, hash, isRestrictedToHash, *keyData, extractable, usages);
2074         result = WTFMove(key);
2075         return true;
2076     }
2077
2078     bool readCryptoKey(JSValue& cryptoKey)
2079     {
2080         uint32_t keyFormatVersion;
2081         if (!read(keyFormatVersion) || keyFormatVersion > currentKeyFormatVersion)
2082             return false;
2083
2084         int32_t extractable;
2085         if (!read(extractable))
2086             return false;
2087
2088         uint32_t usagesCount;
2089         if (!read(usagesCount))
2090             return false;
2091
2092         CryptoKeyUsage usages = 0;
2093         for (uint32_t i = 0; i < usagesCount; ++i) {
2094             CryptoKeyUsageTag usage;
2095             if (!read(usage))
2096                 return false;
2097             switch (usage) {
2098             case CryptoKeyUsageTag::Encrypt:
2099                 usages |= CryptoKeyUsageEncrypt;
2100                 break;
2101             case CryptoKeyUsageTag::Decrypt:
2102                 usages |= CryptoKeyUsageDecrypt;
2103                 break;
2104             case CryptoKeyUsageTag::Sign:
2105                 usages |= CryptoKeyUsageSign;
2106                 break;
2107             case CryptoKeyUsageTag::Verify:
2108                 usages |= CryptoKeyUsageVerify;
2109                 break;
2110             case CryptoKeyUsageTag::DeriveKey:
2111                 usages |= CryptoKeyUsageDeriveKey;
2112                 break;
2113             case CryptoKeyUsageTag::DeriveBits:
2114                 usages |= CryptoKeyUsageDeriveBits;
2115                 break;
2116             case CryptoKeyUsageTag::WrapKey:
2117                 usages |= CryptoKeyUsageWrapKey;
2118                 break;
2119             case CryptoKeyUsageTag::UnwrapKey:
2120                 usages |= CryptoKeyUsageUnwrapKey;
2121                 break;
2122             }
2123         }
2124
2125         CryptoKeyClassSubtag cryptoKeyClass;
2126         if (!read(cryptoKeyClass))
2127             return false;
2128         RefPtr<CryptoKey> result;
2129         switch (cryptoKeyClass) {
2130         case CryptoKeyClassSubtag::HMAC:
2131             if (!readHMACKey(extractable, usages, result))
2132                 return false;
2133             break;
2134         case CryptoKeyClassSubtag::AES:
2135             if (!readAESKey(extractable, usages, result))
2136                 return false;
2137             break;
2138         case CryptoKeyClassSubtag::RSA:
2139             if (!readRSAKey(extractable, usages, result))
2140                 return false;
2141             break;
2142         }
2143         cryptoKey = getJSValue(result.get());
2144         return true;
2145     }
2146 #endif
2147
2148     template<class T>
2149     JSValue getJSValue(T* nativeObj)
2150     {
2151         return toJS(m_exec, jsCast<JSDOMGlobalObject*>(m_globalObject), nativeObj);
2152     }
2153
2154     template<class T>
2155     JSValue getJSValue(T& nativeObj)
2156     {
2157         return getJSValue(&nativeObj);
2158     }
2159
2160     JSValue readTerminal()
2161     {
2162         SerializationTag tag = readTag();
2163         switch (tag) {
2164         case UndefinedTag:
2165             return jsUndefined();
2166         case NullTag:
2167             return jsNull();
2168         case IntTag: {
2169             int32_t i;
2170             if (!read(i))
2171                 return JSValue();
2172             return jsNumber(i);
2173         }
2174         case ZeroTag:
2175             return jsNumber(0);
2176         case OneTag:
2177             return jsNumber(1);
2178         case FalseTag:
2179             return jsBoolean(false);
2180         case TrueTag:
2181             return jsBoolean(true);
2182         case FalseObjectTag: {
2183             BooleanObject* obj = BooleanObject::create(m_exec->vm(), m_globalObject->booleanObjectStructure());
2184             obj->setInternalValue(m_exec->vm(), jsBoolean(false));
2185             m_gcBuffer.append(obj);
2186             return obj;
2187         }
2188         case TrueObjectTag: {
2189             BooleanObject* obj = BooleanObject::create(m_exec->vm(), m_globalObject->booleanObjectStructure());
2190             obj->setInternalValue(m_exec->vm(), jsBoolean(true));
2191              m_gcBuffer.append(obj);
2192             return obj;
2193         }
2194         case DoubleTag: {
2195             double d;
2196             if (!read(d))
2197                 return JSValue();
2198             return jsNumber(d);
2199         }
2200         case NumberObjectTag: {
2201             double d;
2202             if (!read(d))
2203                 return JSValue();
2204             NumberObject* obj = constructNumber(m_exec, m_globalObject, jsNumber(d));
2205             m_gcBuffer.append(obj);
2206             return obj;
2207         }
2208         case DateTag: {
2209             double d;
2210             if (!read(d))
2211                 return JSValue();
2212             return DateInstance::create(m_exec->vm(), m_globalObject->dateStructure(), d);
2213         }
2214         case FileTag: {
2215             RefPtr<File> file;
2216             if (!readFile(file))
2217                 return JSValue();
2218             if (!m_isDOMGlobalObject)
2219                 return jsNull();
2220             return toJS(m_exec, jsCast<JSDOMGlobalObject*>(m_globalObject), file.get());
2221         }
2222         case FileListTag: {
2223             unsigned length = 0;
2224             if (!read(length))
2225                 return JSValue();
2226             Vector<RefPtr<File>> files;
2227             for (unsigned i = 0; i < length; i++) {
2228                 RefPtr<File> file;
2229                 if (!readFile(file))
2230                     return JSValue();
2231                 if (m_isDOMGlobalObject)
2232                     files.append(WTFMove(file));
2233             }
2234             if (!m_isDOMGlobalObject)
2235                 return jsNull();
2236             return getJSValue(FileList::create(WTFMove(files)).get());
2237         }
2238         case ImageDataTag: {
2239             int32_t width;
2240             if (!read(width))
2241                 return JSValue();
2242             int32_t height;
2243             if (!read(height))
2244                 return JSValue();
2245             uint32_t length;
2246             if (!read(length))
2247                 return JSValue();
2248             if (m_end < ((uint8_t*)0) + length || m_ptr > m_end - length) {
2249                 fail();
2250                 return JSValue();
2251             }
2252             if (!m_isDOMGlobalObject) {
2253                 m_ptr += length;
2254                 return jsNull();
2255             }
2256             RefPtr<ImageData> result = ImageData::create(IntSize(width, height));
2257             memcpy(result->data()->data(), m_ptr, length);
2258             m_ptr += length;
2259             return getJSValue(result.get());
2260         }
2261         case BlobTag: {
2262             CachedStringRef url;
2263             if (!readStringData(url))
2264                 return JSValue();
2265             CachedStringRef type;
2266             if (!readStringData(type))
2267                 return JSValue();
2268             unsigned long long size = 0;
2269             if (!read(size))
2270                 return JSValue();
2271             if (!m_isDOMGlobalObject)
2272                 return jsNull();
2273             return getJSValue(Blob::deserialize(URL(URL(), url->string()), type->string(), size).get());
2274         }
2275         case StringTag: {
2276             CachedStringRef cachedString;
2277             if (!readStringData(cachedString))
2278                 return JSValue();
2279             return cachedString->jsString(m_exec);
2280         }
2281         case EmptyStringTag:
2282             return jsEmptyString(&m_exec->vm());
2283         case StringObjectTag: {
2284             CachedStringRef cachedString;
2285             if (!readStringData(cachedString))
2286                 return JSValue();
2287             StringObject* obj = constructString(m_exec->vm(), m_globalObject, cachedString->jsString(m_exec));
2288             m_gcBuffer.append(obj);
2289             return obj;
2290         }
2291         case EmptyStringObjectTag: {
2292             VM& vm = m_exec->vm();
2293             StringObject* obj = constructString(vm, m_globalObject, jsEmptyString(&vm));
2294             m_gcBuffer.append(obj);
2295             return obj;
2296         }
2297         case RegExpTag: {
2298             CachedStringRef pattern;
2299             if (!readStringData(pattern))
2300                 return JSValue();
2301             CachedStringRef flags;
2302             if (!readStringData(flags))
2303                 return JSValue();
2304             RegExpFlags reFlags = regExpFlags(flags->string());
2305             ASSERT(reFlags != InvalidFlags);
2306             VM& vm = m_exec->vm();
2307             RegExp* regExp = RegExp::create(vm, pattern->string(), reFlags);
2308             return RegExpObject::create(vm, m_globalObject->regExpStructure(), regExp);
2309         }
2310         case ObjectReferenceTag: {
2311             unsigned index = 0;
2312             if (!readConstantPoolIndex(m_gcBuffer, index)) {
2313                 fail();
2314                 return JSValue();
2315             }
2316             return m_gcBuffer.at(index);
2317         }
2318         case MessagePortReferenceTag: {
2319             uint32_t index;
2320             bool indexSuccessfullyRead = read(index);
2321             if (!indexSuccessfullyRead || !m_messagePorts || index >= m_messagePorts->size()) {
2322                 fail();
2323                 return JSValue();
2324             }
2325             return getJSValue(m_messagePorts->at(index).get());
2326         }
2327         case ArrayBufferTag: {
2328             RefPtr<ArrayBuffer> arrayBuffer;
2329             if (!readArrayBuffer(arrayBuffer)) {
2330                 fail();
2331                 return JSValue();
2332             }
2333             JSValue result = getJSValue(arrayBuffer.get());
2334             m_gcBuffer.append(result);
2335             return result;
2336         }
2337         case ArrayBufferTransferTag: {
2338             uint32_t index;
2339             bool indexSuccessfullyRead = read(index);
2340             if (!indexSuccessfullyRead || index >= m_arrayBuffers.size()) {
2341                 fail();
2342                 return JSValue();
2343             }
2344
2345             if (!m_arrayBuffers[index])
2346                 m_arrayBuffers[index] = ArrayBuffer::create(m_arrayBufferContents->at(index));
2347
2348             return getJSValue(m_arrayBuffers[index].get());
2349         }
2350         case ArrayBufferViewTag: {
2351             JSValue arrayBufferView;
2352             if (!readArrayBufferView(arrayBufferView)) {
2353                 fail();
2354                 return JSValue();
2355             }
2356             m_gcBuffer.append(arrayBufferView);
2357             return arrayBufferView;
2358         }
2359 #if ENABLE(SUBTLE_CRYPTO)
2360         case CryptoKeyTag: {
2361             Vector<uint8_t> wrappedKey;
2362             if (!read(wrappedKey)) {
2363                 fail();
2364                 return JSValue();
2365             }
2366             Vector<uint8_t> serializedKey;
2367             if (!unwrapCryptoKey(m_exec, wrappedKey, serializedKey)) {
2368                 fail();
2369                 return JSValue();
2370             }
2371             JSValue cryptoKey;
2372             CloneDeserializer rawKeyDeserializer(m_exec, m_globalObject, nullptr, nullptr, serializedKey);
2373             if (!rawKeyDeserializer.readCryptoKey(cryptoKey)) {
2374                 fail();
2375                 return JSValue();
2376             }
2377             m_gcBuffer.append(cryptoKey);
2378             return cryptoKey;
2379         }
2380 #endif
2381         default:
2382             m_ptr--; // Push the tag back
2383             return JSValue();
2384         }
2385     }
2386
2387     template<SerializationTag Tag>
2388     bool consumeCollectionDataTerminationIfPossible()
2389     {
2390         if (readTag() == Tag)
2391             return true;
2392         m_ptr--;
2393         return false;
2394     }
2395
2396     JSGlobalObject* m_globalObject;
2397     bool m_isDOMGlobalObject;
2398     const uint8_t* m_ptr;
2399     const uint8_t* m_end;
2400     unsigned m_version;
2401     Vector<CachedString> m_constantPool;
2402     MessagePortArray* m_messagePorts;
2403     ArrayBufferContentsArray* m_arrayBufferContents;
2404     ArrayBufferArray m_arrayBuffers;
2405 };
2406
2407 DeserializationResult CloneDeserializer::deserialize()
2408 {
2409     Vector<uint32_t, 16> indexStack;
2410     Vector<Identifier, 16> propertyNameStack;
2411     Vector<JSObject*, 32> outputObjectStack;
2412     Vector<JSValue, 4> mapKeyStack;
2413     Vector<JSMap*, 4> mapStack;
2414     Vector<JSSet*, 4> setStack;
2415     Vector<WalkerState, 16> stateStack;
2416     WalkerState state = StateUnknown;
2417     JSValue outValue;
2418
2419     while (1) {
2420         switch (state) {
2421         arrayStartState:
2422         case ArrayStartState: {
2423             uint32_t length;
2424             if (!read(length)) {
2425                 fail();
2426                 goto error;
2427             }
2428             JSArray* outArray = constructEmptyArray(m_exec, 0, m_globalObject, length);
2429             m_gcBuffer.append(outArray);
2430             outputObjectStack.append(outArray);
2431         }
2432         arrayStartVisitMember:
2433         FALLTHROUGH;
2434         case ArrayStartVisitMember: {
2435             uint32_t index;
2436             if (!read(index)) {
2437                 fail();
2438                 goto error;
2439             }
2440             if (index == TerminatorTag) {
2441                 JSObject* outArray = outputObjectStack.last();
2442                 outValue = outArray;
2443                 outputObjectStack.removeLast();
2444                 break;
2445             } else if (index == NonIndexPropertiesTag) {
2446                 goto objectStartVisitMember;
2447             }
2448
2449             if (JSValue terminal = readTerminal()) {
2450                 putProperty(outputObjectStack.last(), index, terminal);
2451                 goto arrayStartVisitMember;
2452             }
2453             if (m_failed)
2454                 goto error;
2455             indexStack.append(index);
2456             stateStack.append(ArrayEndVisitMember);
2457             goto stateUnknown;
2458         }
2459         case ArrayEndVisitMember: {
2460             JSObject* outArray = outputObjectStack.last();
2461             putProperty(outArray, indexStack.last(), outValue);
2462             indexStack.removeLast();
2463             goto arrayStartVisitMember;
2464         }
2465         objectStartState:
2466         case ObjectStartState: {
2467             if (outputObjectStack.size() > maximumFilterRecursion)
2468                 return std::make_pair(JSValue(), StackOverflowError);
2469             JSObject* outObject = constructEmptyObject(m_exec, m_globalObject->objectPrototype());
2470             m_gcBuffer.append(outObject);
2471             outputObjectStack.append(outObject);
2472         }
2473         objectStartVisitMember:
2474         FALLTHROUGH;
2475         case ObjectStartVisitMember: {
2476             CachedStringRef cachedString;
2477             bool wasTerminator = false;
2478             if (!readStringData(cachedString, wasTerminator)) {
2479                 if (!wasTerminator)
2480                     goto error;
2481
2482                 JSObject* outObject = outputObjectStack.last();
2483                 outValue = outObject;
2484                 outputObjectStack.removeLast();
2485                 break;
2486             }
2487
2488             if (JSValue terminal = readTerminal()) {
2489                 putProperty(outputObjectStack.last(), Identifier::fromString(m_exec, cachedString->string()), terminal);
2490                 goto objectStartVisitMember;
2491             }
2492             stateStack.append(ObjectEndVisitMember);
2493             propertyNameStack.append(Identifier::fromString(m_exec, cachedString->string()));
2494             goto stateUnknown;
2495         }
2496         case ObjectEndVisitMember: {
2497             putProperty(outputObjectStack.last(), propertyNameStack.last(), outValue);
2498             propertyNameStack.removeLast();
2499             goto objectStartVisitMember;
2500         }
2501         mapObjectStartState: {
2502             if (outputObjectStack.size() > maximumFilterRecursion)
2503                 return std::make_pair(JSValue(), StackOverflowError);
2504             JSMap* map = JSMap::create(m_exec->vm(), m_globalObject->mapStructure());
2505             m_gcBuffer.append(map);
2506             outputObjectStack.append(map);
2507             mapStack.append(map);
2508             goto mapDataStartVisitEntry;
2509         }
2510         mapDataStartVisitEntry:
2511         case MapDataStartVisitEntry: {
2512             if (consumeCollectionDataTerminationIfPossible<NonMapPropertiesTag>()) {
2513                 mapStack.removeLast();
2514                 goto objectStartVisitMember;
2515             }
2516             stateStack.append(MapDataEndVisitKey);
2517             goto stateUnknown;
2518         }
2519         case MapDataEndVisitKey: {
2520             mapKeyStack.append(outValue);
2521             stateStack.append(MapDataEndVisitValue);
2522             goto stateUnknown;
2523         }
2524         case MapDataEndVisitValue: {
2525             mapStack.last()->set(m_exec, mapKeyStack.last(), outValue);
2526             mapKeyStack.removeLast();
2527             goto mapDataStartVisitEntry;
2528         }
2529
2530         setObjectStartState: {
2531             if (outputObjectStack.size() > maximumFilterRecursion)
2532                 return std::make_pair(JSValue(), StackOverflowError);
2533             JSSet* set = JSSet::create(m_exec->vm(), m_globalObject->setStructure());
2534             m_gcBuffer.append(set);
2535             outputObjectStack.append(set);
2536             setStack.append(set);
2537             goto setDataStartVisitEntry;
2538         }
2539         setDataStartVisitEntry:
2540         case SetDataStartVisitEntry: {
2541             if (consumeCollectionDataTerminationIfPossible<NonSetPropertiesTag>()) {
2542                 setStack.removeLast();
2543                 goto objectStartVisitMember;
2544             }
2545             stateStack.append(SetDataEndVisitKey);
2546             goto stateUnknown;
2547         }
2548         case SetDataEndVisitKey: {
2549             JSSet* set = setStack.last();
2550             set->add(m_exec, outValue);
2551             goto setDataStartVisitEntry;
2552         }
2553
2554         stateUnknown:
2555         case StateUnknown:
2556             if (JSValue terminal = readTerminal()) {
2557                 outValue = terminal;
2558                 break;
2559             }
2560             SerializationTag tag = readTag();
2561             if (tag == ArrayTag)
2562                 goto arrayStartState;
2563             if (tag == ObjectTag)
2564                 goto objectStartState;
2565             if (tag == MapObjectTag)
2566                 goto mapObjectStartState;
2567             if (tag == SetObjectTag)
2568                 goto setObjectStartState;
2569             goto error;
2570         }
2571         if (stateStack.isEmpty())
2572             break;
2573
2574         state = stateStack.last();
2575         stateStack.removeLast();
2576     }
2577     ASSERT(outValue);
2578     ASSERT(!m_failed);
2579     return std::make_pair(outValue, SuccessfullyCompleted);
2580 error:
2581     fail();
2582     return std::make_pair(JSValue(), ValidationError);
2583 }
2584
2585 void SerializedScriptValue::addBlobURL(const String& string)
2586 {
2587     m_blobURLs.append(Vector<uint16_t>());
2588     m_blobURLs.last().reserveCapacity(string.length());
2589     for (size_t i = 0; i < string.length(); i++)
2590         m_blobURLs.last().append(string.characterAt(i));
2591     m_blobURLs.last().resize(m_blobURLs.last().size());
2592 }
2593
2594 SerializedScriptValue::~SerializedScriptValue()
2595 {
2596 }
2597
2598 SerializedScriptValue::SerializedScriptValue(const Vector<uint8_t>& buffer)
2599     : m_data(buffer)
2600 {
2601 }
2602
2603 SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer)
2604 {
2605     m_data.swap(buffer);
2606 }
2607
2608 SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer, Vector<String>& blobURLs)
2609 {
2610     m_data.swap(buffer);
2611     for (auto& string : blobURLs)
2612         addBlobURL(string);
2613 }
2614
2615 SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer, Vector<String>& blobURLs, std::unique_ptr<ArrayBufferContentsArray> arrayBufferContentsArray)
2616     : m_arrayBufferContentsArray(WTFMove(arrayBufferContentsArray))
2617 {
2618     m_data.swap(buffer);
2619     for (auto& string : blobURLs)
2620         addBlobURL(string);
2621 }
2622
2623 std::unique_ptr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValue::transferArrayBuffers(
2624     ExecState* exec, ArrayBufferArray& arrayBuffers, SerializationReturnCode& code)
2625 {
2626     for (size_t i = 0; i < arrayBuffers.size(); i++) {
2627         if (arrayBuffers[i]->isNeutered()) {
2628             code = ValidationError;
2629             return nullptr;
2630         }
2631     }
2632
2633     auto contents = std::make_unique<ArrayBufferContentsArray>(arrayBuffers.size());
2634     Vector<Ref<DOMWrapperWorld>> worlds;
2635     static_cast<JSVMClientData*>(exec->vm().clientData)->getAllWorlds(worlds);
2636
2637     HashSet<JSC::ArrayBuffer*> visited;
2638     for (size_t arrayBufferIndex = 0; arrayBufferIndex < arrayBuffers.size(); arrayBufferIndex++) {
2639         if (visited.contains(arrayBuffers[arrayBufferIndex].get()))
2640             continue;
2641         visited.add(arrayBuffers[arrayBufferIndex].get());
2642
2643         bool result = arrayBuffers[arrayBufferIndex]->transfer(contents->at(arrayBufferIndex));
2644         if (!result) {
2645             code = ValidationError;
2646             return nullptr;
2647         }
2648     }
2649     return contents;
2650 }
2651
2652 RefPtr<SerializedScriptValue> SerializedScriptValue::create(ExecState* exec, JSValue value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, SerializationErrorMode throwExceptions)
2653 {
2654     Vector<uint8_t> buffer;
2655     Vector<String> blobURLs;
2656     SerializationReturnCode code = CloneSerializer::serialize(exec, value, messagePorts, arrayBuffers, blobURLs, buffer);
2657
2658     std::unique_ptr<ArrayBufferContentsArray> arrayBufferContentsArray;
2659
2660     if (arrayBuffers && serializationDidCompleteSuccessfully(code))
2661         arrayBufferContentsArray = transferArrayBuffers(exec, *arrayBuffers, code);
2662
2663     if (throwExceptions == Throwing)
2664         maybeThrowExceptionIfSerializationFailed(exec, code);
2665
2666     if (!serializationDidCompleteSuccessfully(code))
2667         return nullptr;
2668
2669     return adoptRef(*new SerializedScriptValue(buffer, blobURLs, WTFMove(arrayBufferContentsArray)));
2670 }
2671
2672 RefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& string)
2673 {
2674     Vector<uint8_t> buffer;
2675     if (!CloneSerializer::serialize(string, buffer))
2676         return nullptr;
2677     return adoptRef(*new SerializedScriptValue(buffer));
2678 }
2679
2680 #if ENABLE(INDEXED_DATABASE)
2681 Ref<SerializedScriptValue> SerializedScriptValue::numberValue(double value)
2682 {
2683     Vector<uint8_t> buffer;
2684     CloneSerializer::serializeNumber(value, buffer);
2685     return adoptRef(*new SerializedScriptValue(buffer));
2686 }
2687
2688 Ref<SerializedScriptValue> SerializedScriptValue::undefinedValue()
2689 {
2690     Vector<uint8_t> buffer;
2691     CloneSerializer::serializeUndefined(buffer);
2692     return adoptRef(*new SerializedScriptValue(buffer));
2693 }
2694 #endif
2695
2696 RefPtr<SerializedScriptValue> SerializedScriptValue::create(JSContextRef originContext, JSValueRef apiValue, JSValueRef* exception)
2697 {
2698     ExecState* exec = toJS(originContext);
2699     JSLockHolder locker(exec);
2700     JSValue value = toJS(exec, apiValue);
2701     RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::create(exec, value, nullptr, nullptr);
2702     if (exec->hadException()) {
2703         if (exception)
2704             *exception = toRef(exec, exec->exception()->value());
2705         exec->clearException();
2706         return nullptr;
2707     }
2708     ASSERT(serializedValue);
2709     return serializedValue;
2710 }
2711
2712 String SerializedScriptValue::toString()
2713 {
2714     return CloneDeserializer::deserializeString(m_data);
2715 }
2716
2717 JSValue SerializedScriptValue::deserialize(ExecState* exec, JSGlobalObject* globalObject,
2718                                            MessagePortArray* messagePorts, SerializationErrorMode throwExceptions)
2719 {
2720     DeserializationResult result = CloneDeserializer::deserialize(exec, globalObject, messagePorts,
2721                                                                   m_arrayBufferContentsArray.get(), m_data);
2722     if (throwExceptions == Throwing)
2723         maybeThrowExceptionIfSerializationFailed(exec, result.second);
2724     return result.first ? result.first : jsNull();
2725 }
2726
2727 JSValueRef SerializedScriptValue::deserialize(JSContextRef destinationContext, JSValueRef* exception)
2728 {
2729     ExecState* exec = toJS(destinationContext);
2730     JSLockHolder locker(exec);
2731     JSValue value = deserialize(exec, exec->lexicalGlobalObject(), nullptr);
2732     if (exec->hadException()) {
2733         if (exception)
2734             *exception = toRef(exec, exec->exception()->value());
2735         exec->clearException();
2736         return nullptr;
2737     }
2738     ASSERT(value);
2739     return toRef(exec, value);
2740 }
2741
2742 Ref<SerializedScriptValue> SerializedScriptValue::nullValue()
2743 {
2744     Vector<uint8_t> buffer;
2745     return adoptRef(*new SerializedScriptValue(buffer));
2746 }
2747
2748 void SerializedScriptValue::maybeThrowExceptionIfSerializationFailed(ExecState* exec, SerializationReturnCode code)
2749 {
2750     if (code == SuccessfullyCompleted)
2751         return;
2752     
2753     switch (code) {
2754     case StackOverflowError:
2755         exec->vm().throwException(exec, createStackOverflowError(exec));
2756         break;
2757     case ValidationError:
2758         exec->vm().throwException(exec, createTypeError(exec, "Unable to deserialize data."));
2759         break;
2760     case DataCloneError:
2761         setDOMException(exec, DATA_CLONE_ERR);
2762         break;
2763     case ExistingExceptionError:
2764         break;
2765     case UnspecifiedError:
2766         break;
2767     default:
2768         ASSERT_NOT_REACHED();
2769     }
2770 }
2771
2772 bool SerializedScriptValue::serializationDidCompleteSuccessfully(SerializationReturnCode code)
2773 {
2774     return (code == SuccessfullyCompleted);
2775 }
2776
2777 uint32_t SerializedScriptValue::wireFormatVersion()
2778 {
2779     return CurrentVersion;
2780 }
2781
2782 }