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