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