| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef ScriptValueSerializer_h |
| #define ScriptValueSerializer_h |
| |
| #include "base/gtest_prod_util.h" |
| #include "bindings/core/v8/SerializationTag.h" |
| #include "bindings/core/v8/SerializedScriptValue.h" |
| #include "bindings/core/v8/V8Binding.h" |
| #include "core/CoreExport.h" |
| #include "wtf/HashMap.h" |
| #include "wtf/Noncopyable.h" |
| #include "wtf/Vector.h" |
| #include "wtf/text/WTFString.h" |
| #include "wtf/typed_arrays/ArrayBufferContents.h" |
| #include <v8.h> |
| |
| namespace blink { |
| |
| class CompositorProxy; |
| class DOMArrayBuffer; |
| class DOMArrayBufferView; |
| class DOMSharedArrayBuffer; |
| class File; |
| class FileList; |
| class ImageData; |
| class StaticBitmapImage; |
| |
| typedef Vector<WTF::ArrayBufferContents, 1> ArrayBufferContentsArray; |
| typedef Vector<RefPtr<StaticBitmapImage>, 1> ImageBitmapContentsArray; |
| |
| // V8ObjectMap is a map from V8 objects to arbitrary values of type T. |
| // V8 objects (or handles to V8 objects) cannot be used as keys in ordinary |
| // wtf::HashMaps; this class should be used instead. GCObject must be a subtype |
| // of v8::Object. |
| // Suggested usage: |
| // V8ObjectMap<v8::Object, int> map; |
| // v8::Local<v8::Object> obj = ...; |
| // map.set(obj, 42); |
| template <typename GCObject, typename T> |
| class V8ObjectMap { |
| STACK_ALLOCATED(); |
| |
| public: |
| bool contains(const v8::Local<GCObject>& handle) { |
| return m_map.contains(*handle); |
| } |
| |
| bool tryGet(const v8::Local<GCObject>& handle, T* valueOut) { |
| typename HandleToT::iterator result = m_map.find(*handle); |
| if (result != m_map.end()) { |
| *valueOut = result->value; |
| return true; |
| } |
| return false; |
| } |
| |
| void set(const v8::Local<GCObject>& handle, const T& value) { |
| m_map.set(*handle, value); |
| } |
| |
| private: |
| // This implementation uses GetIdentityHash(), which sets a hidden property on |
| // the object containing a random integer (or returns the one that had been |
| // previously set). This ensures that the table never needs to be rebuilt |
| // across garbage collections at the expense of doing additional allocation |
| // and making more round trips into V8. Note that since GetIdentityHash() is |
| // defined only on v8::Objects, this V8ObjectMap cannot be used to map |
| // v8::Strings to T (because the public V8 API considers a v8::String to be a |
| // v8::Primitive). |
| |
| // If V8 exposes a way to get at the address of the object held by a handle, |
| // then we can produce an alternate implementation that does not need to do |
| // any V8-side allocation; however, it will need to rehash after every garbage |
| // collection because a key object may have been moved. |
| template <typename G> |
| struct V8HandlePtrHash { |
| STATIC_ONLY(V8HandlePtrHash); |
| static v8::Local<G> unsafeHandleFromRawValue(const G* value) { |
| const v8::Local<G>* handle = |
| reinterpret_cast<const v8::Local<G>*>(&value); |
| return *handle; |
| } |
| |
| static unsigned hash(const G* key) { |
| return static_cast<unsigned>( |
| unsafeHandleFromRawValue(key)->GetIdentityHash()); |
| } |
| static bool equal(const G* a, const G* b) { |
| return unsafeHandleFromRawValue(a) == unsafeHandleFromRawValue(b); |
| } |
| // For HashArg. |
| static const bool safeToCompareToEmptyOrDeleted = false; |
| }; |
| |
| typedef WTF::HashMap<GCObject*, T, V8HandlePtrHash<GCObject>> HandleToT; |
| HandleToT m_map; |
| }; |
| |
| // SerializedScriptValueWriter is responsible for serializing primitive types |
| // and storing information used to reconstruct composite types. |
| class CORE_EXPORT SerializedScriptValueWriter { |
| STACK_ALLOCATED(); |
| WTF_MAKE_NONCOPYABLE(SerializedScriptValueWriter); |
| |
| public: |
| typedef UChar BufferValueType; |
| |
| SerializedScriptValueWriter() : m_position(0) {} |
| |
| protected: |
| friend class ScriptValueSerializer; |
| |
| String takeWireString(); |
| |
| // Write functions for primitive types. |
| void writeUndefined(); |
| void writeNull(); |
| void writeTrue(); |
| void writeFalse(); |
| void writeBooleanObject(bool value); |
| void writeOneByteString(v8::Local<v8::String>&); |
| void writeUCharString(v8::Local<v8::String>&); |
| void writeStringObject(const char* data, int length); |
| void writeWebCoreString(const String&); |
| void writeVersion(); |
| void writeInt32(int32_t value); |
| void writeUint32(uint32_t value); |
| void writeDate(double numberValue); |
| void writeNumber(double number); |
| void writeNumberObject(double number); |
| void writeBlob(const String& uuid, |
| const String& type, |
| unsigned long long size); |
| void writeBlobIndex(int blobIndex); |
| void writeCompositorProxy(const CompositorProxy&); |
| void writeFile(const File&); |
| void writeFileIndex(int blobIndex); |
| void writeFileList(const FileList&); |
| void writeFileListIndex(const Vector<int>& blobIndices); |
| void writeArrayBuffer(const DOMArrayBuffer&); |
| void writeArrayBufferView(const DOMArrayBufferView&); |
| void doWriteImageData(uint32_t width, |
| uint32_t height, |
| const uint8_t* pixelData, |
| uint32_t pixelDataLength); |
| void writeImageData(uint32_t width, |
| uint32_t height, |
| const uint8_t* pixelData, |
| uint32_t pixelDataLength); |
| void writeImageBitmap(uint32_t width, |
| uint32_t height, |
| uint32_t isOriginClean, |
| uint32_t isPremultiplied, |
| const uint8_t* pixelData, |
| uint32_t pixelDataLength); |
| void writeRegExp(v8::Local<v8::String> pattern, v8::RegExp::Flags); |
| void writeTransferredMessagePort(uint32_t index); |
| void writeTransferredArrayBuffer(uint32_t index); |
| void writeTransferredImageBitmap(uint32_t index); |
| void writeTransferredOffscreenCanvas(uint32_t width, |
| uint32_t height, |
| uint32_t canvasId, |
| uint32_t clientId, |
| uint32_t localId, |
| uint64_t nonce); |
| void writeTransferredSharedArrayBuffer(uint32_t index); |
| void writeObjectReference(uint32_t reference); |
| void writeObject(uint32_t numProperties); |
| void writeSparseArray(uint32_t numProperties, uint32_t length); |
| void writeDenseArray(uint32_t numProperties, uint32_t length); |
| void writeReferenceCount(uint32_t numberOfReferences); |
| void writeGenerateFreshObject(); |
| void writeGenerateFreshSparseArray(uint32_t length); |
| void writeGenerateFreshDenseArray(uint32_t length); |
| void writeGenerateFreshMap(); |
| void writeGenerateFreshSet(); |
| void writeMap(uint32_t length); |
| void writeSet(uint32_t length); |
| |
| void doWriteFile(const File&); |
| void doWriteArrayBuffer(const DOMArrayBuffer&); |
| void doWriteString(const char* data, int length); |
| void doWriteWebCoreString(const String&); |
| int bytesNeededToWireEncode(uint32_t value); |
| |
| template <class T> |
| void doWriteUintHelper(T value) { |
| while (true) { |
| uint8_t b = (value & SerializedScriptValue::varIntMask); |
| value >>= SerializedScriptValue::varIntShift; |
| if (!value) { |
| append(b); |
| break; |
| } |
| append(b | (1 << SerializedScriptValue::varIntShift)); |
| } |
| } |
| |
| void doWriteUint32(uint32_t value); |
| void doWriteUint64(uint64_t value); |
| void doWriteNumber(double number); |
| void append(SerializationTag); |
| void append(uint8_t b); |
| void append(const uint8_t* data, int length); |
| void ensureSpace(unsigned extra); |
| void fillHole(); |
| uint8_t* byteAt(int position); |
| int v8StringWriteOptions(); |
| |
| private: |
| Vector<BufferValueType> m_buffer; |
| unsigned m_position; |
| }; |
| |
| class CORE_EXPORT ScriptValueSerializer { |
| STACK_ALLOCATED(); |
| WTF_MAKE_NONCOPYABLE(ScriptValueSerializer); |
| |
| protected: |
| class StateBase; |
| enum class Status { Success, InputError, DataCloneError, JSException }; |
| |
| public: |
| ScriptValueSerializer(SerializedScriptValueWriter&, |
| WebBlobInfoArray*, |
| ScriptState*); |
| v8::Isolate* isolate() { return m_scriptState->isolate(); } |
| v8::Local<v8::Context> context() { return m_scriptState->context(); } |
| |
| PassRefPtr<SerializedScriptValue> serialize(v8::Local<v8::Value>, |
| Transferables*, |
| ExceptionState&); |
| |
| static String serializeWTFString(const String&); |
| static String serializeNullValue(); |
| |
| protected: |
| class StateBase { |
| USING_FAST_MALLOC(StateBase); |
| WTF_MAKE_NONCOPYABLE(StateBase); |
| |
| public: |
| virtual ~StateBase() {} |
| |
| // Link to the next state to form a stack. |
| StateBase* nextState() { return m_next; } |
| |
| // Composite object we're processing in this state. |
| v8::Local<v8::Value> composite() { return m_composite; } |
| |
| // Serializes (a part of) the current composite and returns |
| // the next state to process or null when this is the final |
| // state. |
| virtual StateBase* advance(ScriptValueSerializer&) = 0; |
| |
| protected: |
| StateBase(v8::Local<v8::Value> composite, StateBase* next) |
| : m_composite(composite), m_next(next) {} |
| |
| private: |
| v8::Local<v8::Value> m_composite; |
| StateBase* m_next; |
| }; |
| |
| // Dummy state that is used to signal serialization errors. |
| class ErrorState final : public StateBase { |
| public: |
| ErrorState() : StateBase(v8Undefined(), 0) {} |
| |
| StateBase* advance(ScriptValueSerializer&) override { |
| delete this; |
| return 0; |
| } |
| }; |
| |
| template <typename T> |
| class State : public StateBase { |
| public: |
| v8::Local<T> composite() { |
| return v8::Local<T>::Cast(StateBase::composite()); |
| } |
| |
| protected: |
| State(v8::Local<T> composite, StateBase* next) |
| : StateBase(composite, next) {} |
| }; |
| |
| class AbstractObjectState : public State<v8::Object> { |
| public: |
| AbstractObjectState(v8::Local<v8::Object> object, StateBase* next) |
| : State<v8::Object>(object, next), |
| m_index(0), |
| m_numSerializedProperties(0) {} |
| |
| protected: |
| virtual StateBase* objectDone(unsigned numProperties, |
| ScriptValueSerializer&) = 0; |
| |
| StateBase* serializeProperties(ScriptValueSerializer&); |
| v8::Local<v8::Array> m_propertyNames; |
| |
| private: |
| unsigned m_index; |
| unsigned m_numSerializedProperties; |
| }; |
| |
| class ObjectState final : public AbstractObjectState { |
| public: |
| ObjectState(v8::Local<v8::Object> object, StateBase* next) |
| : AbstractObjectState(object, next) {} |
| |
| StateBase* advance(ScriptValueSerializer&) override; |
| |
| protected: |
| StateBase* objectDone(unsigned numProperties, |
| ScriptValueSerializer&) override; |
| }; |
| |
| class DenseArrayState final : public AbstractObjectState { |
| public: |
| DenseArrayState(v8::Local<v8::Array> array, |
| v8::Local<v8::Array> propertyNames, |
| StateBase* next, |
| v8::Isolate* isolate) |
| : AbstractObjectState(array, next), |
| m_arrayIndex(0), |
| m_arrayLength(array->Length()) { |
| m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames); |
| } |
| |
| StateBase* advance(ScriptValueSerializer&) override; |
| |
| protected: |
| StateBase* objectDone(unsigned numProperties, |
| ScriptValueSerializer&) override; |
| |
| private: |
| uint32_t m_arrayIndex; |
| uint32_t m_arrayLength; |
| }; |
| |
| class SparseArrayState final : public AbstractObjectState { |
| public: |
| SparseArrayState(v8::Local<v8::Array> array, |
| v8::Local<v8::Array> propertyNames, |
| StateBase* next, |
| v8::Isolate* isolate) |
| : AbstractObjectState(array, next) { |
| m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames); |
| } |
| |
| StateBase* advance(ScriptValueSerializer&) override; |
| |
| protected: |
| StateBase* objectDone(unsigned numProperties, |
| ScriptValueSerializer&) override; |
| }; |
| |
| template <typename T> |
| class CollectionState : public State<T> { |
| public: |
| CollectionState(v8::Local<T> collection, StateBase* next) |
| : State<T>(collection, next), |
| m_entries(collection->AsArray()), |
| m_index(0), |
| m_length(m_entries->Length()) {} |
| |
| StateBase* advance(ScriptValueSerializer&) override; |
| |
| private: |
| v8::Local<v8::Array> m_entries; |
| uint32_t m_index; |
| uint32_t m_length; |
| }; |
| |
| typedef CollectionState<v8::Map> MapState; |
| typedef CollectionState<v8::Set> SetState; |
| |
| virtual StateBase* doSerializeObject(v8::Local<v8::Object>, StateBase* next); |
| |
| // Marks object as having been visited by the serializer and assigns it a |
| // unique object reference ID. An object may only be greyed once. |
| void greyObject(const v8::Local<v8::Object>&); |
| |
| StateBase* handleError(Status errorStatus, const String& message, StateBase*); |
| |
| SerializedScriptValueWriter& writer() { return m_writer; } |
| |
| private: |
| StateBase* doSerialize(v8::Local<v8::Value>, StateBase* next); |
| StateBase* doSerializeArrayBuffer(v8::Local<v8::Value> arrayBuffer, |
| StateBase* next); |
| void transferData(Transferables*, ExceptionState&, SerializedScriptValue*); |
| |
| StateBase* checkException(StateBase*); |
| StateBase* writeObject(uint32_t numProperties, StateBase*); |
| StateBase* writeSparseArray(uint32_t numProperties, |
| uint32_t length, |
| StateBase*); |
| StateBase* writeDenseArray(uint32_t numProperties, |
| uint32_t length, |
| StateBase*); |
| |
| template <typename T> |
| StateBase* writeCollection(uint32_t length, StateBase*); |
| |
| StateBase* push(StateBase* state) { |
| ASSERT(state); |
| ++m_depth; |
| return checkComposite(state) ? state |
| : handleError(Status::InputError, |
| "Value being cloned is either " |
| "cyclic or too deeply nested.", |
| state); |
| } |
| |
| StateBase* pop(StateBase* state) { |
| ASSERT(state); |
| --m_depth; |
| StateBase* next = state->nextState(); |
| delete state; |
| return next; |
| } |
| |
| bool checkComposite(StateBase* top); |
| void writeString(v8::Local<v8::Value>); |
| void writeStringObject(v8::Local<v8::Value>); |
| void writeNumberObject(v8::Local<v8::Value>); |
| void writeBooleanObject(v8::Local<v8::Value>); |
| StateBase* writeBlob(v8::Local<v8::Value>, StateBase* next); |
| StateBase* writeCompositorProxy(v8::Local<v8::Value>, StateBase* next); |
| StateBase* writeFile(v8::Local<v8::Value>, StateBase* next); |
| StateBase* writeFileList(v8::Local<v8::Value>, StateBase* next); |
| void writeImageData(v8::Local<v8::Value>); |
| StateBase* writeAndGreyImageBitmap(v8::Local<v8::Object>, StateBase* next); |
| void writeRegExp(v8::Local<v8::Value>); |
| StateBase* writeAndGreyArrayBufferView(v8::Local<v8::Object>, |
| StateBase* next); |
| StateBase* writeWasmCompiledModule(v8::Local<v8::Object>, StateBase* next); |
| StateBase* writeAndGreyArrayBuffer(v8::Local<v8::Object>, StateBase* next); |
| StateBase* writeTransferredOffscreenCanvas(v8::Local<v8::Value>, |
| StateBase* next); |
| StateBase* writeTransferredSharedArrayBuffer(v8::Local<v8::Value>, |
| uint32_t index, |
| StateBase* next); |
| static bool shouldSerializeDensely(uint32_t length, uint32_t propertyCount); |
| |
| StateBase* startArrayState(v8::Local<v8::Array>, StateBase* next); |
| StateBase* startObjectState(v8::Local<v8::Object>, StateBase* next); |
| StateBase* startMapState(v8::Local<v8::Map>, StateBase* next); |
| StateBase* startSetState(v8::Local<v8::Set>, StateBase* next); |
| |
| bool appendBlobInfo(const String& uuid, |
| const String& type, |
| unsigned long long size, |
| int* index); |
| bool appendFileInfo(const File*, int* index); |
| |
| void copyTransferables(const Transferables&); |
| |
| RefPtr<ScriptState> m_scriptState; |
| SerializedScriptValueWriter& m_writer; |
| v8::TryCatch m_tryCatch; |
| int m_depth; |
| Status m_status; |
| String m_errorMessage; |
| typedef V8ObjectMap<v8::Object, uint32_t> ObjectPool; |
| ObjectPool m_objectPool; |
| ObjectPool m_transferredMessagePorts; |
| ObjectPool m_transferredArrayBuffers; |
| ObjectPool m_transferredImageBitmaps; |
| ObjectPool m_transferredOffscreenCanvas; |
| uint32_t m_nextObjectReference; |
| WebBlobInfoArray* m_blobInfo; |
| BlobDataHandleMap* m_blobDataHandles; |
| |
| // Counts of object types encountered while serializing the object graph. |
| int m_primitiveCount = 0; |
| int m_jsObjectCount = 0; |
| int m_domWrapperCount = 0; |
| }; |
| |
| class ScriptValueDeserializer; |
| |
| // SerializedScriptValueReader is responsible for deserializing primitive types |
| // and restoring information about saved objects of composite types. |
| class CORE_EXPORT SerializedScriptValueReader { |
| STACK_ALLOCATED(); |
| WTF_MAKE_NONCOPYABLE(SerializedScriptValueReader); |
| |
| public: |
| SerializedScriptValueReader(const uint8_t* buffer, |
| int length, |
| const WebBlobInfoArray* blobInfo, |
| BlobDataHandleMap& blobDataHandles, |
| ScriptState* scriptState) |
| : m_scriptState(scriptState), |
| m_buffer(buffer), |
| m_length(length), |
| m_position(0), |
| m_version(0), |
| m_blobInfo(blobInfo), |
| m_blobDataHandles(blobDataHandles) { |
| ASSERT(!(reinterpret_cast<size_t>(buffer) & 1)); |
| ASSERT(length >= 0); |
| } |
| |
| bool isEof() const { return m_position >= m_length; } |
| |
| ScriptState* getScriptState() const { return m_scriptState.get(); } |
| |
| virtual bool read(v8::Local<v8::Value>*, ScriptValueDeserializer&); |
| bool readVersion(uint32_t& version); |
| void setVersion(uint32_t); |
| |
| protected: |
| v8::Isolate* isolate() const { return m_scriptState->isolate(); } |
| v8::Local<v8::Context> context() const { return m_scriptState->context(); } |
| unsigned length() const { return m_length; } |
| unsigned position() const { return m_position; } |
| |
| const uint8_t* allocate(uint32_t size) { |
| const uint8_t* allocated = m_buffer + m_position; |
| m_position += size; |
| return allocated; |
| } |
| |
| bool readWithTag(SerializationTag, |
| v8::Local<v8::Value>*, |
| ScriptValueDeserializer&); |
| |
| bool readTag(SerializationTag*); |
| bool readWebCoreString(String*); |
| bool readUint32(v8::Local<v8::Value>*); |
| |
| bool doReadUint32(uint32_t* value); |
| |
| private: |
| void undoReadTag(); |
| bool readArrayBufferViewSubTag(ArrayBufferViewSubTag*); |
| bool readString(v8::Local<v8::Value>*); |
| bool readUCharString(v8::Local<v8::Value>*); |
| bool readStringObject(v8::Local<v8::Value>*); |
| bool readInt32(v8::Local<v8::Value>*); |
| bool readDate(v8::Local<v8::Value>*); |
| bool readNumber(v8::Local<v8::Value>*); |
| bool readNumberObject(v8::Local<v8::Value>*); |
| bool doReadImageDataProperties(uint32_t* width, |
| uint32_t* height, |
| uint32_t* pixelDataLength); |
| bool readImageData(v8::Local<v8::Value>*); |
| bool readImageBitmap(v8::Local<v8::Value>*); |
| bool readCompositorProxy(v8::Local<v8::Value>*); |
| DOMArrayBuffer* doReadArrayBuffer(); |
| bool readArrayBuffer(v8::Local<v8::Value>*); |
| bool readArrayBufferView(v8::Local<v8::Value>*, ScriptValueDeserializer&); |
| bool readWasmCompiledModule(v8::Local<v8::Value>*); |
| bool readRegExp(v8::Local<v8::Value>*); |
| bool readBlob(v8::Local<v8::Value>*, bool isIndexed); |
| bool readFile(v8::Local<v8::Value>*, bool isIndexed); |
| bool readFileList(v8::Local<v8::Value>*, bool isIndexed); |
| File* readFileHelper(); |
| File* readFileIndexHelper(); |
| |
| template <class T> |
| bool doReadUintHelper(T* value) { |
| *value = 0; |
| uint8_t currentByte; |
| int shift = 0; |
| do { |
| if (m_position >= m_length) |
| return false; |
| currentByte = m_buffer[m_position++]; |
| *value |= (static_cast<T>(currentByte & SerializedScriptValue::varIntMask) |
| << shift); |
| shift += SerializedScriptValue::varIntShift; |
| } while (currentByte & (1 << SerializedScriptValue::varIntShift)); |
| return true; |
| } |
| |
| bool doReadUint64(uint64_t* value); |
| bool doReadNumber(double* number); |
| PassRefPtr<BlobDataHandle> getOrCreateBlobDataHandle(const String& uuid, |
| const String& type, |
| long long size = -1); |
| |
| RefPtr<ScriptState> m_scriptState; |
| const uint8_t* m_buffer; |
| const unsigned m_length; |
| unsigned m_position; |
| uint32_t m_version; |
| const WebBlobInfoArray* m_blobInfo; |
| const BlobDataHandleMap& m_blobDataHandles; |
| |
| FRIEND_TEST_ALL_PREFIXES(ScriptValueSerializerTest, Uint64Decode); |
| }; |
| |
| class CORE_EXPORT ScriptValueDeserializer { |
| STACK_ALLOCATED(); |
| WTF_MAKE_NONCOPYABLE(ScriptValueDeserializer); |
| |
| public: |
| ScriptValueDeserializer(SerializedScriptValueReader& reader, |
| MessagePortArray* messagePorts, |
| ArrayBufferContentsArray* arrayBufferContents, |
| ImageBitmapContentsArray* imageBitmapContents) |
| : m_reader(reader), |
| m_transferredMessagePorts(messagePorts), |
| m_arrayBufferContents(arrayBufferContents), |
| m_imageBitmapContents(imageBitmapContents), |
| m_arrayBuffers(arrayBufferContents ? arrayBufferContents->size() : 0), |
| m_imageBitmaps(imageBitmapContents ? imageBitmapContents->size() : 0), |
| m_version(0) {} |
| |
| v8::Local<v8::Value> deserialize(); |
| bool newSparseArray(uint32_t); |
| bool newDenseArray(uint32_t length); |
| bool newMap(); |
| bool newSet(); |
| bool consumeTopOfStack(v8::Local<v8::Value>*); |
| bool newObject(); |
| bool completeObject(uint32_t numProperties, v8::Local<v8::Value>*); |
| bool completeSparseArray(uint32_t numProperties, |
| uint32_t length, |
| v8::Local<v8::Value>*); |
| bool completeDenseArray(uint32_t numProperties, |
| uint32_t length, |
| v8::Local<v8::Value>*); |
| bool completeMap(uint32_t length, v8::Local<v8::Value>*); |
| bool completeSet(uint32_t length, v8::Local<v8::Value>*); |
| void pushObjectReference(const v8::Local<v8::Value>&); |
| bool tryGetTransferredMessagePort(uint32_t index, v8::Local<v8::Value>*); |
| bool tryGetTransferredArrayBuffer(uint32_t index, v8::Local<v8::Value>*); |
| bool tryGetTransferredImageBitmap(uint32_t index, v8::Local<v8::Value>*); |
| bool tryGetTransferredOffscreenCanvas(uint32_t width, |
| uint32_t height, |
| uint32_t canvasId, |
| uint32_t clientId, |
| uint32_t localId, |
| uint64_t nonce, |
| v8::Local<v8::Value>*); |
| bool tryGetTransferredSharedArrayBuffer(uint32_t index, |
| v8::Local<v8::Value>*); |
| bool tryGetObjectFromObjectReference(uint32_t reference, |
| v8::Local<v8::Value>*); |
| uint32_t objectReferenceCount(); |
| |
| protected: |
| SerializedScriptValueReader& reader() { return m_reader; } |
| virtual bool read(v8::Local<v8::Value>*); |
| |
| private: |
| bool initializeObject(v8::Local<v8::Object>, |
| uint32_t numProperties, |
| v8::Local<v8::Value>*); |
| bool doDeserialize(); |
| void push(v8::Local<v8::Value> value) { m_stack.append(value); }; |
| void pop(unsigned length) { |
| ASSERT(length <= m_stack.size()); |
| m_stack.shrink(m_stack.size() - length); |
| } |
| unsigned stackDepth() const { return m_stack.size(); } |
| |
| v8::Local<v8::Value> element(unsigned index); |
| void openComposite(const v8::Local<v8::Value>&); |
| bool closeComposite(v8::Local<v8::Value>*); |
| |
| SerializedScriptValueReader& m_reader; |
| Vector<v8::Local<v8::Value>> m_stack; |
| Vector<v8::Local<v8::Value>> m_objectPool; |
| Vector<uint32_t> m_openCompositeReferenceStack; |
| MessagePortArray* m_transferredMessagePorts; |
| ArrayBufferContentsArray* m_arrayBufferContents; |
| ImageBitmapContentsArray* m_imageBitmapContents; |
| Vector<v8::Local<v8::Value>> m_arrayBuffers; |
| Vector<v8::Local<v8::Value>> m_imageBitmaps; |
| uint32_t m_version; |
| }; |
| |
| } // namespace blink |
| |
| #endif // ScriptValueSerializer_h |