Index: Source/WebCore/bindings/v8/SerializedScriptValue.cpp |
diff --git a/Source/WebCore/bindings/v8/SerializedScriptValue.cpp b/Source/WebCore/bindings/v8/SerializedScriptValue.cpp |
index 42a37082ea0d8fe2966bc3afbde05c7321b99558..8f37300111c77843e32ec15d8677d6d0f9b12e12 100644 |
--- a/Source/WebCore/bindings/v8/SerializedScriptValue.cpp |
+++ b/Source/WebCore/bindings/v8/SerializedScriptValue.cpp |
@@ -47,6 +47,8 @@ |
#include "Int32Array.h" |
#include "Int8Array.h" |
#include "MessagePort.h" |
+#include "ScriptValueDeserializer.h" |
+#include "ScriptValueSerializer.h" |
#include "SharedBuffer.h" |
#include "Uint16Array.h" |
#include "Uint32Array.h" |
@@ -267,7 +269,7 @@ private: |
// Writer is responsible for serializing primitive types and storing |
// information used to reconstruct composite types. |
-class Writer { |
+class Writer : public ScriptValueWriter { |
WTF_MAKE_NONCOPYABLE(Writer); |
public: |
Writer() |
@@ -1107,23 +1109,6 @@ Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, Stat |
return 0; |
} |
-// Interface used by Reader to create objects of composite types. |
-class CompositeCreator { |
-public: |
- virtual ~CompositeCreator() { } |
- |
- virtual bool consumeTopOfStack(v8::Handle<v8::Value>*) = 0; |
- virtual uint32_t objectReferenceCount() = 0; |
- virtual void pushObjectReference(const v8::Handle<v8::Value>&) = 0; |
- virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle<v8::Value>*) = 0; |
- virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Value>*) = 0; |
- virtual bool newArray(uint32_t length) = 0; |
- virtual bool newObject() = 0; |
- virtual bool completeArray(uint32_t length, v8::Handle<v8::Value>*) = 0; |
- virtual bool completeObject(uint32_t numProperties, v8::Handle<v8::Value>*) = 0; |
- virtual bool completeSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>*) = 0; |
-}; |
- |
// Reader is responsible for deserializing primitive types and |
// restoring information about saved objects of composite types. |
class Reader { |
@@ -1137,194 +1122,200 @@ public: |
ASSERT(length >= 0); |
} |
- bool isEof() const { return m_position >= m_length; } |
+ uint32_t version() const { return m_version; } |
- bool read(v8::Handle<v8::Value>* value, CompositeCreator& creator) |
+ bool read(ScriptValueDeserializer& deserializer) |
{ |
- SerializationTag tag; |
- if (!readTag(&tag)) |
+ if (!readVersion(m_version) || m_version > wireFormatVersion) |
return false; |
- switch (tag) { |
- case ReferenceCountTag: { |
- if (m_version <= 0) |
- return false; |
- uint32_t referenceTableSize; |
- if (!doReadUint32(&referenceTableSize)) |
- return false; |
- // If this test fails, then the serializer and deserializer disagree about the assignment |
- // of object reference IDs. On the deserialization side, this means there are too many or too few |
- // calls to pushObjectReference. |
- if (referenceTableSize != creator.objectReferenceCount()) |
- return false; |
- return true; |
- } |
- case InvalidTag: |
- return false; |
- case PaddingTag: |
- return true; |
- case UndefinedTag: |
- *value = v8::Undefined(); |
- break; |
- case NullTag: |
- *value = v8::Null(); |
- break; |
- case TrueTag: |
- *value = v8::True(); |
- break; |
- case FalseTag: |
- *value = v8::False(); |
- break; |
- case TrueObjectTag: |
- *value = v8::BooleanObject::New(true); |
- creator.pushObjectReference(*value); |
- break; |
- case FalseObjectTag: |
- *value = v8::BooleanObject::New(false); |
- creator.pushObjectReference(*value); |
- break; |
- case StringTag: |
- if (!readString(value)) |
- return false; |
- break; |
- case StringObjectTag: |
- if (!readStringObject(value)) |
- return false; |
- creator.pushObjectReference(*value); |
- break; |
- case Int32Tag: |
- if (!readInt32(value)) |
- return false; |
- break; |
- case Uint32Tag: |
- if (!readUint32(value)) |
- return false; |
- break; |
- case DateTag: |
- if (!readDate(value)) |
- return false; |
- creator.pushObjectReference(*value); |
- break; |
- case NumberTag: |
- if (!readNumber(value)) |
- return false; |
- break; |
- case NumberObjectTag: |
- if (!readNumberObject(value)) |
- return false; |
- creator.pushObjectReference(*value); |
- break; |
- case BlobTag: |
- if (!readBlob(value)) |
- return false; |
- creator.pushObjectReference(*value); |
- break; |
- case FileTag: |
- if (!readFile(value)) |
- return false; |
- creator.pushObjectReference(*value); |
- break; |
- case FileListTag: |
- if (!readFileList(value)) |
- return false; |
- creator.pushObjectReference(*value); |
- break; |
- case ImageDataTag: |
- if (!readImageData(value)) |
- return false; |
- creator.pushObjectReference(*value); |
- break; |
- case ArrayTag: { |
- uint32_t length; |
- if (!doReadUint32(&length)) |
- return false; |
- if (!creator.completeArray(length, value)) |
- return false; |
- break; |
- } |
- case RegExpTag: |
- if (!readRegExp(value)) |
+ while (!isEof()) { |
+ SerializationTag tag; |
+ if (!readTag(&tag)) |
return false; |
- creator.pushObjectReference(*value); |
- break; |
- case ObjectTag: { |
- uint32_t numProperties; |
- if (!doReadUint32(&numProperties)) |
- return false; |
- if (!creator.completeObject(numProperties, value)) |
- return false; |
- break; |
- } |
- case SparseArrayTag: { |
- uint32_t numProperties; |
- uint32_t length; |
- if (!doReadUint32(&numProperties)) |
- return false; |
- if (!doReadUint32(&length)) |
- return false; |
- if (!creator.completeSparseArray(numProperties, length, value)) |
- return false; |
- break; |
- } |
- case ArrayBufferViewTag: { |
- if (m_version <= 0) |
- return false; |
- if (!readArrayBufferView(value, creator)) |
- return false; |
- creator.pushObjectReference(*value); |
- break; |
- } |
- case ArrayBufferTag: { |
- if (m_version <= 0) |
- return false; |
- if (!readArrayBuffer(value)) |
- return false; |
- creator.pushObjectReference(*value); |
- break; |
- } |
- case GenerateFreshObjectTag: { |
- if (m_version <= 0) |
- return false; |
- if (!creator.newObject()) |
- return false; |
- return true; |
- } |
- case GenerateFreshArrayTag: { |
- if (m_version <= 0) |
- return false; |
- uint32_t length; |
- if (!doReadUint32(&length)) |
- return false; |
- if (!creator.newArray(length)) |
- return false; |
- return true; |
- } |
- case MessagePortTag: { |
- if (m_version <= 0) |
- return false; |
- uint32_t index; |
- if (!doReadUint32(&index)) |
- return false; |
- if (!creator.tryGetTransferredMessagePort(index, value)) |
- return false; |
- break; |
- } |
- case ObjectReferenceTag: { |
- if (m_version <= 0) |
- return false; |
- uint32_t reference; |
- if (!doReadUint32(&reference)) |
+ switch (tag) { |
+ case ReferenceCountTag: { |
+ if (m_version <= 0) |
+ return false; |
+ uint32_t referenceTableSize; |
+ if (!doReadUint32(&referenceTableSize)) |
+ return false; |
+ // If this test fails, then the serializer and deserializer disagree about the assignment |
+ // of object reference IDs. |
+ if (referenceTableSize != deserializer.objectReferenceCount()) |
+ return false; |
+ break; |
+ } |
+ case InvalidTag: |
return false; |
- if (!creator.tryGetObjectFromObjectReference(reference, value)) |
+ case PaddingTag: |
+ break; |
+ case UndefinedTag: |
+ if (!deserializer.pushUndefined()) |
+ return false; |
+ break; |
+ case NullTag: |
+ if (!deserializer.pushNull()) |
+ return false; |
+ break; |
+ case TrueTag: |
+ if (!deserializer.pushTrue()) |
+ return false; |
+ break; |
+ case FalseTag: |
+ if (!deserializer.pushFalse()) |
+ return false; |
+ break; |
+ case TrueObjectTag: |
+ if (!deserializer.pushTrueObject()) |
+ return false; |
+ deserializer.addReferenceForTop(); |
+ break; |
+ case FalseObjectTag: |
+ if (!deserializer.pushFalseObject()) |
+ return false; |
+ deserializer.addReferenceForTop(); |
+ break; |
+ case StringTag: |
+ if (!readString(deserializer)) |
+ return false; |
+ break; |
+ case StringObjectTag: |
+ if (!readStringObject(deserializer)) |
+ return false; |
+ break; |
+ case Int32Tag: |
+ if (!readInt32(deserializer)) |
+ return false; |
+ break; |
+ case Uint32Tag: |
+ if (!readUint32(deserializer)) |
+ return false; |
+ break; |
+ case DateTag: |
+ if (!readDate(deserializer)) |
+ return false; |
+ break; |
+ case NumberTag: |
+ if (!readNumber(deserializer)) |
+ return false; |
+ break; |
+ case NumberObjectTag: |
+ if (!readNumberObject(deserializer)) |
+ return false; |
+ break; |
+ case BlobTag: |
+ if (!readBlob(deserializer)) |
+ return false; |
+ break; |
+ case FileTag: |
+ if (!readFile(deserializer)) |
+ return false; |
+ break; |
+ case FileListTag: |
+ if (!readFileList(deserializer)) |
+ return false; |
+ break; |
+ case ImageDataTag: |
+ if (!readImageData(deserializer)) |
+ return false; |
+ break; |
+ case ArrayTag: { |
+ uint32_t length; |
+ if (!doReadUint32(&length)) |
+ return false; |
+ if (!deserializer.pushArray(length)) |
+ return false; |
+ break; |
+ } |
+ case RegExpTag: |
+ if (!readRegExp(deserializer)) |
+ return false; |
+ break; |
+ case ObjectTag: { |
+ uint32_t numProperties; |
+ if (!doReadUint32(&numProperties)) |
+ return false; |
+ if (!deserializer.pushObject(numProperties)) |
+ return false; |
+ break; |
+ } |
+ case SparseArrayTag: { |
+ uint32_t numProperties; |
+ uint32_t length; |
+ if (!doReadUint32(&numProperties)) |
+ return false; |
+ if (!doReadUint32(&length)) |
+ return false; |
+ if (!deserializer.pushSparseArray(numProperties, length)) |
+ return false; |
+ break; |
+ } |
+ case ArrayBufferViewTag: { |
+ if (m_version <= 0) |
+ return false; |
+ if (!readArrayBufferView(deserializer)) |
+ return false; |
+ break; |
+ } |
+ case ArrayBufferTag: { |
+ if (m_version <= 0) |
+ return false; |
+ if (!readArrayBuffer(deserializer)) |
+ return false; |
+ break; |
+ } |
+ case GenerateFreshObjectTag: { |
+ if (m_version <= 0) |
+ return false; |
+ if (!deserializer.newObject()) |
+ return false; |
+ break; |
+ } |
+ case GenerateFreshArrayTag: { |
+ if (m_version <= 0) |
+ return false; |
+ uint32_t length; |
+ if (!doReadUint32(&length)) |
+ return false; |
+ if (!deserializer.newArray(length)) |
+ return false; |
+ break; |
+ } |
+ // FIXMEDART: uncomment this. |
+ /* |
+ case MessagePortTag: { |
+ if (m_version <= 0) |
+ return false; |
+ uint32_t index; |
+ if (!doReadUint32(&index)) |
+ return false; |
+ if (!deserializer.tryGetTransferredMessagePort(index, value)) |
+ return false; |
+ break; |
+ } |
+ */ |
+ case ObjectReferenceTag: { |
+ if (m_version <= 0) |
+ return false; |
+ uint32_t reference; |
+ if (!doReadUint32(&reference)) |
+ return false; |
+ if (!deserializer.tryGetObjectFromObjectReference(reference)) |
+ return false; |
+ break; |
+ } |
+ default: |
return false; |
- break; |
- } |
- default: |
- return false; |
+ } |
} |
- return !value->IsEmpty(); |
+ |
+ return true; |
} |
+private: |
+ bool isEof() const { return m_position >= m_length; } |
+ |
bool readVersion(uint32_t& version) |
{ |
SerializationTag tag; |
@@ -1344,12 +1335,6 @@ public: |
return doReadUint32(&version); |
} |
- void setVersion(uint32_t version) |
- { |
- m_version = version; |
- } |
- |
-private: |
bool readTag(SerializationTag* tag) |
{ |
if (m_position >= m_length) |
@@ -1372,24 +1357,25 @@ private: |
return true; |
} |
- bool readString(v8::Handle<v8::Value>* value) |
+ bool readString(ScriptValueDeserializer& deserializer) |
{ |
uint32_t length; |
if (!doReadUint32(&length)) |
return false; |
if (m_position + length > m_length) |
return false; |
- *value = v8::String::New(reinterpret_cast<const char*>(m_buffer + m_position), length); |
+ const char* data = reinterpret_cast<const char*>(m_buffer + m_position); |
m_position += length; |
- return true; |
+ return deserializer.pushScriptString(data, length); |
} |
- bool readStringObject(v8::Handle<v8::Value>* value) |
+ bool readStringObject(ScriptValueDeserializer& deserializer) |
{ |
- v8::Handle<v8::Value> stringValue; |
- if (!readString(&stringValue) || !stringValue->IsString()) |
+ if (!readString(deserializer)) |
+ return false; |
+ if (!deserializer.pushScriptStringObject()) |
return false; |
- *value = v8::StringObject::New(stringValue.As<v8::String>()); |
+ deserializer.addReferenceForTop(); |
return true; |
} |
@@ -1405,52 +1391,53 @@ private: |
return true; |
} |
- bool readInt32(v8::Handle<v8::Value>* value) |
+ bool readInt32(ScriptValueDeserializer& deserializer) |
{ |
uint32_t rawValue; |
if (!doReadUint32(&rawValue)) |
return false; |
- *value = v8::Integer::New(static_cast<int32_t>(ZigZag::decode(rawValue))); |
- return true; |
+ return deserializer.pushInt32(static_cast<int32_t>(ZigZag::decode(rawValue))); |
} |
- bool readUint32(v8::Handle<v8::Value>* value) |
+ bool readUint32(ScriptValueDeserializer& deserializer) |
{ |
uint32_t rawValue; |
if (!doReadUint32(&rawValue)) |
return false; |
- *value = v8::Integer::NewFromUnsigned(rawValue); |
- return true; |
+ return deserializer.pushUInt32(rawValue); |
} |
- bool readDate(v8::Handle<v8::Value>* value) |
+ bool readDate(ScriptValueDeserializer& deserializer) |
{ |
double numberValue; |
if (!doReadNumber(&numberValue)) |
return false; |
- *value = v8::Date::New(numberValue); |
+ if (!deserializer.pushDate(numberValue)) |
+ return false; |
+ deserializer.addReferenceForTop(); |
return true; |
} |
- bool readNumber(v8::Handle<v8::Value>* value) |
+ bool readNumber(ScriptValueDeserializer& deserializer) |
{ |
double number; |
if (!doReadNumber(&number)) |
return false; |
- *value = v8::Number::New(number); |
- return true; |
+ return deserializer.pushNumber(number); |
} |
- |
- bool readNumberObject(v8::Handle<v8::Value>* value) |
+ |
+ bool readNumberObject(ScriptValueDeserializer& deserializer) |
{ |
double number; |
if (!doReadNumber(&number)) |
return false; |
- *value = v8::NumberObject::New(number); |
+ if (!deserializer.pushNumberObject(number)) |
+ return false; |
+ deserializer.addReferenceForTop(); |
return true; |
} |
- bool readImageData(v8::Handle<v8::Value>* value) |
+ bool readImageData(ScriptValueDeserializer& deserializer) |
{ |
uint32_t width; |
uint32_t height; |
@@ -1469,7 +1456,9 @@ private: |
ASSERT(pixelArray->length() >= pixelDataLength); |
memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength); |
m_position += pixelDataLength; |
- *value = toV8(imageData.release()); |
+ if (!deserializer.pushImageData(imageData)) |
+ return false; |
+ deserializer.addReferenceForTop(); |
return true; |
} |
@@ -1486,107 +1475,115 @@ private: |
return arrayBuffer.release(); |
} |
- bool readArrayBuffer(v8::Handle<v8::Value>* value) |
+ bool readArrayBuffer(ScriptValueDeserializer& deserializer) |
{ |
RefPtr<ArrayBuffer> arrayBuffer = doReadArrayBuffer(); |
if (!arrayBuffer) |
return false; |
- *value = toV8(arrayBuffer.release()); |
+ if (!deserializer.pushArrayBuffer(arrayBuffer)) |
+ return false; |
+ deserializer.addReferenceForTop(); |
return true; |
} |
- bool readArrayBufferView(v8::Handle<v8::Value>* value, CompositeCreator& creator) |
+ bool readArrayBufferView(ScriptValueDeserializer& deserializer) |
{ |
ArrayBufferViewSubTag subTag; |
uint32_t byteOffset; |
uint32_t byteLength; |
RefPtr<ArrayBuffer> arrayBuffer; |
- v8::Handle<v8::Value> arrayBufferV8Value; |
if (!readArrayBufferViewSubTag(&subTag)) |
return false; |
if (!doReadUint32(&byteOffset)) |
return false; |
if (!doReadUint32(&byteLength)) |
return false; |
- if (!creator.consumeTopOfStack(&arrayBufferV8Value)) |
- return false; |
- arrayBuffer = V8ArrayBuffer::toNative(arrayBufferV8Value.As<v8::Object>()); |
- if (!arrayBuffer) |
- return false; |
switch (subTag) { |
case ByteArrayTag: |
- *value = toV8(Int8Array::create(arrayBuffer.release(), byteOffset, byteLength)); |
- break; |
+ if (!deserializer.pushInt8Array(byteOffset, byteLength)) |
+ return false; |
+ deserializer.addReferenceForTop(); |
+ return true; |
case UnsignedByteArrayTag: |
- *value = toV8(Uint8Array::create(arrayBuffer.release(), byteOffset, byteLength)); |
- break; |
+ return deserializer.pushUint8Array(byteOffset, byteLength); |
case ShortArrayTag: { |
uint32_t shortLength = byteLength / sizeof(int16_t); |
if (shortLength * sizeof(int16_t) != byteLength) |
return false; |
- *value = toV8(Int16Array::create(arrayBuffer.release(), byteOffset, shortLength)); |
- break; |
+ if (!deserializer.pushInt16Array(byteOffset, byteLength)) |
+ return false; |
+ deserializer.addReferenceForTop(); |
+ return true; |
} |
case UnsignedShortArrayTag: { |
uint32_t shortLength = byteLength / sizeof(uint16_t); |
if (shortLength * sizeof(uint16_t) != byteLength) |
return false; |
- *value = toV8(Uint16Array::create(arrayBuffer.release(), byteOffset, shortLength)); |
- break; |
+ if (!deserializer.pushUint16Array(byteOffset, byteLength)) |
+ return false; |
+ deserializer.addReferenceForTop(); |
+ return true; |
} |
case IntArrayTag: { |
uint32_t intLength = byteLength / sizeof(int32_t); |
if (intLength * sizeof(int32_t) != byteLength) |
return false; |
- *value = toV8(Int32Array::create(arrayBuffer.release(), byteOffset, intLength)); |
- break; |
+ if (!deserializer.pushInt32Array(byteOffset, byteLength)) |
+ return false; |
+ deserializer.addReferenceForTop(); |
+ return true; |
} |
case UnsignedIntArrayTag: { |
uint32_t intLength = byteLength / sizeof(uint32_t); |
if (intLength * sizeof(uint32_t) != byteLength) |
return false; |
- *value = toV8(Uint32Array::create(arrayBuffer.release(), byteOffset, intLength)); |
- break; |
+ if (!deserializer.pushUint32Array(byteOffset, byteLength)) |
+ return false; |
+ deserializer.addReferenceForTop(); |
+ return true; |
} |
case FloatArrayTag: { |
uint32_t floatLength = byteLength / sizeof(float); |
if (floatLength * sizeof(float) != byteLength) |
return false; |
- *value = toV8(Float32Array::create(arrayBuffer.release(), byteOffset, floatLength)); |
- break; |
+ if (!deserializer.pushFloat32Array(byteOffset, byteLength)) |
+ return false; |
+ deserializer.addReferenceForTop(); |
+ return true; |
} |
case DoubleArrayTag: { |
uint32_t floatLength = byteLength / sizeof(double); |
if (floatLength * sizeof(double) != byteLength) |
return false; |
- *value = toV8(Float64Array::create(arrayBuffer.release(), byteOffset, floatLength)); |
- break; |
+ if (!deserializer.pushFloat64Array(byteOffset, byteLength)) |
+ return false; |
+ deserializer.addReferenceForTop(); |
+ return true; |
} |
case DataViewTag: |
- *value = toV8(DataView::create(arrayBuffer.release(), byteOffset, byteLength)); |
- break; |
+ if (!deserializer.pushDataView(byteOffset, byteLength)) |
+ return false; |
+ deserializer.addReferenceForTop(); |
+ return true; |
default: |
return false; |
} |
- // The various *Array::create() methods will return null if the range the view expects is |
- // mismatched with the range the buffer can provide or if the byte offset is not aligned |
- // to the size of the element type. |
- return !value->IsEmpty(); |
} |
- bool readRegExp(v8::Handle<v8::Value>* value) |
+ bool readRegExp(ScriptValueDeserializer& deserializer) |
{ |
- v8::Handle<v8::Value> pattern; |
- if (!readString(&pattern)) |
+ if (!readString(deserializer)) |
return false; |
uint32_t flags; |
if (!doReadUint32(&flags)) |
return false; |
- *value = v8::RegExp::New(pattern.As<v8::String>(), static_cast<v8::RegExp::Flags>(flags)); |
+ if (!deserializer.pushRegExp(flags)) |
+ return false; |
+ deserializer.addReferenceForTop(); |
return true; |
} |
- bool readBlob(v8::Handle<v8::Value>* value) |
+ bool readBlob(ScriptValueDeserializer& deserializer) |
{ |
String url; |
String type; |
@@ -1597,12 +1594,13 @@ private: |
return false; |
if (!doReadUint64(&size)) |
return false; |
- PassRefPtr<Blob> blob = Blob::create(KURL(ParsedURLString, url), type, size); |
- *value = toV8(blob); |
+ if (!deserializer.pushBlob(Blob::create(KURL(ParsedURLString, url), type, size))) |
+ return false; |
+ deserializer.addReferenceForTop(); |
return true; |
} |
- bool readFile(v8::Handle<v8::Value>* value) |
+ bool readFile(ScriptValueDeserializer& deserializer) |
{ |
String path; |
String url; |
@@ -1613,17 +1611,18 @@ private: |
return false; |
if (!readWebCoreString(&type)) |
return false; |
- PassRefPtr<File> file = File::create(path, KURL(ParsedURLString, url), type); |
- *value = toV8(file); |
+ if (!deserializer.pushFile(File::create(path, KURL(ParsedURLString, url), type))) |
+ return false; |
+ deserializer.addReferenceForTop(); |
return true; |
} |
- bool readFileList(v8::Handle<v8::Value>* value) |
+ bool readFileList(ScriptValueDeserializer& deserializer) |
{ |
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; |
@@ -1636,7 +1635,9 @@ private: |
return false; |
fileList->append(File::create(path, KURL(ParsedURLString, urlString), type)); |
} |
- *value = toV8(fileList); |
+ if (!deserializer.pushFileList(fileList)) |
+ return false; |
+ deserializer.addReferenceForTop(); |
return true; |
} |
@@ -1682,9 +1683,9 @@ private: |
uint32_t m_version; |
}; |
-class Deserializer : public CompositeCreator { |
+class V8Deserializer : public ScriptValueDeserializer { |
public: |
- explicit Deserializer(Reader& reader, MessagePortArray* messagePorts) |
+ explicit V8Deserializer(Reader& reader, MessagePortArray* messagePorts) |
: m_reader(reader) |
, m_transferredMessagePorts(messagePorts) |
, m_version(0) |
@@ -1693,18 +1694,12 @@ public: |
v8::Handle<v8::Value> deserialize() |
{ |
- if (!m_reader.readVersion(m_version) || m_version > wireFormatVersion) |
- return v8::Null(); |
- m_reader.setVersion(m_version); |
v8::HandleScope scope; |
- while (!m_reader.isEof()) { |
- if (!doDeserialize()) |
- return v8::Null(); |
- } |
+ if (!m_reader.read(*this)) |
+ return v8::Null(); |
if (stackDepth() != 1 || m_openCompositeReferenceStack.size()) |
return v8::Null(); |
- v8::Handle<v8::Value> result = scope.Close(element(0)); |
- return result; |
+ return scope.Close(element(0)); |
} |
virtual bool newArray(uint32_t length) |
@@ -1716,21 +1711,78 @@ public: |
return true; |
} |
- virtual bool consumeTopOfStack(v8::Handle<v8::Value>* object) |
+ virtual bool newObject() |
{ |
- if (stackDepth() < 1) |
+ v8::Local<v8::Object> object = v8::Object::New(); |
+ if (object.IsEmpty()) |
return false; |
- *object = element(stackDepth() - 1); |
- pop(1); |
+ openComposite(object); |
+ return true; |
+ } |
+ |
+ virtual bool tryGetObjectFromObjectReference(uint32_t reference) |
+ { |
+ if (reference >= m_objectPool.size()) |
+ return false; |
+ v8::Handle<v8::Value> value = m_objectPool[reference]; |
+ ASSERT(!value.IsEmpty()); |
+ return push(value); |
+ } |
+ |
+ virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Value>* object) |
+ { |
+ if (!m_transferredMessagePorts) |
+ return false; |
+ if (index >= m_transferredMessagePorts->size()) |
+ return false; |
+ *object = V8MessagePort::wrap(m_transferredMessagePorts->at(index).get()); |
return true; |
} |
- virtual bool completeArray(uint32_t length, v8::Handle<v8::Value>* value) |
+ virtual uint32_t objectReferenceCount() |
+ { |
+ return m_objectPool.size(); |
+ } |
+ |
+ virtual void addReferenceForTop() |
+ { |
+ ASSERT(stackDepth() > 0); |
+ v8::Handle<v8::Value> value = element(stackDepth() - 1); |
+ ASSERT(!value.IsEmpty()); |
+ m_objectPool.append(value); |
+ } |
+ |
+ |
+ virtual bool pushUndefined() { return push(v8::Undefined()); } |
+ virtual bool pushNull() { return push(v8::Null()); } |
+ virtual bool pushTrue() { return push(v8::True()); } |
+ virtual bool pushTrueObject() { return push(v8::BooleanObject::New(true)); } |
+ virtual bool pushFalse() { return push(v8::False()); } |
+ virtual bool pushFalseObject() { return push(v8::BooleanObject::New(false)); } |
+ virtual bool pushScriptString(const char* data, uint32_t length) { return push(v8::String::New(data, length)); } |
+ virtual bool pushScriptStringObject() |
+ { |
+ if (stackDepth() < 1) |
+ return false; |
+ v8::Handle<v8::Value> string = popValue(); |
+ return push(v8::StringObject::New(string.As<v8::String>())); |
+ } |
+ virtual bool pushInt32(int32_t value) { return push(v8::Integer::New(value)); } |
+ virtual bool pushUInt32(uint32_t value) { return push(v8::Integer::NewFromUnsigned(value)); } |
+ virtual bool pushDate(double numberValue) { return push(v8::Date::New(numberValue)); } |
+ virtual bool pushNumber(double value) { return push(v8::Number::New(value)); } |
+ virtual bool pushNumberObject(double value) { return push(v8::NumberObject::New(value)); } |
+ virtual bool pushBlob(PassRefPtr<Blob> blob) { return push(toV8(blob)); } |
+ virtual bool pushFile(PassRefPtr<File> file) { return push(toV8(file)); } |
+ virtual bool pushFileList(PassRefPtr<FileList> fileList) { return push(toV8(fileList)); } |
+ virtual bool pushImageData(PassRefPtr<ImageData> imageData) { return push(toV8(imageData)); } |
+ |
+ virtual bool pushArray(uint32_t length) |
{ |
if (length > stackDepth()) |
return false; |
v8::Local<v8::Array> array; |
- if (m_version > 0) { |
+ if (m_reader.version() > 0) { |
v8::Local<v8::Value> composite; |
if (!closeComposite(&composite)) |
return false; |
@@ -1744,23 +1796,21 @@ public: |
for (unsigned i = 0; i < length; ++i) |
array->Set(i, element(depth + i)); |
pop(length); |
- *value = array; |
- return true; |
+ return push(array); |
} |
- virtual bool newObject() |
+ virtual bool pushRegExp(uint32_t flags) |
{ |
- v8::Local<v8::Object> object = v8::Object::New(); |
- if (object.IsEmpty()) |
+ if (stackDepth() < 1) |
return false; |
- openComposite(object); |
- return true; |
+ v8::Handle<v8::Value> pattern = popValue(); |
+ return push(v8::RegExp::New(pattern.As<v8::String>(), static_cast<v8::RegExp::Flags>(flags))); |
} |
- virtual bool completeObject(uint32_t numProperties, v8::Handle<v8::Value>* value) |
+ virtual bool pushObject(uint32_t numProperties) |
{ |
v8::Local<v8::Object> object; |
- if (m_version > 0) { |
+ if (m_reader.version() > 0) { |
v8::Local<v8::Value> composite; |
if (!closeComposite(&composite)) |
return false; |
@@ -1769,13 +1819,13 @@ public: |
object = v8::Object::New(); |
if (object.IsEmpty()) |
return false; |
- return initializeObject(object, numProperties, value); |
+ return initializeObject(object, numProperties); |
} |
- virtual bool completeSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) |
+ virtual bool pushSparseArray(uint32_t numProperties, uint32_t length) |
{ |
v8::Local<v8::Array> array; |
- if (m_version > 0) { |
+ if (m_reader.version() > 0) { |
v8::Local<v8::Value> composite; |
if (!closeComposite(&composite)) |
return false; |
@@ -1784,74 +1834,76 @@ public: |
array = v8::Array::New(length); |
if (array.IsEmpty()) |
return false; |
- return initializeObject(array, numProperties, value); |
+ return initializeObject(array, numProperties); |
} |
- virtual void pushObjectReference(const v8::Handle<v8::Value>& object) |
- { |
- m_objectPool.append(object); |
- } |
+ virtual bool pushInt8Array(uint32_t byteOffset, uint32_t byteLength) { return pushTypedArray<Int8Array>(byteOffset, byteLength); } |
+ virtual bool pushUint8Array(uint32_t byteOffset, uint32_t byteLength) { return pushTypedArray<Uint8Array>(byteOffset, byteLength); } |
+ virtual bool pushInt16Array(uint32_t byteOffset, uint32_t byteLength) { return pushTypedArray<Int16Array>(byteOffset, byteLength); } |
+ virtual bool pushUint16Array(uint32_t byteOffset, uint32_t byteLength) { return pushTypedArray<Uint16Array>(byteOffset, byteLength); } |
+ virtual bool pushInt32Array(uint32_t byteOffset, uint32_t byteLength) { return pushTypedArray<Int32Array>(byteOffset, byteLength); } |
+ virtual bool pushUint32Array(uint32_t byteOffset, uint32_t byteLength) { return pushTypedArray<Uint32Array>(byteOffset, byteLength); } |
+ virtual bool pushFloat32Array(uint32_t byteOffset, uint32_t byteLength) { return pushTypedArray<Float32Array>(byteOffset, byteLength); } |
+ virtual bool pushFloat64Array(uint32_t byteOffset, uint32_t byteLength) { return pushTypedArray<Float64Array>(byteOffset, byteLength); } |
+ virtual bool pushDataView(uint32_t byteOffset, uint32_t byteLength) { return pushTypedArray<DataView>(byteOffset, byteLength); } |
+ virtual bool pushArrayBuffer(PassRefPtr<ArrayBuffer> arrayBuffer) { return push(toV8(arrayBuffer)); } |
- virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Value>* object) |
+private: |
+ template <class C> |
+ bool pushTypedArray(uint32_t byteOffset, uint32_t byteLength) |
{ |
- if (!m_transferredMessagePorts) |
- return false; |
- if (index >= m_transferredMessagePorts->size()) |
+ if (stackDepth() < 1) |
return false; |
- *object = V8MessagePort::wrap(m_transferredMessagePorts->at(index).get()); |
- return true; |
- } |
- |
- virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle<v8::Value>* object) |
- { |
- if (reference >= m_objectPool.size()) |
+ RefPtr<ArrayBuffer> arrayBuffer = V8ArrayBuffer::toNative(popValue().As<v8::Object>()); |
+ if (!arrayBuffer) |
return false; |
- *object = m_objectPool[reference]; |
- return object; |
- } |
- virtual uint32_t objectReferenceCount() |
- { |
- return m_objectPool.size(); |
+ // The various *Array::create() methods will return null if the range the view expects is |
+ // mismatched with the range the buffer can provide or if the byte offset is not aligned |
+ // to the size of the element type. |
+ return push(toV8(C::create(arrayBuffer.release(), byteOffset, byteLength))); |
} |
-private: |
- bool initializeObject(v8::Handle<v8::Object> object, uint32_t numProperties, v8::Handle<v8::Value>* value) |
+ bool initializeObject(v8::Handle<v8::Object> object, uint32_t numProperties) |
{ |
+ ASSERT(!object.IsEmpty()); |
unsigned length = 2 * numProperties; |
if (length > stackDepth()) |
return false; |
for (unsigned i = stackDepth() - length; i < stackDepth(); i += 2) { |
- v8::Local<v8::Value> propertyName = element(i); |
- v8::Local<v8::Value> propertyValue = element(i + 1); |
+ v8::Handle<v8::Value> propertyName = element(i); |
+ v8::Handle<v8::Value> propertyValue = element(i + 1); |
object->Set(propertyName, propertyValue); |
} |
pop(length); |
- *value = object; |
- return true; |
+ return push(object); |
} |
- bool doDeserialize() |
+ bool push(v8::Handle<v8::Value> value) |
{ |
- v8::Local<v8::Value> value; |
- if (!m_reader.read(&value, *this)) |
+ if (value.IsEmpty()) |
return false; |
- if (!value.IsEmpty()) |
- push(value); |
+ m_stack.append(value); |
return true; |
} |
- 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); |
} |
+ v8::Handle<v8::Value> popValue() |
+ { |
+ ASSERT(stackDepth() >= 1); |
+ v8::Handle<v8::Value> top = element(stackDepth() - 1); |
+ pop(1); |
+ return top; |
+ } |
+ |
unsigned stackDepth() const { return m_stack.size(); } |
- v8::Local<v8::Value> element(unsigned index) |
+ v8::Handle<v8::Value> element(unsigned index) |
{ |
ASSERT(index < m_stack.size()); |
return m_stack[index]; |
@@ -1877,7 +1929,7 @@ private: |
} |
Reader& m_reader; |
- Vector<v8::Local<v8::Value> > m_stack; |
+ Vector<v8::Handle<v8::Value> > m_stack; |
Vector<v8::Handle<v8::Value> > m_objectPool; |
Vector<uint32_t> m_openCompositeReferenceStack; |
MessagePortArray* m_transferredMessagePorts; |
@@ -2015,8 +2067,24 @@ v8::Handle<v8::Value> SerializedScriptValue::deserialize(MessagePortArray* messa |
return v8::Null(); |
COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes); |
Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->characters()), 2 * m_data.length()); |
- Deserializer deserializer(reader, messagePorts); |
+ V8Deserializer deserializer(reader, messagePorts); |
return deserializer.deserialize(); |
} |
+PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(ScriptValueSerializer* serializer) |
+{ |
+ Writer writer; |
+ serializer->serialize(&writer); |
+ return adoptRef(new SerializedScriptValue(StringImpl::adopt(writer.data()))); |
+} |
+ |
+bool SerializedScriptValue::deserialize(ScriptValueDeserializer* deserializer) |
+{ |
+ if (!m_data.impl()) |
+ return false; |
+ COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes); |
+ Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->characters()), 2 * m_data.length()); |
+ return reader.read(*deserializer); |
+} |
+ |
} // namespace WebCore |