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