Changeset 57145 in webkit


Ignore:
Timestamp:
Apr 6, 2010 6:33:32 AM (14 years ago)
Author:
vitalyr@chromium.org
Message:

2010-04-06 Vitaly Repeshko <vitalyr@chromium.org>

Reviewed by Yury Semikhatsky.

[V8] Extend the set of types supported by SerializedScriptValue
https://bugs.webkit.org/show_bug.cgi?id=37052

New types include sparse arrays, Uint32, Date, and ImageData.

Serialization process became more flexible. A state can either
directly write primitive values (instead of returning them like
iterator) or construct a new state for serializing complex values
that will return to the current state when done.

Deserialization process now avoids exposing the tags using a set
of factory functions for complex objects instead.

Internal buffer type changed to uint8_t to be independent of
whether char is signed or not.

  • bindings/v8/SerializedScriptValue.cpp: (WebCore::): (WebCore::Writer::Writer): (WebCore::Writer::writeString): (WebCore::Writer::writeUint32): (WebCore::Writer::writeDate): (WebCore::Writer::writeNumber): (WebCore::Writer::writeImageData): (WebCore::Writer::writeArray): (WebCore::Writer::writeObject): (WebCore::Writer::writeSparseArray): (WebCore::Writer::doWriteUint32): (WebCore::Writer::doWriteNumber): (WebCore::Writer::append): (WebCore::Writer::fillHole): (WebCore::Writer::byteAt): (WebCore::Serializer::Serializer): (WebCore::Serializer::serialize): (WebCore::Serializer::writeArray): (WebCore::Serializer::writeObject): (WebCore::Serializer::writeSparseArray): (WebCore::Serializer::StateBase::StateBase): (WebCore::Serializer::ErrorState::ErrorState): (WebCore::Serializer::ErrorState::advance): (WebCore::Serializer::State::composite): (WebCore::Serializer::State::State): (WebCore::Serializer::ArrayState::ArrayState): (WebCore::Serializer::ArrayState::advance): (WebCore::Serializer::AbstractObjectState::AbstractObjectState): (WebCore::Serializer::AbstractObjectState::advance): (WebCore::Serializer::ObjectState::ObjectState): (WebCore::Serializer::ObjectState::objectDone): (WebCore::Serializer::SparseArrayState::SparseArrayState): (WebCore::Serializer::SparseArrayState::objectDone): (WebCore::Serializer::push): (WebCore::Serializer::pop): (WebCore::Serializer::handleError): (WebCore::Serializer::checkComposite): (WebCore::Serializer::writeString): (WebCore::Serializer::writeImageData): (WebCore::Serializer::newArrayState): (WebCore::Serializer::newObjectState): (WebCore::Serializer::doSerialize): (WebCore::Reader::Reader): (WebCore::Reader::read): (WebCore::Reader::readString): (WebCore::Reader::readUint32): (WebCore::Reader::readDate): (WebCore::Reader::readNumber): (WebCore::Reader::readImageData): (WebCore::Reader::doReadUint32): (WebCore::Reader::doReadNumber): (WebCore::Deserializer::Deserializer): (WebCore::Deserializer::createArray): (WebCore::Deserializer::createObject): (WebCore::Deserializer::createSparseArray): (WebCore::Deserializer::initializeObject): (WebCore::Deserializer::doDeserialize): (WebCore::Deserializer::stackDepth): (WebCore::SerializedScriptValue::deserialize):
Location:
trunk/WebCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r57141 r57145  
     12010-04-06  Vitaly Repeshko  <vitalyr@chromium.org>
     2
     3        Reviewed by Yury Semikhatsky.
     4
     5        [V8] Extend the set of types supported by SerializedScriptValue
     6        https://bugs.webkit.org/show_bug.cgi?id=37052
     7
     8        New types include sparse arrays, Uint32, Date, and ImageData.
     9
     10        Serialization process became more flexible. A state can either
     11        directly write primitive values (instead of returning them like
     12        iterator) or construct a new state for serializing complex values
     13        that will return to the current state when done.
     14
     15        Deserialization process now avoids exposing the tags using a set
     16        of factory functions for complex objects instead.
     17
     18        Internal buffer type changed to uint8_t to be independent of
     19        whether char is signed or not.
     20
     21        * bindings/v8/SerializedScriptValue.cpp:
     22        (WebCore::):
     23        (WebCore::Writer::Writer):
     24        (WebCore::Writer::writeString):
     25        (WebCore::Writer::writeUint32):
     26        (WebCore::Writer::writeDate):
     27        (WebCore::Writer::writeNumber):
     28        (WebCore::Writer::writeImageData):
     29        (WebCore::Writer::writeArray):
     30        (WebCore::Writer::writeObject):
     31        (WebCore::Writer::writeSparseArray):
     32        (WebCore::Writer::doWriteUint32):
     33        (WebCore::Writer::doWriteNumber):
     34        (WebCore::Writer::append):
     35        (WebCore::Writer::fillHole):
     36        (WebCore::Writer::byteAt):
     37        (WebCore::Serializer::Serializer):
     38        (WebCore::Serializer::serialize):
     39        (WebCore::Serializer::writeArray):
     40        (WebCore::Serializer::writeObject):
     41        (WebCore::Serializer::writeSparseArray):
     42        (WebCore::Serializer::StateBase::StateBase):
     43        (WebCore::Serializer::ErrorState::ErrorState):
     44        (WebCore::Serializer::ErrorState::advance):
     45        (WebCore::Serializer::State::composite):
     46        (WebCore::Serializer::State::State):
     47        (WebCore::Serializer::ArrayState::ArrayState):
     48        (WebCore::Serializer::ArrayState::advance):
     49        (WebCore::Serializer::AbstractObjectState::AbstractObjectState):
     50        (WebCore::Serializer::AbstractObjectState::advance):
     51        (WebCore::Serializer::ObjectState::ObjectState):
     52        (WebCore::Serializer::ObjectState::objectDone):
     53        (WebCore::Serializer::SparseArrayState::SparseArrayState):
     54        (WebCore::Serializer::SparseArrayState::objectDone):
     55        (WebCore::Serializer::push):
     56        (WebCore::Serializer::pop):
     57        (WebCore::Serializer::handleError):
     58        (WebCore::Serializer::checkComposite):
     59        (WebCore::Serializer::writeString):
     60        (WebCore::Serializer::writeImageData):
     61        (WebCore::Serializer::newArrayState):
     62        (WebCore::Serializer::newObjectState):
     63        (WebCore::Serializer::doSerialize):
     64        (WebCore::Reader::Reader):
     65        (WebCore::Reader::read):
     66        (WebCore::Reader::readString):
     67        (WebCore::Reader::readUint32):
     68        (WebCore::Reader::readDate):
     69        (WebCore::Reader::readNumber):
     70        (WebCore::Reader::readImageData):
     71        (WebCore::Reader::doReadUint32):
     72        (WebCore::Reader::doReadNumber):
     73        (WebCore::Deserializer::Deserializer):
     74        (WebCore::Deserializer::createArray):
     75        (WebCore::Deserializer::createObject):
     76        (WebCore::Deserializer::createSparseArray):
     77        (WebCore::Deserializer::initializeObject):
     78        (WebCore::Deserializer::doDeserialize):
     79        (WebCore::Deserializer::stackDepth):
     80        (WebCore::SerializedScriptValue::deserialize):
     81
    1822010-04-06  Csaba Osztrogonác  <ossy@webkit.org>
    283
  • trunk/WebCore/bindings/v8/SerializedScriptValue.cpp

    r57133 r57145  
    3232#include "SerializedScriptValue.h"
    3333
     34#include "ByteArray.h"
     35#include "CanvasPixelArray.h"
     36#include "ImageData.h"
    3437#include "SharedBuffer.h"
     38#include "V8ImageData.h"
    3539
    3640#include <v8.h>
     
    4145// FIXME:
    4246// - catch V8 exceptions
    43 // - be ready to get empty handles
    4447// - consider crashing in debug mode on deserialization errors
    4548
     
    6164    StringTag = 'S',
    6265    Int32Tag = 'I',
     66    Uint32Tag = 'U',
     67    DateTag = 'D',
    6368    NumberTag = 'N',
     69    ImageDataTag = '#',
     70    ArrayTag = '[',
    6471    ObjectTag = '{',
    65     ArrayTag = '[',
     72    SparseArrayTag = '@',
    6673};
    67 
    68 // Helpers to do verbose handle casts.
    69 
    70 template <typename T, typename U>
    71 static v8::Handle<T> handleCast(v8::Handle<U> handle) { return v8::Handle<T>::Cast(handle); }
    72 
    73 template <typename T, typename U>
    74 static v8::Local<T> handleCast(v8::Local<U> handle) { return v8::Local<T>::Cast(handle); }
    7574
    7675static bool shouldCheckForCycles(int depth)
     
    119118class Writer : Noncopyable {
    120119public:
    121     Writer() : m_position(0)
     120    Writer()
     121        : m_position(0)
    122122    {
    123123    }
     
    135135    void writeString(const char* data, int length)
    136136    {
     137        ASSERT(length >= 0);
    137138        append(StringTag);
    138139        doWriteUint32(static_cast<uint32_t>(length));
    139         append(data, length);
     140        append(reinterpret_cast<const uint8_t*>(data), length);
    140141    }
    141142
     
    146147    }
    147148
     149    void writeUint32(uint32_t value)
     150    {
     151        append(Uint32Tag);
     152        doWriteUint32(value);
     153    }
     154
     155    void writeDate(double numberValue)
     156    {
     157        append(DateTag);
     158        doWriteNumber(numberValue);
     159    }
     160
    148161    void writeNumber(double number)
    149162    {
    150163        append(NumberTag);
    151         append(reinterpret_cast<char*>(&number), sizeof(number));
    152     }
    153 
    154     // Records that a composite object can be constructed by using
    155     // |length| previously stored values.
    156     void endComposite(SerializationTag tag, int32_t length)
    157     {
    158         ASSERT(tag == ObjectTag || tag == ArrayTag);
    159         append(tag);
    160         doWriteUint32(static_cast<uint32_t>(length));
     164        doWriteNumber(number);
     165    }
     166
     167    void writeImageData(uint32_t width, uint32_t height, const uint8_t* pixelData, uint32_t pixelDataLength)
     168    {
     169        append(ImageDataTag);
     170        doWriteUint32(width);
     171        doWriteUint32(height);
     172        doWriteUint32(pixelDataLength);
     173        append(pixelData, pixelDataLength);
     174    }
     175
     176    void writeArray(uint32_t length)
     177    {
     178        append(ArrayTag);
     179        doWriteUint32(length);
     180    }
     181
     182    void writeObject(uint32_t numProperties)
     183    {
     184        append(ObjectTag);
     185        doWriteUint32(numProperties);
     186    }
     187
     188    void writeSparseArray(uint32_t numProperties, uint32_t length)
     189    {
     190        append(SparseArrayTag);
     191        doWriteUint32(numProperties);
     192        doWriteUint32(length);
    161193    }
    162194
     
    171203    {
    172204        while (true) {
    173             char b = (value & varIntMask);
     205            uint8_t b = (value & varIntMask);
    174206            value >>= varIntShift;
    175207            if (!value) {
     
    181213    }
    182214
     215    void doWriteNumber(double number)
     216    {
     217        append(reinterpret_cast<uint8_t*>(&number), sizeof(number));
     218    }
     219
    183220    void append(SerializationTag tag)
    184221    {
    185         append(static_cast<char>(tag));
    186     }
    187 
    188     void append(char b)
     222        append(static_cast<uint8_t>(tag));
     223    }
     224
     225    void append(uint8_t b)
    189226    {
    190227        ensureSpace(1);
    191         *charAt(m_position++) = b;
    192     }
    193 
    194     void append(const char* data, int length)
     228        *byteAt(m_position++) = b;
     229    }
     230
     231    void append(const uint8_t* data, int length)
    195232    {
    196233        ensureSpace(length);
    197         memcpy(charAt(m_position), data, length);
     234        memcpy(byteAt(m_position), data, length);
    198235        m_position += length;
    199236    }
     
    211248        // the bytes in the last UChar is not initialized.
    212249        if (m_position % 2)
    213             *charAt(m_position) = static_cast<char>(PaddingTag);
    214     }
    215 
    216     char* charAt(int position) { return reinterpret_cast<char*>(m_buffer.data()) + position; }
     250            *byteAt(m_position) = static_cast<uint8_t>(PaddingTag);
     251    }
     252
     253    uint8_t* byteAt(int position) { return reinterpret_cast<uint8_t*>(m_buffer.data()) + position; }
    217254
    218255    Vector<BufferValueType> m_buffer;
     
    221258
    222259class Serializer {
     260    class StateBase;
    223261public:
    224262    explicit Serializer(Writer& writer)
    225263        : m_writer(writer)
    226         , m_state(0)
    227264        , m_depth(0)
     265        , m_hasError(false)
    228266    {
    229267    }
     
    232270    {
    233271        v8::HandleScope scope;
    234         StackCleaner cleaner(&m_state);
    235         if (!doSerialize(value))
    236             return false;
    237         while (top()) {
    238             int length;
    239             while (!top()->isDone(&length)) {
    240                 // Note that doSerialize() can change current top().
    241                 if (!doSerialize(top()->advance()))
    242                     return false;
    243             }
    244             m_writer.endComposite(top()->tag(), length);
    245             pop();
    246         }
    247         return true;
     272        StateBase* state = doSerialize(value, 0);
     273        while (state)
     274            state = state->advance(*this);
     275        return !m_hasError;
     276    }
     277
     278    // Functions used by serialization states.
     279
     280    StateBase* doSerialize(v8::Handle<v8::Value> value, StateBase* next);
     281
     282    StateBase* writeArray(uint32_t length, StateBase* state)
     283    {
     284        m_writer.writeArray(length);
     285        return pop(state);
     286    }
     287
     288    StateBase* writeObject(uint32_t numProperties, StateBase* state)
     289    {
     290        m_writer.writeObject(numProperties);
     291        return pop(state);
     292    }
     293
     294    StateBase* writeSparseArray(uint32_t numProperties, uint32_t length, StateBase* state)
     295    {
     296        m_writer.writeSparseArray(numProperties, length);
     297        return pop(state);
    248298    }
    249299
     
    255305        // Link to the next state to form a stack.
    256306        StateBase* nextState() { return m_next; }
    257         void setNextState(StateBase* next) { m_next = next; }
    258307
    259308        // Composite object we're processing in this state.
    260309        v8::Handle<v8::Value> composite() { return m_composite; }
    261310
    262         // Serialization tag for the current composite.
    263         virtual SerializationTag tag() const = 0;
    264 
    265         // Returns whether iteration over subobjects of the current
    266         // composite object is done. If yes, |*length| is set to the
    267         // number of subobjects.
    268         virtual bool isDone(int* length) = 0;
    269 
    270         // Advances to the next subobject.
    271         // Requires: !this->isDone().
    272         virtual v8::Local<v8::Value> advance() = 0;
     311        // Serializes (a part of) the current composite and returns
     312        // the next state to process or null when this is the final
     313        // state.
     314        virtual StateBase* advance(Serializer&) = 0;
    273315
    274316    protected:
    275         StateBase(v8::Handle<v8::Value> composite)
    276             : m_next(0)
    277             , m_composite(composite)
     317        StateBase(v8::Handle<v8::Value> composite, StateBase* next)
     318            : m_composite(composite)
     319            , m_next(next)
    278320        {
    279321        }
    280322
    281323    private:
     324        v8::Handle<v8::Value> m_composite;
    282325        StateBase* m_next;
    283         v8::Handle<v8::Value> m_composite;
    284326    };
    285327
    286     template <typename T, SerializationTag compositeTag>
     328    // Dummy state that is used to signal serialization errors.
     329    class ErrorState : public StateBase {
     330    public:
     331        ErrorState()
     332            : StateBase(v8::Handle<v8::Value>(), 0)
     333        {
     334        }
     335
     336        virtual StateBase* advance(Serializer&)
     337        {
     338            delete this;
     339            return 0;
     340        }
     341    };
     342
     343    template <typename T>
    287344    class State : public StateBase {
    288345    public:
    289         v8::Handle<T> composite() { return handleCast<T>(StateBase::composite()); }
    290 
    291         virtual SerializationTag tag() const { return compositeTag; }
     346        v8::Handle<T> composite() { return v8::Handle<T>::Cast(StateBase::composite()); }
    292347
    293348    protected:
    294         explicit State(v8::Handle<T> composite) : StateBase(composite)
     349        State(v8::Handle<T> composite, StateBase* next)
     350            : StateBase(composite, next)
    295351        {
    296352        }
    297353    };
    298354
    299     // Helper to clean up the state stack in case of errors.
    300     class StackCleaner : Noncopyable {
     355#if 0
     356    // Currently unused, see comment in newArrayState.
     357    class ArrayState : public State<v8::Array> {
    301358    public:
    302         explicit StackCleaner(StateBase** stack) : m_stack(stack)
    303         {
    304         }
    305 
    306         ~StackCleaner()
    307         {
    308             StateBase* state = *m_stack;
    309             while (state) {
    310                 StateBase* tmp = state->nextState();
    311                 delete state;
    312                 state = tmp;
     359        ArrayState(v8::Handle<v8::Array> array, StateBase* next)
     360            : State<v8::Array>(array, next)
     361            , m_index(-1)
     362        {
     363        }
     364
     365        virtual StateBase* advance(Serializer& serializer)
     366        {
     367            ++m_index;
     368            for (; m_index < composite()->Length(); ++m_index) {
     369                if (StateBase* newState = serializer.doSerialize(composite()->Get(m_index), this))
     370                    return newState;
    313371            }
    314             *m_stack = 0;
    315         }
    316 
    317     private:
    318         StateBase** m_stack;
    319     };
    320 
    321     class ArrayState : public State<v8::Array, ArrayTag> {
    322     public:
    323         ArrayState(v8::Handle<v8::Array> array)
    324             : State<v8::Array, ArrayTag>(array)
    325             , m_index(0)
    326         {
    327         }
    328 
    329         virtual bool isDone(int* length)
    330         {
    331             *length = composite()->Length();
    332             return static_cast<int>(m_index) >= *length;
    333         }
    334 
    335         virtual v8::Local<v8::Value> advance()
    336         {
    337             ASSERT(m_index < composite()->Length());
    338             v8::HandleScope scope;
    339             return scope.Close(composite()->Get(v8::Integer::New(m_index++)));
     372            return serializer.writeArray(composite()->Length(), this);
    340373        }
    341374
     
    343376        unsigned m_index;
    344377    };
    345 
    346     class ObjectState : public State<v8::Object, ObjectTag> {
     378#endif
     379
     380    class AbstractObjectState : public State<v8::Object> {
    347381    public:
    348         ObjectState(v8::Handle<v8::Object> object)
    349             : State<v8::Object, ObjectTag>(object)
     382        AbstractObjectState(v8::Handle<v8::Object> object, StateBase* next)
     383            : State<v8::Object>(object, next)
    350384            , m_propertyNames(object->GetPropertyNames())
    351385            , m_index(-1)
    352             , m_length(0)
    353         {
    354             nextProperty();
    355         }
    356 
    357         virtual bool isDone(int* length)
    358         {
    359             *length = m_length;
    360             return m_index >= 2 * m_propertyNames->Length();
    361         }
    362 
    363         virtual v8::Local<v8::Value> advance()
    364         {
    365             ASSERT(m_index < 2 * m_propertyNames->Length());
    366             if (!(m_index % 2)) {
    367                 ++m_index;
    368                 return m_propertyName;
     386            , m_nameDone(false)
     387        {
     388        }
     389
     390        virtual StateBase* advance(Serializer& serializer)
     391        {
     392            ++m_index;
     393            for (; m_index < m_propertyNames->Length(); ++m_index) {
     394                if (m_propertyName.IsEmpty()) {
     395                    v8::Local<v8::Value> propertyName = m_propertyNames->Get(m_index);
     396                    if ((propertyName->IsString() && composite()->HasRealNamedProperty(propertyName.As<v8::String>()))
     397                        || (propertyName->IsUint32() && composite()->HasRealIndexedProperty(propertyName->Uint32Value()))) {
     398                        m_propertyName = propertyName;
     399                    } else
     400                        continue;
     401                }
     402                ASSERT(!m_propertyName.IsEmpty());
     403                if (!m_nameDone) {
     404                    m_nameDone = true;
     405                    if (StateBase* newState = serializer.doSerialize(m_propertyName, this))
     406                        return newState;
     407                }
     408                v8::Local<v8::Value> value = composite()->Get(m_propertyName);
     409                m_nameDone = false;
     410                m_propertyName.Clear();
     411                if (StateBase* newState = serializer.doSerialize(value, this))
     412                    return newState;
    369413            }
    370             v8::Local<v8::Value> result = composite()->Get(m_propertyName);
    371             nextProperty();
    372             return result;
    373         }
     414            return objectDone(m_index, serializer);
     415        }
     416
     417    protected:
     418        virtual StateBase* objectDone(unsigned numProperties, Serializer&) = 0;
    374419
    375420    private:
    376         void nextProperty()
    377         {
    378             v8::HandleScope scope;
    379             ++m_index;
    380             ASSERT(!(m_index % 2));
    381             for (; m_index < 2 * m_propertyNames->Length(); m_index += 2) {
    382                 v8::Local<v8::Value> propertyName = m_propertyNames->Get(v8::Integer::New(m_index / 2));
    383                 if ((propertyName->IsString() && composite()->HasRealNamedProperty(handleCast<v8::String>(propertyName)))
    384                     || (propertyName->IsInt32() && composite()->HasRealIndexedProperty(propertyName->Uint32Value()))) {
    385                     m_propertyName = scope.Close(propertyName);
    386                     m_length += 2;
    387                     return;
    388                 }
    389             }
    390         }
    391 
    392421        v8::Local<v8::Array> m_propertyNames;
    393422        v8::Local<v8::Value> m_propertyName;
    394423        unsigned m_index;
    395         unsigned m_length;
     424        bool m_nameDone;
    396425    };
    397426
    398     bool doSerialize(v8::Handle<v8::Value> value)
    399     {
    400         if (value->IsUndefined())
    401             m_writer.writeUndefined();
    402         else if (value->IsNull())
    403             m_writer.writeNull();
    404         else if (value->IsTrue())
    405             m_writer.writeTrue();
    406         else if (value->IsFalse())
    407             m_writer.writeFalse();
    408         else if (value->IsInt32())
    409             m_writer.writeInt32(value->Int32Value());
    410         else if (value->IsNumber())
    411             m_writer.writeNumber(handleCast<v8::Number>(value)->Value());
    412         else if (value->IsString()) {
    413             v8::String::Utf8Value stringValue(value);
    414             m_writer.writeString(*stringValue, stringValue.length());
    415         } else if (value->IsArray()) {
    416             if (!checkComposite(value))
    417                 return false;
    418             push(new ArrayState(handleCast<v8::Array>(value)));
    419         } else if (value->IsObject()) {
    420             if (!checkComposite(value))
    421                 return false;
    422             push(new ObjectState(handleCast<v8::Object>(value)));
    423             // FIXME:
    424             // - check not a wrapper
    425             // - support File, ImageData, etc.
    426         }
    427         return true;
    428     }
    429 
    430     void push(StateBase* state)
    431     {
    432         state->setNextState(m_state);
    433         m_state = state;
     427    class ObjectState : public AbstractObjectState {
     428    public:
     429        ObjectState(v8::Handle<v8::Object> object, StateBase* next)
     430            : AbstractObjectState(object, next)
     431        {
     432        }
     433
     434    protected:
     435        virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer)
     436        {
     437            return serializer.writeObject(numProperties, this);
     438        }
     439    };
     440
     441    class SparseArrayState : public AbstractObjectState {
     442    public:
     443        SparseArrayState(v8::Handle<v8::Array> array, StateBase* next)
     444            : AbstractObjectState(array, next)
     445        {
     446        }
     447
     448    protected:
     449        virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer)
     450        {
     451            return serializer.writeSparseArray(numProperties, composite().As<v8::Array>()->Length(), this);
     452        }
     453    };
     454
     455    StateBase* push(StateBase* state)
     456    {
     457        ASSERT(state);
    434458        ++m_depth;
    435     }
    436 
    437     StateBase* top() { return m_state; }
    438 
    439     void pop()
    440     {
    441         if (!m_state)
    442             return;
    443         StateBase* top = m_state;
    444         m_state = top->nextState();
    445         delete top;
     459        return checkComposite(state) ? state : handleError(state);
     460    }
     461
     462    StateBase* pop(StateBase* state)
     463    {
     464        ASSERT(state);
    446465        --m_depth;
    447     }
    448 
    449     bool checkComposite(v8::Handle<v8::Value> composite)
    450     {
     466        StateBase* next = state->nextState();
     467        delete state;
     468        return next;
     469    }
     470
     471    StateBase* handleError(StateBase* state)
     472    {
     473        m_hasError = true;
     474        while (state) {
     475            StateBase* tmp = state->nextState();
     476            delete state;
     477            state = tmp;
     478        }
     479        return new ErrorState;
     480    }
     481
     482    bool checkComposite(StateBase* top)
     483    {
     484        ASSERT(top);
    451485        if (m_depth > maxDepth)
    452486            return false;
    453487        if (!shouldCheckForCycles(m_depth))
    454488            return true;
    455         for (StateBase* state = top(); state; state = state->nextState()) {
     489        v8::Handle<v8::Value> composite = top->composite();
     490        for (StateBase* state = top->nextState(); state; state = state->nextState()) {
    456491            if (state->composite() == composite)
    457492                return false;
     
    460495    }
    461496
     497    void writeString(v8::Handle<v8::Value> value)
     498    {
     499        v8::String::Utf8Value stringValue(value);
     500        m_writer.writeString(*stringValue, stringValue.length());
     501    }
     502
     503    void writeImageData(v8::Handle<v8::Value> value)
     504    {
     505        ImageData* imageData = V8ImageData::toNative(value.As<v8::Object>());
     506        if (!imageData)
     507            return;
     508        WTF::ByteArray* pixelArray = imageData->data()->data();
     509        m_writer.writeImageData(imageData->width(), imageData->height(), pixelArray->data(), pixelArray->length());
     510    }
     511
     512    static StateBase* newArrayState(v8::Handle<v8::Array> array, StateBase* next)
     513    {
     514        // FIXME: use plain Array state when we can quickly check that
     515        // an array is not sparse and has only indexed properties.
     516        return new SparseArrayState(array, next);
     517    }
     518
     519    static StateBase* newObjectState(v8::Handle<v8::Object> object, StateBase* next)
     520    {
     521        // FIXME:
     522        // - check not a wrapper
     523        // - support File, etc.
     524        return new ObjectState(object, next);
     525    }
     526
    462527    Writer& m_writer;
    463     StateBase* m_state;
    464528    int m_depth;
     529    bool m_hasError;
     530};
     531
     532Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, StateBase* next)
     533{
     534    if (value->IsUndefined())
     535        m_writer.writeUndefined();
     536    else if (value->IsNull())
     537        m_writer.writeNull();
     538    else if (value->IsTrue())
     539        m_writer.writeTrue();
     540    else if (value->IsFalse())
     541        m_writer.writeFalse();
     542    else if (value->IsInt32())
     543        m_writer.writeInt32(value->Int32Value());
     544    else if (value->IsUint32())
     545        m_writer.writeUint32(value->Uint32Value());
     546    else if (value->IsDate())
     547        m_writer.writeDate(value->NumberValue());
     548    else if (value->IsNumber())
     549        m_writer.writeNumber(value.As<v8::Number>()->Value());
     550    else if (value->IsString())
     551        writeString(value);
     552    else if (value->IsArray())
     553        return push(newArrayState(value.As<v8::Array>(), next));
     554    else if (V8ImageData::HasInstance(value))
     555        writeImageData(value);
     556    else if (value->IsObject())
     557        return push(newObjectState(value.As<v8::Object>(), next));
     558    return 0;
     559}
     560
     561// Interface used by Reader to create objects of composite types.
     562class CompositeCreator {
     563public:
     564    virtual ~CompositeCreator() { }
     565
     566    virtual bool createArray(uint32_t length, v8::Handle<v8::Value>* value) = 0;
     567    virtual bool createObject(uint32_t numProperties, v8::Handle<v8::Value>* value) = 0;
     568    virtual bool createSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) = 0;
    465569};
    466570
     
    469573class Reader {
    470574public:
    471     Reader(const char* buffer, int length)
     575    Reader(const uint8_t* buffer, int length)
    472576        : m_buffer(buffer)
    473577        , m_length(length)
     
    479583    bool isEof() const { return m_position >= m_length; }
    480584
    481     bool read(SerializationTag* tag, v8::Handle<v8::Value>* value, int* length)
    482     {
    483         uint32_t rawLength;
    484         if (!readTag(tag))
    485             return false;
    486         switch (*tag) {
     585    bool read(v8::Handle<v8::Value>* value, CompositeCreator& creator)
     586    {
     587        SerializationTag tag;
     588        if (!readTag(&tag))
     589            return false;
     590        switch (tag) {
    487591        case InvalidTag:
    488592            return false;
    489593        case PaddingTag:
    490             break;
     594            return true;
    491595        case UndefinedTag:
    492596            *value = v8::Undefined();
     
    509613                return false;
    510614            break;
     615        case Uint32Tag:
     616            if (!readUint32(value))
     617                return false;
     618            break;
     619        case DateTag:
     620            if (!readDate(value))
     621                return false;
     622            break;
    511623        case NumberTag:
    512624            if (!readNumber(value))
    513625                return false;
    514626            break;
    515         case ObjectTag:
    516         case ArrayTag:
    517             if (!doReadUint32(&rawLength))
    518                 return false;
    519             *length = rawLength;
    520             break;
    521         }
    522         return true;
     627        case ImageDataTag:
     628            if (!readImageData(value))
     629                return false;
     630            break;
     631        case ArrayTag: {
     632            uint32_t length;
     633            if (!doReadUint32(&length))
     634                return false;
     635            if (!creator.createArray(length, value))
     636                return false;
     637            break;
     638        }
     639        case ObjectTag: {
     640            uint32_t numProperties;
     641            if (!doReadUint32(&numProperties))
     642                return false;
     643            if (!creator.createObject(numProperties, value))
     644                return false;
     645            break;
     646        }
     647        case SparseArrayTag: {
     648            uint32_t numProperties;
     649            uint32_t length;
     650            if (!doReadUint32(&numProperties))
     651                return false;
     652            if (!doReadUint32(&length))
     653                return false;
     654            if (!creator.createSparseArray(numProperties, length, value))
     655                return false;
     656            break;
     657        }
     658        default:
     659            return false;
     660        }
     661        return !value->IsEmpty();
    523662    }
    524663
     
    539678        if (m_position + length > m_length)
    540679            return false;
    541         *value = v8::String::New(m_buffer + m_position, length);
     680        *value = v8::String::New(reinterpret_cast<const char*>(m_buffer + m_position), length);
    542681        m_position += length;
    543682        return true;
     
    553692    }
    554693
     694    bool readUint32(v8::Handle<v8::Value>* value)
     695    {
     696        uint32_t rawValue;
     697        if (!doReadUint32(&rawValue))
     698            return false;
     699        *value = v8::Integer::New(rawValue);
     700        return true;
     701    }
     702
     703    bool readDate(v8::Handle<v8::Value>* value)
     704    {
     705        double numberValue;
     706        if (!doReadNumber(&numberValue))
     707            return false;
     708        *value = v8::Date::New(numberValue);
     709        return true;
     710    }
     711
    555712    bool readNumber(v8::Handle<v8::Value>* value)
    556713    {
    557         if (m_position + sizeof(double) > m_length)
    558             return false;
    559714        double number;
    560         char* numberAsByteArray = reinterpret_cast<char*>(&number);
    561         for (unsigned i = 0; i < sizeof(double); ++i)
    562             numberAsByteArray[i] = m_buffer[m_position++];
     715        if (!doReadNumber(&number))
     716            return false;
    563717        *value = v8::Number::New(number);
    564718        return true;
    565719    }
    566720
     721    bool readImageData(v8::Handle<v8::Value>* value)
     722    {
     723        uint32_t width;
     724        uint32_t height;
     725        uint32_t pixelDataLength;
     726        if (!doReadUint32(&width))
     727            return false;
     728        if (!doReadUint32(&height))
     729            return false;
     730        if (!doReadUint32(&pixelDataLength))
     731            return false;
     732        if (m_position + pixelDataLength > m_length)
     733            return false;
     734        PassRefPtr<ImageData> imageData = ImageData::create(width, height);
     735        WTF::ByteArray* pixelArray = imageData->data()->data();
     736        ASSERT(pixelArray);
     737        ASSERT(pixelArray->length() >= pixelDataLength);
     738        memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength);
     739        m_position += pixelDataLength;
     740        *value = toV8(imageData);
     741        return true;
     742    }
     743
    567744    bool doReadUint32(uint32_t* value)
    568745    {
    569746        *value = 0;
    570         char currentByte;
     747        uint8_t currentByte;
    571748        int shift = 0;
    572749        do {
     
    580757    }
    581758
    582     const char* m_buffer;
     759    bool doReadNumber(double* number)
     760    {
     761        if (m_position + sizeof(double) > m_length)
     762            return false;
     763        uint8_t* numberAsByteArray = reinterpret_cast<uint8_t*>(number);
     764        for (unsigned i = 0; i < sizeof(double); ++i)
     765            numberAsByteArray[i] = m_buffer[m_position++];
     766        return true;
     767    }
     768
     769    const uint8_t* m_buffer;
    583770    const unsigned m_length;
    584771    unsigned m_position;
    585772};
    586773
    587 class Deserializer {
     774class Deserializer : public CompositeCreator {
    588775public:
    589     explicit Deserializer(Reader& reader) : m_reader(reader)
     776    explicit Deserializer(Reader& reader)
     777        : m_reader(reader)
    590778    {
    591779    }
     
    603791    }
    604792
     793    virtual bool createArray(uint32_t length, v8::Handle<v8::Value>* value)
     794    {
     795        if (length > stackDepth())
     796            return false;
     797        v8::Local<v8::Array> array = v8::Array::New(length);
     798        if (array.IsEmpty())
     799            return false;
     800        const int depth = stackDepth() - length;
     801        for (unsigned i = 0; i < length; ++i)
     802            array->Set(i, element(depth + i));
     803        pop(length);
     804        *value = array;
     805        return true;
     806    }
     807
     808    virtual bool createObject(uint32_t numProperties, v8::Handle<v8::Value>* value)
     809    {
     810        v8::Local<v8::Object> object = v8::Object::New();
     811        if (object.IsEmpty())
     812            return false;
     813        return initializeObject(object, numProperties, value);
     814    }
     815
     816    virtual bool createSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value)
     817    {
     818        v8::Local<v8::Array> array = v8::Array::New(length);
     819        if (array.IsEmpty())
     820            return false;
     821        return initializeObject(array, numProperties, value);
     822    }
     823
    605824private:
     825    bool initializeObject(v8::Handle<v8::Object> object, uint32_t numProperties, v8::Handle<v8::Value>* value)
     826    {
     827        unsigned length = 2 * numProperties;
     828        if (length > stackDepth())
     829            return false;
     830        for (unsigned i = stackDepth() - length; i < stackDepth(); i += 2) {
     831            v8::Local<v8::Value> propertyName = element(i);
     832            v8::Local<v8::Value> propertyValue = element(i + 1);
     833            object->Set(propertyName, propertyValue);
     834        }
     835        pop(length);
     836        *value = object;
     837        return true;
     838    }
     839
    606840    bool doDeserialize()
    607841    {
    608         SerializationTag tag;
    609842        v8::Local<v8::Value> value;
    610         int length = 0;
    611         if (!m_reader.read(&tag, &value, &length))
    612             return false;
    613         if (!value.IsEmpty()) {
     843        if (!m_reader.read(&value, *this))
     844            return false;
     845        if (!value.IsEmpty())
    614846            push(value);
    615         } else if (tag == ObjectTag) {
    616             if (length > stackDepth())
    617                 return false;
    618             v8::Local<v8::Object> object = v8::Object::New();
    619             for (int i = stackDepth() - length; i < stackDepth(); i += 2) {
    620                 v8::Local<v8::Value> propertyName = element(i);
    621                 v8::Local<v8::Value> propertyValue = element(i + 1);
    622                 object->Set(propertyName, propertyValue);
    623             }
    624             pop(length);
    625             push(object);
    626         } else if (tag == ArrayTag) {
    627             if (length > stackDepth())
    628                 return false;
    629             v8::Local<v8::Array> array = v8::Array::New(length);
    630             const int depth = stackDepth() - length;
    631             {
    632                 v8::HandleScope scope;
    633                 for (int i = 0; i < length; ++i)
    634                     array->Set(v8::Integer::New(i), element(depth + i));
    635             }
    636             pop(length);
    637             push(array);
    638         } else if (tag != PaddingTag)
    639             return false;
    640847        return true;
    641848    }
     
    649856    }
    650857
    651     int stackDepth() const { return m_stack.size(); }
     858    unsigned stackDepth() const { return m_stack.size(); }
    652859
    653860    v8::Local<v8::Value> element(unsigned index)
     
    692899        return v8::Null();
    693900    COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
    694     Reader reader(reinterpret_cast<const char*>(m_data.impl()->characters()), 2 * m_data.length());
     901    Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->characters()), 2 * m_data.length());
    695902    Deserializer deserializer(reader);
    696903    return deserializer.deserialize();
Note: See TracChangeset for help on using the changeset viewer.