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