summaryrefslogtreecommitdiffstats
path: root/WebCore/bindings/v8/SerializedScriptValue.cpp
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-06 11:45:16 +0100
committerSteve Block <steveblock@google.com>2011-05-12 13:44:10 +0100
commitcad810f21b803229eb11403f9209855525a25d57 (patch)
tree29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /WebCore/bindings/v8/SerializedScriptValue.cpp
parent121b0cf4517156d0ac5111caf9830c51b69bae8f (diff)
downloadexternal_webkit-cad810f21b803229eb11403f9209855525a25d57.zip
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'WebCore/bindings/v8/SerializedScriptValue.cpp')
-rw-r--r--WebCore/bindings/v8/SerializedScriptValue.cpp1184
1 files changed, 0 insertions, 1184 deletions
diff --git a/WebCore/bindings/v8/SerializedScriptValue.cpp b/WebCore/bindings/v8/SerializedScriptValue.cpp
deleted file mode 100644
index 5a89e1b..0000000
--- a/WebCore/bindings/v8/SerializedScriptValue.cpp
+++ /dev/null
@@ -1,1184 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "SerializedScriptValue.h"
-
-#include "Blob.h"
-#include "ByteArray.h"
-#include "CanvasPixelArray.h"
-#include "ExceptionCode.h"
-#include "File.h"
-#include "FileList.h"
-#include "ImageData.h"
-#include "SharedBuffer.h"
-#include "V8Binding.h"
-#include "V8Blob.h"
-#include "V8File.h"
-#include "V8FileList.h"
-#include "V8ImageData.h"
-#include "V8Proxy.h"
-#include "V8Utilities.h"
-
-#include <wtf/Assertions.h>
-#include <wtf/RefCounted.h>
-#include <wtf/Vector.h>
-
-// FIXME:
-// - catch V8 exceptions
-// - consider crashing in debug mode on deserialization errors
-
-namespace WebCore {
-
-namespace {
-
-typedef UChar BufferValueType;
-
-// Serialization format is a sequence of (tag, optional data)
-// pairs. Tag always takes exactly one byte.
-enum SerializationTag {
- InvalidTag = '!',
- PaddingTag = '\0',
- UndefinedTag = '_',
- NullTag = '0',
- TrueTag = 'T',
- FalseTag = 'F',
- StringTag = 'S',
- Int32Tag = 'I',
- Uint32Tag = 'U',
- DateTag = 'D',
- NumberTag = 'N',
- BlobTag = 'b',
- FileTag = 'f',
- FileListTag = 'l',
- ImageDataTag = '#',
- ArrayTag = '[',
- ObjectTag = '{',
- SparseArrayTag = '@',
- RegExpTag = 'R',
-};
-
-static bool shouldCheckForCycles(int depth)
-{
- ASSERT(depth >= 0);
- // Since we are not required to spot the cycle as soon as it
- // happens we can check for cycles only when the current depth
- // is a power of two.
- return !(depth & (depth - 1));
-}
-
-static const int maxDepth = 20000;
-
-// VarInt encoding constants.
-static const int varIntShift = 7;
-static const int varIntMask = (1 << varIntShift) - 1;
-
-// ZigZag encoding helps VarInt encoding stay small for negative
-// numbers with small absolute values.
-class ZigZag {
-public:
- static uint32_t encode(uint32_t value)
- {
- if (value & (1U << 31))
- value = ((~value) << 1) + 1;
- else
- value <<= 1;
- return value;
- }
-
- static uint32_t decode(uint32_t value)
- {
- if (value & 1)
- value = ~(value >> 1);
- else
- value >>= 1;
- return value;
- }
-
-private:
- ZigZag();
-};
-
-// Writer is responsible for serializing primitive types and storing
-// information used to reconstruct composite types.
-class Writer : Noncopyable {
-public:
- Writer()
- : m_position(0)
- {
- }
-
- // Write functions for primitive types.
-
- void writeUndefined() { append(UndefinedTag); }
-
- void writeNull() { append(NullTag); }
-
- void writeTrue() { append(TrueTag); }
-
- void writeFalse() { append(FalseTag); }
-
- void writeString(const char* data, int length)
- {
- ASSERT(length >= 0);
- append(StringTag);
- doWriteString(data, length);
- }
-
- void writeWebCoreString(const String& string)
- {
- // Uses UTF8 encoding so we can read it back as either V8 or
- // WebCore string.
- append(StringTag);
- doWriteWebCoreString(string);
- }
-
- void writeInt32(int32_t value)
- {
- append(Int32Tag);
- doWriteUint32(ZigZag::encode(static_cast<uint32_t>(value)));
- }
-
- void writeUint32(uint32_t value)
- {
- append(Uint32Tag);
- doWriteUint32(value);
- }
-
- void writeDate(double numberValue)
- {
- append(DateTag);
- doWriteNumber(numberValue);
- }
-
- void writeNumber(double number)
- {
- append(NumberTag);
- doWriteNumber(number);
- }
-
- void writeBlob(const String& url, const String& type, unsigned long long size)
- {
- append(BlobTag);
- doWriteWebCoreString(url);
- doWriteWebCoreString(type);
- doWriteUint64(size);
- }
-
- void writeFile(const String& path, const String& url, const String& type)
- {
- append(FileTag);
- doWriteWebCoreString(path);
- doWriteWebCoreString(url);
- doWriteWebCoreString(type);
- }
-
- void writeFileList(const FileList& fileList)
- {
- append(FileListTag);
- uint32_t length = fileList.length();
- doWriteUint32(length);
- for (unsigned i = 0; i < length; ++i) {
- doWriteWebCoreString(fileList.item(i)->path());
- doWriteWebCoreString(fileList.item(i)->url().string());
- doWriteWebCoreString(fileList.item(i)->type());
- }
- }
-
- void writeImageData(uint32_t width, uint32_t height, const uint8_t* pixelData, uint32_t pixelDataLength)
- {
- append(ImageDataTag);
- doWriteUint32(width);
- doWriteUint32(height);
- doWriteUint32(pixelDataLength);
- append(pixelData, pixelDataLength);
- }
-
- void writeRegExp(v8::Local<v8::String> pattern, v8::RegExp::Flags flags)
- {
- append(RegExpTag);
- v8::String::Utf8Value patternUtf8Value(pattern);
- doWriteString(*patternUtf8Value, patternUtf8Value.length());
- doWriteUint32(static_cast<uint32_t>(flags));
- }
-
- void writeArray(uint32_t length)
- {
- append(ArrayTag);
- doWriteUint32(length);
- }
-
- void writeObject(uint32_t numProperties)
- {
- append(ObjectTag);
- doWriteUint32(numProperties);
- }
-
- void writeSparseArray(uint32_t numProperties, uint32_t length)
- {
- append(SparseArrayTag);
- doWriteUint32(numProperties);
- doWriteUint32(length);
- }
-
- Vector<BufferValueType>& data()
- {
- fillHole();
- return m_buffer;
- }
-
-private:
- void doWriteString(const char* data, int length)
- {
- doWriteUint32(static_cast<uint32_t>(length));
- append(reinterpret_cast<const uint8_t*>(data), length);
- }
-
- void doWriteWebCoreString(const String& string)
- {
- RefPtr<SharedBuffer> buffer = utf8Buffer(string);
- doWriteString(buffer->data(), buffer->size());
- }
-
- template<class T>
- void doWriteUintHelper(T value)
- {
- while (true) {
- uint8_t b = (value & varIntMask);
- value >>= varIntShift;
- if (!value) {
- append(b);
- break;
- }
- append(b | (1 << varIntShift));
- }
- }
-
- void doWriteUint32(uint32_t value)
- {
- doWriteUintHelper(value);
- }
-
- void doWriteUint64(uint64_t value)
- {
- doWriteUintHelper(value);
- }
-
- void doWriteNumber(double number)
- {
- append(reinterpret_cast<uint8_t*>(&number), sizeof(number));
- }
-
- void append(SerializationTag tag)
- {
- append(static_cast<uint8_t>(tag));
- }
-
- void append(uint8_t b)
- {
- ensureSpace(1);
- *byteAt(m_position++) = b;
- }
-
- void append(const uint8_t* data, int length)
- {
- ensureSpace(length);
- memcpy(byteAt(m_position), data, length);
- m_position += length;
- }
-
- void ensureSpace(int extra)
- {
- COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
- m_buffer.grow((m_position + extra + 1) / 2); // "+ 1" to round up.
- }
-
- void fillHole()
- {
- COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
- // If the writer is at odd position in the buffer, then one of
- // the bytes in the last UChar is not initialized.
- if (m_position % 2)
- *byteAt(m_position) = static_cast<uint8_t>(PaddingTag);
- }
-
- uint8_t* byteAt(int position) { return reinterpret_cast<uint8_t*>(m_buffer.data()) + position; }
-
- Vector<BufferValueType> m_buffer;
- unsigned m_position;
-};
-
-class Serializer {
- class StateBase;
-public:
- explicit Serializer(Writer& writer)
- : m_writer(writer)
- , m_depth(0)
- , m_hasError(false)
- {
- }
-
- bool serialize(v8::Handle<v8::Value> value)
- {
- v8::HandleScope scope;
- StateBase* state = doSerialize(value, 0);
- while (state)
- state = state->advance(*this);
- return !m_hasError;
- }
-
- // Functions used by serialization states.
-
- StateBase* doSerialize(v8::Handle<v8::Value> value, StateBase* next);
-
- StateBase* writeArray(uint32_t length, StateBase* state)
- {
- m_writer.writeArray(length);
- return pop(state);
- }
-
- StateBase* writeObject(uint32_t numProperties, StateBase* state)
- {
- m_writer.writeObject(numProperties);
- return pop(state);
- }
-
- StateBase* writeSparseArray(uint32_t numProperties, uint32_t length, StateBase* state)
- {
- m_writer.writeSparseArray(numProperties, length);
- return pop(state);
- }
-
-private:
- class StateBase : public Noncopyable {
- public:
- virtual ~StateBase() { }
-
- // Link to the next state to form a stack.
- StateBase* nextState() { return m_next; }
-
- // Composite object we're processing in this state.
- v8::Handle<v8::Value> composite() { return m_composite; }
-
- // Serializes (a part of) the current composite and returns
- // the next state to process or null when this is the final
- // state.
- virtual StateBase* advance(Serializer&) = 0;
-
- protected:
- StateBase(v8::Handle<v8::Value> composite, StateBase* next)
- : m_composite(composite)
- , m_next(next)
- {
- }
-
- private:
- v8::Handle<v8::Value> m_composite;
- StateBase* m_next;
- };
-
- // Dummy state that is used to signal serialization errors.
- class ErrorState : public StateBase {
- public:
- ErrorState()
- : StateBase(v8::Handle<v8::Value>(), 0)
- {
- }
-
- virtual StateBase* advance(Serializer&)
- {
- delete this;
- return 0;
- }
- };
-
- template <typename T>
- class State : public StateBase {
- public:
- v8::Handle<T> composite() { return v8::Handle<T>::Cast(StateBase::composite()); }
-
- protected:
- State(v8::Handle<T> composite, StateBase* next)
- : StateBase(composite, next)
- {
- }
- };
-
-#if 0
- // Currently unused, see comment in newArrayState.
- class ArrayState : public State<v8::Array> {
- public:
- ArrayState(v8::Handle<v8::Array> array, StateBase* next)
- : State<v8::Array>(array, next)
- , m_index(-1)
- {
- }
-
- virtual StateBase* advance(Serializer& serializer)
- {
- ++m_index;
- for (; m_index < composite()->Length(); ++m_index) {
- if (StateBase* newState = serializer.doSerialize(composite()->Get(m_index), this))
- return newState;
- }
- return serializer.writeArray(composite()->Length(), this);
- }
-
- private:
- unsigned m_index;
- };
-#endif
-
- class AbstractObjectState : public State<v8::Object> {
- public:
- AbstractObjectState(v8::Handle<v8::Object> object, StateBase* next)
- : State<v8::Object>(object, next)
- , m_propertyNames(object->GetPropertyNames())
- , m_index(-1)
- , m_numSerializedProperties(0)
- , m_nameDone(false)
- {
- }
-
- virtual StateBase* advance(Serializer& serializer)
- {
- ++m_index;
- for (; m_index < m_propertyNames->Length(); ++m_index) {
- if (m_propertyName.IsEmpty()) {
- v8::Local<v8::Value> propertyName = m_propertyNames->Get(m_index);
- if ((propertyName->IsString() && composite()->HasRealNamedProperty(propertyName.As<v8::String>()))
- || (propertyName->IsUint32() && composite()->HasRealIndexedProperty(propertyName->Uint32Value()))) {
- m_propertyName = propertyName;
- } else
- continue;
- }
- ASSERT(!m_propertyName.IsEmpty());
- if (!m_nameDone) {
- m_nameDone = true;
- if (StateBase* newState = serializer.doSerialize(m_propertyName, this))
- return newState;
- }
- v8::Local<v8::Value> value = composite()->Get(m_propertyName);
- m_nameDone = false;
- m_propertyName.Clear();
- ++m_numSerializedProperties;
- if (StateBase* newState = serializer.doSerialize(value, this))
- return newState;
- }
- return objectDone(m_numSerializedProperties, serializer);
- }
-
- protected:
- virtual StateBase* objectDone(unsigned numProperties, Serializer&) = 0;
-
- private:
- v8::Local<v8::Array> m_propertyNames;
- v8::Local<v8::Value> m_propertyName;
- unsigned m_index;
- unsigned m_numSerializedProperties;
- bool m_nameDone;
- };
-
- class ObjectState : public AbstractObjectState {
- public:
- ObjectState(v8::Handle<v8::Object> object, StateBase* next)
- : AbstractObjectState(object, next)
- {
- }
-
- protected:
- virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer)
- {
- return serializer.writeObject(numProperties, this);
- }
- };
-
- class SparseArrayState : public AbstractObjectState {
- public:
- SparseArrayState(v8::Handle<v8::Array> array, StateBase* next)
- : AbstractObjectState(array, next)
- {
- }
-
- protected:
- virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer)
- {
- return serializer.writeSparseArray(numProperties, composite().As<v8::Array>()->Length(), this);
- }
- };
-
- StateBase* push(StateBase* state)
- {
- ASSERT(state);
- ++m_depth;
- return checkComposite(state) ? state : handleError(state);
- }
-
- StateBase* pop(StateBase* state)
- {
- ASSERT(state);
- --m_depth;
- StateBase* next = state->nextState();
- delete state;
- return next;
- }
-
- StateBase* handleError(StateBase* state)
- {
- m_hasError = true;
- while (state) {
- StateBase* tmp = state->nextState();
- delete state;
- state = tmp;
- }
- return new ErrorState;
- }
-
- bool checkComposite(StateBase* top)
- {
- ASSERT(top);
- if (m_depth > maxDepth)
- return false;
- if (!shouldCheckForCycles(m_depth))
- return true;
- v8::Handle<v8::Value> composite = top->composite();
- for (StateBase* state = top->nextState(); state; state = state->nextState()) {
- if (state->composite() == composite)
- return false;
- }
- return true;
- }
-
- void writeString(v8::Handle<v8::Value> value)
- {
- v8::String::Utf8Value stringValue(value);
- m_writer.writeString(*stringValue, stringValue.length());
- }
-
- void writeBlob(v8::Handle<v8::Value> value)
- {
- Blob* blob = V8Blob::toNative(value.As<v8::Object>());
- if (!blob)
- return;
- m_writer.writeBlob(blob->url().string(), blob->type(), blob->size());
- }
-
- void writeFile(v8::Handle<v8::Value> value)
- {
- File* file = V8File::toNative(value.As<v8::Object>());
- if (!file)
- return;
- m_writer.writeFile(file->path(), file->url().string(), file->type());
- }
-
- void writeFileList(v8::Handle<v8::Value> value)
- {
- FileList* fileList = V8FileList::toNative(value.As<v8::Object>());
- if (!fileList)
- return;
- m_writer.writeFileList(*fileList);
- }
-
- void writeImageData(v8::Handle<v8::Value> value)
- {
- ImageData* imageData = V8ImageData::toNative(value.As<v8::Object>());
- if (!imageData)
- return;
- WTF::ByteArray* pixelArray = imageData->data()->data();
- m_writer.writeImageData(imageData->width(), imageData->height(), pixelArray->data(), pixelArray->length());
- }
-
- void writeRegExp(v8::Handle<v8::Value> value)
- {
- v8::Handle<v8::RegExp> regExp = value.As<v8::RegExp>();
- m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags());
- }
-
- static StateBase* newArrayState(v8::Handle<v8::Array> array, StateBase* next)
- {
- // FIXME: use plain Array state when we can quickly check that
- // an array is not sparse and has only indexed properties.
- return new SparseArrayState(array, next);
- }
-
- static StateBase* newObjectState(v8::Handle<v8::Object> object, StateBase* next)
- {
- // FIXME:
- // - check not a wrapper
- // - support File, etc.
- return new ObjectState(object, next);
- }
-
- Writer& m_writer;
- int m_depth;
- bool m_hasError;
-};
-
-Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, StateBase* next)
-{
- if (value->IsUndefined())
- m_writer.writeUndefined();
- else if (value->IsNull())
- m_writer.writeNull();
- else if (value->IsTrue())
- m_writer.writeTrue();
- else if (value->IsFalse())
- m_writer.writeFalse();
- else if (value->IsInt32())
- m_writer.writeInt32(value->Int32Value());
- else if (value->IsUint32())
- m_writer.writeUint32(value->Uint32Value());
- else if (value->IsDate())
- m_writer.writeDate(value->NumberValue());
- else if (value->IsNumber())
- m_writer.writeNumber(value.As<v8::Number>()->Value());
- else if (value->IsString())
- writeString(value);
- else if (value->IsArray())
- return push(newArrayState(value.As<v8::Array>(), next));
- else if (V8File::HasInstance(value))
- writeFile(value);
- else if (V8Blob::HasInstance(value))
- writeBlob(value);
- else if (V8FileList::HasInstance(value))
- writeFileList(value);
- else if (V8ImageData::HasInstance(value))
- writeImageData(value);
- else if (value->IsRegExp())
- writeRegExp(value);
- else if (value->IsObject())
- return push(newObjectState(value.As<v8::Object>(), next));
- return 0;
-}
-
-// Interface used by Reader to create objects of composite types.
-class CompositeCreator {
-public:
- virtual ~CompositeCreator() { }
-
- virtual bool createArray(uint32_t length, v8::Handle<v8::Value>* value) = 0;
- virtual bool createObject(uint32_t numProperties, v8::Handle<v8::Value>* value) = 0;
- virtual bool createSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) = 0;
-};
-
-// Reader is responsible for deserializing primitive types and
-// restoring information about saved objects of composite types.
-class Reader {
-public:
- Reader(const uint8_t* buffer, int length)
- : m_buffer(buffer)
- , m_length(length)
- , m_position(0)
- {
- ASSERT(length >= 0);
- }
-
- bool isEof() const { return m_position >= m_length; }
-
- bool read(v8::Handle<v8::Value>* value, CompositeCreator& creator)
- {
- SerializationTag tag;
- if (!readTag(&tag))
- return false;
- switch (tag) {
- 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 StringTag:
- if (!readString(value))
- return false;
- break;
- case Int32Tag:
- if (!readInt32(value))
- return false;
- break;
- case Uint32Tag:
- if (!readUint32(value))
- return false;
- break;
- case DateTag:
- if (!readDate(value))
- return false;
- break;
- case NumberTag:
- if (!readNumber(value))
- return false;
- break;
- case BlobTag:
- if (!readBlob(value))
- return false;
- break;
- case FileTag:
- if (!readFile(value))
- return false;
- break;
- case FileListTag:
- if (!readFileList(value))
- return false;
- break;
- case ImageDataTag:
- if (!readImageData(value))
- return false;
- break;
- case ArrayTag: {
- uint32_t length;
- if (!doReadUint32(&length))
- return false;
- if (!creator.createArray(length, value))
- return false;
- break;
- }
- case RegExpTag:
- if (!readRegExp(value))
- return false;
- break;
- case ObjectTag: {
- uint32_t numProperties;
- if (!doReadUint32(&numProperties))
- return false;
- if (!creator.createObject(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.createSparseArray(numProperties, length, value))
- return false;
- break;
- }
- default:
- return false;
- }
- return !value->IsEmpty();
- }
-
-private:
- bool readTag(SerializationTag* tag)
- {
- if (m_position >= m_length)
- return false;
- *tag = static_cast<SerializationTag>(m_buffer[m_position++]);
- return true;
- }
-
- bool readString(v8::Handle<v8::Value>* value)
- {
- 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);
- m_position += length;
- return true;
- }
-
- bool readWebCoreString(String* string)
- {
- uint32_t length;
- if (!doReadUint32(&length))
- return false;
- if (m_position + length > m_length)
- return false;
- *string = String::fromUTF8(reinterpret_cast<const char*>(m_buffer + m_position), length);
- m_position += length;
- return true;
- }
-
- bool readInt32(v8::Handle<v8::Value>* value)
- {
- uint32_t rawValue;
- if (!doReadUint32(&rawValue))
- return false;
- *value = v8::Integer::New(static_cast<int32_t>(ZigZag::decode(rawValue)));
- return true;
- }
-
- bool readUint32(v8::Handle<v8::Value>* value)
- {
- uint32_t rawValue;
- if (!doReadUint32(&rawValue))
- return false;
- *value = v8::Integer::NewFromUnsigned(rawValue);
- return true;
- }
-
- bool readDate(v8::Handle<v8::Value>* value)
- {
- double numberValue;
- if (!doReadNumber(&numberValue))
- return false;
- *value = v8::Date::New(numberValue);
- return true;
- }
-
- bool readNumber(v8::Handle<v8::Value>* value)
- {
- double number;
- if (!doReadNumber(&number))
- return false;
- *value = v8::Number::New(number);
- return true;
- }
-
- bool readImageData(v8::Handle<v8::Value>* value)
- {
- uint32_t width;
- uint32_t height;
- uint32_t pixelDataLength;
- if (!doReadUint32(&width))
- return false;
- if (!doReadUint32(&height))
- return false;
- if (!doReadUint32(&pixelDataLength))
- return false;
- if (m_position + pixelDataLength > m_length)
- return false;
- PassRefPtr<ImageData> imageData = ImageData::create(width, height);
- WTF::ByteArray* pixelArray = imageData->data()->data();
- ASSERT(pixelArray);
- ASSERT(pixelArray->length() >= pixelDataLength);
- memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength);
- m_position += pixelDataLength;
- *value = toV8(imageData);
- return true;
- }
-
- bool readRegExp(v8::Handle<v8::Value>* value)
- {
- v8::Handle<v8::Value> pattern;
- if (!readString(&pattern))
- return false;
- uint32_t flags;
- if (!doReadUint32(&flags))
- return false;
- *value = v8::RegExp::New(pattern.As<v8::String>(), static_cast<v8::RegExp::Flags>(flags));
- return true;
- }
-
- bool readBlob(v8::Handle<v8::Value>* value)
- {
- 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);
- return true;
- }
-
- bool readFile(v8::Handle<v8::Value>* value)
- {
- String path;
- String url;
- String type;
- if (!readWebCoreString(&path))
- return false;
- if (!readWebCoreString(&url))
- return false;
- if (!readWebCoreString(&type))
- return false;
- PassRefPtr<File> file = File::create(path, KURL(ParsedURLString, url), type);
- *value = toV8(file);
- return true;
- }
-
- bool readFileList(v8::Handle<v8::Value>* value)
- {
- uint32_t length;
- if (!doReadUint32(&length))
- return false;
- PassRefPtr<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))
- return false;
- if (!readWebCoreString(&type))
- return false;
- fileList->append(File::create(path, KURL(ParsedURLString, urlString), type));
- }
- *value = toV8(fileList);
- return true;
- }
-
- template<class T>
- bool doReadUintHelper(T* value)
- {
- *value = 0;
- uint8_t currentByte;
- int shift = 0;
- do {
- if (m_position >= m_length)
- return false;
- currentByte = m_buffer[m_position++];
- *value |= ((currentByte & varIntMask) << shift);
- shift += varIntShift;
- } while (currentByte & (1 << varIntShift));
- return true;
- }
-
- bool doReadUint32(uint32_t* value)
- {
- return doReadUintHelper(value);
- }
-
- bool doReadUint64(uint64_t* value)
- {
- return doReadUintHelper(value);
- }
-
- bool doReadNumber(double* number)
- {
- if (m_position + sizeof(double) > m_length)
- return false;
- uint8_t* numberAsByteArray = reinterpret_cast<uint8_t*>(number);
- for (unsigned i = 0; i < sizeof(double); ++i)
- numberAsByteArray[i] = m_buffer[m_position++];
- return true;
- }
-
- const uint8_t* m_buffer;
- const unsigned m_length;
- unsigned m_position;
-};
-
-class Deserializer : public CompositeCreator {
-public:
- explicit Deserializer(Reader& reader)
- : m_reader(reader)
- {
- }
-
- v8::Handle<v8::Value> deserialize()
- {
- v8::HandleScope scope;
- while (!m_reader.isEof()) {
- if (!doDeserialize())
- return v8::Null();
- }
- if (stackDepth() != 1)
- return v8::Null();
- return scope.Close(element(0));
- }
-
- virtual bool createArray(uint32_t length, v8::Handle<v8::Value>* value)
- {
- if (length > stackDepth())
- return false;
- v8::Local<v8::Array> array = v8::Array::New(length);
- if (array.IsEmpty())
- return false;
- const int depth = stackDepth() - length;
- for (unsigned i = 0; i < length; ++i)
- array->Set(i, element(depth + i));
- pop(length);
- *value = array;
- return true;
- }
-
- virtual bool createObject(uint32_t numProperties, v8::Handle<v8::Value>* value)
- {
- v8::Local<v8::Object> object = v8::Object::New();
- if (object.IsEmpty())
- return false;
- return initializeObject(object, numProperties, value);
- }
-
- virtual bool createSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value)
- {
- v8::Local<v8::Array> array = v8::Array::New(length);
- if (array.IsEmpty())
- return false;
- return initializeObject(array, numProperties, value);
- }
-
-private:
- bool initializeObject(v8::Handle<v8::Object> object, uint32_t numProperties, v8::Handle<v8::Value>* value)
- {
- 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);
- object->Set(propertyName, propertyValue);
- }
- pop(length);
- *value = object;
- return true;
- }
-
- bool doDeserialize()
- {
- v8::Local<v8::Value> value;
- if (!m_reader.read(&value, *this))
- return false;
- if (!value.IsEmpty())
- push(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);
- }
-
- unsigned stackDepth() const { return m_stack.size(); }
-
- v8::Local<v8::Value> element(unsigned index)
- {
- ASSERT(index < m_stack.size());
- return m_stack[index];
- }
-
- Reader& m_reader;
- Vector<v8::Local<v8::Value> > m_stack;
-};
-
-} // namespace
-
-void SerializedScriptValue::deserializeAndSetProperty(v8::Handle<v8::Object> object, const char* propertyName,
- v8::PropertyAttribute attribute, SerializedScriptValue* value)
-{
- if (!value)
- return;
- v8::Handle<v8::Value> deserialized = value->deserialize();
- object->ForceSet(v8::String::NewSymbol(propertyName), deserialized, attribute);
-}
-
-PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value, bool& didThrow)
-{
- return adoptRef(new SerializedScriptValue(value, didThrow));
-}
-
-PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value)
-{
- bool didThrow;
- return adoptRef(new SerializedScriptValue(value, didThrow));
-}
-
-PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWire(String data)
-{
- return adoptRef(new SerializedScriptValue(data, WireData));
-}
-
-PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(String data)
-{
- return adoptRef(new SerializedScriptValue(data, StringValue));
-}
-
-PassRefPtr<SerializedScriptValue> SerializedScriptValue::create()
-{
- return adoptRef(new SerializedScriptValue());
-}
-
-SerializedScriptValue* SerializedScriptValue::nullValue()
-{
- DEFINE_STATIC_LOCAL(RefPtr<SerializedScriptValue>, nullValue, (SerializedScriptValue::create()));
- return nullValue.get();
-}
-
-PassRefPtr<SerializedScriptValue> SerializedScriptValue::release()
-{
- RefPtr<SerializedScriptValue> result = adoptRef(new SerializedScriptValue(m_data, WireData));
- m_data = String().crossThreadString();
- return result.release();
-}
-
-SerializedScriptValue::SerializedScriptValue()
-{
-}
-
-SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, bool& didThrow)
-{
- didThrow = false;
- Writer writer;
- Serializer serializer(writer);
- if (!serializer.serialize(value)) {
- throwError(NOT_SUPPORTED_ERR);
- didThrow = true;
- return;
- }
- m_data = String(StringImpl::adopt(writer.data())).crossThreadString();
-}
-
-SerializedScriptValue::SerializedScriptValue(String data, StringDataMode mode)
-{
- if (mode == WireData)
- m_data = data.crossThreadString();
- else {
- ASSERT(mode == StringValue);
- Writer writer;
- writer.writeWebCoreString(data);
- m_data = String(StringImpl::adopt(writer.data())).crossThreadString();
- }
-}
-
-v8::Handle<v8::Value> SerializedScriptValue::deserialize()
-{
- if (!m_data.impl())
- 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);
- return deserializer.deserialize();
-}
-
-} // namespace WebCore