| Index: Source/bindings/v8/SerializedScriptValue.cpp
|
| diff --git a/Source/bindings/v8/SerializedScriptValue.cpp b/Source/bindings/v8/SerializedScriptValue.cpp
|
| index a19f8b1e5ef2369563feef293dc909b9957621a7..5ec34f43086dd3a625ef9213356b54d050f4fe31 100644
|
| --- a/Source/bindings/v8/SerializedScriptValue.cpp
|
| +++ b/Source/bindings/v8/SerializedScriptValue.cpp
|
| @@ -61,6 +61,7 @@
|
| #include "core/html/ImageData.h"
|
| #include "core/html/canvas/DataView.h"
|
| #include "platform/SharedBuffer.h"
|
| +#include "platform/blob/BlobInfo.h"
|
| #include "wtf/ArrayBuffer.h"
|
| #include "wtf/ArrayBufferContents.h"
|
| #include "wtf/ArrayBufferView.h"
|
| @@ -186,9 +187,9 @@ enum SerializationTag {
|
| DateTag = 'D', // value:double -> Date (ref)
|
| MessagePortTag = 'M', // index:int -> MessagePort. Fills the result with transferred MessagePort.
|
| NumberTag = 'N', // value:double -> Number
|
| - BlobTag = 'b', // url:WebCoreString, type:WebCoreString, size:uint64_t -> Blob (ref)
|
| + BlobTag = 'b', // uuid:WebCoreString, type:WebCoreString, size:uint64_t -> Blob (ref)
|
| FileTag = 'f', // file:RawFile -> File (ref)
|
| - DOMFileSystemTag = 'd', // type:int32_t, name:WebCoreString, url:WebCoreString -> FileSystem (ref)
|
| + DOMFileSystemTag = 'd', // type:int32_t, name:WebCoreString, uuid:WebCoreString -> FileSystem (ref)
|
| FileListTag = 'l', // length:uint32_t, files:RawFile[length] -> FileList (ref)
|
| ImageDataTag = '#', // width:uint32_t, height:uint32_t, pixelDataLength:uint32_t, data:byte[pixelDataLength] -> ImageData (ref)
|
| ObjectTag = '{', // numProperties:uint32_t -> pops the last object from the open stack;
|
| @@ -392,6 +393,12 @@ public:
|
| doWriteUint64(size);
|
| }
|
|
|
| + void writeBlob(int blobIndex)
|
| + {
|
| + append(BlobTag);
|
| + doWriteUint32(blobIndex);
|
| + }
|
| +
|
| void writeDOMFileSystem(int type, const String& name, const String& url)
|
| {
|
| append(DOMFileSystemTag);
|
| @@ -406,6 +413,14 @@ public:
|
| doWriteFile(file);
|
| }
|
|
|
| + void writeFile(int blobIndex)
|
| + {
|
| + append(FileTag);
|
| + doWriteUint32(blobIndex);
|
| + }
|
| +
|
| + // Note: We could dedupe the files in this list, but it's probably
|
| + // pretty rare that there are any duplicates.
|
| void writeFileList(const FileList& fileList)
|
| {
|
| append(FileListTag);
|
| @@ -415,6 +430,16 @@ public:
|
| doWriteFile(*fileList.item(i));
|
| }
|
|
|
| + void writeFileList(const Vector<int>& blobIndices)
|
| + {
|
| + append(FileListTag);
|
| + uint32_t length = blobIndices.size();
|
| + doWriteUint32(length);
|
| + for (unsigned i = 0; i < length; ++i) {
|
| + doWriteUint32(blobIndices[i]);
|
| + }
|
| + }
|
| +
|
| void writeArrayBuffer(const ArrayBuffer& arrayBuffer)
|
| {
|
| append(ArrayBufferTag);
|
| @@ -693,13 +718,14 @@ public:
|
| JSFailure
|
| };
|
|
|
| - Serializer(Writer& writer, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, v8::Isolate* isolate)
|
| + Serializer(Writer& writer, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, Vector<BlobInfo>* blobInfo, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, v8::Isolate* isolate)
|
| : m_writer(writer)
|
| , m_tryCatch(tryCatch)
|
| , m_depth(0)
|
| , m_execDepth(0)
|
| , m_status(Success)
|
| , m_nextObjectReference(0)
|
| + , m_blobInfo(blobInfo)
|
| , m_blobDataHandles(blobDataHandles)
|
| , m_isolate(isolate)
|
| {
|
| @@ -1071,8 +1097,14 @@ private:
|
| Blob* blob = V8Blob::toNative(value.As<v8::Object>());
|
| if (!blob)
|
| return;
|
| - m_writer.writeBlob(blob->uuid(), blob->type(), blob->size());
|
| + int blobIndex = -1;
|
| m_blobDataHandles.add(blob->uuid(), blob->blobDataHandle());
|
| + if (appendBlobInfo(blob->uuid(), blob->type(), blob->size(), &blobIndex)) {
|
| + ASSERT(blobIndex >= 0);
|
| + m_writer.writeBlob(blobIndex);
|
| + } else {
|
| + m_writer.writeBlob(blob->uuid(), blob->type(), blob->size());
|
| + }
|
| }
|
|
|
| StateBase* writeDOMFileSystem(v8::Handle<v8::Value> value, StateBase* next)
|
| @@ -1091,8 +1123,14 @@ private:
|
| File* file = V8File::toNative(value.As<v8::Object>());
|
| if (!file)
|
| return;
|
| - m_writer.writeFile(*file);
|
| + int blobIndex = -1;
|
| m_blobDataHandles.add(file->uuid(), file->blobDataHandle());
|
| + if (appendFileInfo(file->uuid(), file->path(), file->name(), file->type(), &blobIndex)) {
|
| + ASSERT(blobIndex >= 0);
|
| + m_writer.writeFile(blobIndex);
|
| + } else {
|
| + m_writer.writeFile(*file);
|
| + }
|
| }
|
|
|
| void writeFileList(v8::Handle<v8::Value> value)
|
| @@ -1100,10 +1138,25 @@ private:
|
| FileList* fileList = V8FileList::toNative(value.As<v8::Object>());
|
| if (!fileList)
|
| return;
|
| - m_writer.writeFileList(*fileList);
|
| unsigned length = fileList->length();
|
| - for (unsigned i = 0; i < length; ++i)
|
| - m_blobDataHandles.add(fileList->item(i)->uuid(), fileList->item(i)->blobDataHandle());
|
| + Vector<int> blobIndices;
|
| + bool useBlobIndices = false;
|
| + for (unsigned i = 0; i < length; ++i) {
|
| + int blobIndex = -1;
|
| + const File* file = fileList->item(i);
|
| + m_blobDataHandles.add(file->uuid(), file->blobDataHandle());
|
| + if (appendFileInfo(file->uuid(), file->path(), file->name(), file->type(), &blobIndex)) {
|
| + ASSERT(!i || useBlobIndices);
|
| + ASSERT(blobIndex >= 0);
|
| + useBlobIndices = true;
|
| + blobIndices.append(blobIndex);
|
| + }
|
| + }
|
| + if (useBlobIndices) {
|
| + m_writer.writeFileList(blobIndices);
|
| + } else {
|
| + m_writer.writeFileList(*fileList);
|
| + }
|
| }
|
|
|
| void writeImageData(v8::Handle<v8::Value> value)
|
| @@ -1214,6 +1267,24 @@ private:
|
| m_objectPool.set(object, objectReference);
|
| }
|
|
|
| + bool appendBlobInfo(const String& uuid, const String& type, unsigned long long size, int* index)
|
| + {
|
| + if (!m_blobInfo)
|
| + return false;
|
| + *index = m_blobInfo->size();
|
| + m_blobInfo->append(BlobInfo(uuid, type, size));
|
| + return true;
|
| + }
|
| +
|
| + bool appendFileInfo(const String& uuid, const String& filePath, const String& fileName, const String& type, int* index)
|
| + {
|
| + if (!m_blobInfo)
|
| + return false;
|
| + *index = m_blobInfo->size();
|
| + m_blobInfo->append(BlobInfo(uuid, filePath, fileName, type));
|
| + return true;
|
| + }
|
| +
|
| Writer& m_writer;
|
| v8::TryCatch& m_tryCatch;
|
| int m_depth;
|
| @@ -1224,6 +1295,7 @@ private:
|
| ObjectPool m_transferredMessagePorts;
|
| ObjectPool m_transferredArrayBuffers;
|
| uint32_t m_nextObjectReference;
|
| + Vector<BlobInfo>* m_blobInfo;
|
| BlobDataHandleMap& m_blobDataHandles;
|
| v8::Isolate* m_isolate;
|
| };
|
| @@ -1339,12 +1411,13 @@ public:
|
| // restoring information about saved objects of composite types.
|
| class Reader {
|
| public:
|
| - Reader(const uint8_t* buffer, int length, v8::Isolate* isolate, const BlobDataHandleMap& blobDataHandles)
|
| + Reader(const uint8_t* buffer, int length, v8::Isolate* isolate, const Vector<BlobInfo>* blobInfo, BlobDataHandleMap& blobDataHandles)
|
| : m_buffer(buffer)
|
| , m_length(length)
|
| , m_position(0)
|
| , m_version(0)
|
| , m_isolate(isolate)
|
| + , m_blobInfo(blobInfo)
|
| , m_blobDataHandles(blobDataHandles)
|
| {
|
| ASSERT(!(reinterpret_cast<size_t>(buffer) & 1));
|
| @@ -1860,12 +1933,22 @@ private:
|
| String uuid;
|
| String type;
|
| uint64_t size;
|
| - if (!readWebCoreString(&uuid))
|
| - return false;
|
| - if (!readWebCoreString(&type))
|
| - return false;
|
| - if (!doReadUint64(&size))
|
| - return false;
|
| + if (m_blobInfo) {
|
| + uint32_t index;
|
| + if (!doReadUint32(&index) || index >= m_blobInfo->size())
|
| + return false;
|
| + const BlobInfo& info = (*m_blobInfo)[index];
|
| + uuid = info.uuid();
|
| + type = info.type();
|
| + size = info.size();
|
| + } else {
|
| + if (!readWebCoreString(&uuid))
|
| + return false;
|
| + if (!readWebCoreString(&type))
|
| + return false;
|
| + if (!doReadUint64(&size))
|
| + return false;
|
| + }
|
| RefPtr<Blob> blob = Blob::create(getOrCreateBlobDataHandle(uuid, type, size));
|
| *value = toV8(blob.release(), v8::Handle<v8::Object>(), m_isolate);
|
| return true;
|
| @@ -1889,9 +1972,10 @@ private:
|
|
|
| bool readFile(v8::Handle<v8::Value>* value)
|
| {
|
| - RefPtr<File> file = doReadFileHelper();
|
| + RefPtr<File> file = readSingleFile();
|
| if (!file)
|
| return false;
|
| +
|
| *value = toV8(file.release(), v8::Handle<v8::Object>(), m_isolate);
|
| return true;
|
| }
|
| @@ -1905,28 +1989,35 @@ private:
|
| return false;
|
| RefPtr<FileList> fileList = FileList::create();
|
| for (unsigned i = 0; i < length; ++i) {
|
| - RefPtr<File> file = doReadFileHelper();
|
| + RefPtr<File> file = readSingleFile();
|
| if (!file)
|
| return false;
|
| - fileList->append(file.release());
|
| + fileList->append(file.get());
|
| }
|
| *value = toV8(fileList.release(), v8::Handle<v8::Object>(), m_isolate);
|
| return true;
|
| }
|
|
|
| - PassRefPtr<File> doReadFileHelper()
|
| + PassRefPtr<File> readSingleFile()
|
| {
|
| - if (m_version < 3)
|
| - return 0;
|
| + RefPtr<File> file;
|
| + if (m_blobInfo) {
|
| + uint32_t index;
|
| + if (!doReadUint32(&index) || index >= m_blobInfo->size())
|
| + return file;
|
| + const BlobInfo& info = (*m_blobInfo)[index];
|
| + file = File::create(info.filePath(), info.fileName(), getOrCreateBlobDataHandle(info.uuid(), info.type(), info.size()), info.lastModified(), info.size());
|
| + return file;
|
| + }
|
| String path;
|
| String uuid;
|
| String type;
|
| if (!readWebCoreString(&path))
|
| - return 0;
|
| + return file;
|
| if (!readWebCoreString(&uuid))
|
| - return 0;
|
| + return file;
|
| if (!readWebCoreString(&type))
|
| - return 0;
|
| + return file;
|
| return File::create(path, getOrCreateBlobDataHandle(uuid, type));
|
| }
|
|
|
| @@ -1977,7 +2068,7 @@ private:
|
| // the collection of BDH's for blobs to work, which would encourage lifetimes to be considered
|
| // when passing ssv's around cross process. At present, we get 'lucky' in some cases because
|
| // the blob in the src process happens to still exist at the time the dest process is deserializing.
|
| - // For example in sharedWorker.postMesssage(...).
|
| + // For example in sharedWorker.postMessage(...).
|
| BlobDataHandleMap::const_iterator it = m_blobDataHandles.find(uuid);
|
| if (it != m_blobDataHandles.end()) {
|
| // make assertions about type and size?
|
| @@ -1991,7 +2082,8 @@ private:
|
| unsigned m_position;
|
| uint32_t m_version;
|
| v8::Isolate* m_isolate;
|
| - const BlobDataHandleMap& m_blobDataHandles;
|
| + const Vector<BlobInfo>* m_blobInfo;
|
| + BlobDataHandleMap m_blobDataHandles;
|
| };
|
|
|
|
|
| @@ -2254,19 +2346,24 @@ private:
|
|
|
| PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, bool& didThrow, v8::Isolate* isolate)
|
| {
|
| - return adoptRef(new SerializedScriptValue(value, messagePorts, arrayBuffers, didThrow, isolate));
|
| + return adoptRef(new SerializedScriptValue(value, messagePorts, arrayBuffers, 0, didThrow, isolate));
|
| +}
|
| +
|
| +PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, Vector<BlobInfo>* blobInfo, bool& didThrow, v8::Isolate* isolate)
|
| +{
|
| + return adoptRef(new SerializedScriptValue(value, messagePorts, arrayBuffers, blobInfo, didThrow, isolate));
|
| }
|
|
|
| PassRefPtr<SerializedScriptValue> SerializedScriptValue::createAndSwallowExceptions(v8::Handle<v8::Value> value, v8::Isolate* isolate)
|
| {
|
| bool didThrow;
|
| - return adoptRef(new SerializedScriptValue(value, 0, 0, didThrow, isolate, DoNotThrowExceptions));
|
| + return adoptRef(new SerializedScriptValue(value, 0, 0, 0, didThrow, isolate, DoNotThrowExceptions));
|
| }
|
|
|
| -PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const ScriptValue& value, bool& didThrow, ScriptState* state)
|
| +PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const ScriptValue& value, Vector<BlobInfo>* blobInfo, bool& didThrow, ScriptState* state)
|
| {
|
| ScriptScope scope(state);
|
| - return adoptRef(new SerializedScriptValue(value.v8Value(), 0, 0, didThrow, state->isolate()));
|
| + return adoptRef(new SerializedScriptValue(value.v8Value(), 0, 0, blobInfo, didThrow, state->isolate()));
|
| }
|
|
|
| PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWire(const String& data)
|
| @@ -2403,7 +2500,7 @@ PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValu
|
| return contents.release();
|
| }
|
|
|
| -SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, bool& didThrow, v8::Isolate* isolate, ExceptionPolicy policy)
|
| +SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, Vector<BlobInfo>* blobInfo, bool& didThrow, v8::Isolate* isolate, ExceptionPolicy policy)
|
| : m_externallyAllocatedMemory(0)
|
| {
|
| didThrow = false;
|
| @@ -2411,7 +2508,7 @@ SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, Messag
|
| Serializer::Status status;
|
| {
|
| v8::TryCatch tryCatch;
|
| - Serializer serializer(writer, messagePorts, arrayBuffers, m_blobDataHandles, tryCatch, isolate);
|
| + Serializer serializer(writer, messagePorts, arrayBuffers, blobInfo, m_blobDataHandles, tryCatch, isolate);
|
| status = serializer.serialize(value);
|
| if (status == Serializer::JSException) {
|
| didThrow = true;
|
| @@ -2462,10 +2559,10 @@ SerializedScriptValue::SerializedScriptValue(const String& wireData)
|
|
|
| v8::Handle<v8::Value> SerializedScriptValue::deserialize(MessagePortArray* messagePorts)
|
| {
|
| - return deserialize(v8::Isolate::GetCurrent(), messagePorts);
|
| + return deserialize(v8::Isolate::GetCurrent(), messagePorts, 0);
|
| }
|
|
|
| -v8::Handle<v8::Value> SerializedScriptValue::deserialize(v8::Isolate* isolate, MessagePortArray* messagePorts)
|
| +v8::Handle<v8::Value> SerializedScriptValue::deserialize(v8::Isolate* isolate, MessagePortArray* messagePorts, const Vector<BlobInfo>* blobInfo)
|
| {
|
| if (!m_data.impl())
|
| return v8NullWithCheck(isolate);
|
| @@ -2475,7 +2572,7 @@ v8::Handle<v8::Value> SerializedScriptValue::deserialize(v8::Isolate* isolate, M
|
| // storage. Instead, it should use SharedBuffer or Vector<uint8_t>. The
|
| // information stored in m_data isn't even encoded in UTF-16. Instead,
|
| // unicode characters are encoded as UTF-8 with two code units per UChar.
|
| - Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->characters16()), 2 * m_data.length(), isolate, m_blobDataHandles);
|
| + Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->characters16()), 2 * m_data.length(), isolate, blobInfo, m_blobDataHandles);
|
| Deserializer deserializer(reader, messagePorts, m_arrayBufferContentsArray.get());
|
|
|
| // deserialize() can run arbitrary script (e.g., setters), which could result in |this| being destroyed.
|
|
|