7753d8a2f33487b1972738edb2c70124274ea0e6
[WebKit-https.git] / Source / WebCore / bindings / js / SerializedScriptValue.cpp
1 /*
2  * Copyright (C) 2009-2017 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 "BlobRegistry.h"
31 #include "CryptoKeyAES.h"
32 #include "CryptoKeyEC.h"
33 #include "CryptoKeyHMAC.h"
34 #include "CryptoKeyRSA.h"
35 #include "CryptoKeyRSAComponents.h"
36 #include "CryptoKeyRaw.h"
37 #include "IDBValue.h"
38 #include "JSBlob.h"
39 #include "JSCryptoKey.h"
40 #include "JSDOMBinding.h"
41 #include "JSDOMConvertBufferSource.h"
42 #include "JSDOMGlobalObject.h"
43 #include "JSDOMMatrix.h"
44 #include "JSDOMPoint.h"
45 #include "JSDOMQuad.h"
46 #include "JSDOMRect.h"
47 #include "JSFile.h"
48 #include "JSFileList.h"
49 #include "JSImageBitmap.h"
50 #include "JSImageData.h"
51 #include "JSMessagePort.h"
52 #include "JSNavigator.h"
53 #include "JSRTCCertificate.h"
54 #include "ScriptExecutionContext.h"
55 #include "ScriptState.h"
56 #include "SharedBuffer.h"
57 #include "WebCoreJSClientData.h"
58 #include <JavaScriptCore/APICast.h>
59 #include <JavaScriptCore/BooleanObject.h>
60 #include <JavaScriptCore/CatchScope.h>
61 #include <JavaScriptCore/DateInstance.h>
62 #include <JavaScriptCore/Error.h>
63 #include <JavaScriptCore/Exception.h>
64 #include <JavaScriptCore/ExceptionHelpers.h>
65 #include <JavaScriptCore/IterationKind.h>
66 #include <JavaScriptCore/JSArrayBuffer.h>
67 #include <JavaScriptCore/JSArrayBufferView.h>
68 #include <JavaScriptCore/JSCInlines.h>
69 #include <JavaScriptCore/JSDataView.h>
70 #include <JavaScriptCore/JSMap.h>
71 #include <JavaScriptCore/JSMapIterator.h>
72 #include <JavaScriptCore/JSSet.h>
73 #include <JavaScriptCore/JSSetIterator.h>
74 #include <JavaScriptCore/JSTypedArrays.h>
75 #include <JavaScriptCore/JSWebAssemblyModule.h>
76 #include <JavaScriptCore/ObjectConstructor.h>
77 #include <JavaScriptCore/PropertyNameArray.h>
78 #include <JavaScriptCore/RegExp.h>
79 #include <JavaScriptCore/RegExpObject.h>
80 #include <JavaScriptCore/TypedArrayInlines.h>
81 #include <JavaScriptCore/TypedArrays.h>
82 #include <JavaScriptCore/WasmModule.h>
83 #include <JavaScriptCore/YarrFlags.h>
84 #include <limits>
85 #include <wtf/CompletionHandler.h>
86 #include <wtf/MainThread.h>
87 #include <wtf/RunLoop.h>
88 #include <wtf/Vector.h>
89
90 #if CPU(BIG_ENDIAN) || CPU(MIDDLE_ENDIAN) || CPU(NEEDS_ALIGNED_ACCESS)
91 #define ASSUME_LITTLE_ENDIAN 0
92 #else
93 #define ASSUME_LITTLE_ENDIAN 1
94 #endif
95
96 namespace WebCore {
97 using namespace JSC;
98
99 static const unsigned maximumFilterRecursion = 40000;
100
101 enum class SerializationReturnCode {
102     SuccessfullyCompleted,
103     StackOverflowError,
104     InterruptedExecutionError,
105     ValidationError,
106     ExistingExceptionError,
107     DataCloneError,
108     UnspecifiedError
109 };
110
111 enum WalkerState { StateUnknown, ArrayStartState, ArrayStartVisitMember, ArrayEndVisitMember,
112     ObjectStartState, ObjectStartVisitMember, ObjectEndVisitMember,
113     MapDataStartVisitEntry, MapDataEndVisitKey, MapDataEndVisitValue,
114     SetDataStartVisitEntry, SetDataEndVisitKey };
115
116 // These can't be reordered, and any new types must be added to the end of the list
117 // When making changes to these lists please cover your new type(s) in the API test "IndexedDB.StructuredCloneBackwardCompatibility"
118 enum SerializationTag {
119     ArrayTag = 1,
120     ObjectTag = 2,
121     UndefinedTag = 3,
122     NullTag = 4,
123     IntTag = 5,
124     ZeroTag = 6,
125     OneTag = 7,
126     FalseTag = 8,
127     TrueTag = 9,
128     DoubleTag = 10,
129     DateTag = 11,
130     FileTag = 12,
131     FileListTag = 13,
132     ImageDataTag = 14,
133     BlobTag = 15,
134     StringTag = 16,
135     EmptyStringTag = 17,
136     RegExpTag = 18,
137     ObjectReferenceTag = 19,
138     MessagePortReferenceTag = 20,
139     ArrayBufferTag = 21,
140     ArrayBufferViewTag = 22,
141     ArrayBufferTransferTag = 23,
142     TrueObjectTag = 24,
143     FalseObjectTag = 25,
144     StringObjectTag = 26,
145     EmptyStringObjectTag = 27,
146     NumberObjectTag = 28,
147     SetObjectTag = 29,
148     MapObjectTag = 30,
149     NonMapPropertiesTag = 31,
150     NonSetPropertiesTag = 32,
151 #if ENABLE(WEB_CRYPTO)
152     CryptoKeyTag = 33,
153 #endif
154     SharedArrayBufferTag = 34,
155 #if ENABLE(WEBASSEMBLY)
156     WasmModuleTag = 35,
157 #endif
158     DOMPointReadOnlyTag = 36,
159     DOMPointTag = 37,
160     DOMRectReadOnlyTag = 38,
161     DOMRectTag = 39,
162     DOMMatrixReadOnlyTag = 40,
163     DOMMatrixTag = 41,
164     DOMQuadTag = 42,
165     ImageBitmapTransferTag = 43,
166 #if ENABLE(WEB_RTC)
167     RTCCertificateTag = 44,
168 #endif
169     ErrorTag = 255
170 };
171
172 enum ArrayBufferViewSubtag {
173     DataViewTag = 0,
174     Int8ArrayTag = 1,
175     Uint8ArrayTag = 2,
176     Uint8ClampedArrayTag = 3,
177     Int16ArrayTag = 4,
178     Uint16ArrayTag = 5,
179     Int32ArrayTag = 6,
180     Uint32ArrayTag = 7,
181     Float32ArrayTag = 8,
182     Float64ArrayTag = 9
183 };
184
185 static unsigned typedArrayElementSize(ArrayBufferViewSubtag tag)
186 {
187     switch (tag) {
188     case DataViewTag:
189     case Int8ArrayTag:
190     case Uint8ArrayTag:
191     case Uint8ClampedArrayTag:
192         return 1;
193     case Int16ArrayTag:
194     case Uint16ArrayTag:
195         return 2;
196     case Int32ArrayTag:
197     case Uint32ArrayTag:
198     case Float32ArrayTag:
199         return 4;
200     case Float64ArrayTag:
201         return 8;
202     default:
203         return 0;
204     }
205
206 }
207
208 #if ENABLE(WEB_CRYPTO)
209
210 const uint32_t currentKeyFormatVersion = 1;
211
212 enum class CryptoKeyClassSubtag {
213     HMAC = 0,
214     AES = 1,
215     RSA = 2,
216     EC = 3,
217     Raw = 4,
218 };
219 const uint8_t cryptoKeyClassSubtagMaximumValue = 4;
220
221 enum class CryptoKeyAsymmetricTypeSubtag {
222     Public = 0,
223     Private = 1
224 };
225 const uint8_t cryptoKeyAsymmetricTypeSubtagMaximumValue = 1;
226
227 enum class CryptoKeyUsageTag {
228     Encrypt = 0,
229     Decrypt = 1,
230     Sign = 2,
231     Verify = 3,
232     DeriveKey = 4,
233     DeriveBits = 5,
234     WrapKey = 6,
235     UnwrapKey = 7
236 };
237 const uint8_t cryptoKeyUsageTagMaximumValue = 7;
238
239 enum class CryptoAlgorithmIdentifierTag {
240     RSAES_PKCS1_v1_5 = 0,
241     RSASSA_PKCS1_v1_5 = 1,
242     RSA_PSS = 2,
243     RSA_OAEP = 3,
244     ECDSA = 4,
245     ECDH = 5,
246     AES_CTR = 6,
247     AES_CBC = 7,
248     AES_GCM = 9,
249     AES_CFB = 10,
250     AES_KW = 11,
251     HMAC = 12,
252     SHA_1 = 14,
253     SHA_224 = 15,
254     SHA_256 = 16,
255     SHA_384 = 17,
256     SHA_512 = 18,
257     HKDF = 20,
258     PBKDF2 = 21,
259 };
260 const uint8_t cryptoAlgorithmIdentifierTagMaximumValue = 21;
261
262 static unsigned countUsages(CryptoKeyUsageBitmap usages)
263 {
264     // Fast bit count algorithm for sparse bit maps.
265     unsigned count = 0;
266     while (usages) {
267         usages = usages & (usages - 1);
268         ++count;
269     }
270     return count;
271 }
272
273 #endif
274
275 /* CurrentVersion tracks the serialization version so that persistent stores
276  * are able to correctly bail out in the case of encountering newer formats.
277  *
278  * Initial version was 1.
279  * Version 2. added the ObjectReferenceTag and support for serialization of cyclic graphs.
280  * Version 3. added the FalseObjectTag, TrueObjectTag, NumberObjectTag, StringObjectTag
281  * and EmptyStringObjectTag for serialization of Boolean, Number and String objects.
282  * Version 4. added support for serializing non-index properties of arrays.
283  * Version 5. added support for Map and Set types.
284  * Version 6. added support for 8-bit strings.
285  * Version 7. added support for File's lastModified attribute.
286  */
287 static const unsigned CurrentVersion = 7;
288 static const unsigned TerminatorTag = 0xFFFFFFFF;
289 static const unsigned StringPoolTag = 0xFFFFFFFE;
290 static const unsigned NonIndexPropertiesTag = 0xFFFFFFFD;
291
292 // The high bit of a StringData's length determines the character size.
293 static const unsigned StringDataIs8BitFlag = 0x80000000;
294
295 /*
296  * Object serialization is performed according to the following grammar, all tags
297  * are recorded as a single uint8_t.
298  *
299  * IndexType (used for the object pool and StringData's constant pool) is the
300  * minimum sized unsigned integer type required to represent the maximum index
301  * in the constant pool.
302  *
303  * SerializedValue :- <CurrentVersion:uint32_t> Value
304  * Value :- Array | Object | Map | Set | Terminal
305  *
306  * Array :-
307  *     ArrayTag <length:uint32_t>(<index:uint32_t><value:Value>)* TerminatorTag
308  *
309  * Object :-
310  *     ObjectTag (<name:StringData><value:Value>)* TerminatorTag
311  *
312  * Map :- MapObjectTag MapData
313  *
314  * Set :- SetObjectTag SetData
315  *
316  * MapData :- (<key:Value><value:Value>)* NonMapPropertiesTag (<name:StringData><value:Value>)* TerminatorTag
317  * SetData :- (<key:Value>)* NonSetPropertiesTag (<name:StringData><value:Value>)* TerminatorTag
318  *
319  * Terminal :-
320  *      UndefinedTag
321  *    | NullTag
322  *    | IntTag <value:int32_t>
323  *    | ZeroTag
324  *    | OneTag
325  *    | FalseTag
326  *    | TrueTag
327  *    | FalseObjectTag
328  *    | TrueObjectTag
329  *    | DoubleTag <value:double>
330  *    | NumberObjectTag <value:double>
331  *    | DateTag <value:double>
332  *    | String
333  *    | EmptyStringTag
334  *    | EmptyStringObjectTag
335  *    | File
336  *    | FileList
337  *    | ImageData
338  *    | Blob
339  *    | ObjectReference
340  *    | MessagePortReferenceTag <value:uint32_t>
341  *    | ArrayBuffer
342  *    | ArrayBufferViewTag ArrayBufferViewSubtag <byteOffset:uint32_t> <byteLength:uint32_t> (ArrayBuffer | ObjectReference)
343  *    | ArrayBufferTransferTag <value:uint32_t>
344  *    | CryptoKeyTag <wrappedKeyLength:uint32_t> <factor:byte{wrappedKeyLength}>
345  *    | DOMPoint
346  *    | DOMRect
347  *    | DOMMatrix
348  *    | DOMQuad
349  *    | ImageBitmapTransferTag <value:uint32_t>
350  *    | RTCCertificateTag
351  *
352  * Inside certificate, data is serialized in this format as per spec:
353  *
354  * <expires:double> <certificate:StringData> <origin:StringData> <keyingMaterial:StringData>
355  * We also add fingerprints to make sure we expose to JavaScript the same information.
356  *
357  * Inside wrapped crypto key, data is serialized in this format:
358  *
359  * <keyFormatVersion:uint32_t> <extractable:int32_t> <usagesCount:uint32_t> <usages:byte{usagesCount}> CryptoKeyClassSubtag (CryptoKeyHMAC | CryptoKeyAES | CryptoKeyRSA)
360  *
361  * String :-
362  *      EmptyStringTag
363  *      StringTag StringData
364  *
365  * StringObject:
366  *      EmptyStringObjectTag
367  *      StringObjectTag StringData
368  *
369  * StringData :-
370  *      StringPoolTag <cpIndex:IndexType>
371  *      (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
372  *
373  * File :-
374  *    FileTag FileData
375  *
376  * FileData :-
377  *    <path:StringData> <url:StringData> <type:StringData> <name:StringData> <lastModified:double>
378  *
379  * FileList :-
380  *    FileListTag <length:uint32_t>(<file:FileData>){length}
381  *
382  * ImageData :-
383  *    ImageDataTag <width:int32_t><height:int32_t><length:uint32_t><data:uint8_t{length}>
384  *
385  * Blob :-
386  *    BlobTag <url:StringData><type:StringData><size:long long>
387  *
388  * RegExp :-
389  *    RegExpTag <pattern:StringData><flags:StringData>
390  *
391  * ObjectReference :-
392  *    ObjectReferenceTag <opIndex:IndexType>
393  *
394  * ArrayBuffer :-
395  *    ArrayBufferTag <length:uint32_t> <contents:byte{length}>
396  *
397  * CryptoKeyHMAC :-
398  *    <keySize:uint32_t> <keyData:byte{keySize}> CryptoAlgorithmIdentifierTag // Algorithm tag inner hash function.
399  *
400  * CryptoKeyAES :-
401  *    CryptoAlgorithmIdentifierTag <keySize:uint32_t> <keyData:byte{keySize}>
402  *
403  * CryptoKeyRSA :-
404  *    CryptoAlgorithmIdentifierTag <isRestrictedToHash:int32_t> CryptoAlgorithmIdentifierTag? CryptoKeyAsymmetricTypeSubtag CryptoKeyRSAPublicComponents CryptoKeyRSAPrivateComponents?
405  *
406  * CryptoKeyRSAPublicComponents :-
407  *    <modulusSize:uint32_t> <modulus:byte{modulusSize}> <exponentSize:uint32_t> <exponent:byte{exponentSize}>
408  *
409  * CryptoKeyRSAPrivateComponents :-
410  *    <privateExponentSize:uint32_t> <privateExponent:byte{privateExponentSize}> <primeCount:uint32_t> FirstPrimeInfo? PrimeInfo{primeCount - 1}
411  *
412  * // CRT data could be computed from prime factors. It is only serialized to reuse a code path that's needed for JWK.
413  * FirstPrimeInfo :-
414  *    <factorSize:uint32_t> <factor:byte{factorSize}> <crtExponentSize:uint32_t> <crtExponent:byte{crtExponentSize}>
415  *
416  * PrimeInfo :-
417  *    <factorSize:uint32_t> <factor:byte{factorSize}> <crtExponentSize:uint32_t> <crtExponent:byte{crtExponentSize}> <crtCoefficientSize:uint32_t> <crtCoefficient:byte{crtCoefficientSize}>
418  *
419  * CryptoKeyEC :-
420  *    CryptoAlgorithmIdentifierTag <namedCurve:StringData> CryptoKeyAsymmetricTypeSubtag <keySize:uint32_t> <keyData:byte{keySize}>
421  *
422  * CryptoKeyRaw :-
423  *    CryptoAlgorithmIdentifierTag <keySize:uint32_t> <keyData:byte{keySize}>
424  *
425  * DOMPoint :-
426  *        DOMPointReadOnlyTag DOMPointData
427  *      | DOMPointTag DOMPointData
428  *
429  * DOMPointData :-
430  *      <x:double> <y:double> <z:double> <w:double>
431  *
432  * DOMRect :-
433  *        DOMRectReadOnlyTag DOMRectData
434  *      | DOMRectTag DOMRectData
435  *
436  * DOMRectData :-
437  *      <x:double> <y:double> <width:double> <height:double>
438  *
439  * DOMMatrix :-
440  *        DOMMatrixReadOnlyTag DOMMatrixData
441  *      | DOMMatrixTag DOMMatrixData
442  *
443  * DOMMatrixData :-
444  *        <is2D:uint8_t:true> <m11:double> <m12:double> <m21:double> <m22:double> <m41:double> <m42:double>
445  *      | <is2D:uint8_t:false> <m11:double> <m12:double> <m13:double> <m14:double> <m21:double> <m22:double> <m23:double> <m24:double> <m31:double> <m32:double> <m33:double> <m34:double> <m41:double> <m42:double> <m43:double> <m44:double>
446  *
447  * DOMQuad :-
448  *      DOMQuadTag DOMQuadData
449  *
450  * DOMQuadData :-
451  *      <p1:DOMPointData> <p2:DOMPointData> <p3:DOMPointData> <p4:DOMPointData>
452  *
453  */
454
455 using DeserializationResult = std::pair<JSC::JSValue, SerializationReturnCode>;
456
457 class CloneBase {
458 protected:
459     CloneBase(ExecState* exec)
460         : m_exec(exec)
461         , m_failed(false)
462     {
463     }
464
465     bool shouldTerminate()
466     {
467         VM& vm = m_exec->vm();
468         auto scope = DECLARE_THROW_SCOPE(vm);
469         return scope.exception();
470     }
471
472     void fail()
473     {
474         m_failed = true;
475     }
476
477     ExecState* m_exec;
478     bool m_failed;
479     MarkedArgumentBuffer m_gcBuffer;
480 };
481
482 #if ENABLE(WEB_CRYPTO)
483 static bool wrapCryptoKey(ExecState* exec, const Vector<uint8_t>& key, Vector<uint8_t>& wrappedKey)
484 {
485     ScriptExecutionContext* scriptExecutionContext = scriptExecutionContextFromExecState(exec);
486     if (!scriptExecutionContext)
487         return false;
488     return scriptExecutionContext->wrapCryptoKey(key, wrappedKey);
489 }
490
491 static bool unwrapCryptoKey(ExecState* exec, const Vector<uint8_t>& wrappedKey, Vector<uint8_t>& key)
492 {
493     ScriptExecutionContext* scriptExecutionContext = scriptExecutionContextFromExecState(exec);
494     if (!scriptExecutionContext)
495         return false;
496     return scriptExecutionContext->unwrapCryptoKey(wrappedKey, key);
497 }
498 #endif
499
500 #if ASSUME_LITTLE_ENDIAN
501 template <typename T> static void writeLittleEndian(Vector<uint8_t>& buffer, T value)
502 {
503     buffer.append(reinterpret_cast<uint8_t*>(&value), sizeof(value));
504 }
505 #else
506 template <typename T> static void writeLittleEndian(Vector<uint8_t>& buffer, T value)
507 {
508     for (unsigned i = 0; i < sizeof(T); i++) {
509         buffer.append(value & 0xFF);
510         value >>= 8;
511     }
512 }
513 #endif
514
515 template <> void writeLittleEndian<uint8_t>(Vector<uint8_t>& buffer, uint8_t value)
516 {
517     buffer.append(value);
518 }
519
520 template <typename T> static bool writeLittleEndian(Vector<uint8_t>& buffer, const T* values, uint32_t length)
521 {
522     if (length > std::numeric_limits<uint32_t>::max() / sizeof(T))
523         return false;
524
525 #if ASSUME_LITTLE_ENDIAN
526     buffer.append(reinterpret_cast<const uint8_t*>(values), length * sizeof(T));
527 #else
528     for (unsigned i = 0; i < length; i++) {
529         T value = values[i];
530         for (unsigned j = 0; j < sizeof(T); j++) {
531             buffer.append(static_cast<uint8_t>(value & 0xFF));
532             value >>= 8;
533         }
534     }
535 #endif
536     return true;
537 }
538
539 template <> bool writeLittleEndian<uint8_t>(Vector<uint8_t>& buffer, const uint8_t* values, uint32_t length)
540 {
541     buffer.append(values, length);
542     return true;
543 }
544
545 class CloneSerializer : CloneBase {
546 public:
547     static SerializationReturnCode serialize(ExecState* exec, JSValue value, Vector<RefPtr<MessagePort>>& messagePorts, Vector<RefPtr<JSC::ArrayBuffer>>& arrayBuffers, const Vector<RefPtr<ImageBitmap>>& imageBitmaps,
548 #if ENABLE(WEBASSEMBLY)
549             WasmModuleArray& wasmModules,
550 #endif
551         Vector<String>& blobURLs, const PAL::SessionID& sessionID, Vector<uint8_t>& out, SerializationContext context, ArrayBufferContentsArray& sharedBuffers)
552     {
553         CloneSerializer serializer(exec, messagePorts, arrayBuffers, imageBitmaps,
554 #if ENABLE(WEBASSEMBLY)
555             wasmModules,
556 #endif
557             blobURLs, sessionID, out, context, sharedBuffers);
558         return serializer.serialize(value);
559     }
560
561     static bool serialize(StringView string, Vector<uint8_t>& out)
562     {
563         writeLittleEndian(out, CurrentVersion);
564         if (string.isEmpty()) {
565             writeLittleEndian<uint8_t>(out, EmptyStringTag);
566             return true;
567         }
568         writeLittleEndian<uint8_t>(out, StringTag);
569         if (string.is8Bit()) {
570             writeLittleEndian(out, string.length() | StringDataIs8BitFlag);
571             return writeLittleEndian(out, string.characters8(), string.length());
572         }
573         writeLittleEndian(out, string.length());
574         return writeLittleEndian(out, string.characters16(), string.length());
575     }
576
577 private:
578     typedef HashMap<JSObject*, uint32_t> ObjectPool;
579
580     CloneSerializer(ExecState* exec, Vector<RefPtr<MessagePort>>& messagePorts, Vector<RefPtr<JSC::ArrayBuffer>>& arrayBuffers, const Vector<RefPtr<ImageBitmap>>& imageBitmaps,
581 #if ENABLE(WEBASSEMBLY)
582             WasmModuleArray& wasmModules,
583 #endif
584         Vector<String>& blobURLs, const PAL::SessionID& sessionID, Vector<uint8_t>& out, SerializationContext context, ArrayBufferContentsArray& sharedBuffers)
585         : CloneBase(exec)
586         , m_buffer(out)
587         , m_blobURLs(blobURLs)
588         , m_sessionID(sessionID)
589         , m_emptyIdentifier(Identifier::fromString(exec, emptyString()))
590         , m_context(context)
591         , m_sharedBuffers(sharedBuffers)
592 #if ENABLE(WEBASSEMBLY)
593         , m_wasmModules(wasmModules)
594 #endif
595     {
596         write(CurrentVersion);
597         fillTransferMap(messagePorts, m_transferredMessagePorts);
598         fillTransferMap(arrayBuffers, m_transferredArrayBuffers);
599         fillTransferMap(imageBitmaps, m_transferredImageBitmaps);
600     }
601
602     template <class T>
603     void fillTransferMap(const Vector<RefPtr<T>>& input, ObjectPool& result)
604     {
605         if (input.isEmpty())
606             return;
607         JSDOMGlobalObject* globalObject = jsCast<JSDOMGlobalObject*>(m_exec->lexicalGlobalObject());
608         for (size_t i = 0; i < input.size(); i++) {
609             JSC::JSValue value = toJS(m_exec, globalObject, input[i].get());
610             JSC::JSObject* obj = value.getObject();
611             if (obj && !result.contains(obj))
612                 result.add(obj, i);
613         }
614     }
615
616     SerializationReturnCode serialize(JSValue in);
617
618     bool isArray(VM& vm, JSValue value)
619     {
620         if (!value.isObject())
621             return false;
622         JSObject* object = asObject(value);
623         return object->inherits<JSArray>(vm);
624     }
625
626     bool isMap(VM& vm, JSValue value)
627     {
628         if (!value.isObject())
629             return false;
630         JSObject* object = asObject(value);
631         return object->inherits<JSMap>(vm);
632     }
633     bool isSet(VM& vm, JSValue value)
634     {
635         if (!value.isObject())
636             return false;
637         JSObject* object = asObject(value);
638         return object->inherits<JSSet>(vm);
639     }
640
641     bool checkForDuplicate(JSObject* object)
642     {
643         // Record object for graph reconstruction
644         ObjectPool::const_iterator found = m_objectPool.find(object);
645
646         // Handle duplicate references
647         if (found != m_objectPool.end()) {
648             write(ObjectReferenceTag);
649             ASSERT(found->value < m_objectPool.size());
650             writeObjectIndex(found->value);
651             return true;
652         }
653
654         return false;
655     }
656
657     void recordObject(JSObject* object)
658     {
659         m_objectPool.add(object, m_objectPool.size());
660         m_gcBuffer.appendWithCrashOnOverflow(object);
661     }
662
663     bool startObjectInternal(JSObject* object)
664     {
665         if (checkForDuplicate(object))
666             return false;
667         recordObject(object);
668         return true;
669     }
670
671     bool startObject(JSObject* object)
672     {
673         if (!startObjectInternal(object))
674             return false;
675         write(ObjectTag);
676         return true;
677     }
678
679     bool startArray(JSArray* array)
680     {
681         if (!startObjectInternal(array))
682             return false;
683
684         unsigned length = array->length();
685         write(ArrayTag);
686         write(length);
687         return true;
688     }
689
690     bool startSet(JSSet* set)
691     {
692         if (!startObjectInternal(set))
693             return false;
694
695         write(SetObjectTag);
696         return true;
697     }
698
699     bool startMap(JSMap* map)
700     {
701         if (!startObjectInternal(map))
702             return false;
703
704         write(MapObjectTag);
705         return true;
706     }
707
708     void endObject()
709     {
710         write(TerminatorTag);
711     }
712
713     JSValue getProperty(VM& vm, JSObject* object, const Identifier& propertyName)
714     {
715         PropertySlot slot(object, PropertySlot::InternalMethodType::Get);
716         if (object->methodTable(vm)->getOwnPropertySlot(object, m_exec, propertyName, slot))
717             return slot.getValue(m_exec, propertyName);
718         return JSValue();
719     }
720
721     void dumpImmediate(JSValue value)
722     {
723         if (value.isNull())
724             write(NullTag);
725         else if (value.isUndefined())
726             write(UndefinedTag);
727         else if (value.isNumber()) {
728             if (value.isInt32()) {
729                 if (!value.asInt32())
730                     write(ZeroTag);
731                 else if (value.asInt32() == 1)
732                     write(OneTag);
733                 else {
734                     write(IntTag);
735                     write(static_cast<uint32_t>(value.asInt32()));
736                 }
737             } else {
738                 write(DoubleTag);
739                 write(value.asDouble());
740             }
741         } else if (value.isBoolean()) {
742             if (value.isTrue())
743                 write(TrueTag);
744             else
745                 write(FalseTag);
746         }
747     }
748
749     void dumpString(const String& string)
750     {
751         if (string.isEmpty())
752             write(EmptyStringTag);
753         else {
754             write(StringTag);
755             write(string);
756         }
757     }
758
759     void dumpStringObject(const String& string)
760     {
761         if (string.isEmpty())
762             write(EmptyStringObjectTag);
763         else {
764             write(StringObjectTag);
765             write(string);
766         }
767     }
768
769     JSC::JSValue toJSArrayBuffer(ArrayBuffer& arrayBuffer)
770     {
771         auto& vm = m_exec->vm();
772         auto* globalObject = m_exec->lexicalGlobalObject();
773         if (globalObject->inherits<JSDOMGlobalObject>(vm))
774             return toJS(m_exec, jsCast<JSDOMGlobalObject*>(globalObject), &arrayBuffer);
775
776         if (auto* buffer = arrayBuffer.m_wrapper.get())
777             return buffer;
778
779         return JSC::JSArrayBuffer::create(vm, globalObject->arrayBufferStructure(arrayBuffer.sharingMode()), &arrayBuffer);
780     }
781
782     bool dumpArrayBufferView(JSObject* obj, SerializationReturnCode& code)
783     {
784         VM& vm = m_exec->vm();
785         write(ArrayBufferViewTag);
786         if (obj->inherits<JSDataView>(vm))
787             write(DataViewTag);
788         else if (obj->inherits<JSUint8ClampedArray>(vm))
789             write(Uint8ClampedArrayTag);
790         else if (obj->inherits<JSInt8Array>(vm))
791             write(Int8ArrayTag);
792         else if (obj->inherits<JSUint8Array>(vm))
793             write(Uint8ArrayTag);
794         else if (obj->inherits<JSInt16Array>(vm))
795             write(Int16ArrayTag);
796         else if (obj->inherits<JSUint16Array>(vm))
797             write(Uint16ArrayTag);
798         else if (obj->inherits<JSInt32Array>(vm))
799             write(Int32ArrayTag);
800         else if (obj->inherits<JSUint32Array>(vm))
801             write(Uint32ArrayTag);
802         else if (obj->inherits<JSFloat32Array>(vm))
803             write(Float32ArrayTag);
804         else if (obj->inherits<JSFloat64Array>(vm))
805             write(Float64ArrayTag);
806         else
807             return false;
808
809         RefPtr<ArrayBufferView> arrayBufferView = toPossiblySharedArrayBufferView(vm, obj);
810         write(static_cast<uint32_t>(arrayBufferView->byteOffset()));
811         write(static_cast<uint32_t>(arrayBufferView->byteLength()));
812         RefPtr<ArrayBuffer> arrayBuffer = arrayBufferView->possiblySharedBuffer();
813         if (!arrayBuffer) {
814             code = SerializationReturnCode::ValidationError;
815             return true;
816         }
817
818         return dumpIfTerminal(toJSArrayBuffer(*arrayBuffer), code);
819     }
820
821     void dumpDOMPoint(const DOMPointReadOnly& point)
822     {
823         write(point.x());
824         write(point.y());
825         write(point.z());
826         write(point.w());
827     }
828
829     void dumpDOMPoint(JSObject* obj)
830     {
831         VM& vm = m_exec->vm();
832         if (obj->inherits<JSDOMPoint>(vm))
833             write(DOMPointTag);
834         else
835             write(DOMPointReadOnlyTag);
836
837         dumpDOMPoint(jsCast<JSDOMPointReadOnly*>(obj)->wrapped());
838     }
839
840     void dumpDOMRect(JSObject* obj)
841     {
842         VM& vm = m_exec->vm();
843         if (obj->inherits<JSDOMRect>(vm))
844             write(DOMRectTag);
845         else
846             write(DOMRectReadOnlyTag);
847
848         auto& rect = jsCast<JSDOMRectReadOnly*>(obj)->wrapped();
849         write(rect.x());
850         write(rect.y());
851         write(rect.width());
852         write(rect.height());
853     }
854
855     void dumpDOMMatrix(JSObject* obj)
856     {
857         VM& vm = m_exec->vm();
858         if (obj->inherits<JSDOMMatrix>(vm))
859             write(DOMMatrixTag);
860         else
861             write(DOMMatrixReadOnlyTag);
862
863         auto& matrix = jsCast<JSDOMMatrixReadOnly*>(obj)->wrapped();
864         bool is2D = matrix.is2D();
865         write(static_cast<uint8_t>(is2D));
866         if (is2D) {
867             write(matrix.m11());
868             write(matrix.m12());
869             write(matrix.m21());
870             write(matrix.m22());
871             write(matrix.m41());
872             write(matrix.m42());
873         } else {
874             write(matrix.m11());
875             write(matrix.m12());
876             write(matrix.m13());
877             write(matrix.m14());
878             write(matrix.m21());
879             write(matrix.m22());
880             write(matrix.m23());
881             write(matrix.m24());
882             write(matrix.m31());
883             write(matrix.m32());
884             write(matrix.m33());
885             write(matrix.m34());
886             write(matrix.m41());
887             write(matrix.m42());
888             write(matrix.m43());
889             write(matrix.m44());
890         }
891     }
892
893     void dumpDOMQuad(JSObject* obj)
894     {
895         write(DOMQuadTag);
896
897         auto& quad = jsCast<JSDOMQuad*>(obj)->wrapped();
898         dumpDOMPoint(quad.p1());
899         dumpDOMPoint(quad.p2());
900         dumpDOMPoint(quad.p3());
901         dumpDOMPoint(quad.p4());
902     }
903
904     void dumpImageBitmap(JSObject* obj, SerializationReturnCode& code)
905     {
906         auto index = m_transferredImageBitmaps.find(obj);
907         if (index != m_transferredImageBitmaps.end()) {
908             write(ImageBitmapTransferTag);
909             write(index->value);
910             return;
911         }
912
913         // Copying ImageBitmaps is not yet supported.
914         code = SerializationReturnCode::ValidationError;
915     }
916
917     bool dumpIfTerminal(JSValue value, SerializationReturnCode& code)
918     {
919         if (!value.isCell()) {
920             dumpImmediate(value);
921             return true;
922         }
923         ASSERT(value.isCell());
924
925         if (value.isString()) {
926             dumpString(asString(value)->value(m_exec));
927             return true;
928         }
929
930         if (value.isSymbol()) {
931             code = SerializationReturnCode::DataCloneError;
932             return true;
933         }
934
935         VM& vm = m_exec->vm();
936         if (isArray(vm, value))
937             return false;
938
939         if (value.isObject()) {
940             auto* obj = asObject(value);
941             if (auto* dateObject = jsDynamicCast<DateInstance*>(vm, obj)) {
942                 write(DateTag);
943                 write(dateObject->internalNumber());
944                 return true;
945             }
946             if (auto* booleanObject = jsDynamicCast<BooleanObject*>(vm, obj)) {
947                 if (!startObjectInternal(booleanObject)) // handle duplicates
948                     return true;
949                 write(booleanObject->internalValue().toBoolean(m_exec) ? TrueObjectTag : FalseObjectTag);
950                 return true;
951             }
952             if (auto* stringObject = jsDynamicCast<StringObject*>(vm, obj)) {
953                 if (!startObjectInternal(stringObject)) // handle duplicates
954                     return true;
955                 String str = asString(stringObject->internalValue())->value(m_exec);
956                 dumpStringObject(str);
957                 return true;
958             }
959             if (auto* numberObject = jsDynamicCast<NumberObject*>(vm, obj)) {
960                 if (!startObjectInternal(numberObject)) // handle duplicates
961                     return true;
962                 write(NumberObjectTag);
963                 write(numberObject->internalValue().asNumber());
964                 return true;
965             }
966             if (auto* file = JSFile::toWrapped(vm, obj)) {
967                 write(FileTag);
968                 write(*file);
969                 return true;
970             }
971             if (auto* list = JSFileList::toWrapped(vm, obj)) {
972                 write(FileListTag);
973                 write(list->length());
974                 for (auto& file : list->files())
975                     write(file.get());
976                 return true;
977             }
978             if (auto* blob = JSBlob::toWrapped(vm, obj)) {
979                 write(BlobTag);
980                 m_blobURLs.append(blob->url());
981                 write(blob->url());
982                 write(blob->type());
983                 write(blob->size());
984                 return true;
985             }
986             if (auto* data = JSImageData::toWrapped(vm, obj)) {
987                 write(ImageDataTag);
988                 write(data->width());
989                 write(data->height());
990                 write(data->data()->length());
991                 write(data->data()->data(), data->data()->length());
992                 return true;
993             }
994             if (auto* regExp = jsDynamicCast<RegExpObject*>(vm, obj)) {
995                 char flags[3];
996                 int flagCount = 0;
997                 if (regExp->regExp()->global())
998                     flags[flagCount++] = 'g';
999                 if (regExp->regExp()->ignoreCase())
1000                     flags[flagCount++] = 'i';
1001                 if (regExp->regExp()->multiline())
1002                     flags[flagCount++] = 'm';
1003                 write(RegExpTag);
1004                 write(regExp->regExp()->pattern());
1005                 write(String(flags, flagCount));
1006                 return true;
1007             }
1008             if (obj->inherits<JSMessagePort>(vm)) {
1009                 auto index = m_transferredMessagePorts.find(obj);
1010                 if (index != m_transferredMessagePorts.end()) {
1011                     write(MessagePortReferenceTag);
1012                     write(index->value);
1013                     return true;
1014                 }
1015                 // MessagePort object could not be found in transferred message ports
1016                 code = SerializationReturnCode::ValidationError;
1017                 return true;
1018             }
1019             if (auto* arrayBuffer = toPossiblySharedArrayBuffer(vm, obj)) {
1020                 if (arrayBuffer->isNeutered()) {
1021                     code = SerializationReturnCode::ValidationError;
1022                     return true;
1023                 }
1024                 auto index = m_transferredArrayBuffers.find(obj);
1025                 if (index != m_transferredArrayBuffers.end()) {
1026                     write(ArrayBufferTransferTag);
1027                     write(index->value);
1028                     return true;
1029                 }
1030                 if (!startObjectInternal(obj)) // handle duplicates
1031                     return true;
1032                 
1033                 if (arrayBuffer->isShared() && m_context == SerializationContext::WorkerPostMessage) {
1034                     uint32_t index = m_sharedBuffers.size();
1035                     ArrayBufferContents contents;
1036                     if (arrayBuffer->shareWith(contents)) {
1037                         write(SharedArrayBufferTag);
1038                         m_sharedBuffers.append(WTFMove(contents));
1039                         write(index);
1040                         return true;
1041                     }
1042                 }
1043                 
1044                 write(ArrayBufferTag);
1045                 write(arrayBuffer->byteLength());
1046                 write(static_cast<const uint8_t*>(arrayBuffer->data()), arrayBuffer->byteLength());
1047                 return true;
1048             }
1049             if (obj->inherits<JSArrayBufferView>(vm)) {
1050                 if (checkForDuplicate(obj))
1051                     return true;
1052                 bool success = dumpArrayBufferView(obj, code);
1053                 recordObject(obj);
1054                 return success;
1055             }
1056 #if ENABLE(WEB_CRYPTO)
1057             if (auto* key = JSCryptoKey::toWrapped(vm, obj)) {
1058                 write(CryptoKeyTag);
1059                 Vector<uint8_t> serializedKey;
1060                 Vector<String> dummyBlobURLs;
1061                 PAL::SessionID dummySessionID;
1062                 Vector<RefPtr<MessagePort>> dummyMessagePorts;
1063                 Vector<RefPtr<JSC::ArrayBuffer>> dummyArrayBuffers;
1064 #if ENABLE(WEBASSEMBLY)
1065                 WasmModuleArray dummyModules;
1066 #endif
1067                 ArrayBufferContentsArray dummySharedBuffers;
1068                 CloneSerializer rawKeySerializer(m_exec, dummyMessagePorts, dummyArrayBuffers, { },
1069 #if ENABLE(WEBASSEMBLY)
1070                     dummyModules,
1071 #endif
1072                     dummyBlobURLs, dummySessionID, serializedKey, SerializationContext::Default, dummySharedBuffers);
1073                 rawKeySerializer.write(key);
1074                 Vector<uint8_t> wrappedKey;
1075                 if (!wrapCryptoKey(m_exec, serializedKey, wrappedKey))
1076                     return false;
1077                 write(wrappedKey);
1078                 return true;
1079             }
1080 #endif
1081 #if ENABLE(WEB_RTC)
1082             if (auto* rtcCertificate = JSRTCCertificate::toWrapped(vm, obj)) {
1083                 write(RTCCertificateTag);
1084                 write(rtcCertificate->expires());
1085                 write(rtcCertificate->pemCertificate());
1086                 write(rtcCertificate->origin().toString());
1087                 write(rtcCertificate->pemPrivateKey());
1088                 write(static_cast<unsigned>(rtcCertificate->getFingerprints().size()));
1089                 for (const auto& fingerprint : rtcCertificate->getFingerprints()) {
1090                     write(fingerprint.algorithm);
1091                     write(fingerprint.value);
1092                 }
1093                 return true;
1094             }
1095 #endif
1096 #if ENABLE(WEBASSEMBLY)
1097             if (JSWebAssemblyModule* module = jsDynamicCast<JSWebAssemblyModule*>(vm, obj)) {
1098                 if (m_context != SerializationContext::WorkerPostMessage && m_context != SerializationContext::WindowPostMessage)
1099                     return false;
1100
1101                 uint32_t index = m_wasmModules.size(); 
1102                 m_wasmModules.append(makeRef(module->module()));
1103                 write(WasmModuleTag);
1104                 write(index);
1105                 return true;
1106             }
1107 #endif
1108             if (obj->inherits<JSDOMPointReadOnly>(vm)) {
1109                 dumpDOMPoint(obj);
1110                 return true;
1111             }
1112             if (obj->inherits<JSDOMRectReadOnly>(vm)) {
1113                 dumpDOMRect(obj);
1114                 return true;
1115             }
1116             if (obj->inherits<JSDOMMatrixReadOnly>(vm)) {
1117                 dumpDOMMatrix(obj);
1118                 return true;
1119             }
1120             if (obj->inherits<JSDOMQuad>(vm)) {
1121                 dumpDOMQuad(obj);
1122                 return true;
1123             }
1124             if (obj->inherits(vm, JSImageBitmap::info())) {
1125                 dumpImageBitmap(obj, code);
1126                 return true;
1127             }
1128             return false;
1129         }
1130         // Any other types are expected to serialize as null.
1131         write(NullTag);
1132         return true;
1133     }
1134
1135     void write(SerializationTag tag)
1136     {
1137         writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag));
1138     }
1139
1140     void write(ArrayBufferViewSubtag tag)
1141     {
1142         writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag));
1143     }
1144
1145 #if ENABLE(WEB_CRYPTO)
1146     void write(CryptoKeyClassSubtag tag)
1147     {
1148         writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag));
1149     }
1150
1151     void write(CryptoKeyAsymmetricTypeSubtag tag)
1152     {
1153         writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag));
1154     }
1155
1156     void write(CryptoKeyUsageTag tag)
1157     {
1158         writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag));
1159     }
1160
1161     void write(CryptoAlgorithmIdentifierTag tag)
1162     {
1163         writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag));
1164     }
1165 #endif
1166
1167     void write(uint8_t c)
1168     {
1169         writeLittleEndian(m_buffer, c);
1170     }
1171
1172     void write(uint32_t i)
1173     {
1174         writeLittleEndian(m_buffer, i);
1175     }
1176
1177     void write(double d)
1178     {
1179         union {
1180             double d;
1181             int64_t i;
1182         } u;
1183         u.d = d;
1184         writeLittleEndian(m_buffer, u.i);
1185     }
1186
1187     void write(int32_t i)
1188     {
1189         writeLittleEndian(m_buffer, i);
1190     }
1191
1192     void write(unsigned long long i)
1193     {
1194         writeLittleEndian(m_buffer, i);
1195     }
1196     
1197     void write(uint16_t ch)
1198     {
1199         writeLittleEndian(m_buffer, ch);
1200     }
1201
1202     void writeStringIndex(unsigned i)
1203     {
1204         writeConstantPoolIndex(m_constantPool, i);
1205     }
1206     
1207     void writeObjectIndex(unsigned i)
1208     {
1209         writeConstantPoolIndex(m_objectPool, i);
1210     }
1211
1212     template <class T> void writeConstantPoolIndex(const T& constantPool, unsigned i)
1213     {
1214         ASSERT(i < constantPool.size());
1215         if (constantPool.size() <= 0xFF)
1216             write(static_cast<uint8_t>(i));
1217         else if (constantPool.size() <= 0xFFFF)
1218             write(static_cast<uint16_t>(i));
1219         else
1220             write(static_cast<uint32_t>(i));
1221     }
1222
1223     void write(const Identifier& ident)
1224     {
1225         const String& str = ident.string();
1226         StringConstantPool::AddResult addResult = m_constantPool.add(ident.impl(), m_constantPool.size());
1227         if (!addResult.isNewEntry) {
1228             write(StringPoolTag);
1229             writeStringIndex(addResult.iterator->value);
1230             return;
1231         }
1232
1233         unsigned length = str.length();
1234
1235         // Guard against overflow
1236         if (length > (std::numeric_limits<uint32_t>::max() - sizeof(uint32_t)) / sizeof(UChar)) {
1237             fail();
1238             return;
1239         }
1240
1241         if (str.is8Bit())
1242             writeLittleEndian<uint32_t>(m_buffer, length | StringDataIs8BitFlag);
1243         else
1244             writeLittleEndian<uint32_t>(m_buffer, length);
1245
1246         if (!length)
1247             return;
1248         if (str.is8Bit()) {
1249             if (!writeLittleEndian(m_buffer, str.characters8(), length))
1250                 fail();
1251             return;
1252         }
1253         if (!writeLittleEndian(m_buffer, str.characters16(), length))
1254             fail();
1255     }
1256
1257     void write(const String& str)
1258     {
1259         if (str.isNull())
1260             write(m_emptyIdentifier);
1261         else
1262             write(Identifier::fromString(m_exec, str));
1263     }
1264
1265     void write(const Vector<uint8_t>& vector)
1266     {
1267         uint32_t size = vector.size();
1268         write(size);
1269         writeLittleEndian(m_buffer, vector.data(), size);
1270     }
1271
1272     void write(const File& file)
1273     {
1274         m_blobURLs.append(file.url());
1275         write(file.path());
1276         write(file.url());
1277         write(file.type());
1278         write(file.name());
1279         write(static_cast<double>(file.lastModifiedOverride().valueOr(-1)));
1280     }
1281
1282 #if ENABLE(WEB_CRYPTO)
1283     void write(CryptoAlgorithmIdentifier algorithm)
1284     {
1285         switch (algorithm) {
1286         case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
1287             write(CryptoAlgorithmIdentifierTag::RSAES_PKCS1_v1_5);
1288             break;
1289         case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
1290             write(CryptoAlgorithmIdentifierTag::RSASSA_PKCS1_v1_5);
1291             break;
1292         case CryptoAlgorithmIdentifier::RSA_PSS:
1293             write(CryptoAlgorithmIdentifierTag::RSA_PSS);
1294             break;
1295         case CryptoAlgorithmIdentifier::RSA_OAEP:
1296             write(CryptoAlgorithmIdentifierTag::RSA_OAEP);
1297             break;
1298         case CryptoAlgorithmIdentifier::ECDSA:
1299             write(CryptoAlgorithmIdentifierTag::ECDSA);
1300             break;
1301         case CryptoAlgorithmIdentifier::ECDH:
1302             write(CryptoAlgorithmIdentifierTag::ECDH);
1303             break;
1304         case CryptoAlgorithmIdentifier::AES_CTR:
1305             write(CryptoAlgorithmIdentifierTag::AES_CTR);
1306             break;
1307         case CryptoAlgorithmIdentifier::AES_CBC:
1308             write(CryptoAlgorithmIdentifierTag::AES_CBC);
1309             break;
1310         case CryptoAlgorithmIdentifier::AES_GCM:
1311             write(CryptoAlgorithmIdentifierTag::AES_GCM);
1312             break;
1313         case CryptoAlgorithmIdentifier::AES_CFB:
1314             write(CryptoAlgorithmIdentifierTag::AES_CFB);
1315             break;
1316         case CryptoAlgorithmIdentifier::AES_KW:
1317             write(CryptoAlgorithmIdentifierTag::AES_KW);
1318             break;
1319         case CryptoAlgorithmIdentifier::HMAC:
1320             write(CryptoAlgorithmIdentifierTag::HMAC);
1321             break;
1322         case CryptoAlgorithmIdentifier::SHA_1:
1323             write(CryptoAlgorithmIdentifierTag::SHA_1);
1324             break;
1325         case CryptoAlgorithmIdentifier::SHA_224:
1326             write(CryptoAlgorithmIdentifierTag::SHA_224);
1327             break;
1328         case CryptoAlgorithmIdentifier::SHA_256:
1329             write(CryptoAlgorithmIdentifierTag::SHA_256);
1330             break;
1331         case CryptoAlgorithmIdentifier::SHA_384:
1332             write(CryptoAlgorithmIdentifierTag::SHA_384);
1333             break;
1334         case CryptoAlgorithmIdentifier::SHA_512:
1335             write(CryptoAlgorithmIdentifierTag::SHA_512);
1336             break;
1337         case CryptoAlgorithmIdentifier::HKDF:
1338             write(CryptoAlgorithmIdentifierTag::HKDF);
1339             break;
1340         case CryptoAlgorithmIdentifier::PBKDF2:
1341             write(CryptoAlgorithmIdentifierTag::PBKDF2);
1342             break;
1343         }
1344     }
1345
1346     void write(CryptoKeyRSAComponents::Type type)
1347     {
1348         switch (type) {
1349         case CryptoKeyRSAComponents::Type::Public:
1350             write(CryptoKeyAsymmetricTypeSubtag::Public);
1351             return;
1352         case CryptoKeyRSAComponents::Type::Private:
1353             write(CryptoKeyAsymmetricTypeSubtag::Private);
1354             return;
1355         }
1356     }
1357
1358     void write(const CryptoKeyRSAComponents& key)
1359     {
1360         write(key.type());
1361         write(key.modulus());
1362         write(key.exponent());
1363         if (key.type() == CryptoKeyRSAComponents::Type::Public)
1364             return;
1365
1366         write(key.privateExponent());
1367
1368         unsigned primeCount = key.hasAdditionalPrivateKeyParameters() ? key.otherPrimeInfos().size() + 2 : 0;
1369         write(primeCount);
1370         if (!primeCount)
1371             return;
1372
1373         write(key.firstPrimeInfo().primeFactor);
1374         write(key.firstPrimeInfo().factorCRTExponent);
1375         write(key.secondPrimeInfo().primeFactor);
1376         write(key.secondPrimeInfo().factorCRTExponent);
1377         write(key.secondPrimeInfo().factorCRTCoefficient);
1378         for (unsigned i = 2; i < primeCount; ++i) {
1379             write(key.otherPrimeInfos()[i].primeFactor);
1380             write(key.otherPrimeInfos()[i].factorCRTExponent);
1381             write(key.otherPrimeInfos()[i].factorCRTCoefficient);
1382         }
1383     }
1384
1385     void write(const CryptoKey* key)
1386     {
1387         write(currentKeyFormatVersion);
1388
1389         write(key->extractable());
1390
1391         CryptoKeyUsageBitmap usages = key->usagesBitmap();
1392         write(countUsages(usages));
1393         if (usages & CryptoKeyUsageEncrypt)
1394             write(CryptoKeyUsageTag::Encrypt);
1395         if (usages & CryptoKeyUsageDecrypt)
1396             write(CryptoKeyUsageTag::Decrypt);
1397         if (usages & CryptoKeyUsageSign)
1398             write(CryptoKeyUsageTag::Sign);
1399         if (usages & CryptoKeyUsageVerify)
1400             write(CryptoKeyUsageTag::Verify);
1401         if (usages & CryptoKeyUsageDeriveKey)
1402             write(CryptoKeyUsageTag::DeriveKey);
1403         if (usages & CryptoKeyUsageDeriveBits)
1404             write(CryptoKeyUsageTag::DeriveBits);
1405         if (usages & CryptoKeyUsageWrapKey)
1406             write(CryptoKeyUsageTag::WrapKey);
1407         if (usages & CryptoKeyUsageUnwrapKey)
1408             write(CryptoKeyUsageTag::UnwrapKey);
1409
1410         switch (key->keyClass()) {
1411         case CryptoKeyClass::HMAC:
1412             write(CryptoKeyClassSubtag::HMAC);
1413             write(downcast<CryptoKeyHMAC>(*key).key());
1414             write(downcast<CryptoKeyHMAC>(*key).hashAlgorithmIdentifier());
1415             break;
1416         case CryptoKeyClass::AES:
1417             write(CryptoKeyClassSubtag::AES);
1418             write(key->algorithmIdentifier());
1419             write(downcast<CryptoKeyAES>(*key).key());
1420             break;
1421         case CryptoKeyClass::EC:
1422             write(CryptoKeyClassSubtag::EC);
1423             write(key->algorithmIdentifier());
1424             write(downcast<CryptoKeyEC>(*key).namedCurveString());
1425             switch (key->type()) {
1426             case CryptoKey::Type::Public: {
1427                 write(CryptoKeyAsymmetricTypeSubtag::Public);
1428                 auto result = downcast<CryptoKeyEC>(*key).exportRaw();
1429                 ASSERT(!result.hasException());
1430                 write(result.releaseReturnValue());
1431                 break;
1432             }
1433             case CryptoKey::Type::Private: {
1434                 write(CryptoKeyAsymmetricTypeSubtag::Private);
1435                 // Use the standard complied method is not very efficient, but simple/reliable.
1436                 auto result = downcast<CryptoKeyEC>(*key).exportPkcs8();
1437                 ASSERT(!result.hasException());
1438                 write(result.releaseReturnValue());
1439                 break;
1440             }
1441             default:
1442                 ASSERT_NOT_REACHED();
1443             }
1444             break;
1445         case CryptoKeyClass::Raw:
1446             write(CryptoKeyClassSubtag::Raw);
1447             write(key->algorithmIdentifier());
1448             write(downcast<CryptoKeyRaw>(*key).key());
1449             break;
1450         case CryptoKeyClass::RSA:
1451             write(CryptoKeyClassSubtag::RSA);
1452             write(key->algorithmIdentifier());
1453             CryptoAlgorithmIdentifier hash;
1454             bool isRestrictedToHash = downcast<CryptoKeyRSA>(*key).isRestrictedToHash(hash);
1455             write(isRestrictedToHash);
1456             if (isRestrictedToHash)
1457                 write(hash);
1458             write(*downcast<CryptoKeyRSA>(*key).exportData());
1459             break;
1460         }
1461     }
1462 #endif
1463
1464     void write(const uint8_t* data, unsigned length)
1465     {
1466         m_buffer.append(data, length);
1467     }
1468
1469     Vector<uint8_t>& m_buffer;
1470     Vector<String>& m_blobURLs;
1471     PAL::SessionID m_sessionID;
1472     ObjectPool m_objectPool;
1473     ObjectPool m_transferredMessagePorts;
1474     ObjectPool m_transferredArrayBuffers;
1475     ObjectPool m_transferredImageBitmaps;
1476     typedef HashMap<RefPtr<UniquedStringImpl>, uint32_t, IdentifierRepHash> StringConstantPool;
1477     StringConstantPool m_constantPool;
1478     Identifier m_emptyIdentifier;
1479     SerializationContext m_context;
1480     ArrayBufferContentsArray& m_sharedBuffers;
1481 #if ENABLE(WEBASSEMBLY)
1482     WasmModuleArray& m_wasmModules;
1483 #endif
1484 };
1485
1486 SerializationReturnCode CloneSerializer::serialize(JSValue in)
1487 {
1488     VM& vm = m_exec->vm();
1489     Vector<uint32_t, 16> indexStack;
1490     Vector<uint32_t, 16> lengthStack;
1491     Vector<PropertyNameArray, 16> propertyStack;
1492     Vector<JSObject*, 32> inputObjectStack;
1493     Vector<JSMapIterator*, 4> mapIteratorStack;
1494     Vector<JSSetIterator*, 4> setIteratorStack;
1495     Vector<JSValue, 4> mapIteratorValueStack;
1496     Vector<WalkerState, 16> stateStack;
1497     WalkerState state = StateUnknown;
1498     JSValue inValue = in;
1499     while (1) {
1500         switch (state) {
1501             arrayStartState:
1502             case ArrayStartState: {
1503                 ASSERT(isArray(vm, inValue));
1504                 if (inputObjectStack.size() > maximumFilterRecursion)
1505                     return SerializationReturnCode::StackOverflowError;
1506
1507                 JSArray* inArray = asArray(inValue);
1508                 unsigned length = inArray->length();
1509                 if (!startArray(inArray))
1510                     break;
1511                 inputObjectStack.append(inArray);
1512                 indexStack.append(0);
1513                 lengthStack.append(length);
1514             }
1515             arrayStartVisitMember:
1516             FALLTHROUGH;
1517             case ArrayStartVisitMember: {
1518                 JSObject* array = inputObjectStack.last();
1519                 uint32_t index = indexStack.last();
1520                 if (index == lengthStack.last()) {
1521                     indexStack.removeLast();
1522                     lengthStack.removeLast();
1523
1524                     propertyStack.append(PropertyNameArray(&vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude));
1525                     array->methodTable(vm)->getOwnNonIndexPropertyNames(array, m_exec, propertyStack.last(), EnumerationMode());
1526                     if (propertyStack.last().size()) {
1527                         write(NonIndexPropertiesTag);
1528                         indexStack.append(0);
1529                         goto objectStartVisitMember;
1530                     }
1531                     propertyStack.removeLast();
1532
1533                     endObject();
1534                     inputObjectStack.removeLast();
1535                     break;
1536                 }
1537                 inValue = array->getDirectIndex(m_exec, index);
1538                 if (!inValue) {
1539                     indexStack.last()++;
1540                     goto arrayStartVisitMember;
1541                 }
1542
1543                 write(index);
1544                 auto terminalCode = SerializationReturnCode::SuccessfullyCompleted;
1545                 if (dumpIfTerminal(inValue, terminalCode)) {
1546                     if (terminalCode != SerializationReturnCode::SuccessfullyCompleted)
1547                         return terminalCode;
1548                     indexStack.last()++;
1549                     goto arrayStartVisitMember;
1550                 }
1551                 stateStack.append(ArrayEndVisitMember);
1552                 goto stateUnknown;
1553             }
1554             case ArrayEndVisitMember: {
1555                 indexStack.last()++;
1556                 goto arrayStartVisitMember;
1557             }
1558             objectStartState:
1559             case ObjectStartState: {
1560                 ASSERT(inValue.isObject());
1561                 if (inputObjectStack.size() > maximumFilterRecursion)
1562                     return SerializationReturnCode::StackOverflowError;
1563                 JSObject* inObject = asObject(inValue);
1564                 if (!startObject(inObject))
1565                     break;
1566                 // At this point, all supported objects other than Object
1567                 // objects have been handled. If we reach this point and
1568                 // the input is not an Object object then we should throw
1569                 // a DataCloneError.
1570                 if (inObject->classInfo(vm) != JSFinalObject::info())
1571                     return SerializationReturnCode::DataCloneError;
1572                 inputObjectStack.append(inObject);
1573                 indexStack.append(0);
1574                 propertyStack.append(PropertyNameArray(&vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude));
1575                 inObject->methodTable(vm)->getOwnPropertyNames(inObject, m_exec, propertyStack.last(), EnumerationMode());
1576             }
1577             objectStartVisitMember:
1578             FALLTHROUGH;
1579             case ObjectStartVisitMember: {
1580                 JSObject* object = inputObjectStack.last();
1581                 uint32_t index = indexStack.last();
1582                 PropertyNameArray& properties = propertyStack.last();
1583                 if (index == properties.size()) {
1584                     endObject();
1585                     inputObjectStack.removeLast();
1586                     indexStack.removeLast();
1587                     propertyStack.removeLast();
1588                     break;
1589                 }
1590                 inValue = getProperty(vm, object, properties[index]);
1591                 if (shouldTerminate())
1592                     return SerializationReturnCode::ExistingExceptionError;
1593
1594                 if (!inValue) {
1595                     // Property was removed during serialisation
1596                     indexStack.last()++;
1597                     goto objectStartVisitMember;
1598                 }
1599                 write(properties[index]);
1600
1601                 if (shouldTerminate())
1602                     return SerializationReturnCode::ExistingExceptionError;
1603
1604                 auto terminalCode = SerializationReturnCode::SuccessfullyCompleted;
1605                 if (!dumpIfTerminal(inValue, terminalCode)) {
1606                     stateStack.append(ObjectEndVisitMember);
1607                     goto stateUnknown;
1608                 }
1609                 if (terminalCode != SerializationReturnCode::SuccessfullyCompleted)
1610                     return terminalCode;
1611                 FALLTHROUGH;
1612             }
1613             case ObjectEndVisitMember: {
1614                 if (shouldTerminate())
1615                     return SerializationReturnCode::ExistingExceptionError;
1616
1617                 indexStack.last()++;
1618                 goto objectStartVisitMember;
1619             }
1620             mapStartState: {
1621                 ASSERT(inValue.isObject());
1622                 if (inputObjectStack.size() > maximumFilterRecursion)
1623                     return SerializationReturnCode::StackOverflowError;
1624                 JSMap* inMap = jsCast<JSMap*>(inValue);
1625                 if (!startMap(inMap))
1626                     break;
1627                 JSMapIterator* iterator = JSMapIterator::create(vm, vm.mapIteratorStructure(), inMap, IterateKeyValue);
1628                 m_gcBuffer.appendWithCrashOnOverflow(inMap);
1629                 m_gcBuffer.appendWithCrashOnOverflow(iterator);
1630                 mapIteratorStack.append(iterator);
1631                 inputObjectStack.append(inMap);
1632                 goto mapDataStartVisitEntry;
1633             }
1634             mapDataStartVisitEntry:
1635             case MapDataStartVisitEntry: {
1636                 JSMapIterator* iterator = mapIteratorStack.last();
1637                 JSValue key, value;
1638                 if (!iterator->nextKeyValue(m_exec, key, value)) {
1639                     mapIteratorStack.removeLast();
1640                     JSObject* object = inputObjectStack.last();
1641                     ASSERT(jsDynamicCast<JSMap*>(vm, object));
1642                     propertyStack.append(PropertyNameArray(&vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude));
1643                     object->methodTable(vm)->getOwnPropertyNames(object, m_exec, propertyStack.last(), EnumerationMode());
1644                     write(NonMapPropertiesTag);
1645                     indexStack.append(0);
1646                     goto objectStartVisitMember;
1647                 }
1648                 inValue = key;
1649                 m_gcBuffer.appendWithCrashOnOverflow(value);
1650                 mapIteratorValueStack.append(value);
1651                 stateStack.append(MapDataEndVisitKey);
1652                 goto stateUnknown;
1653             }
1654             case MapDataEndVisitKey: {
1655                 inValue = mapIteratorValueStack.last();
1656                 mapIteratorValueStack.removeLast();
1657                 stateStack.append(MapDataEndVisitValue);
1658                 goto stateUnknown;
1659             }
1660             case MapDataEndVisitValue: {
1661                 goto mapDataStartVisitEntry;
1662             }
1663
1664             setStartState: {
1665                 ASSERT(inValue.isObject());
1666                 if (inputObjectStack.size() > maximumFilterRecursion)
1667                     return SerializationReturnCode::StackOverflowError;
1668                 JSSet* inSet = jsCast<JSSet*>(inValue);
1669                 if (!startSet(inSet))
1670                     break;
1671                 JSSetIterator* iterator = JSSetIterator::create(vm, vm.setIteratorStructure(), inSet, IterateKey);
1672                 m_gcBuffer.appendWithCrashOnOverflow(inSet);
1673                 m_gcBuffer.appendWithCrashOnOverflow(iterator);
1674                 setIteratorStack.append(iterator);
1675                 inputObjectStack.append(inSet);
1676                 goto setDataStartVisitEntry;
1677             }
1678             setDataStartVisitEntry:
1679             case SetDataStartVisitEntry: {
1680                 JSSetIterator* iterator = setIteratorStack.last();
1681                 JSValue key;
1682                 if (!iterator->next(m_exec, key)) {
1683                     setIteratorStack.removeLast();
1684                     JSObject* object = inputObjectStack.last();
1685                     ASSERT(jsDynamicCast<JSSet*>(vm, object));
1686                     propertyStack.append(PropertyNameArray(&vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude));
1687                     object->methodTable(vm)->getOwnPropertyNames(object, m_exec, propertyStack.last(), EnumerationMode());
1688                     write(NonSetPropertiesTag);
1689                     indexStack.append(0);
1690                     goto objectStartVisitMember;
1691                 }
1692                 inValue = key;
1693                 stateStack.append(SetDataEndVisitKey);
1694                 goto stateUnknown;
1695             }
1696             case SetDataEndVisitKey: {
1697                 goto setDataStartVisitEntry;
1698             }
1699
1700             stateUnknown:
1701             case StateUnknown: {
1702                 auto terminalCode = SerializationReturnCode::SuccessfullyCompleted;
1703                 if (dumpIfTerminal(inValue, terminalCode)) {
1704                     if (terminalCode != SerializationReturnCode::SuccessfullyCompleted)
1705                         return terminalCode;
1706                     break;
1707                 }
1708
1709                 if (isArray(vm, inValue))
1710                     goto arrayStartState;
1711                 if (isMap(vm, inValue))
1712                     goto mapStartState;
1713                 if (isSet(vm, inValue))
1714                     goto setStartState;
1715                 goto objectStartState;
1716             }
1717         }
1718         if (stateStack.isEmpty())
1719             break;
1720
1721         state = stateStack.last();
1722         stateStack.removeLast();
1723     }
1724     if (m_failed)
1725         return SerializationReturnCode::UnspecifiedError;
1726
1727     return SerializationReturnCode::SuccessfullyCompleted;
1728 }
1729
1730 class CloneDeserializer : CloneBase {
1731 public:
1732     static String deserializeString(const Vector<uint8_t>& buffer)
1733     {
1734         if (buffer.isEmpty())
1735             return String();
1736         const uint8_t* ptr = buffer.begin();
1737         const uint8_t* end = buffer.end();
1738         uint32_t version;
1739         if (!readLittleEndian(ptr, end, version) || version > CurrentVersion)
1740             return String();
1741         uint8_t tag;
1742         if (!readLittleEndian(ptr, end, tag) || tag != StringTag)
1743             return String();
1744         uint32_t length;
1745         if (!readLittleEndian(ptr, end, length))
1746             return String();
1747         bool is8Bit = length & StringDataIs8BitFlag;
1748         length &= ~StringDataIs8BitFlag;
1749         String str;
1750         if (!readString(ptr, end, str, length, is8Bit))
1751             return String();
1752         return str;
1753     }
1754
1755     static DeserializationResult deserialize(ExecState* exec, JSGlobalObject* globalObject, const Vector<RefPtr<MessagePort>>& messagePorts, Vector<std::pair<std::unique_ptr<ImageBuffer>, bool>>&& imageBuffers, ArrayBufferContentsArray* arrayBufferContentsArray, const Vector<uint8_t>& buffer, const Vector<String>& blobURLs, const PAL::SessionID& sessionID, const Vector<String> blobFilePaths, ArrayBufferContentsArray* sharedBuffers
1756 #if ENABLE(WEBASSEMBLY)
1757         , WasmModuleArray* wasmModules
1758 #endif
1759         )
1760     {
1761         if (!buffer.size())
1762             return std::make_pair(jsNull(), SerializationReturnCode::UnspecifiedError);
1763         CloneDeserializer deserializer(exec, globalObject, messagePorts, arrayBufferContentsArray, buffer, blobURLs, sessionID, blobFilePaths, sharedBuffers, WTFMove(imageBuffers)
1764 #if ENABLE(WEBASSEMBLY)
1765             , wasmModules
1766 #endif
1767             );
1768         if (!deserializer.isValid())
1769             return std::make_pair(JSValue(), SerializationReturnCode::ValidationError);
1770         return deserializer.deserialize();
1771     }
1772
1773 private:
1774     struct CachedString {
1775         CachedString(const String& string)
1776             : m_string(string)
1777         {
1778         }
1779
1780         JSValue jsString(ExecState* exec)
1781         {
1782             if (!m_jsString)
1783                 m_jsString = JSC::jsString(exec, m_string);
1784             return m_jsString;
1785         }
1786         const String& string() { return m_string; }
1787         String takeString() { return WTFMove(m_string); }
1788
1789     private:
1790         String m_string;
1791         JSValue m_jsString;
1792     };
1793
1794     struct CachedStringRef {
1795         CachedStringRef()
1796             : m_base(0)
1797             , m_index(0)
1798         {
1799         }
1800         CachedStringRef(Vector<CachedString>* base, size_t index)
1801             : m_base(base)
1802             , m_index(index)
1803         {
1804         }
1805         
1806         CachedString* operator->() { ASSERT(m_base); return &m_base->at(m_index); }
1807         
1808     private:
1809         Vector<CachedString>* m_base;
1810         size_t m_index;
1811     };
1812
1813     CloneDeserializer(ExecState* exec, JSGlobalObject* globalObject, const Vector<RefPtr<MessagePort>>& messagePorts, ArrayBufferContentsArray* arrayBufferContents, Vector<std::pair<std::unique_ptr<ImageBuffer>, bool>>&& imageBuffers,
1814 #if ENABLE(WEBASSEMBLY)
1815         WasmModuleArray* wasmModules,
1816 #endif
1817         const Vector<uint8_t>& buffer)
1818         : CloneBase(exec)
1819         , m_globalObject(globalObject)
1820         , m_isDOMGlobalObject(globalObject->inherits<JSDOMGlobalObject>(globalObject->vm()))
1821         , m_ptr(buffer.data())
1822         , m_end(buffer.data() + buffer.size())
1823         , m_version(0xFFFFFFFF)
1824         , m_messagePorts(messagePorts)
1825         , m_arrayBufferContents(arrayBufferContents)
1826         , m_arrayBuffers(arrayBufferContents ? arrayBufferContents->size() : 0)
1827         , m_imageBuffers(WTFMove(imageBuffers))
1828         , m_imageBitmaps(m_imageBuffers.size())
1829 #if ENABLE(WEBASSEMBLY)
1830         , m_wasmModules(wasmModules)
1831 #endif
1832     {
1833         if (!read(m_version))
1834             m_version = 0xFFFFFFFF;
1835     }
1836
1837     CloneDeserializer(ExecState* exec, JSGlobalObject* globalObject, const Vector<RefPtr<MessagePort>>& messagePorts, ArrayBufferContentsArray* arrayBufferContents, const Vector<uint8_t>& buffer, const Vector<String>& blobURLs, const PAL::SessionID& sessionID, const Vector<String> blobFilePaths, ArrayBufferContentsArray* sharedBuffers, Vector<std::pair<std::unique_ptr<ImageBuffer>, bool>>&& imageBuffers
1838 #if ENABLE(WEBASSEMBLY)
1839         , WasmModuleArray* wasmModules
1840 #endif
1841         )
1842         : CloneBase(exec)
1843         , m_globalObject(globalObject)
1844         , m_isDOMGlobalObject(globalObject->inherits<JSDOMGlobalObject>(globalObject->vm()))
1845         , m_ptr(buffer.data())
1846         , m_end(buffer.data() + buffer.size())
1847         , m_version(0xFFFFFFFF)
1848         , m_messagePorts(messagePorts)
1849         , m_arrayBufferContents(arrayBufferContents)
1850         , m_arrayBuffers(arrayBufferContents ? arrayBufferContents->size() : 0)
1851         , m_blobURLs(blobURLs)
1852         , m_sessionID(sessionID)
1853         , m_blobFilePaths(blobFilePaths)
1854         , m_sharedBuffers(sharedBuffers)
1855         , m_imageBuffers(WTFMove(imageBuffers))
1856         , m_imageBitmaps(m_imageBuffers.size())
1857 #if ENABLE(WEBASSEMBLY)
1858         , m_wasmModules(wasmModules)
1859 #endif
1860     {
1861         if (!read(m_version))
1862             m_version = 0xFFFFFFFF;
1863     }
1864
1865     DeserializationResult deserialize();
1866
1867     bool isValid() const { return m_version <= CurrentVersion; }
1868
1869     template <typename T> bool readLittleEndian(T& value)
1870     {
1871         if (m_failed || !readLittleEndian(m_ptr, m_end, value)) {
1872             fail();
1873             return false;
1874         }
1875         return true;
1876     }
1877 #if ASSUME_LITTLE_ENDIAN
1878     template <typename T> static bool readLittleEndian(const uint8_t*& ptr, const uint8_t* end, T& value)
1879     {
1880         if (ptr > end - sizeof(value))
1881             return false;
1882
1883         if (sizeof(T) == 1)
1884             value = *ptr++;
1885         else {
1886             value = *reinterpret_cast<const T*>(ptr);
1887             ptr += sizeof(T);
1888         }
1889         return true;
1890     }
1891 #else
1892     template <typename T> static bool readLittleEndian(const uint8_t*& ptr, const uint8_t* end, T& value)
1893     {
1894         if (ptr > end - sizeof(value))
1895             return false;
1896
1897         if (sizeof(T) == 1)
1898             value = *ptr++;
1899         else {
1900             value = 0;
1901             for (unsigned i = 0; i < sizeof(T); i++)
1902                 value += ((T)*ptr++) << (i * 8);
1903         }
1904         return true;
1905     }
1906 #endif
1907
1908     bool read(uint32_t& i)
1909     {
1910         return readLittleEndian(i);
1911     }
1912
1913     bool read(int32_t& i)
1914     {
1915         return readLittleEndian(*reinterpret_cast<uint32_t*>(&i));
1916     }
1917
1918     bool read(uint16_t& i)
1919     {
1920         return readLittleEndian(i);
1921     }
1922
1923     bool read(uint8_t& i)
1924     {
1925         return readLittleEndian(i);
1926     }
1927
1928     bool read(double& d)
1929     {
1930         union {
1931             double d;
1932             uint64_t i64;
1933         } u;
1934         if (!readLittleEndian(u.i64))
1935             return false;
1936         d = u.d;
1937         return true;
1938     }
1939
1940     bool read(unsigned long long& i)
1941     {
1942         return readLittleEndian(i);
1943     }
1944
1945     bool readStringIndex(uint32_t& i)
1946     {
1947         return readConstantPoolIndex(m_constantPool, i);
1948     }
1949
1950     template <class T> bool readConstantPoolIndex(const T& constantPool, uint32_t& i)
1951     {
1952         if (constantPool.size() <= 0xFF) {
1953             uint8_t i8;
1954             if (!read(i8))
1955                 return false;
1956             i = i8;
1957             return true;
1958         }
1959         if (constantPool.size() <= 0xFFFF) {
1960             uint16_t i16;
1961             if (!read(i16))
1962                 return false;
1963             i = i16;
1964             return true;
1965         }
1966         return read(i);
1967     }
1968
1969     static bool readString(const uint8_t*& ptr, const uint8_t* end, String& str, unsigned length, bool is8Bit)
1970     {
1971         if (length >= std::numeric_limits<int32_t>::max() / sizeof(UChar))
1972             return false;
1973
1974         if (is8Bit) {
1975             if ((end - ptr) < static_cast<int>(length))
1976                 return false;
1977             str = String(reinterpret_cast<const LChar*>(ptr), length);
1978             ptr += length;
1979             return true;
1980         }
1981
1982         unsigned size = length * sizeof(UChar);
1983         if ((end - ptr) < static_cast<int>(size))
1984             return false;
1985
1986 #if ASSUME_LITTLE_ENDIAN
1987         str = String(reinterpret_cast<const UChar*>(ptr), length);
1988         ptr += length * sizeof(UChar);
1989 #else
1990         Vector<UChar> buffer;
1991         buffer.reserveCapacity(length);
1992         for (unsigned i = 0; i < length; i++) {
1993             uint16_t ch;
1994             readLittleEndian(ptr, end, ch);
1995             buffer.append(ch);
1996         }
1997         str = String::adopt(WTFMove(buffer));
1998 #endif
1999         return true;
2000     }
2001
2002     bool readStringData(CachedStringRef& cachedString)
2003     {
2004         bool scratch;
2005         return readStringData(cachedString, scratch);
2006     }
2007
2008     bool readStringData(CachedStringRef& cachedString, bool& wasTerminator)
2009     {
2010         if (m_failed)
2011             return false;
2012         uint32_t length = 0;
2013         if (!read(length))
2014             return false;
2015         if (length == TerminatorTag) {
2016             wasTerminator = true;
2017             return false;
2018         }
2019         if (length == StringPoolTag) {
2020             unsigned index = 0;
2021             if (!readStringIndex(index)) {
2022                 fail();
2023                 return false;
2024             }
2025             if (index >= m_constantPool.size()) {
2026                 fail();
2027                 return false;
2028             }
2029             cachedString = CachedStringRef(&m_constantPool, index);
2030             return true;
2031         }
2032         bool is8Bit = length & StringDataIs8BitFlag;
2033         length &= ~StringDataIs8BitFlag;
2034         String str;
2035         if (!readString(m_ptr, m_end, str, length, is8Bit)) {
2036             fail();
2037             return false;
2038         }
2039         m_constantPool.append(str);
2040         cachedString = CachedStringRef(&m_constantPool, m_constantPool.size() - 1);
2041         return true;
2042     }
2043
2044     SerializationTag readTag()
2045     {
2046         if (m_ptr >= m_end)
2047             return ErrorTag;
2048         return static_cast<SerializationTag>(*m_ptr++);
2049     }
2050
2051     bool readArrayBufferViewSubtag(ArrayBufferViewSubtag& tag)
2052     {
2053         if (m_ptr >= m_end)
2054             return false;
2055         tag = static_cast<ArrayBufferViewSubtag>(*m_ptr++);
2056         return true;
2057     }
2058
2059     void putProperty(JSObject* object, unsigned index, JSValue value)
2060     {
2061         object->putDirectIndex(m_exec, index, value);
2062     }
2063
2064     void putProperty(JSObject* object, const Identifier& property, JSValue value)
2065     {
2066         object->putDirectMayBeIndex(m_exec, property, value);
2067     }
2068
2069     bool readFile(RefPtr<File>& file)
2070     {
2071         CachedStringRef path;
2072         if (!readStringData(path))
2073             return false;
2074         CachedStringRef url;
2075         if (!readStringData(url))
2076             return false;
2077         CachedStringRef type;
2078         if (!readStringData(type))
2079             return false;
2080         CachedStringRef name;
2081         if (!readStringData(name))
2082             return false;
2083         Optional<int64_t> optionalLastModified;
2084         if (m_version > 6) {
2085             double lastModified;
2086             if (!read(lastModified))
2087                 return false;
2088             if (lastModified >= 0)
2089                 optionalLastModified = lastModified;
2090         }
2091
2092         // If the blob URL for this file has an associated blob file path, prefer that one over the "built-in" path.
2093         String filePath = blobFilePathForBlobURL(url->string());
2094         if (filePath.isEmpty())
2095             filePath = path->string();
2096
2097         if (m_isDOMGlobalObject)
2098             file = File::deserialize(jsCast<JSDOMGlobalObject*>(m_globalObject)->scriptExecutionContext()->sessionID(), filePath, URL(URL(), url->string()), type->string(), name->string(), optionalLastModified);
2099         return true;
2100     }
2101
2102     bool readArrayBuffer(RefPtr<ArrayBuffer>& arrayBuffer)
2103     {
2104         uint32_t length;
2105         if (!read(length))
2106             return false;
2107         if (m_ptr + length > m_end)
2108             return false;
2109         arrayBuffer = ArrayBuffer::create(m_ptr, length);
2110         m_ptr += length;
2111         return true;
2112     }
2113
2114     bool readArrayBufferView(VM& vm, JSValue& arrayBufferView)
2115     {
2116         ArrayBufferViewSubtag arrayBufferViewSubtag;
2117         if (!readArrayBufferViewSubtag(arrayBufferViewSubtag))
2118             return false;
2119         uint32_t byteOffset;
2120         if (!read(byteOffset))
2121             return false;
2122         uint32_t byteLength;
2123         if (!read(byteLength))
2124             return false;
2125         JSObject* arrayBufferObj = asObject(readTerminal());
2126         if (!arrayBufferObj || !arrayBufferObj->inherits<JSArrayBuffer>(vm))
2127             return false;
2128
2129         unsigned elementSize = typedArrayElementSize(arrayBufferViewSubtag);
2130         if (!elementSize)
2131             return false;
2132         unsigned length = byteLength / elementSize;
2133         if (length * elementSize != byteLength)
2134             return false;
2135
2136         RefPtr<ArrayBuffer> arrayBuffer = toPossiblySharedArrayBuffer(vm, arrayBufferObj);
2137         switch (arrayBufferViewSubtag) {
2138         case DataViewTag:
2139             arrayBufferView = toJS(m_exec, m_globalObject, DataView::create(WTFMove(arrayBuffer), byteOffset, length).get());
2140             return true;
2141         case Int8ArrayTag:
2142             arrayBufferView = toJS(m_exec, m_globalObject, Int8Array::tryCreate(WTFMove(arrayBuffer), byteOffset, length).get());
2143             return true;
2144         case Uint8ArrayTag:
2145             arrayBufferView = toJS(m_exec, m_globalObject, Uint8Array::tryCreate(WTFMove(arrayBuffer), byteOffset, length).get());
2146             return true;
2147         case Uint8ClampedArrayTag:
2148             arrayBufferView = toJS(m_exec, m_globalObject, Uint8ClampedArray::tryCreate(WTFMove(arrayBuffer), byteOffset, length).get());
2149             return true;
2150         case Int16ArrayTag:
2151             arrayBufferView = toJS(m_exec, m_globalObject, Int16Array::tryCreate(WTFMove(arrayBuffer), byteOffset, length).get());
2152             return true;
2153         case Uint16ArrayTag:
2154             arrayBufferView = toJS(m_exec, m_globalObject, Uint16Array::tryCreate(WTFMove(arrayBuffer), byteOffset, length).get());
2155             return true;
2156         case Int32ArrayTag:
2157             arrayBufferView = toJS(m_exec, m_globalObject, Int32Array::tryCreate(WTFMove(arrayBuffer), byteOffset, length).get());
2158             return true;
2159         case Uint32ArrayTag:
2160             arrayBufferView = toJS(m_exec, m_globalObject, Uint32Array::tryCreate(WTFMove(arrayBuffer), byteOffset, length).get());
2161             return true;
2162         case Float32ArrayTag:
2163             arrayBufferView = toJS(m_exec, m_globalObject, Float32Array::tryCreate(WTFMove(arrayBuffer), byteOffset, length).get());
2164             return true;
2165         case Float64ArrayTag:
2166             arrayBufferView = toJS(m_exec, m_globalObject, Float64Array::tryCreate(WTFMove(arrayBuffer), byteOffset, length).get());
2167             return true;
2168         default:
2169             return false;
2170         }
2171     }
2172
2173     bool read(Vector<uint8_t>& result)
2174     {
2175         ASSERT(result.isEmpty());
2176         uint32_t size;
2177         if (!read(size))
2178             return false;
2179         if (m_ptr + size > m_end)
2180             return false;
2181         result.append(m_ptr, size);
2182         m_ptr += size;
2183         return true;
2184     }
2185
2186 #if ENABLE(WEB_CRYPTO)
2187     bool read(CryptoAlgorithmIdentifier& result)
2188     {
2189         uint8_t algorithmTag;
2190         if (!read(algorithmTag))
2191             return false;
2192         if (algorithmTag > cryptoAlgorithmIdentifierTagMaximumValue)
2193             return false;
2194         switch (static_cast<CryptoAlgorithmIdentifierTag>(algorithmTag)) {
2195         case CryptoAlgorithmIdentifierTag::RSAES_PKCS1_v1_5:
2196             result = CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5;
2197             break;
2198         case CryptoAlgorithmIdentifierTag::RSASSA_PKCS1_v1_5:
2199             result = CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5;
2200             break;
2201         case CryptoAlgorithmIdentifierTag::RSA_PSS:
2202             result = CryptoAlgorithmIdentifier::RSA_PSS;
2203             break;
2204         case CryptoAlgorithmIdentifierTag::RSA_OAEP:
2205             result = CryptoAlgorithmIdentifier::RSA_OAEP;
2206             break;
2207         case CryptoAlgorithmIdentifierTag::ECDSA:
2208             result = CryptoAlgorithmIdentifier::ECDSA;
2209             break;
2210         case CryptoAlgorithmIdentifierTag::ECDH:
2211             result = CryptoAlgorithmIdentifier::ECDH;
2212             break;
2213         case CryptoAlgorithmIdentifierTag::AES_CTR:
2214             result = CryptoAlgorithmIdentifier::AES_CTR;
2215             break;
2216         case CryptoAlgorithmIdentifierTag::AES_CBC:
2217             result = CryptoAlgorithmIdentifier::AES_CBC;
2218             break;
2219         case CryptoAlgorithmIdentifierTag::AES_GCM:
2220             result = CryptoAlgorithmIdentifier::AES_GCM;
2221             break;
2222         case CryptoAlgorithmIdentifierTag::AES_CFB:
2223             result = CryptoAlgorithmIdentifier::AES_CFB;
2224             break;
2225         case CryptoAlgorithmIdentifierTag::AES_KW:
2226             result = CryptoAlgorithmIdentifier::AES_KW;
2227             break;
2228         case CryptoAlgorithmIdentifierTag::HMAC:
2229             result = CryptoAlgorithmIdentifier::HMAC;
2230             break;
2231         case CryptoAlgorithmIdentifierTag::SHA_1:
2232             result = CryptoAlgorithmIdentifier::SHA_1;
2233             break;
2234         case CryptoAlgorithmIdentifierTag::SHA_224:
2235             result = CryptoAlgorithmIdentifier::SHA_224;
2236             break;
2237         case CryptoAlgorithmIdentifierTag::SHA_256:
2238             result = CryptoAlgorithmIdentifier::SHA_256;
2239             break;
2240         case CryptoAlgorithmIdentifierTag::SHA_384:
2241             result = CryptoAlgorithmIdentifier::SHA_384;
2242             break;
2243         case CryptoAlgorithmIdentifierTag::SHA_512:
2244             result = CryptoAlgorithmIdentifier::SHA_512;
2245             break;
2246         case CryptoAlgorithmIdentifierTag::HKDF:
2247             result = CryptoAlgorithmIdentifier::HKDF;
2248             break;
2249         case CryptoAlgorithmIdentifierTag::PBKDF2:
2250             result = CryptoAlgorithmIdentifier::PBKDF2;
2251             break;
2252         }
2253         return true;
2254     }
2255
2256     bool read(CryptoKeyClassSubtag& result)
2257     {
2258         uint8_t tag;
2259         if (!read(tag))
2260             return false;
2261         if (tag > cryptoKeyClassSubtagMaximumValue)
2262             return false;
2263         result = static_cast<CryptoKeyClassSubtag>(tag);
2264         return true;
2265     }
2266
2267     bool read(CryptoKeyUsageTag& result)
2268     {
2269         uint8_t tag;
2270         if (!read(tag))
2271             return false;
2272         if (tag > cryptoKeyUsageTagMaximumValue)
2273             return false;
2274         result = static_cast<CryptoKeyUsageTag>(tag);
2275         return true;
2276     }
2277
2278     bool read(CryptoKeyAsymmetricTypeSubtag& result)
2279     {
2280         uint8_t tag;
2281         if (!read(tag))
2282             return false;
2283         if (tag > cryptoKeyAsymmetricTypeSubtagMaximumValue)
2284             return false;
2285         result = static_cast<CryptoKeyAsymmetricTypeSubtag>(tag);
2286         return true;
2287     }
2288
2289     bool readHMACKey(bool extractable, CryptoKeyUsageBitmap usages, RefPtr<CryptoKey>& result)
2290     {
2291         Vector<uint8_t> keyData;
2292         if (!read(keyData))
2293             return false;
2294         CryptoAlgorithmIdentifier hash;
2295         if (!read(hash))
2296             return false;
2297         result = CryptoKeyHMAC::importRaw(0, hash, WTFMove(keyData), extractable, usages);
2298         return true;
2299     }
2300
2301     bool readAESKey(bool extractable, CryptoKeyUsageBitmap usages, RefPtr<CryptoKey>& result)
2302     {
2303         CryptoAlgorithmIdentifier algorithm;
2304         if (!read(algorithm))
2305             return false;
2306         if (!CryptoKeyAES::isValidAESAlgorithm(algorithm))
2307             return false;
2308         Vector<uint8_t> keyData;
2309         if (!read(keyData))
2310             return false;
2311         result = CryptoKeyAES::importRaw(algorithm, WTFMove(keyData), extractable, usages);
2312         return true;
2313     }
2314
2315     bool readRSAKey(bool extractable, CryptoKeyUsageBitmap usages, RefPtr<CryptoKey>& result)
2316     {
2317         CryptoAlgorithmIdentifier algorithm;
2318         if (!read(algorithm))
2319             return false;
2320
2321         int32_t isRestrictedToHash;
2322         CryptoAlgorithmIdentifier hash;
2323         if (!read(isRestrictedToHash))
2324             return false;
2325         if (isRestrictedToHash && !read(hash))
2326             return false;
2327
2328         CryptoKeyAsymmetricTypeSubtag type;
2329         if (!read(type))
2330             return false;
2331
2332         Vector<uint8_t> modulus;
2333         if (!read(modulus))
2334             return false;
2335         Vector<uint8_t> exponent;
2336         if (!read(exponent))
2337             return false;
2338
2339         if (type == CryptoKeyAsymmetricTypeSubtag::Public) {
2340             auto keyData = CryptoKeyRSAComponents::createPublic(modulus, exponent);
2341             auto key = CryptoKeyRSA::create(algorithm, hash, isRestrictedToHash, *keyData, extractable, usages);
2342             result = WTFMove(key);
2343             return true;
2344         }
2345
2346         Vector<uint8_t> privateExponent;
2347         if (!read(privateExponent))
2348             return false;
2349
2350         uint32_t primeCount;
2351         if (!read(primeCount))
2352             return false;
2353
2354         if (!primeCount) {
2355             auto keyData = CryptoKeyRSAComponents::createPrivate(modulus, exponent, privateExponent);
2356             auto key = CryptoKeyRSA::create(algorithm, hash, isRestrictedToHash, *keyData, extractable, usages);
2357             result = WTFMove(key);
2358             return true;
2359         }
2360
2361         if (primeCount < 2)
2362             return false;
2363
2364         CryptoKeyRSAComponents::PrimeInfo firstPrimeInfo;
2365         CryptoKeyRSAComponents::PrimeInfo secondPrimeInfo;
2366         Vector<CryptoKeyRSAComponents::PrimeInfo> otherPrimeInfos(primeCount - 2);
2367
2368         if (!read(firstPrimeInfo.primeFactor))
2369             return false;
2370         if (!read(firstPrimeInfo.factorCRTExponent))
2371             return false;
2372         if (!read(secondPrimeInfo.primeFactor))
2373             return false;
2374         if (!read(secondPrimeInfo.factorCRTExponent))
2375             return false;
2376         if (!read(secondPrimeInfo.factorCRTCoefficient))
2377             return false;
2378         for (unsigned i = 2; i < primeCount; ++i) {
2379             if (!read(otherPrimeInfos[i].primeFactor))
2380                 return false;
2381             if (!read(otherPrimeInfos[i].factorCRTExponent))
2382                 return false;
2383             if (!read(otherPrimeInfos[i].factorCRTCoefficient))
2384                 return false;
2385         }
2386
2387         auto keyData = CryptoKeyRSAComponents::createPrivateWithAdditionalData(modulus, exponent, privateExponent, firstPrimeInfo, secondPrimeInfo, otherPrimeInfos);
2388         auto key = CryptoKeyRSA::create(algorithm, hash, isRestrictedToHash, *keyData, extractable, usages);
2389         result = WTFMove(key);
2390         return true;
2391     }
2392
2393     bool readECKey(bool extractable, CryptoKeyUsageBitmap usages, RefPtr<CryptoKey>& result)
2394     {
2395         CryptoAlgorithmIdentifier algorithm;
2396         if (!read(algorithm))
2397             return false;
2398         if (!CryptoKeyEC::isValidECAlgorithm(algorithm))
2399             return false;
2400         CachedStringRef curve;
2401         if (!readStringData(curve))
2402             return false;
2403         CryptoKeyAsymmetricTypeSubtag type;
2404         if (!read(type))
2405             return false;
2406         Vector<uint8_t> keyData;
2407         if (!read(keyData))
2408             return false;
2409
2410         switch (type) {
2411         case CryptoKeyAsymmetricTypeSubtag::Public:
2412             result = CryptoKeyEC::importRaw(algorithm, curve->string(), WTFMove(keyData), extractable, usages);
2413             break;
2414         case CryptoKeyAsymmetricTypeSubtag::Private:
2415             result = CryptoKeyEC::importPkcs8(algorithm, curve->string(), WTFMove(keyData), extractable, usages);
2416             break;
2417         }
2418
2419         return true;
2420     }
2421
2422     bool readRawKey(CryptoKeyUsageBitmap usages, RefPtr<CryptoKey>& result)
2423     {
2424         CryptoAlgorithmIdentifier algorithm;
2425         if (!read(algorithm))
2426             return false;
2427         Vector<uint8_t> keyData;
2428         if (!read(keyData))
2429             return false;
2430         result = CryptoKeyRaw::create(algorithm, WTFMove(keyData), usages);
2431         return true;
2432     }
2433
2434     bool readCryptoKey(JSValue& cryptoKey)
2435     {
2436         uint32_t keyFormatVersion;
2437         if (!read(keyFormatVersion) || keyFormatVersion > currentKeyFormatVersion)
2438             return false;
2439
2440         int32_t extractable;
2441         if (!read(extractable))
2442             return false;
2443
2444         uint32_t usagesCount;
2445         if (!read(usagesCount))
2446             return false;
2447
2448         CryptoKeyUsageBitmap usages = 0;
2449         for (uint32_t i = 0; i < usagesCount; ++i) {
2450             CryptoKeyUsageTag usage;
2451             if (!read(usage))
2452                 return false;
2453             switch (usage) {
2454             case CryptoKeyUsageTag::Encrypt:
2455                 usages |= CryptoKeyUsageEncrypt;
2456                 break;
2457             case CryptoKeyUsageTag::Decrypt:
2458                 usages |= CryptoKeyUsageDecrypt;
2459                 break;
2460             case CryptoKeyUsageTag::Sign:
2461                 usages |= CryptoKeyUsageSign;
2462                 break;
2463             case CryptoKeyUsageTag::Verify:
2464                 usages |= CryptoKeyUsageVerify;
2465                 break;
2466             case CryptoKeyUsageTag::DeriveKey:
2467                 usages |= CryptoKeyUsageDeriveKey;
2468                 break;
2469             case CryptoKeyUsageTag::DeriveBits:
2470                 usages |= CryptoKeyUsageDeriveBits;
2471                 break;
2472             case CryptoKeyUsageTag::WrapKey:
2473                 usages |= CryptoKeyUsageWrapKey;
2474                 break;
2475             case CryptoKeyUsageTag::UnwrapKey:
2476                 usages |= CryptoKeyUsageUnwrapKey;
2477                 break;
2478             }
2479         }
2480
2481         CryptoKeyClassSubtag cryptoKeyClass;
2482         if (!read(cryptoKeyClass))
2483             return false;
2484         RefPtr<CryptoKey> result;
2485         switch (cryptoKeyClass) {
2486         case CryptoKeyClassSubtag::HMAC:
2487             if (!readHMACKey(extractable, usages, result))
2488                 return false;
2489             break;
2490         case CryptoKeyClassSubtag::AES:
2491             if (!readAESKey(extractable, usages, result))
2492                 return false;
2493             break;
2494         case CryptoKeyClassSubtag::RSA:
2495             if (!readRSAKey(extractable, usages, result))
2496                 return false;
2497             break;
2498         case CryptoKeyClassSubtag::EC:
2499             if (!readECKey(extractable, usages, result))
2500                 return false;
2501             break;
2502         case CryptoKeyClassSubtag::Raw:
2503             if (!readRawKey(usages, result))
2504                 return false;
2505             break;
2506         }
2507         cryptoKey = getJSValue(result.get());
2508         return true;
2509     }
2510 #endif
2511
2512     template<class T>
2513     JSValue getJSValue(T* nativeObj)
2514     {
2515         return toJS(m_exec, jsCast<JSDOMGlobalObject*>(m_globalObject), nativeObj);
2516     }
2517
2518     template<class T>
2519     JSValue getJSValue(T& nativeObj)
2520     {
2521         return toJS(m_exec, jsCast<JSDOMGlobalObject*>(m_globalObject), nativeObj);
2522     }
2523
2524     template<class T>
2525     JSValue readDOMPoint()
2526     {
2527         double x;
2528         if (!read(x))
2529             return { };
2530         double y;
2531         if (!read(y))
2532             return { };
2533         double z;
2534         if (!read(z))
2535             return { };
2536         double w;
2537         if (!read(w))
2538             return { };
2539
2540         return toJSNewlyCreated(m_exec, jsCast<JSDOMGlobalObject*>(m_globalObject), T::create(x, y, z, w));
2541     }
2542
2543     template<class T>
2544     JSValue readDOMMatrix()
2545     {
2546         uint8_t is2D;
2547         if (!read(is2D))
2548             return { };
2549
2550         if (is2D) {
2551             double m11;
2552             if (!read(m11))
2553                 return { };
2554             double m12;
2555             if (!read(m12))
2556                 return { };
2557             double m21;
2558             if (!read(m21))
2559                 return { };
2560             double m22;
2561             if (!read(m22))
2562                 return { };
2563             double m41;
2564             if (!read(m41))
2565                 return { };
2566             double m42;
2567             if (!read(m42))
2568                 return { };
2569
2570             TransformationMatrix matrix(m11, m12, m21, m22, m41, m42);
2571             return toJSNewlyCreated(m_exec, jsCast<JSDOMGlobalObject*>(m_globalObject), T::create(WTFMove(matrix), DOMMatrixReadOnly::Is2D::Yes));
2572         } else {
2573             double m11;
2574             if (!read(m11))
2575                 return { };
2576             double m12;
2577             if (!read(m12))
2578                 return { };
2579             double m13;
2580             if (!read(m13))
2581                 return { };
2582             double m14;
2583             if (!read(m14))
2584                 return { };
2585             double m21;
2586             if (!read(m21))
2587                 return { };
2588             double m22;
2589             if (!read(m22))
2590                 return { };
2591             double m23;
2592             if (!read(m23))
2593                 return { };
2594             double m24;
2595             if (!read(m24))
2596                 return { };
2597             double m31;
2598             if (!read(m31))
2599                 return { };
2600             double m32;
2601             if (!read(m32))
2602                 return { };
2603             double m33;
2604             if (!read(m33))
2605                 return { };
2606             double m34;
2607             if (!read(m34))
2608                 return { };
2609             double m41;
2610             if (!read(m41))
2611                 return { };
2612             double m42;
2613             if (!read(m42))
2614                 return { };
2615             double m43;
2616             if (!read(m43))
2617                 return { };
2618             double m44;
2619             if (!read(m44))
2620                 return { };
2621
2622             TransformationMatrix matrix(m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44);
2623             return toJSNewlyCreated(m_exec, jsCast<JSDOMGlobalObject*>(m_globalObject), T::create(WTFMove(matrix), DOMMatrixReadOnly::Is2D::No));
2624         }
2625     }
2626
2627     template<class T>
2628     JSValue readDOMRect()
2629     {
2630         double x;
2631         if (!read(x))
2632             return { };
2633         double y;
2634         if (!read(y))
2635             return { };
2636         double width;
2637         if (!read(width))
2638             return { };
2639         double height;
2640         if (!read(height))
2641             return { };
2642
2643         return toJSNewlyCreated(m_exec, jsCast<JSDOMGlobalObject*>(m_globalObject), T::create(x, y, width, height));
2644     }
2645
2646     Optional<DOMPointInit> readDOMPointInit()
2647     {
2648         DOMPointInit point;
2649         if (!read(point.x))
2650             return WTF::nullopt;
2651         if (!read(point.y))
2652             return WTF::nullopt;
2653         if (!read(point.z))
2654             return WTF::nullopt;
2655         if (!read(point.w))
2656             return WTF::nullopt;
2657
2658         return point;
2659     }
2660
2661     JSValue readDOMQuad()
2662     {
2663         auto p1 = readDOMPointInit();
2664         if (!p1)
2665             return JSValue();
2666         auto p2 = readDOMPointInit();
2667         if (!p2)
2668             return JSValue();
2669         auto p3 = readDOMPointInit();
2670         if (!p3)
2671             return JSValue();
2672         auto p4 = readDOMPointInit();
2673         if (!p4)
2674             return JSValue();
2675
2676         return toJSNewlyCreated(m_exec, jsCast<JSDOMGlobalObject*>(m_globalObject), DOMQuad::create(p1.value(), p2.value(), p3.value(), p4.value()));
2677     }
2678
2679     JSValue readImageBitmap()
2680     {
2681         uint32_t index;
2682         bool indexSuccessfullyRead = read(index);
2683         if (!indexSuccessfullyRead || index >= m_imageBuffers.size()) {
2684             fail();
2685             return JSValue();
2686         }
2687
2688         if (!m_imageBitmaps[index])
2689             m_imageBitmaps[index] = ImageBitmap::create(WTFMove(m_imageBuffers.at(index)));
2690
2691         auto bitmap = m_imageBitmaps[index].get();
2692         return getJSValue(bitmap);
2693     }
2694
2695 #if ENABLE(WEB_RTC)
2696     JSValue readRTCCertificate()
2697     {
2698         double expires;
2699         if (!read(expires)) {
2700             fail();
2701             return JSValue();
2702         }
2703         CachedStringRef certificate;
2704         if (!readStringData(certificate)) {
2705             fail();
2706             return JSValue();
2707         }
2708         CachedStringRef origin;
2709         if (!readStringData(origin)) {
2710             fail();
2711             return JSValue();
2712         }
2713         CachedStringRef keyedMaterial;
2714         if (!readStringData(keyedMaterial)) {
2715             fail();
2716             return JSValue();
2717         }
2718         unsigned size = 0;
2719         if (!read(size))
2720             return JSValue();
2721
2722         Vector<RTCCertificate::DtlsFingerprint> fingerprints;
2723         fingerprints.reserveInitialCapacity(size);
2724         for (unsigned i = 0; i < size; i++) {
2725             CachedStringRef algorithm;
2726             if (!readStringData(algorithm))
2727                 return JSValue();
2728             CachedStringRef value;
2729             if (!readStringData(value))
2730                 return JSValue();
2731             fingerprints.uncheckedAppend(RTCCertificate::DtlsFingerprint { algorithm->string(), value->string() });
2732         }
2733
2734         if (!m_isDOMGlobalObject)
2735             return constructEmptyObject(m_exec, m_globalObject->objectPrototype());
2736
2737         auto rtcCertificate = RTCCertificate::create(SecurityOrigin::createFromString(origin->string()), expires, WTFMove(fingerprints), certificate->takeString(), keyedMaterial->takeString());
2738         return toJSNewlyCreated(m_exec, jsCast<JSDOMGlobalObject*>(m_globalObject), WTFMove(rtcCertificate));
2739     }
2740 #endif
2741
2742     JSValue readTerminal()
2743     {
2744         SerializationTag tag = readTag();
2745         switch (tag) {
2746         case UndefinedTag:
2747             return jsUndefined();
2748         case NullTag:
2749             return jsNull();
2750         case IntTag: {
2751             int32_t i;
2752             if (!read(i))
2753                 return JSValue();
2754             return jsNumber(i);
2755         }
2756         case ZeroTag:
2757             return jsNumber(0);
2758         case OneTag:
2759             return jsNumber(1);
2760         case FalseTag:
2761             return jsBoolean(false);
2762         case TrueTag:
2763             return jsBoolean(true);
2764         case FalseObjectTag: {
2765             BooleanObject* obj = BooleanObject::create(m_exec->vm(), m_globalObject->booleanObjectStructure());
2766             obj->setInternalValue(m_exec->vm(), jsBoolean(false));
2767             m_gcBuffer.appendWithCrashOnOverflow(obj);
2768             return obj;
2769         }
2770         case TrueObjectTag: {
2771             BooleanObject* obj = BooleanObject::create(m_exec->vm(), m_globalObject->booleanObjectStructure());
2772             obj->setInternalValue(m_exec->vm(), jsBoolean(true));
2773             m_gcBuffer.appendWithCrashOnOverflow(obj);
2774             return obj;
2775         }
2776         case DoubleTag: {
2777             double d;
2778             if (!read(d))
2779                 return JSValue();
2780             return jsNumber(d);
2781         }
2782         case NumberObjectTag: {
2783             double d;
2784             if (!read(d))
2785                 return JSValue();
2786             NumberObject* obj = constructNumber(m_exec, m_globalObject, jsNumber(d));
2787             m_gcBuffer.appendWithCrashOnOverflow(obj);
2788             return obj;
2789         }
2790         case DateTag: {
2791             double d;
2792             if (!read(d))
2793                 return JSValue();
2794             return DateInstance::create(m_exec->vm(), m_globalObject->dateStructure(), d);
2795         }
2796         case FileTag: {
2797             RefPtr<File> file;
2798             if (!readFile(file))
2799                 return JSValue();
2800             if (!m_isDOMGlobalObject)
2801                 return jsNull();
2802             return toJS(m_exec, jsCast<JSDOMGlobalObject*>(m_globalObject), file.get());
2803         }
2804         case FileListTag: {
2805             unsigned length = 0;
2806             if (!read(length))
2807                 return JSValue();
2808             Vector<Ref<File>> files;
2809             for (unsigned i = 0; i < length; i++) {
2810                 RefPtr<File> file;
2811                 if (!readFile(file))
2812                     return JSValue();
2813                 if (m_isDOMGlobalObject)
2814                     files.append(file.releaseNonNull());
2815             }
2816             if (!m_isDOMGlobalObject)
2817                 return jsNull();
2818             return getJSValue(FileList::create(WTFMove(files)).get());
2819         }
2820         case ImageDataTag: {
2821             uint32_t width;
2822             if (!read(width))
2823                 return JSValue();
2824             uint32_t height;
2825             if (!read(height))
2826                 return JSValue();
2827             uint32_t length;
2828             if (!read(length))
2829                 return JSValue();
2830             if (static_cast<uint32_t>(m_end - m_ptr) < length) {
2831                 fail();
2832                 return JSValue();
2833             }
2834             if (!m_isDOMGlobalObject) {
2835                 m_ptr += length;
2836                 return jsNull();
2837             }
2838             IntSize imageSize(width, height);
2839             RELEASE_ASSERT(!length || (imageSize.area() * 4).unsafeGet() <= length);
2840             auto result = ImageData::create(imageSize);
2841             if (!result) {
2842                 fail();
2843                 return JSValue();
2844             }
2845             if (length)
2846                 memcpy(result->data()->data(), m_ptr, length);
2847             else
2848                 result->data()->zeroFill();
2849             m_ptr += length;
2850             return getJSValue(result.get());
2851         }
2852         case BlobTag: {
2853             CachedStringRef url;
2854             if (!readStringData(url))
2855                 return JSValue();
2856             CachedStringRef type;
2857             if (!readStringData(type))
2858                 return JSValue();
2859             unsigned long long size = 0;
2860             if (!read(size))
2861                 return JSValue();
2862             if (!m_isDOMGlobalObject)
2863                 return jsNull();
2864             return getJSValue(Blob::deserialize(jsCast<JSDOMGlobalObject*>(m_globalObject)->scriptExecutionContext()->sessionID(), URL(URL(), url->string()), type->string(), size, blobFilePathForBlobURL(url->string())).get());
2865         }
2866         case StringTag: {
2867             CachedStringRef cachedString;
2868             if (!readStringData(cachedString))
2869                 return JSValue();
2870             return cachedString->jsString(m_exec);
2871         }
2872         case EmptyStringTag:
2873             return jsEmptyString(&m_exec->vm());
2874         case StringObjectTag: {
2875             CachedStringRef cachedString;
2876             if (!readStringData(cachedString))
2877                 return JSValue();
2878             StringObject* obj = constructString(m_exec->vm(), m_globalObject, cachedString->jsString(m_exec));
2879             m_gcBuffer.appendWithCrashOnOverflow(obj);
2880             return obj;
2881         }
2882         case EmptyStringObjectTag: {
2883             VM& vm = m_exec->vm();
2884             StringObject* obj = constructString(vm, m_globalObject, jsEmptyString(&vm));
2885             m_gcBuffer.appendWithCrashOnOverflow(obj);
2886             return obj;
2887         }
2888         case RegExpTag: {
2889             CachedStringRef pattern;
2890             if (!readStringData(pattern))
2891                 return JSValue();
2892             CachedStringRef flags;
2893             if (!readStringData(flags))
2894                 return JSValue();
2895             auto reFlags = Yarr::parseFlags(flags->string());
2896             ASSERT(reFlags.hasValue());
2897             VM& vm = m_exec->vm();
2898             RegExp* regExp = RegExp::create(vm, pattern->string(), reFlags.value());
2899             return RegExpObject::create(vm, m_globalObject->regExpStructure(), regExp);
2900         }
2901         case ObjectReferenceTag: {
2902             unsigned index = 0;
2903             if (!readConstantPoolIndex(m_gcBuffer, index)) {
2904                 fail();
2905                 return JSValue();
2906             }
2907             return m_gcBuffer.at(index);
2908         }
2909         case MessagePortReferenceTag: {
2910             uint32_t index;
2911             bool indexSuccessfullyRead = read(index);
2912             if (!indexSuccessfullyRead || index >= m_messagePorts.size()) {
2913                 fail();
2914                 return JSValue();
2915             }
2916             return getJSValue(m_messagePorts[index].get());
2917         }
2918 #if ENABLE(WEBASSEMBLY)
2919         case WasmModuleTag: {
2920             uint32_t index;
2921             bool indexSuccessfullyRead = read(index);
2922             if (!indexSuccessfullyRead || !m_wasmModules || index >= m_wasmModules->size()) {
2923                 fail();
2924                 return JSValue();
2925             }
2926             auto scope = DECLARE_THROW_SCOPE(m_exec->vm());
2927             JSValue result = JSC::JSWebAssemblyModule::createStub(m_exec->vm(), m_exec, m_globalObject->webAssemblyModuleStructure(), m_wasmModules->at(index));
2928             // Since we are cloning a JSWebAssemblyModule, it's impossible for that
2929             // module to not have been a valid module. Therefore, createStub should
2930             // not trow.
2931             scope.releaseAssertNoException();
2932             m_gcBuffer.appendWithCrashOnOverflow(result);
2933             return result;
2934         }
2935 #endif
2936         case ArrayBufferTag: {
2937             RefPtr<ArrayBuffer> arrayBuffer;
2938             if (!readArrayBuffer(arrayBuffer)) {
2939                 fail();
2940                 return JSValue();
2941             }
2942             Structure* structure = m_globalObject->arrayBufferStructure(arrayBuffer->sharingMode());
2943             // A crazy RuntimeFlags mismatch could mean that we are not equipped to handle shared
2944             // array buffers while the sender is. In that case, we would see a null structure here.
2945             if (!structure) {
2946                 fail();
2947                 return JSValue();
2948             }
2949             JSValue result = JSArrayBuffer::create(m_exec->vm(), structure, WTFMove(arrayBuffer));
2950             m_gcBuffer.appendWithCrashOnOverflow(result);
2951             return result;
2952         }
2953         case ArrayBufferTransferTag: {
2954             uint32_t index;
2955             bool indexSuccessfullyRead = read(index);
2956             if (!indexSuccessfullyRead || index >= m_arrayBuffers.size()) {
2957                 fail();
2958                 return JSValue();
2959             }
2960
2961             if (!m_arrayBuffers[index])
2962                 m_arrayBuffers[index] = ArrayBuffer::create(WTFMove(m_arrayBufferContents->at(index)));
2963
2964             return getJSValue(m_arrayBuffers[index].get());
2965         }
2966         case SharedArrayBufferTag: {
2967             uint32_t index = UINT_MAX;
2968             bool indexSuccessfullyRead = read(index);
2969             if (!indexSuccessfullyRead || !m_sharedBuffers || index >= m_sharedBuffers->size()) {
2970                 fail();
2971                 return JSValue();
2972             }
2973             
2974             RELEASE_ASSERT(m_sharedBuffers->at(index));
2975             auto buffer = ArrayBuffer::create(WTFMove(m_sharedBuffers->at(index)));
2976             JSValue result = getJSValue(buffer.get());
2977             m_gcBuffer.appendWithCrashOnOverflow(result);
2978             return result;
2979         }
2980         case ArrayBufferViewTag: {
2981             JSValue arrayBufferView;
2982             if (!readArrayBufferView(m_exec->vm(), arrayBufferView)) {
2983                 fail();
2984                 return JSValue();
2985             }
2986             m_gcBuffer.appendWithCrashOnOverflow(arrayBufferView);
2987             return arrayBufferView;
2988         }
2989 #if ENABLE(WEB_CRYPTO)
2990         case CryptoKeyTag: {
2991             Vector<uint8_t> wrappedKey;
2992             if (!read(wrappedKey)) {
2993                 fail();
2994                 return JSValue();
2995             }
2996             Vector<uint8_t> serializedKey;
2997             if (!unwrapCryptoKey(m_exec, wrappedKey, serializedKey)) {
2998                 fail();
2999                 return JSValue();
3000             }
3001             JSValue cryptoKey;
3002             Vector<RefPtr<MessagePort>> dummyMessagePorts;
3003             CloneDeserializer rawKeyDeserializer(m_exec, m_globalObject, dummyMessagePorts, nullptr, { },
3004 #if ENABLE(WEBASSEMBLY)
3005                 nullptr,
3006 #endif
3007                 serializedKey);
3008             if (!rawKeyDeserializer.readCryptoKey(cryptoKey)) {
3009                 fail();
3010                 return JSValue();
3011             }
3012             m_gcBuffer.appendWithCrashOnOverflow(cryptoKey);
3013             return cryptoKey;
3014         }
3015 #endif
3016         case DOMPointReadOnlyTag:
3017             return readDOMPoint<DOMPointReadOnly>();
3018         case DOMPointTag:
3019             return readDOMPoint<DOMPoint>();
3020         case DOMRectReadOnlyTag:
3021             return readDOMRect<DOMRectReadOnly>();
3022         case DOMRectTag:
3023             return readDOMRect<DOMRect>();
3024         case DOMMatrixReadOnlyTag:
3025             return readDOMMatrix<DOMMatrixReadOnly>();
3026         case DOMMatrixTag:
3027             return readDOMMatrix<DOMMatrix>();
3028         case DOMQuadTag:
3029             return readDOMQuad();
3030         case ImageBitmapTransferTag:
3031             return readImageBitmap();
3032 #if ENABLE(WEB_RTC)
3033         case RTCCertificateTag:
3034             return readRTCCertificate();
3035
3036 #endif
3037         default:
3038             m_ptr--; // Push the tag back
3039             return JSValue();
3040         }
3041     }
3042
3043     template<SerializationTag Tag>
3044     bool consumeCollectionDataTerminationIfPossible()
3045     {
3046         if (readTag() == Tag)
3047             return true;
3048         m_ptr--;
3049         return false;
3050     }
3051
3052     JSGlobalObject* m_globalObject;
3053     bool m_isDOMGlobalObject;
3054     const uint8_t* m_ptr;
3055     const uint8_t* m_end;
3056     unsigned m_version;
3057     Vector<CachedString> m_constantPool;
3058     const Vector<RefPtr<MessagePort>>& m_messagePorts;
3059     ArrayBufferContentsArray* m_arrayBufferContents;
3060     Vector<RefPtr<JSC::ArrayBuffer>> m_arrayBuffers;
3061     Vector<String> m_blobURLs;
3062     PAL::SessionID m_sessionID;
3063     Vector<String> m_blobFilePaths;
3064     ArrayBufferContentsArray* m_sharedBuffers;
3065     Vector<std::pair<std::unique_ptr<ImageBuffer>, bool>> m_imageBuffers;
3066     Vector<RefPtr<ImageBitmap>> m_imageBitmaps;
3067 #if ENABLE(WEBASSEMBLY)
3068     WasmModuleArray* m_wasmModules;
3069 #endif
3070
3071     String blobFilePathForBlobURL(const String& blobURL)
3072     {
3073         size_t i = 0;
3074         for (; i < m_blobURLs.size(); ++i) {
3075             if (m_blobURLs[i] == blobURL)
3076                 break;
3077         }
3078
3079         return i < m_blobURLs.size() ? m_blobFilePaths[i] : String();
3080     }
3081 };
3082
3083 DeserializationResult CloneDeserializer::deserialize()
3084 {
3085     VM& vm = m_exec->vm();
3086     auto scope = DECLARE_THROW_SCOPE(vm);
3087
3088     Vector<uint32_t, 16> indexStack;
3089     Vector<Identifier, 16> propertyNameStack;
3090     Vector<JSObject*, 32> outputObjectStack;
3091     Vector<JSValue, 4> mapKeyStack;
3092     Vector<JSMap*, 4> mapStack;
3093     Vector<JSSet*, 4> setStack;
3094     Vector<WalkerState, 16> stateStack;
3095     WalkerState state = StateUnknown;
3096     JSValue outValue;
3097
3098     while (1) {
3099         switch (state) {
3100         arrayStartState:
3101         case ArrayStartState: {
3102             uint32_t length;
3103             if (!read(length)) {
3104                 fail();
3105                 goto error;
3106             }
3107             JSArray* outArray = constructEmptyArray(m_exec, 0, m_globalObject, length);
3108             if (UNLIKELY(scope.exception()))
3109                 goto error;
3110             m_gcBuffer.appendWithCrashOnOverflow(outArray);
3111             outputObjectStack.append(outArray);
3112         }
3113         arrayStartVisitMember:
3114         FALLTHROUGH;
3115         case ArrayStartVisitMember: {
3116             uint32_t index;
3117             if (!read(index)) {
3118                 fail();
3119                 goto error;
3120             }
3121             if (index == TerminatorTag) {
3122                 JSObject* outArray = outputObjectStack.last();
3123                 outValue = outArray;
3124                 outputObjectStack.removeLast();
3125                 break;
3126             } else if (index == NonIndexPropertiesTag) {
3127                 goto objectStartVisitMember;
3128             }
3129
3130             if (JSValue terminal = readTerminal()) {
3131                 putProperty(outputObjectStack.last(), index, terminal);
3132                 goto arrayStartVisitMember;
3133             }
3134             if (m_failed)
3135                 goto error;
3136             indexStack.append(index);
3137             stateStack.append(ArrayEndVisitMember);
3138             goto stateUnknown;
3139         }
3140         case ArrayEndVisitMember: {
3141             JSObject* outArray = outputObjectStack.last();
3142             putProperty(outArray, indexStack.last(), outValue);
3143             indexStack.removeLast();
3144             goto arrayStartVisitMember;
3145         }
3146         objectStartState:
3147         case ObjectStartState: {
3148             if (outputObjectStack.size() > maximumFilterRecursion)
3149                 return std::make_pair(JSValue(), SerializationReturnCode::StackOverflowError);
3150             JSObject* outObject = constructEmptyObject(m_exec, m_globalObject->objectPrototype());
3151             m_gcBuffer.appendWithCrashOnOverflow(outObject);
3152             outputObjectStack.append(outObject);
3153         }
3154         objectStartVisitMember:
3155         FALLTHROUGH;
3156         case ObjectStartVisitMember: {
3157             CachedStringRef cachedString;
3158             bool wasTerminator = false;
3159             if (!readStringData(cachedString, wasTerminator)) {
3160                 if (!wasTerminator)
3161                     goto error;
3162
3163                 JSObject* outObject = outputObjectStack.last();
3164                 outValue = outObject;
3165                 outputObjectStack.removeLast();
3166                 break;
3167             }
3168
3169             if (JSValue terminal = readTerminal()) {
3170                 putProperty(outputObjectStack.last(), Identifier::fromString(m_exec, cachedString->string()), terminal);
3171                 goto objectStartVisitMember;
3172             }
3173             stateStack.append(ObjectEndVisitMember);
3174             propertyNameStack.append(Identifier::fromString(m_exec, cachedString->string()));
3175             goto stateUnknown;
3176         }
3177         case ObjectEndVisitMember: {
3178             putProperty(outputObjectStack.last(), propertyNameStack.last(), outValue);
3179             propertyNameStack.removeLast();
3180             goto objectStartVisitMember;
3181         }
3182         mapObjectStartState: {
3183             if (outputObjectStack.size() > maximumFilterRecursion)
3184                 return std::make_pair(JSValue(), SerializationReturnCode::StackOverflowError);
3185             JSMap* map = JSMap::create(m_exec, m_exec->vm(), m_globalObject->mapStructure());
3186             if (UNLIKELY(scope.exception()))
3187                 goto error;
3188             m_gcBuffer.appendWithCrashOnOverflow(map);
3189             outputObjectStack.append(map);
3190             mapStack.append(map);
3191             goto mapDataStartVisitEntry;
3192         }
3193         mapDataStartVisitEntry:
3194         case MapDataStartVisitEntry: {
3195             if (consumeCollectionDataTerminationIfPossible<NonMapPropertiesTag>()) {
3196                 mapStack.removeLast();
3197                 goto objectStartVisitMember;
3198             }
3199             stateStack.append(MapDataEndVisitKey);
3200             goto stateUnknown;
3201         }
3202         case MapDataEndVisitKey: {
3203             mapKeyStack.append(outValue);
3204             stateStack.append(MapDataEndVisitValue);
3205             goto stateUnknown;
3206         }
3207         case MapDataEndVisitValue: {
3208             mapStack.last()->set(m_exec, mapKeyStack.last(), outValue);
3209             mapKeyStack.removeLast();
3210             goto mapDataStartVisitEntry;
3211         }
3212
3213         setObjectStartState: {
3214             if (outputObjectStack.size() > maximumFilterRecursion)
3215                 return std::make_pair(JSValue(), SerializationReturnCode::StackOverflowError);
3216             JSSet* set = JSSet::create(m_exec, m_exec->vm(), m_globalObject->setStructure());
3217             if (UNLIKELY(scope.exception()))
3218                 goto error;
3219             m_gcBuffer.appendWithCrashOnOverflow(set);
3220             outputObjectStack.append(set);
3221             setStack.append(set);
3222             goto setDataStartVisitEntry;
3223         }
3224         setDataStartVisitEntry:
3225         case SetDataStartVisitEntry: {
3226             if (consumeCollectionDataTerminationIfPossible<NonSetPropertiesTag>()) {
3227                 setStack.removeLast();
3228                 goto objectStartVisitMember;
3229             }
3230             stateStack.append(SetDataEndVisitKey);
3231             goto stateUnknown;
3232         }
3233         case SetDataEndVisitKey: {
3234             JSSet* set = setStack.last();
3235             set->add(m_exec, outValue);
3236             goto setDataStartVisitEntry;
3237         }
3238
3239         stateUnknown:
3240         case StateUnknown:
3241             if (JSValue terminal = readTerminal()) {
3242                 outValue = terminal;
3243                 break;
3244             }
3245             SerializationTag tag = readTag();
3246             if (tag == ArrayTag)
3247                 goto arrayStartState;
3248             if (tag == ObjectTag)
3249                 goto objectStartState;
3250             if (tag == MapObjectTag)
3251                 goto mapObjectStartState;
3252             if (tag == SetObjectTag)
3253                 goto setObjectStartState;
3254             goto error;
3255         }
3256         if (stateStack.isEmpty())
3257             break;
3258
3259         state = stateStack.last();
3260         stateStack.removeLast();
3261     }
3262     ASSERT(outValue);
3263     ASSERT(!m_failed);
3264     return std::make_pair(outValue, SerializationReturnCode::SuccessfullyCompleted);
3265 error:
3266     fail();
3267     return std::make_pair(JSValue(), SerializationReturnCode::ValidationError);
3268 }
3269
3270 SerializedScriptValue::~SerializedScriptValue() = default;
3271
3272 SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>&& buffer)
3273     : m_data(WTFMove(buffer))
3274 {
3275 }
3276
3277 SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>&& buffer, std::unique_ptr<ArrayBufferContentsArray> arrayBufferContentsArray)
3278     : m_data(WTFMove(buffer))
3279     , m_arrayBufferContentsArray(WTFMove(arrayBufferContentsArray))
3280 {
3281 }
3282
3283 SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>&& buffer, const Vector<String>& blobURLs, const PAL::SessionID& sessionID,  std::unique_ptr<ArrayBufferContentsArray> arrayBufferContentsArray, std::unique_ptr<ArrayBufferContentsArray> sharedBufferContentsArray, Vector<std::pair<std::unique_ptr<ImageBuffer>, bool>>&& imageBuffers
3284 #if ENABLE(WEBASSEMBLY)
3285         , std::unique_ptr<WasmModuleArray> wasmModulesArray
3286 #endif
3287         )
3288     : m_data(WTFMove(buffer))
3289     , m_arrayBufferContentsArray(WTFMove(arrayBufferContentsArray))
3290     , m_sharedBufferContentsArray(WTFMove(sharedBufferContentsArray))
3291     , m_imageBuffers(WTFMove(imageBuffers))
3292 #if ENABLE(WEBASSEMBLY)
3293     , m_wasmModulesArray(WTFMove(wasmModulesArray))
3294 #endif
3295     , m_sessionID(sessionID)
3296 {
3297     // Since this SerializedScriptValue is meant to be passed between threads, its String data members
3298     // need to be isolatedCopies so we don't run into thread safety issues for the StringImpls.
3299     m_blobURLs.reserveInitialCapacity(blobURLs.size());
3300     for (auto& url : blobURLs)
3301         m_blobURLs.uncheckedAppend(url.isolatedCopy());
3302 }
3303
3304 static ExceptionOr<std::unique_ptr<ArrayBufferContentsArray>> transferArrayBuffers(VM& vm, const Vector<RefPtr<JSC::ArrayBuffer>>& arrayBuffers)
3305 {
3306     if (arrayBuffers.isEmpty())
3307         return nullptr;
3308
3309     auto contents = std::make_unique<ArrayBufferContentsArray>(arrayBuffers.size());
3310
3311     HashSet<JSC::ArrayBuffer*> visited;
3312     for (size_t arrayBufferIndex = 0; arrayBufferIndex < arrayBuffers.size(); arrayBufferIndex++) {
3313         if (visited.contains(arrayBuffers[arrayBufferIndex].get()))
3314             continue;
3315         visited.add(arrayBuffers[arrayBufferIndex].get());
3316
3317         bool result = arrayBuffers[arrayBufferIndex]->transferTo(vm, contents->at(arrayBufferIndex));
3318         if (!result)
3319             return Exception { TypeError };
3320     }
3321
3322     return contents;
3323 }
3324
3325 static void maybeThrowExceptionIfSerializationFailed(ExecState& state, SerializationReturnCode code)
3326 {
3327     auto& vm = state.vm();
3328     auto scope = DECLARE_THROW_SCOPE(vm);
3329
3330     switch (code) {
3331     case SerializationReturnCode::SuccessfullyCompleted:
3332         break;
3333     case SerializationReturnCode::StackOverflowError:
3334         throwException(&state, scope, createStackOverflowError(&state));
3335         break;
3336     case SerializationReturnCode::ValidationError:
3337         throwTypeError(&state, scope, "Unable to deserialize data."_s);
3338         break;
3339     case SerializationReturnCode::DataCloneError:
3340         throwDataCloneError(state, scope);
3341         break;
3342     case SerializationReturnCode::ExistingExceptionError:
3343     case SerializationReturnCode::UnspecifiedError:
3344         break;
3345     case SerializationReturnCode::InterruptedExecutionError:
3346         ASSERT_NOT_REACHED();
3347     }
3348 }
3349
3350 static Exception exceptionForSerializationFailure(SerializationReturnCode code)
3351 {
3352     ASSERT(code != SerializationReturnCode::SuccessfullyCompleted);
3353     
3354     switch (code) {
3355     case SerializationReturnCode::StackOverflowError:
3356         return Exception { StackOverflowError };
3357     case SerializationReturnCode::ValidationError:
3358         return Exception { TypeError };
3359     case SerializationReturnCode::DataCloneError:
3360         return Exception { DataCloneError };
3361     case SerializationReturnCode::ExistingExceptionError:
3362         return Exception { ExistingExceptionError };
3363     case SerializationReturnCode::UnspecifiedError:
3364         return Exception { TypeError };
3365     case SerializationReturnCode::SuccessfullyCompleted:
3366     case SerializationReturnCode::InterruptedExecutionError:
3367         ASSERT_NOT_REACHED();
3368         return Exception { TypeError };
3369     }
3370     ASSERT_NOT_REACHED();
3371     return Exception { TypeError };
3372 }
3373
3374 RefPtr<SerializedScriptValue> SerializedScriptValue::create(ExecState& exec, JSValue value, SerializationErrorMode throwExceptions)
3375 {
3376     Vector<uint8_t> buffer;
3377     Vector<String> blobURLs;
3378     PAL::SessionID sessionID;
3379     Vector<RefPtr<MessagePort>> dummyMessagePorts;
3380     Vector<RefPtr<ImageBitmap>> dummyImageBitmaps;
3381     Vector<RefPtr<JSC::ArrayBuffer>> dummyArrayBuffers;
3382 #if ENABLE(WEBASSEMBLY)
3383     WasmModuleArray dummyModules;
3384 #endif
3385     ArrayBufferContentsArray dummySharedBuffers;
3386     auto code = CloneSerializer::serialize(&exec, value, dummyMessagePorts, dummyArrayBuffers, dummyImageBitmaps,
3387 #if ENABLE(WEBASSEMBLY)
3388         dummyModules,
3389 #endif
3390         blobURLs, sessionID, buffer, SerializationContext::Default, dummySharedBuffers);
3391
3392 #if ENABLE(WEBASSEMBLY)
3393     ASSERT_WITH_MESSAGE(dummyModules.isEmpty(), "Wasm::Module serialization is only allowed in the postMessage context");
3394 #endif
3395
3396     if (throwExceptions == SerializationErrorMode::Throwing)
3397         maybeThrowExceptionIfSerializationFailed(exec, code);
3398
3399     if (code != SerializationReturnCode::SuccessfullyCompleted)
3400         return nullptr;
3401
3402     return adoptRef(*new SerializedScriptValue(WTFMove(buffer), blobURLs, sessionID, nullptr, nullptr, { }
3403 #if ENABLE(WEBASSEMBLY)
3404         , nullptr
3405 #endif
3406             ));
3407 }
3408
3409 static bool containsDuplicates(const Vector<RefPtr<ImageBitmap>>& imageBitmaps)
3410 {
3411     HashSet<ImageBitmap*> visited;
3412     for (auto& imageBitmap : imageBitmaps) {
3413         if (!visited.add(imageBitmap.get()))
3414             return true;
3415     }
3416     return false;
3417 }
3418
3419 ExceptionOr<Ref<SerializedScriptValue>> SerializedScriptValue::create(ExecState& state, JSValue value, Vector<JSC::Strong<JSC::JSObject>>&& transferList, Vector<RefPtr<MessagePort>>& messagePorts, SerializationContext context)
3420 {
3421     VM& vm = state.vm();
3422     Vector<RefPtr<JSC::ArrayBuffer>> arrayBuffers;
3423     Vector<RefPtr<ImageBitmap>> imageBitmaps;
3424     for (auto& transferable : transferList) {
3425         if (auto arrayBuffer = toPossiblySharedArrayBuffer(vm, transferable.get())) {
3426             if (arrayBuffer->isNeutered())
3427                 return Exception { DataCloneError };
3428             if (arrayBuffer->isLocked()) {
3429                 auto scope = DECLARE_THROW_SCOPE(vm);
3430                 throwVMTypeError(&state, scope, errorMesasgeForTransfer(arrayBuffer));
3431                 return Exception { ExistingExceptionError };
3432             }
3433             arrayBuffers.append(WTFMove(arrayBuffer));
3434             continue;
3435         }
3436         if (auto port = JSMessagePort::toWrapped(vm, transferable.get())) {
3437             // FIXME: This should check if the port is detached as per https://html.spec.whatwg.org/multipage/infrastructure.html#istransferable.
3438             messagePorts.append(WTFMove(port));
3439             continue;
3440         }
3441
3442         if (auto imageBitmap = JSImageBitmap::toWrapped(vm, transferable.get())) {
3443             if (imageBitmap->isDetached())
3444                 return Exception { DataCloneError };
3445
3446             imageBitmaps.append(WTFMove(imageBitmap));
3447             continue;
3448         }
3449
3450         return Exception { DataCloneError };
3451     }
3452
3453     if (containsDuplicates(imageBitmaps))
3454         return Exception { DataCloneError };
3455
3456     Vector<uint8_t> buffer;
3457     Vector<String> blobURLs;
3458     PAL::SessionID sessionID;
3459 #if ENABLE(WEBASSEMBLY)
3460     WasmModuleArray wasmModules;
3461 #endif
3462     std::unique_ptr<ArrayBufferContentsArray> sharedBuffers = std::make_unique<ArrayBufferContentsArray>();
3463     auto code = CloneSerializer::serialize(&state, value, messagePorts, arrayBuffers, imageBitmaps,
3464 #if ENABLE(WEBASSEMBLY)
3465         wasmModules, 
3466 #endif
3467         blobURLs, sessionID, buffer, context, *sharedBuffers);
3468
3469     if (code != SerializationReturnCode::SuccessfullyCompleted)
3470         return exceptionForSerializationFailure(code);
3471
3472     auto arrayBufferContentsArray = transferArrayBuffers(vm, arrayBuffers);
3473     if (arrayBufferContentsArray.hasException())
3474         return arrayBufferContentsArray.releaseException();
3475
3476     auto imageBuffers = ImageBitmap::detachBitmaps(WTFMove(imageBitmaps));
3477
3478     return adoptRef(*new SerializedScriptValue(WTFMove(buffer), blobURLs, sessionID, arrayBufferContentsArray.releaseReturnValue(), context == SerializationContext::WorkerPostMessage ? WTFMove(sharedBuffers) : nullptr, WTFMove(imageBuffers)
3479 #if ENABLE(WEBASSEMBLY)
3480                 , std::make_unique<WasmModuleArray>(wasmModules)
3481 #endif
3482                 ));
3483 }
3484
3485 RefPtr<SerializedScriptValue> SerializedScriptValue::create(StringView string)
3486 {
3487     Vector<uint8_t> buffer;
3488     if (!CloneSerializer::serialize(string, buffer))
3489         return nullptr;
3490     return adoptRef(*new SerializedScriptValue(WTFMove(buffer)));
3491 }
3492
3493 RefPtr<SerializedScriptValue> SerializedScriptValue::create(JSContextRef originContext, JSValueRef apiValue, JSValueRef* exception)
3494 {
3495     ExecState* exec = toJS(originContext);
3496     VM& vm = exec->vm();
3497     JSLockHolder locker(vm);
3498     auto scope = DECLARE_CATCH_SCOPE(vm);
3499
3500     JSValue value = toJS(exec, apiValue);
3501     auto serializedValue = SerializedScriptValue::create(*exec, value);
3502     if (UNLIKELY(scope.exception())) {
3503         if (exception)
3504             *exception = toRef(exec, scope.exception()->value());
3505         scope.clearException();
3506         return nullptr;
3507     }
3508     ASSERT(serializedValue);
3509     return serializedValue;
3510 }
3511
3512 String SerializedScriptValue::toString()
3513 {
3514     return CloneDeserializer::deserializeString(m_data);
3515 }
3516
3517 JSValue SerializedScriptValue::deserialize(ExecState& exec, JSGlobalObject* globalObject, SerializationErrorMode throwExceptions)
3518 {
3519     return deserialize(exec, globalObject, { }, throwExceptions);
3520 }
3521
3522 JSValue SerializedScriptValue::deserialize(ExecState& exec, JSGlobalObject* globalObject, const Vector<RefPtr<MessagePort>>& messagePorts, SerializationErrorMode throwExceptions)
3523 {
3524     Vector<String> dummyBlobs;
3525     Vector<String> dummyPaths;
3526     PAL::SessionID dummySessionID;
3527     return deserialize(exec, globalObject, messagePorts, dummyBlobs, dummySessionID, dummyPaths, throwExceptions);
3528 }
3529
3530 JSValue SerializedScriptValue::deserialize(ExecState& exec, JSGlobalObject* globalObject, const Vector<RefPtr<MessagePort>>& messagePorts, const Vector<String>& blobURLs, const PAL::SessionID& sessionID, const Vector<String>& blobFilePaths, SerializationErrorMode throwExceptions)
3531 {
3532     DeserializationResult result = CloneDeserializer::deserialize(&exec, globalObject, messagePorts, WTFMove(m_imageBuffers), m_arrayBufferContentsArray.get(), m_data, blobURLs, sessionID, blobFilePaths, m_sharedBufferContentsArray.get()
3533 #if ENABLE(WEBASSEMBLY)
3534         , m_wasmModulesArray.get()
3535 #endif
3536         );
3537     if (throwExceptions == SerializationErrorMode::Throwing)
3538         maybeThrowExceptionIfSerializationFailed(exec, result.second);
3539     return result.first ? result.first : jsNull();
3540 }
3541
3542 JSValueRef SerializedScriptValue::deserialize(JSContextRef destinationContext, JSValueRef* exception)
3543 {
3544     ExecState* exec = toJS(destinationContext);
3545     VM& vm = exec->vm();
3546     JSLockHolder locker(vm);
3547     auto scope = DECLARE_CATCH_SCOPE(vm);
3548
3549     JSValue value = deserialize(*exec, exec->lexicalGlobalObject());
3550     if (UNLIKELY(scope.exception())) {
3551         if (exception)
3552             *exception = toRef(exec, scope.exception()->value());
3553         scope.clearException();
3554         return nullptr;
3555     }
3556     ASSERT(value);
3557     return toRef(exec, value);
3558 }
3559
3560 Ref<SerializedScriptValue> SerializedScriptValue::nullValue()
3561 {
3562     return adoptRef(*new SerializedScriptValue(Vector<uint8_t>()));
3563 }
3564
3565 uint32_t SerializedScriptValue::wireFormatVersion()
3566 {
3567     return CurrentVersion;
3568 }
3569
3570 #if ENABLE(INDEXED_DATABASE)
3571 Vector<String> SerializedScriptValue::blobURLsIsolatedCopy() const
3572 {
3573     Vector<String> result;
3574     result.reserveInitialCapacity(m_blobURLs.size());
3575     for (auto& url : m_blobURLs)
3576         result.uncheckedAppend(url.isolatedCopy());
3577
3578     return result;
3579 }
3580
3581 void SerializedScriptValue::writeBlobsToDiskForIndexedDB(CompletionHandler<void(IDBValue&&)>&& completionHandler)
3582 {
3583     ASSERT(isMainThread());
3584     ASSERT(hasBlobURLs());
3585
3586     // FIXME: Add m_sessionID as a parameter here.
3587     blobRegistry().writeBlobsToTemporaryFiles(m_blobURLs, [completionHandler = WTFMove(completionHandler), this, protectedThis = makeRef(*this)] (auto&& blobFilePaths) mutable {
3588         ASSERT(isMainThread());
3589
3590         if (blobFilePaths.isEmpty()) {
3591             // We should have successfully written blobs to temporary files.
3592             // If we failed, then we can't successfully store this record.
3593             completionHandler({ });
3594             return;
3595         }
3596
3597         ASSERT(m_blobURLs.size() == blobFilePaths.size());
3598         
3599         completionHandler({ *this, m_blobURLs, m_sessionID, blobFilePaths });
3600     });
3601 }
3602
3603 IDBValue SerializedScriptValue::writeBlobsToDiskForIndexedDBSynchronously()
3604 {
3605     ASSERT(!isMainThread());
3606
3607     IDBValue value;
3608     Lock lock;
3609     Condition condition;
3610     lock.lock();
3611
3612     RunLoop::main().dispatch([this, conditionPtr = &condition, valuePtr = &value] {
3613         writeBlobsToDiskForIndexedDB([conditionPtr, valuePtr](IDBValue&& result) {
3614             ASSERT(isMainThread());
3615             valuePtr->setAsIsolatedCopy(result);
3616
3617             conditionPtr->notifyAll();
3618         });
3619     });
3620
3621     condition.wait(lock);
3622
3623     return value;
3624 }
3625
3626 #endif // ENABLE(INDEXED_DATABASE)
3627
3628 } // namespace WebCore