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