| Index: Source/bindings/core/v8/ScriptValueSerializer.cpp
|
| diff --git a/Source/bindings/core/v8/ScriptValueSerializer.cpp b/Source/bindings/core/v8/ScriptValueSerializer.cpp
|
| index 11fb2d37d51ae2af107bfe62c812cfd6931397ac..c7111c2dab7ea45b45e659d1f01ed1c64a285a02 100644
|
| --- a/Source/bindings/core/v8/ScriptValueSerializer.cpp
|
| +++ b/Source/bindings/core/v8/ScriptValueSerializer.cpp
|
| @@ -13,16 +13,21 @@
|
| #include "bindings/core/v8/V8FileList.h"
|
| #include "bindings/core/v8/V8ImageData.h"
|
| #include "bindings/core/v8/V8MessagePort.h"
|
| +#include "bindings/core/v8/V8SharedArrayBuffer.h"
|
| #include "core/dom/CompositorProxy.h"
|
| #include "core/dom/DOMDataView.h"
|
| +#include "core/dom/DOMSharedArrayBuffer.h"
|
| +#include "core/dom/DOMTypedArray.h"
|
| #include "core/fileapi/Blob.h"
|
| #include "core/fileapi/File.h"
|
| #include "core/fileapi/FileList.h"
|
| +#include "platform/RuntimeEnabledFeatures.h"
|
| #include "public/platform/Platform.h"
|
| #include "public/platform/WebBlobInfo.h"
|
| #include "wtf/DateMath.h"
|
| #include "wtf/text/StringHash.h"
|
| #include "wtf/text/StringUTF8Adaptor.h"
|
| +#include <stdio.h>
|
|
|
| // FIXME: consider crashing in debug mode on deserialization errors
|
| // NOTE: be sure to change wireFormatVersion as necessary!
|
| @@ -247,8 +252,7 @@ void SerializedScriptValueWriter::writeArrayBufferView(const DOMArrayBufferView&
|
| {
|
| append(ArrayBufferViewTag);
|
| #if ENABLE(ASSERT)
|
| - const DOMArrayBuffer& arrayBuffer = *arrayBufferView.buffer();
|
| - ASSERT(static_cast<const uint8_t*>(arrayBuffer.data()) + arrayBufferView.byteOffset() ==
|
| + ASSERT(static_cast<const uint8_t*>(arrayBufferView.bufferBase()->data()) + arrayBufferView.byteOffset() ==
|
| static_cast<const uint8_t*>(arrayBufferView.baseAddress()));
|
| #endif
|
| DOMArrayBufferView::ViewType type = arrayBufferView.type();
|
| @@ -320,6 +324,13 @@ void SerializedScriptValueWriter::writeTransferredArrayBuffer(uint32_t index)
|
| doWriteUint32(index);
|
| }
|
|
|
| +void SerializedScriptValueWriter::writeTransferredSharedArrayBuffer(uint32_t index)
|
| +{
|
| + ASSERT(RuntimeEnabledFeatures::sharedArrayBufferEnabled());
|
| + append(SharedArrayBufferTransferTag);
|
| + doWriteUint32(index);
|
| +}
|
| +
|
| void SerializedScriptValueWriter::writeObjectReference(uint32_t reference)
|
| {
|
| append(ObjectReferenceTag);
|
| @@ -600,6 +611,16 @@ static v8::Local<v8::ArrayBuffer> toV8Object(DOMArrayBuffer* impl, v8::Local<v8:
|
| return wrapper.As<v8::ArrayBuffer>();
|
| }
|
|
|
| +static v8::Local<v8::SharedArrayBuffer> toV8Object(DOMSharedArrayBuffer* impl, v8::Local<v8::Object> creationContext, v8::Isolate* isolate)
|
| +{
|
| + ASSERT(RuntimeEnabledFeatures::sharedArrayBufferEnabled());
|
| + if (!impl)
|
| + return v8::Local<v8::SharedArrayBuffer>();
|
| + v8::Local<v8::Value> wrapper = toV8(impl, creationContext, isolate);
|
| + ASSERT(wrapper->IsSharedArrayBuffer());
|
| + return wrapper.As<v8::SharedArrayBuffer>();
|
| +}
|
| +
|
| // Returns true if the provided object is to be considered a 'host object', as used in the
|
| // HTML5 structured clone algorithm.
|
| static bool isHostObject(v8::Local<v8::Object> object)
|
| @@ -611,7 +632,7 @@ static bool isHostObject(v8::Local<v8::Object> object)
|
| return object->InternalFieldCount();
|
| }
|
|
|
| -ScriptValueSerializer::ScriptValueSerializer(SerializedScriptValueWriter& writer, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, WebBlobInfoArray* blobInfo, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, ScriptState* scriptState)
|
| +ScriptValueSerializer::ScriptValueSerializer(SerializedScriptValueWriter& writer, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, SharedArrayBufferArray* sharedArrayBuffers, WebBlobInfoArray* blobInfo, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, ScriptState* scriptState)
|
| : m_scriptState(scriptState)
|
| , m_writer(writer)
|
| , m_tryCatch(tryCatch)
|
| @@ -635,6 +656,15 @@ ScriptValueSerializer::ScriptValueSerializer(SerializedScriptValueWriter& writer
|
| m_transferredArrayBuffers.set(v8ArrayBuffer, i);
|
| }
|
| }
|
| + if (sharedArrayBuffers) {
|
| + ASSERT(sharedArrayBuffers->size() == 0 || RuntimeEnabledFeatures::sharedArrayBufferEnabled());
|
| + for (size_t i = 0; i < sharedArrayBuffers->size(); i++) {
|
| + v8::Local<v8::Object> v8SharedArrayBuffer = toV8Object(sharedArrayBuffers->at(i).get(), creationContext, isolate());
|
| + // Coalesce multiple occurences of the same buffer to the first index.
|
| + if (!m_transferredSharedArrayBuffers.contains(v8SharedArrayBuffer))
|
| + m_transferredSharedArrayBuffers.set(v8SharedArrayBuffer, i);
|
| + }
|
| + }
|
| }
|
|
|
| ScriptValueSerializer::Status ScriptValueSerializer::serialize(v8::Local<v8::Value> value)
|
| @@ -666,6 +696,7 @@ ScriptValueSerializer::StateBase* ScriptValueSerializer::doSerialize(v8::Local<v
|
| ScriptValueSerializer::StateBase* ScriptValueSerializer::doSerializeValue(v8::Local<v8::Value> value, ScriptValueSerializer::StateBase* next)
|
| {
|
| uint32_t arrayBufferIndex;
|
| + uint32_t sharedArrayBufferIndex;
|
| if (value.IsEmpty())
|
| return handleError(InputError, "The empty property name cannot be cloned.", next);
|
| if (value->IsUndefined()) {
|
| @@ -695,6 +726,8 @@ ScriptValueSerializer::StateBase* ScriptValueSerializer::doSerializeValue(v8::Lo
|
| }
|
| } else if (V8ArrayBuffer::hasInstance(value, isolate()) && m_transferredArrayBuffers.tryGet(value.As<v8::Object>(), &arrayBufferIndex)) {
|
| return writeTransferredArrayBuffer(value, arrayBufferIndex, next);
|
| + } else if (V8SharedArrayBuffer::hasInstance(value, isolate()) && m_transferredSharedArrayBuffers.tryGet(value.As<v8::Object>(), &sharedArrayBufferIndex)) {
|
| + return writeTransferredSharedArrayBuffer(value, sharedArrayBufferIndex, next);
|
| } else {
|
| v8::Local<v8::Object> jsObject = value.As<v8::Object>();
|
| if (jsObject.IsEmpty())
|
| @@ -911,9 +944,16 @@ ScriptValueSerializer::StateBase* ScriptValueSerializer::writeAndGreyArrayBuffer
|
| DOMArrayBufferView* arrayBufferView = V8ArrayBufferView::toImpl(object);
|
| if (!arrayBufferView)
|
| return 0;
|
| - if (!arrayBufferView->buffer())
|
| - return handleError(DataCloneError, "An ArrayBuffer could not be cloned.", next);
|
| - v8::Local<v8::Value> underlyingBuffer = toV8(arrayBufferView->buffer(), m_scriptState->context()->Global(), isolate());
|
| + v8::Local<v8::Value> underlyingBuffer;
|
| + if (arrayBufferView->isShared()) {
|
| + if (!arrayBufferView->bufferShared())
|
| + return handleError(DataCloneError, "A SharedArrayBuffer could not be cloned.", next);
|
| + underlyingBuffer = toV8(arrayBufferView->bufferShared(), m_scriptState->context()->Global(), isolate());
|
| + } else {
|
| + if (!arrayBufferView->buffer())
|
| + return handleError(DataCloneError, "An ArrayBuffer could not be cloned.", next);
|
| + underlyingBuffer = toV8(arrayBufferView->buffer(), m_scriptState->context()->Global(), isolate());
|
| + }
|
| if (underlyingBuffer.IsEmpty())
|
| return handleError(DataCloneError, "An ArrayBuffer could not be cloned.", next);
|
| StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next);
|
| @@ -957,6 +997,16 @@ ScriptValueSerializer::StateBase* ScriptValueSerializer::writeTransferredArrayBu
|
| return 0;
|
| }
|
|
|
| +ScriptValueSerializer::StateBase* ScriptValueSerializer::writeTransferredSharedArrayBuffer(v8::Local<v8::Value> value, uint32_t index, ScriptValueSerializer::StateBase* next)
|
| +{
|
| + ASSERT(RuntimeEnabledFeatures::sharedArrayBufferEnabled());
|
| + DOMSharedArrayBuffer* sharedArrayBuffer = V8SharedArrayBuffer::toImpl(value.As<v8::Object>());
|
| + if (!sharedArrayBuffer)
|
| + return 0;
|
| + m_writer.writeTransferredSharedArrayBuffer(index);
|
| + return 0;
|
| +}
|
| +
|
| bool ScriptValueSerializer::shouldSerializeDensely(uint32_t length, uint32_t propertyCount)
|
| {
|
| // Let K be the cost of serializing all property values that are there
|
| @@ -1233,6 +1283,16 @@ bool SerializedScriptValueReader::readWithTag(SerializationTag tag, v8::Local<v8
|
| return false;
|
| break;
|
| }
|
| + case SharedArrayBufferTransferTag: {
|
| + if (!m_version)
|
| + return false;
|
| + uint32_t index;
|
| + if (!doReadUint32(&index))
|
| + return false;
|
| + if (!creator.tryGetTransferredSharedArrayBuffer(index, value))
|
| + return false;
|
| + break;
|
| + }
|
| case ObjectReferenceTag: {
|
| if (!m_version)
|
| return false;
|
| @@ -1454,7 +1514,7 @@ bool SerializedScriptValueReader::readArrayBufferView(v8::Local<v8::Value>* valu
|
| ArrayBufferViewSubTag subTag;
|
| uint32_t byteOffset;
|
| uint32_t byteLength;
|
| - RefPtr<DOMArrayBuffer> arrayBuffer;
|
| + RefPtr<DOMArrayBufferBase> arrayBuffer;
|
| v8::Local<v8::Value> arrayBufferV8Value;
|
| if (!readArrayBufferViewSubTag(&subTag))
|
| return false;
|
| @@ -1466,9 +1526,17 @@ bool SerializedScriptValueReader::readArrayBufferView(v8::Local<v8::Value>* valu
|
| return false;
|
| if (arrayBufferV8Value.IsEmpty())
|
| return false;
|
| - arrayBuffer = V8ArrayBuffer::toImpl(arrayBufferV8Value.As<v8::Object>());
|
| - if (!arrayBuffer)
|
| - return false;
|
| + if (arrayBufferV8Value->IsArrayBuffer()) {
|
| + arrayBuffer = V8ArrayBuffer::toImpl(arrayBufferV8Value.As<v8::Object>());
|
| + if (!arrayBuffer)
|
| + return false;
|
| + } else if (arrayBufferV8Value->IsSharedArrayBuffer()) {
|
| + arrayBuffer = V8SharedArrayBuffer::toImpl(arrayBufferV8Value.As<v8::Object>());
|
| + if (!arrayBuffer)
|
| + return false;
|
| + } else {
|
| + ASSERT_NOT_REACHED();
|
| + }
|
|
|
| // Check the offset, length and alignment.
|
| int elementByteSize;
|
| @@ -1875,6 +1943,25 @@ bool ScriptValueDeserializer::tryGetTransferredArrayBuffer(uint32_t index, v8::L
|
| return true;
|
| }
|
|
|
| +bool ScriptValueDeserializer::tryGetTransferredSharedArrayBuffer(uint32_t index, v8::Local<v8::Value>* object)
|
| +{
|
| + ASSERT(RuntimeEnabledFeatures::sharedArrayBufferEnabled());
|
| + if (!m_arrayBufferContents)
|
| + return false;
|
| + if (index >= m_arrayBuffers.size())
|
| + return false;
|
| + v8::Local<v8::Value> result = m_arrayBuffers.at(index);
|
| + if (result.IsEmpty()) {
|
| + RefPtr<DOMSharedArrayBuffer> buffer = DOMSharedArrayBuffer::create(m_arrayBufferContents->at(index));
|
| + v8::Isolate* isolate = m_reader.scriptState()->isolate();
|
| + v8::Local<v8::Object> creationContext = m_reader.scriptState()->context()->Global();
|
| + result = toV8(buffer.get(), creationContext, isolate);
|
| + m_arrayBuffers[index] = result;
|
| + }
|
| + *object = result;
|
| + return true;
|
| +}
|
| +
|
| bool ScriptValueDeserializer::tryGetObjectFromObjectReference(uint32_t reference, v8::Local<v8::Value>* object)
|
| {
|
| if (reference >= m_objectPool.size())
|
|
|