Index: Source/bindings/v8/SerializedScriptValue.cpp |
diff --git a/Source/bindings/v8/SerializedScriptValue.cpp b/Source/bindings/v8/SerializedScriptValue.cpp |
index de2275a94ef23fc4ef8a78bff899bac666328947..e034c830ec4df0f9ebde381fe49a98b4f2c7598c 100644 |
--- a/Source/bindings/v8/SerializedScriptValue.cpp |
+++ b/Source/bindings/v8/SerializedScriptValue.cpp |
@@ -407,6 +407,12 @@ public: |
doWriteUint64(size); |
} |
+ void writeBlob(int blobIndex) |
+ { |
+ append(BlobTag); |
+ doWriteUint32(blobIndex); |
+ } |
+ |
void writeDOMFileSystem(int type, const String& name, const String& url) |
{ |
append(DOMFileSystemTag); |
@@ -423,6 +429,14 @@ public: |
doWriteWebCoreString(type); |
} |
+ 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); |
@@ -435,6 +449,16 @@ public: |
} |
} |
+ 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); |
@@ -706,14 +730,14 @@ public: |
JSFailure |
}; |
- Serializer(Writer& writer, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, Vector<String>& blobURLs, v8::TryCatch& tryCatch, v8::Isolate* isolate) |
+ Serializer(Writer& writer, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, Vector<BlobInfo>* blobInfo, 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_blobURLs(blobURLs) |
+ , m_blobInfo(blobInfo) |
, m_isolate(isolate) |
{ |
ASSERT(!tryCatch.HasCaught()); |
@@ -1081,8 +1105,13 @@ private: |
Blob* blob = V8Blob::toNative(value.As<v8::Object>()); |
if (!blob) |
return; |
- m_writer.writeBlob(blob->url().string(), blob->type(), blob->size()); |
- m_blobURLs.append(blob->url().string()); |
+ int blobIndex = -1; |
+ if (appendBlobInfo(blob->url().string(), blob->type(), blob->size(), &blobIndex)) { |
+ ASSERT(blobIndex >= 0); |
+ m_writer.writeBlob(blobIndex); |
+ } else { |
+ m_writer.writeBlob(blob->url().string(), blob->type(), blob->size()); |
+ } |
} |
StateBase* writeDOMFileSystem(v8::Handle<v8::Value> value, StateBase* next) |
@@ -1101,8 +1130,13 @@ private: |
File* file = V8File::toNative(value.As<v8::Object>()); |
if (!file) |
return; |
- m_writer.writeFile(file->path(), file->url().string(), file->type()); |
- m_blobURLs.append(file->url().string()); |
+ int blobIndex = -1; |
+ if (appendFileInfo(file->path(), file->name(), file->type(), &blobIndex)) { |
+ ASSERT(blobIndex >= 0); |
+ m_writer.writeFile(blobIndex); |
+ } else { |
+ m_writer.writeFile(file->path(), file->url().string(), file->type()); |
+ } |
} |
void writeFileList(v8::Handle<v8::Value> value) |
@@ -1110,10 +1144,24 @@ 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_blobURLs.append(fileList->item(i)->url().string()); |
+ Vector<int> blobIndices; |
+ bool useBlobIndices = false; |
+ for (unsigned i = 0; i < length; ++i) { |
+ int blobIndex = -1; |
+ const File* file = fileList->item(i); |
+ if (appendFileInfo(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) |
@@ -1222,6 +1270,24 @@ private: |
m_objectPool.set(object, objectReference); |
} |
+ bool appendBlobInfo(const String& url, const String& type, unsigned long long size, int* index) |
+ { |
+ if (!m_blobInfo) |
+ return false; |
+ *index = m_blobInfo->size(); |
+ m_blobInfo->append(BlobInfo(url, type, size)); |
+ return true; |
+ } |
+ |
+ bool appendFileInfo(const String& filePath, const String& fileName, const String& type, int* index) |
+ { |
+ if (!m_blobInfo) |
+ return false; |
+ *index = m_blobInfo->size(); |
+ m_blobInfo->append(BlobInfo(filePath, fileName, type)); |
+ return true; |
+ } |
+ |
Writer& m_writer; |
v8::TryCatch& m_tryCatch; |
int m_depth; |
@@ -1232,7 +1298,7 @@ private: |
ObjectPool m_transferredMessagePorts; |
ObjectPool m_transferredArrayBuffers; |
uint32_t m_nextObjectReference; |
- Vector<String>& m_blobURLs; |
+ Vector<BlobInfo>* m_blobInfo; |
v8::Isolate* m_isolate; |
}; |
@@ -1342,12 +1408,13 @@ public: |
// restoring information about saved objects of composite types. |
class Reader { |
public: |
- Reader(const uint8_t* buffer, int length, v8::Isolate* isolate) |
+ Reader(const uint8_t* buffer, int length, v8::Isolate* isolate, const Vector<BlobInfo>* blobInfo) |
: m_buffer(buffer) |
, m_length(length) |
, m_position(0) |
, m_version(0) |
, m_isolate(isolate) |
+ , m_blobInfo(blobInfo) |
{ |
ASSERT(!(reinterpret_cast<size_t>(buffer) & 1)); |
ASSERT(length >= 0); |
@@ -1861,14 +1928,24 @@ private: |
String url; |
String type; |
uint64_t size; |
- if (!readWebCoreString(&url)) |
- return false; |
- if (!readWebCoreString(&type)) |
- return false; |
- if (!doReadUint64(&size)) |
- return false; |
- PassRefPtr<Blob> blob = Blob::create(KURL(ParsedURLString, url), type, size); |
- *value = toV8(blob, v8::Handle<v8::Object>(), m_isolate); |
+ if (m_blobInfo) { |
+ uint32_t index; |
+ if (!doReadUint32(&index) || index >= m_blobInfo->size()) |
+ return false; |
+ const BlobInfo& info = (*m_blobInfo)[index]; |
+ url = info.url(); |
+ type = info.type(); |
+ size = info.size(); |
+ } else { |
+ if (!readWebCoreString(&url)) |
+ return false; |
+ if (!readWebCoreString(&type)) |
+ return false; |
+ if (!doReadUint64(&size)) |
+ return false; |
+ } |
+ RefPtr<Blob> blob = Blob::create(KURL(ParsedURLString, url), type, size); |
+ *value = toV8(blob.release(), v8::Handle<v8::Object>(), m_isolate); |
return true; |
} |
@@ -1888,19 +1965,36 @@ private: |
return true; |
} |
- bool readFile(v8::Handle<v8::Value>* value) |
+ PassRefPtr<File> readSingleFile() |
{ |
+ 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(), KURL(ParsedURLString, info.url()), info.type(), info.lastModified(), info.size()); |
+ return file; |
+ } |
String path; |
String url; |
String type; |
if (!readWebCoreString(&path)) |
- return false; |
+ return file; |
if (!readWebCoreString(&url)) |
- return false; |
+ return file; |
if (!readWebCoreString(&type)) |
+ return file; |
+ return File::create(path, KURL(ParsedURLString, url), type); |
+ } |
+ |
+ bool readFile(v8::Handle<v8::Value>* value) |
+ { |
+ RefPtr<File> file = readSingleFile(); |
+ if (!file.get()) |
return false; |
- PassRefPtr<File> file = File::create(path, KURL(ParsedURLString, url), type); |
- *value = toV8(file, v8::Handle<v8::Object>(), m_isolate); |
+ |
+ *value = toV8(file.release(), v8::Handle<v8::Object>(), m_isolate); |
return true; |
} |
@@ -1909,20 +2003,14 @@ private: |
uint32_t length; |
if (!doReadUint32(&length)) |
return false; |
- PassRefPtr<FileList> fileList = FileList::create(); |
+ RefPtr<FileList> fileList = FileList::create(); |
for (unsigned i = 0; i < length; ++i) { |
- String path; |
- String urlString; |
- String type; |
- if (!readWebCoreString(&path)) |
- return false; |
- if (!readWebCoreString(&urlString)) |
+ RefPtr<File> file = readSingleFile(); |
+ if (!file.get()) |
return false; |
- if (!readWebCoreString(&type)) |
- return false; |
- fileList->append(File::create(path, KURL(ParsedURLString, urlString), type)); |
+ fileList->append(file.get()); |
} |
- *value = toV8(fileList, v8::Handle<v8::Object>(), m_isolate); |
+ *value = toV8(fileList.release(), v8::Handle<v8::Object>(), m_isolate); |
return true; |
} |
@@ -1967,6 +2055,7 @@ private: |
unsigned m_position; |
uint32_t m_version; |
v8::Isolate* m_isolate; |
+ const Vector<BlobInfo>* m_blobInfo; |
}; |
@@ -2227,21 +2316,31 @@ private: |
} // namespace |
+PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value, Vector<BlobInfo>* blobInfo, bool& didThrow) |
+{ |
+ return create(value, 0, 0, blobInfo, didThrow, v8::Isolate::GetCurrent()); |
+} |
+ |
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::create(v8::Handle<v8::Value> value, v8::Isolate* isolate) |
{ |
bool didThrow; |
- return adoptRef(new SerializedScriptValue(value, 0, 0, didThrow, isolate)); |
+ return adoptRef(new SerializedScriptValue(value, 0, 0, 0, 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::createFromWire(const String& data) |
@@ -2427,15 +2526,16 @@ 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) |
- : m_externallyAllocatedMemory(0) |
+SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, Vector<BlobInfo>* blobInfo, bool& didThrow, v8::Isolate* isolate, ExceptionPolicy policy) |
+ : m_blobInfo(blobInfo) |
+ , m_externallyAllocatedMemory(0) |
{ |
didThrow = false; |
Writer writer(isolate); |
Serializer::Status status; |
{ |
v8::TryCatch tryCatch; |
- Serializer serializer(writer, messagePorts, arrayBuffers, m_blobURLs, tryCatch, isolate); |
+ Serializer serializer(writer, messagePorts, arrayBuffers, m_blobInfo, tryCatch, isolate); |
status = serializer.serialize(value); |
if (status == Serializer::JSException) { |
didThrow = true; |
@@ -2486,10 +2586,15 @@ 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(const Vector<BlobInfo>* blobInfo) |
+{ |
+ return deserialize(v8::Isolate::GetCurrent(), 0, blobInfo); |
} |
-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); |
@@ -2499,7 +2604,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); |
+ Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->characters16()), 2 * m_data.length(), isolate, blobInfo); |
Deserializer deserializer(reader, messagePorts, m_arrayBufferContentsArray.get()); |
// deserialize() can run arbitrary script (e.g., setters), which could result in |this| being destroyed. |