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