| 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
|
|
|