2 * Copyright (C) 2009, 2013 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
28 #include "SerializedScriptValue.h"
31 #include "CryptoKeyAES.h"
32 #include "CryptoKeyDataOctetSequence.h"
33 #include "CryptoKeyDataRSAComponents.h"
34 #include "CryptoKeyHMAC.h"
35 #include "CryptoKeyRSA.h"
36 #include "ExceptionCode.h"
39 #include "ImageData.h"
41 #include "JSCryptoKey.h"
42 #include "JSDOMBinding.h"
43 #include "JSDOMGlobalObject.h"
45 #include "JSFileList.h"
46 #include "JSImageData.h"
47 #include "JSMessagePort.h"
48 #include "JSNavigator.h"
49 #include "ScriptExecutionContext.h"
50 #include "SharedBuffer.h"
51 #include "WebCoreJSClientData.h"
53 #include <JavaScriptCore/APICast.h>
54 #include <runtime/ArrayBuffer.h>
55 #include <runtime/BooleanObject.h>
56 #include <runtime/DateInstance.h>
57 #include <runtime/Error.h>
58 #include <runtime/ExceptionHelpers.h>
59 #include <runtime/JSArrayBuffer.h>
60 #include <runtime/JSArrayBufferView.h>
61 #include <runtime/JSCInlines.h>
62 #include <runtime/JSDataView.h>
63 #include <runtime/JSMap.h>
64 #include <runtime/JSMapIterator.h>
65 #include <runtime/JSSet.h>
66 #include <runtime/JSSetIterator.h>
67 #include <runtime/JSTypedArrays.h>
68 #include <runtime/MapData.h>
69 #include <runtime/MapDataInlines.h>
70 #include <runtime/ObjectConstructor.h>
71 #include <runtime/PropertyNameArray.h>
72 #include <runtime/RegExp.h>
73 #include <runtime/RegExpObject.h>
74 #include <runtime/TypedArrayInlines.h>
75 #include <runtime/TypedArrays.h>
76 #include <wtf/HashTraits.h>
77 #include <wtf/Vector.h>
81 #if CPU(BIG_ENDIAN) || CPU(MIDDLE_ENDIAN) || CPU(NEEDS_ALIGNED_ACCESS)
82 #define ASSUME_LITTLE_ENDIAN 0
84 #define ASSUME_LITTLE_ENDIAN 1
89 static const unsigned maximumFilterRecursion = 40000;
91 enum WalkerState { StateUnknown, ArrayStartState, ArrayStartVisitMember, ArrayEndVisitMember,
92 ObjectStartState, ObjectStartVisitMember, ObjectEndVisitMember,
93 MapDataStartVisitEntry, MapDataEndVisitKey, MapDataEndVisitValue,
94 SetDataStartVisitEntry, SetDataEndVisitKey };
96 // These can't be reordered, and any new types must be added to the end of the list
97 enum SerializationTag {
116 ObjectReferenceTag = 19,
117 MessagePortReferenceTag = 20,
119 ArrayBufferViewTag = 22,
120 ArrayBufferTransferTag = 23,
123 StringObjectTag = 26,
124 EmptyStringObjectTag = 27,
125 NumberObjectTag = 28,
128 NonMapPropertiesTag = 31,
129 NonSetPropertiesTag = 32,
130 #if ENABLE(SUBTLE_CRYPTO)
136 enum ArrayBufferViewSubtag {
140 Uint8ClampedArrayTag = 3,
149 static unsigned typedArrayElementSize(ArrayBufferViewSubtag tag)
155 case Uint8ClampedArrayTag:
162 case Float32ArrayTag:
164 case Float64ArrayTag:
172 #if ENABLE(SUBTLE_CRYPTO)
174 const uint32_t currentKeyFormatVersion = 1;
176 enum class CryptoKeyClassSubtag {
181 const uint8_t cryptoKeyClassSubtagMaximumValue = 2;
183 enum class CryptoKeyAsymmetricTypeSubtag {
187 const uint8_t cryptoKeyAsymmetricTypeSubtagMaximumValue = 1;
189 enum class CryptoKeyUsageTag {
199 const uint8_t cryptoKeyUsageTagMaximumValue = 7;
201 enum class CryptoAlgorithmIdentifierTag {
202 RSAES_PKCS1_v1_5 = 0,
203 RSASSA_PKCS1_v1_5 = 1,
225 const uint8_t cryptoAlgorithmIdentifierTagMaximumValue = 21;
227 static unsigned countUsages(CryptoKeyUsage usages)
229 // Fast bit count algorithm for sparse bit maps.
232 usages = usages & (usages - 1);
240 /* CurrentVersion tracks the serialization version so that persistent stores
241 * are able to correctly bail out in the case of encountering newer formats.
243 * Initial version was 1.
244 * Version 2. added the ObjectReferenceTag and support for serialization of cyclic graphs.
245 * Version 3. added the FalseObjectTag, TrueObjectTag, NumberObjectTag, StringObjectTag
246 * and EmptyStringObjectTag for serialization of Boolean, Number and String objects.
247 * Version 4. added support for serializing non-index properties of arrays.
248 * Version 5. added support for Map and Set types.
250 static const unsigned CurrentVersion = 5;
251 static const unsigned TerminatorTag = 0xFFFFFFFF;
252 static const unsigned StringPoolTag = 0xFFFFFFFE;
253 static const unsigned NonIndexPropertiesTag = 0xFFFFFFFD;
256 * Object serialization is performed according to the following grammar, all tags
257 * are recorded as a single uint8_t.
259 * IndexType (used for the object pool and StringData's constant pool) is the
260 * minimum sized unsigned integer type required to represent the maximum index
261 * in the constant pool.
263 * SerializedValue :- <CurrentVersion:uint32_t> Value
264 * Value :- Array | Object | Map | Set | Terminal
267 * ArrayTag <length:uint32_t>(<index:uint32_t><value:Value>)* TerminatorTag
270 * ObjectTag (<name:StringData><value:Value>)* TerminatorTag
272 * Map :- MapObjectTag MapData
274 * Set :- SetObjectTag SetData
276 * MapData :- (<key:Value><value:Value>)* NonMapPropertiesTag (<name:StringData><value:Value>)* TerminatorTag
277 * SetData :- (<key:Value>)* NonSetPropertiesTag (<name:StringData><value:Value>)* TerminatorTag
282 * | IntTag <value:int32_t>
289 * | DoubleTag <value:double>
290 * | NumberObjectTag <value:double>
291 * | DateTag <value:double>
294 * | EmptyStringObjectTag
300 * | MessagePortReferenceTag <value:uint32_t>
302 * | ArrayBufferViewTag ArrayBufferViewSubtag <byteOffset:uint32_t> <byteLength:uint32_t> (ArrayBuffer | ObjectReference)
303 * | ArrayBufferTransferTag <value:uint32_t>
304 * | CryptoKeyTag <wrappedKeyLength:uint32_t> <factor:byte{wrappedKeyLength}>
306 * Inside wrapped crypto key, data is serialized in this format:
308 * <keyFormatVersion:uint32_t> <extractable:int32_t> <usagesCount:uint32_t> <usages:byte{usagesCount}> CryptoKeyClassSubtag (CryptoKeyHMAC | CryptoKeyAES | CryptoKeyRSA)
312 * StringTag StringData
315 * EmptyStringObjectTag
316 * StringObjectTag StringData
319 * StringPoolTag <cpIndex:IndexType>
320 * (not (TerminatorTag | StringPoolTag))<length:uint32_t><characters:UChar{length}> // Added to constant pool when seen, string length 0xFFFFFFFF is disallowed
326 * <path:StringData> <url:StringData> <type:StringData> <name:StringData>
329 * FileListTag <length:uint32_t>(<file:FileData>){length}
332 * ImageDataTag <width:int32_t><height:int32_t><length:uint32_t><data:uint8_t{length}>
335 * BlobTag <url:StringData><type:StringData><size:long long>
338 * RegExpTag <pattern:StringData><flags:StringData>
341 * ObjectReferenceTag <opIndex:IndexType>
344 * ArrayBufferTag <length:uint32_t> <contents:byte{length}>
347 * <keySize:uint32_t> <keyData:byte{keySize}> CryptoAlgorithmIdentifierTag // Algorithm tag inner hash function.
350 * CryptoAlgorithmIdentifierTag <keySize:uint32_t> <keyData:byte{keySize}>
353 * CryptoAlgorithmIdentifierTag <isRestrictedToHash:int32_t> CryptoAlgorithmIdentifierTag? CryptoKeyAsymmetricTypeSubtag CryptoKeyRSAPublicComponents CryptoKeyRSAPrivateComponents?
355 * CryptoKeyRSAPublicComponents :-
356 * <modulusSize:uint32_t> <modulus:byte{modulusSize}> <exponentSize:uint32_t> <exponent:byte{exponentSize}>
358 * CryptoKeyRSAPrivateComponents :-
359 * <privateExponentSize:uint32_t> <privateExponent:byte{privateExponentSize}> <primeCount:uint32_t> FirstPrimeInfo? PrimeInfo{primeCount - 1}
361 * // CRT data could be computed from prime factors. It is only serialized to reuse a code path that's needed for JWK.
363 * <factorSize:uint32_t> <factor:byte{factorSize}> <crtExponentSize:uint32_t> <crtExponent:byte{crtExponentSize}>
366 * <factorSize:uint32_t> <factor:byte{factorSize}> <crtExponentSize:uint32_t> <crtExponent:byte{crtExponentSize}> <crtCoefficientSize:uint32_t> <crtCoefficient:byte{crtCoefficientSize}>
369 typedef std::pair<JSC::JSValue, SerializationReturnCode> DeserializationResult;
373 CloneBase(ExecState* exec)
379 bool shouldTerminate()
381 return m_exec->hadException();
384 void throwStackOverflow()
386 m_exec->vm().throwException(m_exec, createStackOverflowError(m_exec));
396 MarkedArgumentBuffer m_gcBuffer;
399 #if ENABLE(SUBTLE_CRYPTO)
400 static bool wrapCryptoKey(ExecState* exec, const Vector<uint8_t>& key, Vector<uint8_t>& wrappedKey)
402 ScriptExecutionContext* scriptExecutionContext = scriptExecutionContextFromExecState(exec);
403 if (!scriptExecutionContext)
405 return scriptExecutionContext->wrapCryptoKey(key, wrappedKey);
408 static bool unwrapCryptoKey(ExecState* exec, const Vector<uint8_t>& wrappedKey, Vector<uint8_t>& key)
410 ScriptExecutionContext* scriptExecutionContext = scriptExecutionContextFromExecState(exec);
411 if (!scriptExecutionContext)
413 return scriptExecutionContext->unwrapCryptoKey(wrappedKey, key);
417 #if ASSUME_LITTLE_ENDIAN
418 template <typename T> static void writeLittleEndian(Vector<uint8_t>& buffer, T value)
420 buffer.append(reinterpret_cast<uint8_t*>(&value), sizeof(value));
423 template <typename T> static void writeLittleEndian(Vector<uint8_t>& buffer, T value)
425 for (unsigned i = 0; i < sizeof(T); i++) {
426 buffer.append(value & 0xFF);
432 template <> void writeLittleEndian<uint8_t>(Vector<uint8_t>& buffer, uint8_t value)
434 buffer.append(value);
437 template <typename T> static bool writeLittleEndian(Vector<uint8_t>& buffer, const T* values, uint32_t length)
439 if (length > std::numeric_limits<uint32_t>::max() / sizeof(T))
442 #if ASSUME_LITTLE_ENDIAN
443 buffer.append(reinterpret_cast<const uint8_t*>(values), length * sizeof(T));
445 for (unsigned i = 0; i < length; i++) {
447 for (unsigned j = 0; j < sizeof(T); j++) {
448 buffer.append(static_cast<uint8_t>(value & 0xFF));
456 static bool writeLittleEndianUInt16(Vector<uint8_t>& buffer, const LChar* values, uint32_t length)
458 if (length > std::numeric_limits<uint32_t>::max() / 2)
461 for (unsigned i = 0; i < length; ++i) {
462 buffer.append(values[i]);
469 template <> bool writeLittleEndian<uint8_t>(Vector<uint8_t>& buffer, const uint8_t* values, uint32_t length)
471 buffer.append(values, length);
475 class CloneSerializer : CloneBase {
477 static SerializationReturnCode serialize(ExecState* exec, JSValue value,
478 MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers,
479 Vector<String>& blobURLs, Vector<uint8_t>& out)
481 CloneSerializer serializer(exec, messagePorts, arrayBuffers, blobURLs, out);
482 return serializer.serialize(value);
485 static bool serialize(const String& s, Vector<uint8_t>& out)
487 writeLittleEndian(out, CurrentVersion);
489 writeLittleEndian<uint8_t>(out, EmptyStringTag);
492 writeLittleEndian<uint8_t>(out, StringTag);
493 writeLittleEndian(out, s.length());
495 return writeLittleEndianUInt16(out, s.characters8(), s.length());
496 return writeLittleEndian(out, s.characters16(), s.length());
499 static void serializeUndefined(Vector<uint8_t>& out)
501 writeLittleEndian(out, CurrentVersion);
502 writeLittleEndian<uint8_t>(out, UndefinedTag);
505 static void serializeBoolean(bool value, Vector<uint8_t>& out)
507 writeLittleEndian(out, CurrentVersion);
508 writeLittleEndian<uint8_t>(out, value ? TrueTag : FalseTag);
511 static void serializeNumber(double value, Vector<uint8_t>& out)
513 writeLittleEndian(out, CurrentVersion);
514 writeLittleEndian<uint8_t>(out, DoubleTag);
520 writeLittleEndian(out, u.i);
524 typedef HashMap<JSObject*, uint32_t> ObjectPool;
526 CloneSerializer(ExecState* exec, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, Vector<String>& blobURLs, Vector<uint8_t>& out)
529 , m_blobURLs(blobURLs)
530 , m_emptyIdentifier(Identifier::fromString(exec, emptyString()))
532 write(CurrentVersion);
533 fillTransferMap(messagePorts, m_transferredMessagePorts);
534 fillTransferMap(arrayBuffers, m_transferredArrayBuffers);
538 void fillTransferMap(Vector<RefPtr<T>, 1>* input, ObjectPool& result)
542 JSDOMGlobalObject* globalObject = jsCast<JSDOMGlobalObject*>(m_exec->lexicalGlobalObject());
543 for (size_t i = 0; i < input->size(); i++) {
544 JSC::JSValue value = toJS(m_exec, globalObject, input->at(i).get());
545 JSC::JSObject* obj = value.getObject();
546 if (obj && !result.contains(obj))
551 SerializationReturnCode serialize(JSValue in);
553 bool isArray(JSValue value)
555 if (!value.isObject())
557 JSObject* object = asObject(value);
558 return isJSArray(object) || object->inherits(JSArray::info());
561 bool isMap(JSValue value)
563 if (!value.isObject())
565 JSObject* object = asObject(value);
566 return object->inherits(JSMap::info());
568 bool isSet(JSValue value)
570 if (!value.isObject())
572 JSObject* object = asObject(value);
573 return object->inherits(JSSet::info());
576 bool checkForDuplicate(JSObject* object)
578 // Record object for graph reconstruction
579 ObjectPool::const_iterator found = m_objectPool.find(object);
581 // Handle duplicate references
582 if (found != m_objectPool.end()) {
583 write(ObjectReferenceTag);
584 ASSERT(found->value < m_objectPool.size());
585 writeObjectIndex(found->value);
592 void recordObject(JSObject* object)
594 m_objectPool.add(object, m_objectPool.size());
595 m_gcBuffer.append(object);
598 bool startObjectInternal(JSObject* object)
600 if (checkForDuplicate(object))
602 recordObject(object);
606 bool startObject(JSObject* object)
608 if (!startObjectInternal(object))
614 bool startArray(JSArray* array)
616 if (!startObjectInternal(array))
619 unsigned length = array->length();
625 bool startSet(JSSet* set)
627 if (!startObjectInternal(set))
634 bool startMap(JSMap* map)
636 if (!startObjectInternal(map))
645 write(TerminatorTag);
648 JSValue getProperty(JSObject* object, const Identifier& propertyName)
650 PropertySlot slot(object);
651 if (object->methodTable()->getOwnPropertySlot(object, m_exec, propertyName, slot))
652 return slot.getValue(m_exec, propertyName);
656 void dumpImmediate(JSValue value)
660 else if (value.isUndefined())
662 else if (value.isNumber()) {
663 if (value.isInt32()) {
664 if (!value.asInt32())
666 else if (value.asInt32() == 1)
670 write(static_cast<uint32_t>(value.asInt32()));
674 write(value.asDouble());
676 } else if (value.isBoolean()) {
684 void dumpString(const String& string)
686 if (string.isEmpty())
687 write(EmptyStringTag);
694 void dumpStringObject(const String& string)
696 if (string.isEmpty())
697 write(EmptyStringObjectTag);
699 write(StringObjectTag);
704 bool dumpArrayBufferView(JSObject* obj, SerializationReturnCode& code)
706 write(ArrayBufferViewTag);
707 if (obj->inherits(JSDataView::info()))
709 else if (obj->inherits(JSUint8ClampedArray::info()))
710 write(Uint8ClampedArrayTag);
711 else if (obj->inherits(JSInt8Array::info()))
713 else if (obj->inherits(JSUint8Array::info()))
714 write(Uint8ArrayTag);
715 else if (obj->inherits(JSInt16Array::info()))
716 write(Int16ArrayTag);
717 else if (obj->inherits(JSUint16Array::info()))
718 write(Uint16ArrayTag);
719 else if (obj->inherits(JSInt32Array::info()))
720 write(Int32ArrayTag);
721 else if (obj->inherits(JSUint32Array::info()))
722 write(Uint32ArrayTag);
723 else if (obj->inherits(JSFloat32Array::info()))
724 write(Float32ArrayTag);
725 else if (obj->inherits(JSFloat64Array::info()))
726 write(Float64ArrayTag);
730 RefPtr<ArrayBufferView> arrayBufferView = toArrayBufferView(obj);
731 write(static_cast<uint32_t>(arrayBufferView->byteOffset()));
732 write(static_cast<uint32_t>(arrayBufferView->byteLength()));
733 RefPtr<ArrayBuffer> arrayBuffer = arrayBufferView->buffer();
735 code = ValidationError;
738 JSValue bufferObj = toJS(m_exec, jsCast<JSDOMGlobalObject*>(m_exec->lexicalGlobalObject()), arrayBuffer.get());
739 return dumpIfTerminal(bufferObj, code);
742 bool dumpIfTerminal(JSValue value, SerializationReturnCode& code)
744 if (!value.isCell()) {
745 dumpImmediate(value);
749 if (value.isString()) {
750 String str = asString(value)->value(m_exec);
755 if (value.isNumber()) {
757 write(value.asNumber());
761 if (value.isObject() && asObject(value)->inherits(DateInstance::info())) {
763 write(asDateInstance(value)->internalNumber());
770 if (value.isObject()) {
771 JSObject* obj = asObject(value);
772 if (obj->inherits(BooleanObject::info())) {
773 if (!startObjectInternal(obj)) // handle duplicates
775 write(asBooleanObject(value)->internalValue().toBoolean(m_exec) ? TrueObjectTag : FalseObjectTag);
778 if (obj->inherits(StringObject::info())) {
779 if (!startObjectInternal(obj)) // handle duplicates
781 String str = asString(asStringObject(value)->internalValue())->value(m_exec);
782 dumpStringObject(str);
785 if (obj->inherits(NumberObject::info())) {
786 if (!startObjectInternal(obj)) // handle duplicates
788 write(NumberObjectTag);
789 NumberObject* obj = static_cast<NumberObject*>(asObject(value));
790 write(obj->internalValue().asNumber());
793 if (File* file = JSFile::toWrapped(obj)) {
798 if (FileList* list = JSFileList::toWrapped(obj)) {
800 unsigned length = list->length();
802 for (unsigned i = 0; i < length; i++)
803 write(list->item(i));
806 if (Blob* blob = JSBlob::toWrapped(obj)) {
808 m_blobURLs.append(blob->url());
814 if (ImageData* data = JSImageData::toWrapped(obj)) {
816 write(data->width());
817 write(data->height());
818 write(data->data()->length());
819 write(data->data()->data(), data->data()->length());
822 if (obj->inherits(RegExpObject::info())) {
823 RegExpObject* regExp = asRegExpObject(obj);
826 if (regExp->regExp()->global())
827 flags[flagCount++] = 'g';
828 if (regExp->regExp()->ignoreCase())
829 flags[flagCount++] = 'i';
830 if (regExp->regExp()->multiline())
831 flags[flagCount++] = 'm';
833 write(regExp->regExp()->pattern());
834 write(String(flags, flagCount));
837 if (obj->inherits(JSMessagePort::info())) {
838 ObjectPool::iterator index = m_transferredMessagePorts.find(obj);
839 if (index != m_transferredMessagePorts.end()) {
840 write(MessagePortReferenceTag);
844 // MessagePort object could not be found in transferred message ports
845 code = ValidationError;
848 if (ArrayBuffer* arrayBuffer = toArrayBuffer(obj)) {
849 if (arrayBuffer->isNeutered()) {
850 code = ValidationError;
853 ObjectPool::iterator index = m_transferredArrayBuffers.find(obj);
854 if (index != m_transferredArrayBuffers.end()) {
855 write(ArrayBufferTransferTag);
859 if (!startObjectInternal(obj)) // handle duplicates
861 write(ArrayBufferTag);
862 write(arrayBuffer->byteLength());
863 write(static_cast<const uint8_t*>(arrayBuffer->data()), arrayBuffer->byteLength());
866 if (obj->inherits(JSArrayBufferView::info())) {
867 if (checkForDuplicate(obj))
869 bool success = dumpArrayBufferView(obj, code);
873 #if ENABLE(SUBTLE_CRYPTO)
874 if (CryptoKey* key = JSCryptoKey::toWrapped(obj)) {
876 Vector<uint8_t> serializedKey;
877 Vector<String> dummyBlobURLs;
878 CloneSerializer rawKeySerializer(m_exec, nullptr, nullptr, dummyBlobURLs, serializedKey);
879 rawKeySerializer.write(key);
880 Vector<uint8_t> wrappedKey;
881 if (!wrapCryptoKey(m_exec, serializedKey, wrappedKey))
890 // Any other types are expected to serialize as null.
895 void write(SerializationTag tag)
897 writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag));
900 void write(ArrayBufferViewSubtag tag)
902 writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag));
905 #if ENABLE(SUBTLE_CRYPTO)
906 void write(CryptoKeyClassSubtag tag)
908 writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag));
911 void write(CryptoKeyAsymmetricTypeSubtag tag)
913 writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag));
916 void write(CryptoKeyUsageTag tag)
918 writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag));
921 void write(CryptoAlgorithmIdentifierTag tag)
923 writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag));
927 void write(uint8_t c)
929 writeLittleEndian(m_buffer, c);
932 void write(uint32_t i)
934 writeLittleEndian(m_buffer, i);
944 writeLittleEndian(m_buffer, u.i);
947 void write(int32_t i)
949 writeLittleEndian(m_buffer, i);
952 void write(unsigned long long i)
954 writeLittleEndian(m_buffer, i);
957 void write(uint16_t ch)
959 writeLittleEndian(m_buffer, ch);
962 void writeStringIndex(unsigned i)
964 writeConstantPoolIndex(m_constantPool, i);
967 void writeObjectIndex(unsigned i)
969 writeConstantPoolIndex(m_objectPool, i);
972 template <class T> void writeConstantPoolIndex(const T& constantPool, unsigned i)
974 ASSERT(i < constantPool.size());
975 if (constantPool.size() <= 0xFF)
976 write(static_cast<uint8_t>(i));
977 else if (constantPool.size() <= 0xFFFF)
978 write(static_cast<uint16_t>(i));
980 write(static_cast<uint32_t>(i));
983 void write(const Identifier& ident)
985 const String& str = ident.string();
986 StringConstantPool::AddResult addResult = m_constantPool.add(str.impl(), m_constantPool.size());
987 if (!addResult.isNewEntry) {
988 write(StringPoolTag);
989 writeStringIndex(addResult.iterator->value);
993 unsigned length = str.length();
995 // This condition is unlikely to happen as they would imply an ~8gb
996 // string but we should guard against it anyway
997 if (length >= StringPoolTag) {
1002 // Guard against overflow
1003 if (length > (std::numeric_limits<uint32_t>::max() - sizeof(uint32_t)) / sizeof(UChar)) {
1008 writeLittleEndian<uint32_t>(m_buffer, length);
1009 if (!length || str.is8Bit()) {
1010 if (!writeLittleEndianUInt16(m_buffer, str.characters8(), length))
1014 if (!writeLittleEndian(m_buffer, str.characters16(), length))
1018 void write(const String& str)
1021 write(m_emptyIdentifier);
1023 write(Identifier::fromString(m_exec, str));
1026 void write(const Vector<uint8_t>& vector)
1028 uint32_t size = vector.size();
1030 writeLittleEndian(m_buffer, vector.data(), size);
1033 void write(const File* file)
1035 m_blobURLs.append(file->url());
1036 write(file->path());
1038 write(file->type());
1039 write(file->name());
1042 #if ENABLE(SUBTLE_CRYPTO)
1043 void write(CryptoAlgorithmIdentifier algorithm)
1045 switch (algorithm) {
1046 case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
1047 write(CryptoAlgorithmIdentifierTag::RSAES_PKCS1_v1_5);
1049 case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
1050 write(CryptoAlgorithmIdentifierTag::RSASSA_PKCS1_v1_5);
1052 case CryptoAlgorithmIdentifier::RSA_PSS:
1053 write(CryptoAlgorithmIdentifierTag::RSA_PSS);
1055 case CryptoAlgorithmIdentifier::RSA_OAEP:
1056 write(CryptoAlgorithmIdentifierTag::RSA_OAEP);
1058 case CryptoAlgorithmIdentifier::ECDSA:
1059 write(CryptoAlgorithmIdentifierTag::ECDSA);
1061 case CryptoAlgorithmIdentifier::ECDH:
1062 write(CryptoAlgorithmIdentifierTag::ECDH);
1064 case CryptoAlgorithmIdentifier::AES_CTR:
1065 write(CryptoAlgorithmIdentifierTag::AES_CTR);
1067 case CryptoAlgorithmIdentifier::AES_CBC:
1068 write(CryptoAlgorithmIdentifierTag::AES_CBC);
1070 case CryptoAlgorithmIdentifier::AES_CMAC:
1071 write(CryptoAlgorithmIdentifierTag::AES_CMAC);
1073 case CryptoAlgorithmIdentifier::AES_GCM:
1074 write(CryptoAlgorithmIdentifierTag::AES_GCM);
1076 case CryptoAlgorithmIdentifier::AES_CFB:
1077 write(CryptoAlgorithmIdentifierTag::AES_CFB);
1079 case CryptoAlgorithmIdentifier::AES_KW:
1080 write(CryptoAlgorithmIdentifierTag::AES_KW);
1082 case CryptoAlgorithmIdentifier::HMAC:
1083 write(CryptoAlgorithmIdentifierTag::HMAC);
1085 case CryptoAlgorithmIdentifier::DH:
1086 write(CryptoAlgorithmIdentifierTag::DH);
1088 case CryptoAlgorithmIdentifier::SHA_1:
1089 write(CryptoAlgorithmIdentifierTag::SHA_1);
1091 case CryptoAlgorithmIdentifier::SHA_224:
1092 write(CryptoAlgorithmIdentifierTag::SHA_224);
1094 case CryptoAlgorithmIdentifier::SHA_256:
1095 write(CryptoAlgorithmIdentifierTag::SHA_256);
1097 case CryptoAlgorithmIdentifier::SHA_384:
1098 write(CryptoAlgorithmIdentifierTag::SHA_384);
1100 case CryptoAlgorithmIdentifier::SHA_512:
1101 write(CryptoAlgorithmIdentifierTag::SHA_512);
1103 case CryptoAlgorithmIdentifier::CONCAT:
1104 write(CryptoAlgorithmIdentifierTag::CONCAT);
1106 case CryptoAlgorithmIdentifier::HKDF_CTR:
1107 write(CryptoAlgorithmIdentifierTag::HKDF_CTR);
1109 case CryptoAlgorithmIdentifier::PBKDF2:
1110 write(CryptoAlgorithmIdentifierTag::PBKDF2);
1115 void write(CryptoKeyDataRSAComponents::Type type)
1118 case CryptoKeyDataRSAComponents::Type::Public:
1119 write(CryptoKeyAsymmetricTypeSubtag::Public);
1121 case CryptoKeyDataRSAComponents::Type::Private:
1122 write(CryptoKeyAsymmetricTypeSubtag::Private);
1127 void write(const CryptoKeyDataRSAComponents& key)
1130 write(key.modulus());
1131 write(key.exponent());
1132 if (key.type() == CryptoKeyDataRSAComponents::Type::Public)
1135 write(key.privateExponent());
1137 unsigned primeCount = key.hasAdditionalPrivateKeyParameters() ? key.otherPrimeInfos().size() + 2 : 0;
1142 write(key.firstPrimeInfo().primeFactor);
1143 write(key.firstPrimeInfo().factorCRTExponent);
1144 write(key.secondPrimeInfo().primeFactor);
1145 write(key.secondPrimeInfo().factorCRTExponent);
1146 write(key.secondPrimeInfo().factorCRTCoefficient);
1147 for (unsigned i = 2; i < primeCount; ++i) {
1148 write(key.otherPrimeInfos()[i].primeFactor);
1149 write(key.otherPrimeInfos()[i].factorCRTExponent);
1150 write(key.otherPrimeInfos()[i].factorCRTCoefficient);
1154 void write(const CryptoKey* key)
1156 write(currentKeyFormatVersion);
1158 write(key->extractable());
1160 CryptoKeyUsage usages = key->usagesBitmap();
1161 write(countUsages(usages));
1162 if (usages & CryptoKeyUsageEncrypt)
1163 write(CryptoKeyUsageTag::Encrypt);
1164 if (usages & CryptoKeyUsageDecrypt)
1165 write(CryptoKeyUsageTag::Decrypt);
1166 if (usages & CryptoKeyUsageSign)
1167 write(CryptoKeyUsageTag::Sign);
1168 if (usages & CryptoKeyUsageVerify)
1169 write(CryptoKeyUsageTag::Verify);
1170 if (usages & CryptoKeyUsageDeriveKey)
1171 write(CryptoKeyUsageTag::DeriveKey);
1172 if (usages & CryptoKeyUsageDeriveBits)
1173 write(CryptoKeyUsageTag::DeriveBits);
1174 if (usages & CryptoKeyUsageWrapKey)
1175 write(CryptoKeyUsageTag::WrapKey);
1176 if (usages & CryptoKeyUsageUnwrapKey)
1177 write(CryptoKeyUsageTag::UnwrapKey);
1179 switch (key->keyClass()) {
1180 case CryptoKeyClass::HMAC:
1181 write(CryptoKeyClassSubtag::HMAC);
1182 write(downcast<CryptoKeyHMAC>(*key).key());
1183 write(downcast<CryptoKeyHMAC>(*key).hashAlgorithmIdentifier());
1185 case CryptoKeyClass::AES:
1186 write(CryptoKeyClassSubtag::AES);
1187 write(key->algorithmIdentifier());
1188 write(downcast<CryptoKeyAES>(*key).key());
1190 case CryptoKeyClass::RSA:
1191 write(CryptoKeyClassSubtag::RSA);
1192 write(key->algorithmIdentifier());
1193 CryptoAlgorithmIdentifier hash;
1194 bool isRestrictedToHash = downcast<CryptoKeyRSA>(*key).isRestrictedToHash(hash);
1195 write(isRestrictedToHash);
1196 if (isRestrictedToHash)
1198 write(downcast<CryptoKeyDataRSAComponents>(*key->exportData()));
1204 void write(const uint8_t* data, unsigned length)
1206 m_buffer.append(data, length);
1209 Vector<uint8_t>& m_buffer;
1210 Vector<String>& m_blobURLs;
1211 ObjectPool m_objectPool;
1212 ObjectPool m_transferredMessagePorts;
1213 ObjectPool m_transferredArrayBuffers;
1214 typedef HashMap<RefPtr<StringImpl>, uint32_t, IdentifierRepHash> StringConstantPool;
1215 StringConstantPool m_constantPool;
1216 Identifier m_emptyIdentifier;
1219 SerializationReturnCode CloneSerializer::serialize(JSValue in)
1221 Vector<uint32_t, 16> indexStack;
1222 Vector<uint32_t, 16> lengthStack;
1223 Vector<PropertyNameArray, 16> propertyStack;
1224 Vector<JSObject*, 32> inputObjectStack;
1225 Vector<JSMapIterator*, 4> mapIteratorStack;
1226 Vector<JSSetIterator*, 4> setIteratorStack;
1227 Vector<JSValue, 4> mapIteratorValueStack;
1228 Vector<WalkerState, 16> stateStack;
1229 WalkerState state = StateUnknown;
1230 JSValue inValue = in;
1234 case ArrayStartState: {
1235 ASSERT(isArray(inValue));
1236 if (inputObjectStack.size() > maximumFilterRecursion)
1237 return StackOverflowError;
1239 JSArray* inArray = asArray(inValue);
1240 unsigned length = inArray->length();
1241 if (!startArray(inArray))
1243 inputObjectStack.append(inArray);
1244 indexStack.append(0);
1245 lengthStack.append(length);
1247 arrayStartVisitMember:
1249 case ArrayStartVisitMember: {
1250 JSObject* array = inputObjectStack.last();
1251 uint32_t index = indexStack.last();
1252 if (index == lengthStack.last()) {
1253 indexStack.removeLast();
1254 lengthStack.removeLast();
1256 propertyStack.append(PropertyNameArray(m_exec));
1257 array->methodTable()->getOwnNonIndexPropertyNames(array, m_exec, propertyStack.last(), EnumerationMode());
1258 if (propertyStack.last().size()) {
1259 write(NonIndexPropertiesTag);
1260 indexStack.append(0);
1261 goto objectStartVisitMember;
1263 propertyStack.removeLast();
1266 inputObjectStack.removeLast();
1269 inValue = array->getDirectIndex(m_exec, index);
1271 indexStack.last()++;
1272 goto arrayStartVisitMember;
1276 SerializationReturnCode terminalCode = SuccessfullyCompleted;
1277 if (dumpIfTerminal(inValue, terminalCode)) {
1278 if (terminalCode != SuccessfullyCompleted)
1279 return terminalCode;
1280 indexStack.last()++;
1281 goto arrayStartVisitMember;
1283 stateStack.append(ArrayEndVisitMember);
1286 case ArrayEndVisitMember: {
1287 indexStack.last()++;
1288 goto arrayStartVisitMember;
1291 case ObjectStartState: {
1292 ASSERT(inValue.isObject());
1293 if (inputObjectStack.size() > maximumFilterRecursion)
1294 return StackOverflowError;
1295 JSObject* inObject = asObject(inValue);
1296 if (!startObject(inObject))
1298 // At this point, all supported objects other than Object
1299 // objects have been handled. If we reach this point and
1300 // the input is not an Object object then we should throw
1301 // a DataCloneError.
1302 if (inObject->classInfo() != JSFinalObject::info())
1303 return DataCloneError;
1304 inputObjectStack.append(inObject);
1305 indexStack.append(0);
1306 propertyStack.append(PropertyNameArray(m_exec));
1307 inObject->methodTable()->getOwnPropertyNames(inObject, m_exec, propertyStack.last(), EnumerationMode());
1309 objectStartVisitMember:
1311 case ObjectStartVisitMember: {
1312 JSObject* object = inputObjectStack.last();
1313 uint32_t index = indexStack.last();
1314 PropertyNameArray& properties = propertyStack.last();
1315 if (index == properties.size()) {
1317 inputObjectStack.removeLast();
1318 indexStack.removeLast();
1319 propertyStack.removeLast();
1322 inValue = getProperty(object, properties[index]);
1323 if (shouldTerminate())
1324 return ExistingExceptionError;
1327 // Property was removed during serialisation
1328 indexStack.last()++;
1329 goto objectStartVisitMember;
1331 write(properties[index]);
1333 if (shouldTerminate())
1334 return ExistingExceptionError;
1336 SerializationReturnCode terminalCode = SuccessfullyCompleted;
1337 if (!dumpIfTerminal(inValue, terminalCode)) {
1338 stateStack.append(ObjectEndVisitMember);
1341 if (terminalCode != SuccessfullyCompleted)
1342 return terminalCode;
1345 case ObjectEndVisitMember: {
1346 if (shouldTerminate())
1347 return ExistingExceptionError;
1349 indexStack.last()++;
1350 goto objectStartVisitMember;
1353 ASSERT(inValue.isObject());
1354 if (inputObjectStack.size() > maximumFilterRecursion)
1355 return StackOverflowError;
1356 JSMap* inMap = jsCast<JSMap*>(inValue);
1357 if (!startMap(inMap))
1359 JSMapIterator* iterator = JSMapIterator::create(m_exec->vm(), m_exec->lexicalGlobalObject()->mapIteratorStructure(), inMap, MapIterateKeyValue);
1360 m_gcBuffer.append(inMap);
1361 m_gcBuffer.append(iterator);
1362 mapIteratorStack.append(iterator);
1363 inputObjectStack.append(inMap);
1364 goto mapDataStartVisitEntry;
1366 mapDataStartVisitEntry:
1367 case MapDataStartVisitEntry: {
1368 JSMapIterator* iterator = mapIteratorStack.last();
1370 if (!iterator->nextKeyValue(key, value)) {
1371 mapIteratorStack.removeLast();
1372 JSObject* object = inputObjectStack.last();
1373 ASSERT(jsDynamicCast<JSMap*>(object));
1374 propertyStack.append(PropertyNameArray(m_exec));
1375 object->methodTable()->getOwnPropertyNames(object, m_exec, propertyStack.last(), EnumerationMode());
1376 write(NonMapPropertiesTag);
1377 indexStack.append(0);
1378 goto objectStartVisitMember;
1381 m_gcBuffer.append(value);
1382 mapIteratorValueStack.append(value);
1383 stateStack.append(MapDataEndVisitKey);
1386 case MapDataEndVisitKey: {
1387 inValue = mapIteratorValueStack.last();
1388 mapIteratorValueStack.removeLast();
1389 stateStack.append(MapDataEndVisitValue);
1392 case MapDataEndVisitValue: {
1393 goto mapDataStartVisitEntry;
1397 ASSERT(inValue.isObject());
1398 if (inputObjectStack.size() > maximumFilterRecursion)
1399 return StackOverflowError;
1400 JSSet* inSet = jsCast<JSSet*>(inValue);
1401 if (!startSet(inSet))
1403 JSSetIterator* iterator = JSSetIterator::create(m_exec->vm(), m_exec->lexicalGlobalObject()->setIteratorStructure(), inSet, SetIterateKey);
1404 m_gcBuffer.append(inSet);
1405 m_gcBuffer.append(iterator);
1406 setIteratorStack.append(iterator);
1407 inputObjectStack.append(inSet);
1408 goto setDataStartVisitEntry;
1410 setDataStartVisitEntry:
1411 case SetDataStartVisitEntry: {
1412 JSSetIterator* iterator = setIteratorStack.last();
1414 if (!iterator->next(m_exec, key)) {
1415 setIteratorStack.removeLast();
1416 JSObject* object = inputObjectStack.last();
1417 ASSERT(jsDynamicCast<JSSet*>(object));
1418 propertyStack.append(PropertyNameArray(m_exec));
1419 object->methodTable()->getOwnPropertyNames(object, m_exec, propertyStack.last(), EnumerationMode());
1420 write(NonSetPropertiesTag);
1421 indexStack.append(0);
1422 goto objectStartVisitMember;
1425 stateStack.append(SetDataEndVisitKey);
1428 case SetDataEndVisitKey: {
1429 goto setDataStartVisitEntry;
1433 case StateUnknown: {
1434 SerializationReturnCode terminalCode = SuccessfullyCompleted;
1435 if (dumpIfTerminal(inValue, terminalCode)) {
1436 if (terminalCode != SuccessfullyCompleted)
1437 return terminalCode;
1441 if (isArray(inValue))
1442 goto arrayStartState;
1447 goto objectStartState;
1450 if (stateStack.isEmpty())
1453 state = stateStack.last();
1454 stateStack.removeLast();
1457 return UnspecifiedError;
1459 return SuccessfullyCompleted;
1462 typedef Vector<JSC::ArrayBufferContents> ArrayBufferContentsArray;
1464 class CloneDeserializer : CloneBase {
1466 static String deserializeString(const Vector<uint8_t>& buffer)
1468 if (buffer.isEmpty())
1470 const uint8_t* ptr = buffer.begin();
1471 const uint8_t* end = buffer.end();
1473 if (!readLittleEndian(ptr, end, version) || version > CurrentVersion)
1476 if (!readLittleEndian(ptr, end, tag) || tag != StringTag)
1479 if (!readLittleEndian(ptr, end, length) || length >= StringPoolTag)
1482 if (!readString(ptr, end, str, length))
1484 return String(str.impl());
1487 static DeserializationResult deserialize(ExecState* exec, JSGlobalObject* globalObject,
1488 MessagePortArray* messagePorts, ArrayBufferContentsArray* arrayBufferContentsArray,
1489 const Vector<uint8_t>& buffer)
1492 return std::make_pair(jsNull(), UnspecifiedError);
1493 CloneDeserializer deserializer(exec, globalObject, messagePorts, arrayBufferContentsArray, buffer);
1494 if (!deserializer.isValid())
1495 return std::make_pair(JSValue(), ValidationError);
1496 return deserializer.deserialize();
1500 struct CachedString {
1501 CachedString(const String& string)
1506 JSValue jsString(ExecState* exec)
1509 m_jsString = JSC::jsString(exec, m_string);
1512 const String& string() { return m_string; }
1519 struct CachedStringRef {
1525 CachedStringRef(Vector<CachedString>* base, size_t index)
1531 CachedString* operator->() { ASSERT(m_base); return &m_base->at(m_index); }
1534 Vector<CachedString>* m_base;
1538 CloneDeserializer(ExecState* exec, JSGlobalObject* globalObject,
1539 MessagePortArray* messagePorts, ArrayBufferContentsArray* arrayBufferContents,
1540 const Vector<uint8_t>& buffer)
1542 , m_globalObject(globalObject)
1543 , m_isDOMGlobalObject(globalObject->inherits(JSDOMGlobalObject::info()))
1544 , m_ptr(buffer.data())
1545 , m_end(buffer.data() + buffer.size())
1546 , m_version(0xFFFFFFFF)
1547 , m_messagePorts(messagePorts)
1548 , m_arrayBufferContents(arrayBufferContents)
1549 , m_arrayBuffers(arrayBufferContents ? arrayBufferContents->size() : 0)
1551 if (!read(m_version))
1552 m_version = 0xFFFFFFFF;
1555 DeserializationResult deserialize();
1557 void throwValidationError()
1559 m_exec->vm().throwException(m_exec, createTypeError(m_exec, "Unable to deserialize data."));
1562 bool isValid() const { return m_version <= CurrentVersion; }
1564 template <typename T> bool readLittleEndian(T& value)
1566 if (m_failed || !readLittleEndian(m_ptr, m_end, value)) {
1572 #if ASSUME_LITTLE_ENDIAN
1573 template <typename T> static bool readLittleEndian(const uint8_t*& ptr, const uint8_t* end, T& value)
1575 if (ptr > end - sizeof(value))
1581 value = *reinterpret_cast<const T*>(ptr);
1587 template <typename T> static bool readLittleEndian(const uint8_t*& ptr, const uint8_t* end, T& value)
1589 if (ptr > end - sizeof(value))
1596 for (unsigned i = 0; i < sizeof(T); i++)
1597 value += ((T)*ptr++) << (i * 8);
1603 bool read(uint32_t& i)
1605 return readLittleEndian(i);
1608 bool read(int32_t& i)
1610 return readLittleEndian(*reinterpret_cast<uint32_t*>(&i));
1613 bool read(uint16_t& i)
1615 return readLittleEndian(i);
1618 bool read(uint8_t& i)
1620 return readLittleEndian(i);
1623 bool read(double& d)
1629 if (!readLittleEndian(u.i64))
1635 bool read(unsigned long long& i)
1637 return readLittleEndian(i);
1640 bool readStringIndex(uint32_t& i)
1642 return readConstantPoolIndex(m_constantPool, i);
1645 template <class T> bool readConstantPoolIndex(const T& constantPool, uint32_t& i)
1647 if (constantPool.size() <= 0xFF) {
1654 if (constantPool.size() <= 0xFFFF) {
1664 static bool readString(const uint8_t*& ptr, const uint8_t* end, String& str, unsigned length)
1666 if (length >= std::numeric_limits<int32_t>::max() / sizeof(UChar))
1669 unsigned size = length * sizeof(UChar);
1670 if ((end - ptr) < static_cast<int>(size))
1673 #if ASSUME_LITTLE_ENDIAN
1674 str = String(reinterpret_cast<const UChar*>(ptr), length);
1675 ptr += length * sizeof(UChar);
1677 Vector<UChar> buffer;
1678 buffer.reserveCapacity(length);
1679 for (unsigned i = 0; i < length; i++) {
1681 readLittleEndian(ptr, end, ch);
1684 str = String::adopt(buffer);
1689 bool readStringData(CachedStringRef& cachedString)
1692 return readStringData(cachedString, scratch);
1695 bool readStringData(CachedStringRef& cachedString, bool& wasTerminator)
1699 uint32_t length = 0;
1702 if (length == TerminatorTag) {
1703 wasTerminator = true;
1706 if (length == StringPoolTag) {
1708 if (!readStringIndex(index)) {
1712 if (index >= m_constantPool.size()) {
1716 cachedString = CachedStringRef(&m_constantPool, index);
1720 if (!readString(m_ptr, m_end, str, length)) {
1724 m_constantPool.append(str);
1725 cachedString = CachedStringRef(&m_constantPool, m_constantPool.size() - 1);
1729 SerializationTag readTag()
1733 return static_cast<SerializationTag>(*m_ptr++);
1736 bool readArrayBufferViewSubtag(ArrayBufferViewSubtag& tag)
1740 tag = static_cast<ArrayBufferViewSubtag>(*m_ptr++);
1744 void putProperty(JSObject* object, unsigned index, JSValue value)
1746 object->putDirectIndex(m_exec, index, value);
1749 void putProperty(JSObject* object, const Identifier& property, JSValue value)
1751 object->putDirectMayBeIndex(m_exec, property, value);
1754 bool readFile(RefPtr<File>& file)
1756 CachedStringRef path;
1757 if (!readStringData(path))
1759 CachedStringRef url;
1760 if (!readStringData(url))
1762 CachedStringRef type;
1763 if (!readStringData(type))
1765 CachedStringRef name;
1766 if (!readStringData(name))
1768 if (m_isDOMGlobalObject)
1769 file = File::deserialize(path->string(), URL(URL(), url->string()), type->string(), name->string());
1773 bool readArrayBuffer(RefPtr<ArrayBuffer>& arrayBuffer)
1778 if (m_ptr + length > m_end)
1780 arrayBuffer = ArrayBuffer::create(m_ptr, length);
1785 bool readArrayBufferView(JSValue& arrayBufferView)
1787 ArrayBufferViewSubtag arrayBufferViewSubtag;
1788 if (!readArrayBufferViewSubtag(arrayBufferViewSubtag))
1790 uint32_t byteOffset;
1791 if (!read(byteOffset))
1793 uint32_t byteLength;
1794 if (!read(byteLength))
1796 JSObject* arrayBufferObj = asObject(readTerminal());
1797 if (!arrayBufferObj || !arrayBufferObj->inherits(JSArrayBuffer::info()))
1800 unsigned elementSize = typedArrayElementSize(arrayBufferViewSubtag);
1803 unsigned length = byteLength / elementSize;
1804 if (length * elementSize != byteLength)
1807 RefPtr<ArrayBuffer> arrayBuffer = toArrayBuffer(arrayBufferObj);
1808 switch (arrayBufferViewSubtag) {
1810 arrayBufferView = getJSValue(DataView::create(arrayBuffer, byteOffset, length).get());
1813 arrayBufferView = getJSValue(Int8Array::create(arrayBuffer, byteOffset, length).get());
1816 arrayBufferView = getJSValue(Uint8Array::create(arrayBuffer, byteOffset, length).get());
1818 case Uint8ClampedArrayTag:
1819 arrayBufferView = getJSValue(Uint8ClampedArray::create(arrayBuffer, byteOffset, length).get());
1822 arrayBufferView = getJSValue(Int16Array::create(arrayBuffer, byteOffset, length).get());
1824 case Uint16ArrayTag:
1825 arrayBufferView = getJSValue(Uint16Array::create(arrayBuffer, byteOffset, length).get());
1828 arrayBufferView = getJSValue(Int32Array::create(arrayBuffer, byteOffset, length).get());
1830 case Uint32ArrayTag:
1831 arrayBufferView = getJSValue(Uint32Array::create(arrayBuffer, byteOffset, length).get());
1833 case Float32ArrayTag:
1834 arrayBufferView = getJSValue(Float32Array::create(arrayBuffer, byteOffset, length).get());
1836 case Float64ArrayTag:
1837 arrayBufferView = getJSValue(Float64Array::create(arrayBuffer, byteOffset, length).get());
1844 bool read(Vector<uint8_t>& result)
1846 ASSERT(result.isEmpty());
1850 if (m_ptr + size > m_end)
1852 result.append(m_ptr, size);
1857 #if ENABLE(SUBTLE_CRYPTO)
1858 bool read(CryptoAlgorithmIdentifier& result)
1860 uint8_t algorithmTag;
1861 if (!read(algorithmTag))
1863 if (algorithmTag > cryptoAlgorithmIdentifierTagMaximumValue)
1865 switch (static_cast<CryptoAlgorithmIdentifierTag>(algorithmTag)) {
1866 case CryptoAlgorithmIdentifierTag::RSAES_PKCS1_v1_5:
1867 result = CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5;
1869 case CryptoAlgorithmIdentifierTag::RSASSA_PKCS1_v1_5:
1870 result = CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5;
1872 case CryptoAlgorithmIdentifierTag::RSA_PSS:
1873 result = CryptoAlgorithmIdentifier::RSA_PSS;
1875 case CryptoAlgorithmIdentifierTag::RSA_OAEP:
1876 result = CryptoAlgorithmIdentifier::RSA_OAEP;
1878 case CryptoAlgorithmIdentifierTag::ECDSA:
1879 result = CryptoAlgorithmIdentifier::ECDSA;
1881 case CryptoAlgorithmIdentifierTag::ECDH:
1882 result = CryptoAlgorithmIdentifier::ECDH;
1884 case CryptoAlgorithmIdentifierTag::AES_CTR:
1885 result = CryptoAlgorithmIdentifier::AES_CTR;
1887 case CryptoAlgorithmIdentifierTag::AES_CBC:
1888 result = CryptoAlgorithmIdentifier::AES_CBC;
1890 case CryptoAlgorithmIdentifierTag::AES_CMAC:
1891 result = CryptoAlgorithmIdentifier::AES_CMAC;
1893 case CryptoAlgorithmIdentifierTag::AES_GCM:
1894 result = CryptoAlgorithmIdentifier::AES_GCM;
1896 case CryptoAlgorithmIdentifierTag::AES_CFB:
1897 result = CryptoAlgorithmIdentifier::AES_CFB;
1899 case CryptoAlgorithmIdentifierTag::AES_KW:
1900 result = CryptoAlgorithmIdentifier::AES_KW;
1902 case CryptoAlgorithmIdentifierTag::HMAC:
1903 result = CryptoAlgorithmIdentifier::HMAC;
1905 case CryptoAlgorithmIdentifierTag::DH:
1906 result = CryptoAlgorithmIdentifier::DH;
1908 case CryptoAlgorithmIdentifierTag::SHA_1:
1909 result = CryptoAlgorithmIdentifier::SHA_1;
1911 case CryptoAlgorithmIdentifierTag::SHA_224:
1912 result = CryptoAlgorithmIdentifier::SHA_224;
1914 case CryptoAlgorithmIdentifierTag::SHA_256:
1915 result = CryptoAlgorithmIdentifier::SHA_256;
1917 case CryptoAlgorithmIdentifierTag::SHA_384:
1918 result = CryptoAlgorithmIdentifier::SHA_384;
1920 case CryptoAlgorithmIdentifierTag::SHA_512:
1921 result = CryptoAlgorithmIdentifier::SHA_512;
1923 case CryptoAlgorithmIdentifierTag::CONCAT:
1924 result = CryptoAlgorithmIdentifier::CONCAT;
1926 case CryptoAlgorithmIdentifierTag::HKDF_CTR:
1927 result = CryptoAlgorithmIdentifier::HKDF_CTR;
1929 case CryptoAlgorithmIdentifierTag::PBKDF2:
1930 result = CryptoAlgorithmIdentifier::PBKDF2;
1936 bool read(CryptoKeyClassSubtag& result)
1941 if (tag > cryptoKeyClassSubtagMaximumValue)
1943 result = static_cast<CryptoKeyClassSubtag>(tag);
1947 bool read(CryptoKeyUsageTag& result)
1952 if (tag > cryptoKeyUsageTagMaximumValue)
1954 result = static_cast<CryptoKeyUsageTag>(tag);
1958 bool read(CryptoKeyAsymmetricTypeSubtag& result)
1963 if (tag > cryptoKeyAsymmetricTypeSubtagMaximumValue)
1965 result = static_cast<CryptoKeyAsymmetricTypeSubtag>(tag);
1969 bool readHMACKey(bool extractable, CryptoKeyUsage usages, RefPtr<CryptoKey>& result)
1971 Vector<uint8_t> keyData;
1974 CryptoAlgorithmIdentifier hash;
1977 result = CryptoKeyHMAC::create(keyData, hash, extractable, usages);
1981 bool readAESKey(bool extractable, CryptoKeyUsage usages, RefPtr<CryptoKey>& result)
1983 CryptoAlgorithmIdentifier algorithm;
1984 if (!read(algorithm))
1986 if (!CryptoKeyAES::isValidAESAlgorithm(algorithm))
1988 Vector<uint8_t> keyData;
1991 result = CryptoKeyAES::create(algorithm, keyData, extractable, usages);
1995 bool readRSAKey(bool extractable, CryptoKeyUsage usages, RefPtr<CryptoKey>& result)
1997 CryptoAlgorithmIdentifier algorithm;
1998 if (!read(algorithm))
2001 int32_t isRestrictedToHash;
2002 CryptoAlgorithmIdentifier hash;
2003 if (!read(isRestrictedToHash))
2005 if (isRestrictedToHash && !read(hash))
2008 CryptoKeyAsymmetricTypeSubtag type;
2012 Vector<uint8_t> modulus;
2015 Vector<uint8_t> exponent;
2016 if (!read(exponent))
2019 if (type == CryptoKeyAsymmetricTypeSubtag::Public) {
2020 auto keyData = CryptoKeyDataRSAComponents::createPublic(modulus, exponent);
2021 auto key = CryptoKeyRSA::create(algorithm, *keyData, extractable, usages);
2022 if (isRestrictedToHash)
2023 key->restrictToHash(hash);
2024 result = WTF::move(key);
2028 Vector<uint8_t> privateExponent;
2029 if (!read(privateExponent))
2032 uint32_t primeCount;
2033 if (!read(primeCount))
2037 auto keyData = CryptoKeyDataRSAComponents::createPrivate(modulus, exponent, privateExponent);
2038 auto key = CryptoKeyRSA::create(algorithm, *keyData, extractable, usages);
2039 if (isRestrictedToHash)
2040 key->restrictToHash(hash);
2041 result = WTF::move(key);
2048 CryptoKeyDataRSAComponents::PrimeInfo firstPrimeInfo;
2049 CryptoKeyDataRSAComponents::PrimeInfo secondPrimeInfo;
2050 Vector<CryptoKeyDataRSAComponents::PrimeInfo> otherPrimeInfos(primeCount - 2);
2052 if (!read(firstPrimeInfo.primeFactor))
2054 if (!read(firstPrimeInfo.factorCRTExponent))
2056 if (!read(secondPrimeInfo.primeFactor))
2058 if (!read(secondPrimeInfo.factorCRTExponent))
2060 if (!read(secondPrimeInfo.factorCRTCoefficient))
2062 for (unsigned i = 2; i < primeCount; ++i) {
2063 if (!read(otherPrimeInfos[i].primeFactor))
2065 if (!read(otherPrimeInfos[i].factorCRTExponent))
2067 if (!read(otherPrimeInfos[i].factorCRTCoefficient))
2071 auto keyData = CryptoKeyDataRSAComponents::createPrivateWithAdditionalData(modulus, exponent, privateExponent, firstPrimeInfo, secondPrimeInfo, otherPrimeInfos);
2072 auto key = CryptoKeyRSA::create(algorithm, *keyData, extractable, usages);
2073 if (isRestrictedToHash)
2074 key->restrictToHash(hash);
2075 result = WTF::move(key);
2079 bool readCryptoKey(JSValue& cryptoKey)
2081 uint32_t keyFormatVersion;
2082 if (!read(keyFormatVersion) || keyFormatVersion > currentKeyFormatVersion)
2085 int32_t extractable;
2086 if (!read(extractable))
2089 uint32_t usagesCount;
2090 if (!read(usagesCount))
2093 CryptoKeyUsage usages = 0;
2094 for (uint32_t i = 0; i < usagesCount; ++i) {
2095 CryptoKeyUsageTag usage;
2099 case CryptoKeyUsageTag::Encrypt:
2100 usages |= CryptoKeyUsageEncrypt;
2102 case CryptoKeyUsageTag::Decrypt:
2103 usages |= CryptoKeyUsageDecrypt;
2105 case CryptoKeyUsageTag::Sign:
2106 usages |= CryptoKeyUsageSign;
2108 case CryptoKeyUsageTag::Verify:
2109 usages |= CryptoKeyUsageVerify;
2111 case CryptoKeyUsageTag::DeriveKey:
2112 usages |= CryptoKeyUsageDeriveKey;
2114 case CryptoKeyUsageTag::DeriveBits:
2115 usages |= CryptoKeyUsageDeriveBits;
2117 case CryptoKeyUsageTag::WrapKey:
2118 usages |= CryptoKeyUsageWrapKey;
2120 case CryptoKeyUsageTag::UnwrapKey:
2121 usages |= CryptoKeyUsageUnwrapKey;
2126 CryptoKeyClassSubtag cryptoKeyClass;
2127 if (!read(cryptoKeyClass))
2129 RefPtr<CryptoKey> result;
2130 switch (cryptoKeyClass) {
2131 case CryptoKeyClassSubtag::HMAC:
2132 if (!readHMACKey(extractable, usages, result))
2135 case CryptoKeyClassSubtag::AES:
2136 if (!readAESKey(extractable, usages, result))
2139 case CryptoKeyClassSubtag::RSA:
2140 if (!readRSAKey(extractable, usages, result))
2144 cryptoKey = getJSValue(result.get());
2150 JSValue getJSValue(T* nativeObj)
2152 return toJS(m_exec, jsCast<JSDOMGlobalObject*>(m_globalObject), nativeObj);
2156 JSValue getJSValue(T& nativeObj)
2158 return getJSValue(&nativeObj);
2161 JSValue readTerminal()
2163 SerializationTag tag = readTag();
2166 return jsUndefined();
2180 return jsBoolean(false);
2182 return jsBoolean(true);
2183 case FalseObjectTag: {
2184 BooleanObject* obj = BooleanObject::create(m_exec->vm(), m_globalObject->booleanObjectStructure());
2185 obj->setInternalValue(m_exec->vm(), jsBoolean(false));
2186 m_gcBuffer.append(obj);
2189 case TrueObjectTag: {
2190 BooleanObject* obj = BooleanObject::create(m_exec->vm(), m_globalObject->booleanObjectStructure());
2191 obj->setInternalValue(m_exec->vm(), jsBoolean(true));
2192 m_gcBuffer.append(obj);
2201 case NumberObjectTag: {
2205 NumberObject* obj = constructNumber(m_exec, m_globalObject, jsNumber(d));
2206 m_gcBuffer.append(obj);
2213 return DateInstance::create(m_exec->vm(), m_globalObject->dateStructure(), d);
2217 if (!readFile(file))
2219 if (!m_isDOMGlobalObject)
2221 return toJS(m_exec, jsCast<JSDOMGlobalObject*>(m_globalObject), file.get());
2224 unsigned length = 0;
2227 Vector<RefPtr<File>> files;
2228 for (unsigned i = 0; i < length; i++) {
2230 if (!readFile(file))
2232 if (m_isDOMGlobalObject)
2233 files.append(WTF::move(file));
2235 if (!m_isDOMGlobalObject)
2237 return getJSValue(FileList::create(WTF::move(files)).get());
2239 case ImageDataTag: {
2249 if (m_end < ((uint8_t*)0) + length || m_ptr > m_end - length) {
2253 if (!m_isDOMGlobalObject) {
2257 RefPtr<ImageData> result = ImageData::create(IntSize(width, height));
2258 memcpy(result->data()->data(), m_ptr, length);
2260 return getJSValue(result.get());
2263 CachedStringRef url;
2264 if (!readStringData(url))
2266 CachedStringRef type;
2267 if (!readStringData(type))
2269 unsigned long long size = 0;
2272 if (!m_isDOMGlobalObject)
2274 return getJSValue(Blob::deserialize(URL(URL(), url->string()), type->string(), size).get());
2277 CachedStringRef cachedString;
2278 if (!readStringData(cachedString))
2280 return cachedString->jsString(m_exec);
2282 case EmptyStringTag:
2283 return jsEmptyString(&m_exec->vm());
2284 case StringObjectTag: {
2285 CachedStringRef cachedString;
2286 if (!readStringData(cachedString))
2288 StringObject* obj = constructString(m_exec->vm(), m_globalObject, cachedString->jsString(m_exec));
2289 m_gcBuffer.append(obj);
2292 case EmptyStringObjectTag: {
2293 VM& vm = m_exec->vm();
2294 StringObject* obj = constructString(vm, m_globalObject, jsEmptyString(&vm));
2295 m_gcBuffer.append(obj);
2299 CachedStringRef pattern;
2300 if (!readStringData(pattern))
2302 CachedStringRef flags;
2303 if (!readStringData(flags))
2305 RegExpFlags reFlags = regExpFlags(flags->string());
2306 ASSERT(reFlags != InvalidFlags);
2307 VM& vm = m_exec->vm();
2308 RegExp* regExp = RegExp::create(vm, pattern->string(), reFlags);
2309 return RegExpObject::create(vm, m_globalObject->regExpStructure(), regExp);
2311 case ObjectReferenceTag: {
2313 if (!readConstantPoolIndex(m_gcBuffer, index)) {
2317 return m_gcBuffer.at(index);
2319 case MessagePortReferenceTag: {
2321 bool indexSuccessfullyRead = read(index);
2322 if (!indexSuccessfullyRead || !m_messagePorts || index >= m_messagePorts->size()) {
2326 return getJSValue(m_messagePorts->at(index).get());
2328 case ArrayBufferTag: {
2329 RefPtr<ArrayBuffer> arrayBuffer;
2330 if (!readArrayBuffer(arrayBuffer)) {
2334 JSValue result = getJSValue(arrayBuffer.get());
2335 m_gcBuffer.append(result);
2338 case ArrayBufferTransferTag: {
2340 bool indexSuccessfullyRead = read(index);
2341 if (!indexSuccessfullyRead || index >= m_arrayBuffers.size()) {
2346 if (!m_arrayBuffers[index])
2347 m_arrayBuffers[index] = ArrayBuffer::create(m_arrayBufferContents->at(index));
2349 return getJSValue(m_arrayBuffers[index].get());
2351 case ArrayBufferViewTag: {
2352 JSValue arrayBufferView;
2353 if (!readArrayBufferView(arrayBufferView)) {
2357 m_gcBuffer.append(arrayBufferView);
2358 return arrayBufferView;
2360 #if ENABLE(SUBTLE_CRYPTO)
2361 case CryptoKeyTag: {
2362 Vector<uint8_t> wrappedKey;
2363 if (!read(wrappedKey)) {
2367 Vector<uint8_t> serializedKey;
2368 if (!unwrapCryptoKey(m_exec, wrappedKey, serializedKey)) {
2373 CloneDeserializer rawKeyDeserializer(m_exec, m_globalObject, nullptr, nullptr, serializedKey);
2374 if (!rawKeyDeserializer.readCryptoKey(cryptoKey)) {
2378 m_gcBuffer.append(cryptoKey);
2383 m_ptr--; // Push the tag back
2388 template<SerializationTag Tag>
2389 bool consumeCollectionDataTerminationIfPossible()
2391 if (readTag() == Tag)
2397 JSGlobalObject* m_globalObject;
2398 bool m_isDOMGlobalObject;
2399 const uint8_t* m_ptr;
2400 const uint8_t* m_end;
2402 Vector<CachedString> m_constantPool;
2403 MessagePortArray* m_messagePorts;
2404 ArrayBufferContentsArray* m_arrayBufferContents;
2405 ArrayBufferArray m_arrayBuffers;
2408 DeserializationResult CloneDeserializer::deserialize()
2410 Vector<uint32_t, 16> indexStack;
2411 Vector<Identifier, 16> propertyNameStack;
2412 Vector<JSObject*, 32> outputObjectStack;
2413 Vector<JSValue, 4> mapKeyStack;
2414 Vector<JSMap*, 4> mapStack;
2415 Vector<JSSet*, 4> setStack;
2416 Vector<WalkerState, 16> stateStack;
2417 WalkerState state = StateUnknown;
2423 case ArrayStartState: {
2425 if (!read(length)) {
2429 JSArray* outArray = constructEmptyArray(m_exec, 0, m_globalObject, length);
2430 m_gcBuffer.append(outArray);
2431 outputObjectStack.append(outArray);
2433 arrayStartVisitMember:
2435 case ArrayStartVisitMember: {
2441 if (index == TerminatorTag) {
2442 JSObject* outArray = outputObjectStack.last();
2443 outValue = outArray;
2444 outputObjectStack.removeLast();
2446 } else if (index == NonIndexPropertiesTag) {
2447 goto objectStartVisitMember;
2450 if (JSValue terminal = readTerminal()) {
2451 putProperty(outputObjectStack.last(), index, terminal);
2452 goto arrayStartVisitMember;
2456 indexStack.append(index);
2457 stateStack.append(ArrayEndVisitMember);
2460 case ArrayEndVisitMember: {
2461 JSObject* outArray = outputObjectStack.last();
2462 putProperty(outArray, indexStack.last(), outValue);
2463 indexStack.removeLast();
2464 goto arrayStartVisitMember;
2467 case ObjectStartState: {
2468 if (outputObjectStack.size() > maximumFilterRecursion)
2469 return std::make_pair(JSValue(), StackOverflowError);
2470 JSObject* outObject = constructEmptyObject(m_exec, m_globalObject->objectPrototype());
2471 m_gcBuffer.append(outObject);
2472 outputObjectStack.append(outObject);
2474 objectStartVisitMember:
2476 case ObjectStartVisitMember: {
2477 CachedStringRef cachedString;
2478 bool wasTerminator = false;
2479 if (!readStringData(cachedString, wasTerminator)) {
2483 JSObject* outObject = outputObjectStack.last();
2484 outValue = outObject;
2485 outputObjectStack.removeLast();
2489 if (JSValue terminal = readTerminal()) {
2490 putProperty(outputObjectStack.last(), Identifier::fromString(m_exec, cachedString->string()), terminal);
2491 goto objectStartVisitMember;
2493 stateStack.append(ObjectEndVisitMember);
2494 propertyNameStack.append(Identifier::fromString(m_exec, cachedString->string()));
2497 case ObjectEndVisitMember: {
2498 putProperty(outputObjectStack.last(), propertyNameStack.last(), outValue);
2499 propertyNameStack.removeLast();
2500 goto objectStartVisitMember;
2502 mapObjectStartState: {
2503 if (outputObjectStack.size() > maximumFilterRecursion)
2504 return std::make_pair(JSValue(), StackOverflowError);
2505 JSMap* map = JSMap::create(m_exec->vm(), m_globalObject->mapStructure());
2506 m_gcBuffer.append(map);
2507 outputObjectStack.append(map);
2508 mapStack.append(map);
2509 goto mapDataStartVisitEntry;
2511 mapDataStartVisitEntry:
2512 case MapDataStartVisitEntry: {
2513 if (consumeCollectionDataTerminationIfPossible<NonMapPropertiesTag>()) {
2514 mapStack.removeLast();
2515 goto objectStartVisitMember;
2517 stateStack.append(MapDataEndVisitKey);
2520 case MapDataEndVisitKey: {
2521 mapKeyStack.append(outValue);
2522 stateStack.append(MapDataEndVisitValue);
2525 case MapDataEndVisitValue: {
2526 mapStack.last()->set(m_exec, mapKeyStack.last(), outValue);
2527 mapKeyStack.removeLast();
2528 goto mapDataStartVisitEntry;
2531 setObjectStartState: {
2532 if (outputObjectStack.size() > maximumFilterRecursion)
2533 return std::make_pair(JSValue(), StackOverflowError);
2534 JSSet* set = JSSet::create(m_exec->vm(), m_globalObject->setStructure());
2535 m_gcBuffer.append(set);
2536 outputObjectStack.append(set);
2537 setStack.append(set);
2538 goto setDataStartVisitEntry;
2540 setDataStartVisitEntry:
2541 case SetDataStartVisitEntry: {
2542 if (consumeCollectionDataTerminationIfPossible<NonSetPropertiesTag>()) {
2543 setStack.removeLast();
2544 goto objectStartVisitMember;
2546 stateStack.append(SetDataEndVisitKey);
2549 case SetDataEndVisitKey: {
2550 JSSet* set = setStack.last();
2551 set->add(m_exec, outValue);
2552 goto setDataStartVisitEntry;
2557 if (JSValue terminal = readTerminal()) {
2558 outValue = terminal;
2561 SerializationTag tag = readTag();
2562 if (tag == ArrayTag)
2563 goto arrayStartState;
2564 if (tag == ObjectTag)
2565 goto objectStartState;
2566 if (tag == MapObjectTag)
2567 goto mapObjectStartState;
2568 if (tag == SetObjectTag)
2569 goto setObjectStartState;
2572 if (stateStack.isEmpty())
2575 state = stateStack.last();
2576 stateStack.removeLast();
2580 return std::make_pair(outValue, SuccessfullyCompleted);
2583 return std::make_pair(JSValue(), ValidationError);
2586 void SerializedScriptValue::addBlobURL(const String& string)
2588 m_blobURLs.append(Vector<uint16_t>());
2589 m_blobURLs.last().reserveCapacity(string.length());
2590 for (size_t i = 0; i < string.length(); i++)
2591 m_blobURLs.last().append(string.characterAt(i));
2592 m_blobURLs.last().resize(m_blobURLs.last().size());
2595 SerializedScriptValue::~SerializedScriptValue()
2599 SerializedScriptValue::SerializedScriptValue(const Vector<uint8_t>& buffer)
2604 SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer)
2606 m_data.swap(buffer);
2609 SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer, Vector<String>& blobURLs)
2611 m_data.swap(buffer);
2612 for (auto& string : blobURLs)
2616 SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer, Vector<String>& blobURLs, std::unique_ptr<ArrayBufferContentsArray> arrayBufferContentsArray)
2617 : m_arrayBufferContentsArray(WTF::move(arrayBufferContentsArray))
2619 m_data.swap(buffer);
2620 for (auto& string : blobURLs)
2624 std::unique_ptr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValue::transferArrayBuffers(
2625 ExecState* exec, ArrayBufferArray& arrayBuffers, SerializationReturnCode& code)
2627 for (size_t i = 0; i < arrayBuffers.size(); i++) {
2628 if (arrayBuffers[i]->isNeutered()) {
2629 code = ValidationError;
2634 auto contents = std::make_unique<ArrayBufferContentsArray>(arrayBuffers.size());
2635 Vector<Ref<DOMWrapperWorld>> worlds;
2636 static_cast<WebCoreJSClientData*>(exec->vm().clientData)->getAllWorlds(worlds);
2638 HashSet<JSC::ArrayBuffer*> visited;
2639 for (size_t arrayBufferIndex = 0; arrayBufferIndex < arrayBuffers.size(); arrayBufferIndex++) {
2640 if (visited.contains(arrayBuffers[arrayBufferIndex].get()))
2642 visited.add(arrayBuffers[arrayBufferIndex].get());
2644 bool result = arrayBuffers[arrayBufferIndex]->transfer(contents->at(arrayBufferIndex));
2646 code = ValidationError;
2653 RefPtr<SerializedScriptValue> SerializedScriptValue::create(ExecState* exec, JSValue value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, SerializationErrorMode throwExceptions)
2655 Vector<uint8_t> buffer;
2656 Vector<String> blobURLs;
2657 SerializationReturnCode code = CloneSerializer::serialize(exec, value, messagePorts, arrayBuffers, blobURLs, buffer);
2659 std::unique_ptr<ArrayBufferContentsArray> arrayBufferContentsArray;
2661 if (arrayBuffers && serializationDidCompleteSuccessfully(code))
2662 arrayBufferContentsArray = transferArrayBuffers(exec, *arrayBuffers, code);
2664 if (throwExceptions == Throwing)
2665 maybeThrowExceptionIfSerializationFailed(exec, code);
2667 if (!serializationDidCompleteSuccessfully(code))
2670 return adoptRef(*new SerializedScriptValue(buffer, blobURLs, WTF::move(arrayBufferContentsArray)));
2673 RefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& string)
2675 Vector<uint8_t> buffer;
2676 if (!CloneSerializer::serialize(string, buffer))
2678 return adoptRef(*new SerializedScriptValue(buffer));
2681 #if ENABLE(INDEXED_DATABASE)
2682 Ref<SerializedScriptValue> SerializedScriptValue::numberValue(double value)
2684 Vector<uint8_t> buffer;
2685 CloneSerializer::serializeNumber(value, buffer);
2686 return adoptRef(*new SerializedScriptValue(buffer));
2689 Ref<SerializedScriptValue> SerializedScriptValue::undefinedValue()
2691 Vector<uint8_t> buffer;
2692 CloneSerializer::serializeUndefined(buffer);
2693 return adoptRef(*new SerializedScriptValue(buffer));
2697 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(JSContextRef originContext, JSValueRef apiValue, JSValueRef* exception)
2699 ExecState* exec = toJS(originContext);
2700 JSLockHolder locker(exec);
2701 JSValue value = toJS(exec, apiValue);
2702 RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::create(exec, value, nullptr, nullptr);
2703 if (exec->hadException()) {
2705 *exception = toRef(exec, exec->exception());
2706 exec->clearException();
2709 ASSERT(serializedValue);
2710 return serializedValue.release();
2713 String SerializedScriptValue::toString()
2715 return CloneDeserializer::deserializeString(m_data);
2718 JSValue SerializedScriptValue::deserialize(ExecState* exec, JSGlobalObject* globalObject,
2719 MessagePortArray* messagePorts, SerializationErrorMode throwExceptions)
2721 DeserializationResult result = CloneDeserializer::deserialize(exec, globalObject, messagePorts,
2722 m_arrayBufferContentsArray.get(), m_data);
2723 if (throwExceptions == Throwing)
2724 maybeThrowExceptionIfSerializationFailed(exec, result.second);
2725 return result.first ? result.first : jsNull();
2728 JSValueRef SerializedScriptValue::deserialize(JSContextRef destinationContext, JSValueRef* exception)
2730 ExecState* exec = toJS(destinationContext);
2731 JSLockHolder locker(exec);
2732 JSValue value = deserialize(exec, exec->lexicalGlobalObject(), nullptr);
2733 if (exec->hadException()) {
2735 *exception = toRef(exec, exec->exception());
2736 exec->clearException();
2740 return toRef(exec, value);
2743 Ref<SerializedScriptValue> SerializedScriptValue::nullValue()
2745 Vector<uint8_t> buffer;
2746 return adoptRef(*new SerializedScriptValue(buffer));
2749 void SerializedScriptValue::maybeThrowExceptionIfSerializationFailed(ExecState* exec, SerializationReturnCode code)
2751 if (code == SuccessfullyCompleted)
2755 case StackOverflowError:
2756 exec->vm().throwException(exec, createStackOverflowError(exec));
2758 case ValidationError:
2759 exec->vm().throwException(exec, createTypeError(exec, "Unable to deserialize data."));
2761 case DataCloneError:
2762 setDOMException(exec, DATA_CLONE_ERR);
2764 case ExistingExceptionError:
2766 case UnspecifiedError:
2769 ASSERT_NOT_REACHED();
2773 bool SerializedScriptValue::serializationDidCompleteSuccessfully(SerializationReturnCode code)
2775 return (code == SuccessfullyCompleted);
2778 uint32_t SerializedScriptValue::wireFormatVersion()
2780 return CurrentVersion;