WebCore/bindings/v8/SerializedScriptValue.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2010 Google Inc. All rights reserved.
       
     3  *
       
     4  * Redistribution and use in source and binary forms, with or without
       
     5  * modification, are permitted provided that the following conditions are
       
     6  * met:
       
     7  *
       
     8  *     * Redistributions of source code must retain the above copyright
       
     9  * notice, this list of conditions and the following disclaimer.
       
    10  *     * Redistributions in binary form must reproduce the above
       
    11  * copyright notice, this list of conditions and the following disclaimer
       
    12  * in the documentation and/or other materials provided with the
       
    13  * distribution.
       
    14  *     * Neither the name of Google Inc. nor the names of its
       
    15  * contributors may be used to endorse or promote products derived from
       
    16  * this software without specific prior written permission.
       
    17  *
       
    18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
       
    19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
       
    20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
       
    21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
       
    22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
       
    23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
       
    24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
       
    25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
       
    26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    29  */
       
    30 
       
    31 #include "config.h"
       
    32 #include "SerializedScriptValue.h"
       
    33 
       
    34 #include "Blob.h"
       
    35 #include "ByteArray.h"
       
    36 #include "CanvasPixelArray.h"
       
    37 #include "ExceptionCode.h"
       
    38 #include "File.h"
       
    39 #include "FileList.h"
       
    40 #include "ImageData.h"
       
    41 #include "SharedBuffer.h"
       
    42 #include "V8Binding.h"
       
    43 #include "V8Blob.h"
       
    44 #include "V8File.h"
       
    45 #include "V8FileList.h"
       
    46 #include "V8ImageData.h"
       
    47 #include "V8Proxy.h"
       
    48 
       
    49 #include <wtf/Assertions.h>
       
    50 #include <wtf/RefCounted.h>
       
    51 #include <wtf/Vector.h>
       
    52 
       
    53 // FIXME:
       
    54 // - catch V8 exceptions
       
    55 // - consider crashing in debug mode on deserialization errors
       
    56 
       
    57 namespace WebCore {
       
    58 
       
    59 namespace {
       
    60 
       
    61 typedef UChar BufferValueType;
       
    62 
       
    63 // Serialization format is a sequence of (tag, optional data)
       
    64 // pairs. Tag always takes exactly one byte.
       
    65 enum SerializationTag {
       
    66     InvalidTag = '!',
       
    67     PaddingTag = '\0',
       
    68     UndefinedTag = '_',
       
    69     NullTag = '0',
       
    70     TrueTag = 'T',
       
    71     FalseTag = 'F',
       
    72     StringTag = 'S',
       
    73     Int32Tag = 'I',
       
    74     Uint32Tag = 'U',
       
    75     DateTag = 'D',
       
    76     NumberTag = 'N',
       
    77     BlobTag = 'b',
       
    78     FileTag = 'f',
       
    79     FileListTag = 'l',
       
    80     ImageDataTag = '#',
       
    81     ArrayTag = '[',
       
    82     ObjectTag = '{',
       
    83     SparseArrayTag = '@',
       
    84 };
       
    85 
       
    86 static bool shouldCheckForCycles(int depth)
       
    87 {
       
    88     ASSERT(depth >= 0);
       
    89     // Since we are not required to spot the cycle as soon as it
       
    90     // happens we can check for cycles only when the current depth
       
    91     // is a power of two.
       
    92     return !(depth & (depth - 1));
       
    93 }
       
    94 
       
    95 static const int maxDepth = 20000;
       
    96 
       
    97 // VarInt encoding constants.
       
    98 static const int varIntShift = 7;
       
    99 static const int varIntMask = (1 << varIntShift) - 1;
       
   100 
       
   101 // ZigZag encoding helps VarInt encoding stay small for negative
       
   102 // numbers with small absolute values.
       
   103 class ZigZag {
       
   104 public:
       
   105     static uint32_t encode(uint32_t value)
       
   106     {
       
   107         if (value & (1U << 31))
       
   108             value = ((~value) << 1) + 1;
       
   109         else
       
   110             value <<= 1;
       
   111         return value;
       
   112     }
       
   113 
       
   114     static uint32_t decode(uint32_t value)
       
   115     {
       
   116         if (value & 1)
       
   117             value = ~(value >> 1);
       
   118         else
       
   119             value >>= 1;
       
   120         return value;
       
   121     }
       
   122 
       
   123 private:
       
   124     ZigZag();
       
   125 };
       
   126 
       
   127 // Writer is responsible for serializing primitive types and storing
       
   128 // information used to reconstruct composite types.
       
   129 class Writer : Noncopyable {
       
   130 public:
       
   131     Writer()
       
   132         : m_position(0)
       
   133     {
       
   134     }
       
   135 
       
   136     // Write functions for primitive types.
       
   137 
       
   138     void writeUndefined() { append(UndefinedTag); }
       
   139 
       
   140     void writeNull() { append(NullTag); }
       
   141 
       
   142     void writeTrue() { append(TrueTag); }
       
   143 
       
   144     void writeFalse() { append(FalseTag); }
       
   145 
       
   146     void writeString(const char* data, int length)
       
   147     {
       
   148         ASSERT(length >= 0);
       
   149         append(StringTag);
       
   150         doWriteString(data, length);
       
   151     }
       
   152 
       
   153     void writeWebCoreString(const String& string)
       
   154     {
       
   155         // Uses UTF8 encoding so we can read it back as either V8 or
       
   156         // WebCore string.
       
   157         append(StringTag);
       
   158         doWriteWebCoreString(string);
       
   159     }
       
   160 
       
   161     void writeInt32(int32_t value)
       
   162     {
       
   163         append(Int32Tag);
       
   164         doWriteUint32(ZigZag::encode(static_cast<uint32_t>(value)));
       
   165     }
       
   166 
       
   167     void writeUint32(uint32_t value)
       
   168     {
       
   169         append(Uint32Tag);
       
   170         doWriteUint32(value);
       
   171     }
       
   172 
       
   173     void writeDate(double numberValue)
       
   174     {
       
   175         append(DateTag);
       
   176         doWriteNumber(numberValue);
       
   177     }
       
   178 
       
   179     void writeNumber(double number)
       
   180     {
       
   181         append(NumberTag);
       
   182         doWriteNumber(number);
       
   183     }
       
   184 
       
   185     void writeBlob(const String& path)
       
   186     {
       
   187         append(BlobTag);
       
   188         doWriteWebCoreString(path);
       
   189     }
       
   190 
       
   191     void writeFile(const String& path)
       
   192     {
       
   193         append(FileTag);
       
   194         doWriteWebCoreString(path);
       
   195     }
       
   196 
       
   197     void writeFileList(const FileList& fileList)
       
   198     {
       
   199         append(FileListTag);
       
   200         uint32_t length = fileList.length();
       
   201         doWriteUint32(length);
       
   202         for (unsigned i = 0; i < length; ++i)
       
   203             doWriteWebCoreString(fileList.item(i)->path());
       
   204     }
       
   205 
       
   206     void writeImageData(uint32_t width, uint32_t height, const uint8_t* pixelData, uint32_t pixelDataLength)
       
   207     {
       
   208         append(ImageDataTag);
       
   209         doWriteUint32(width);
       
   210         doWriteUint32(height);
       
   211         doWriteUint32(pixelDataLength);
       
   212         append(pixelData, pixelDataLength);
       
   213     }
       
   214 
       
   215     void writeArray(uint32_t length)
       
   216     {
       
   217         append(ArrayTag);
       
   218         doWriteUint32(length);
       
   219     }
       
   220 
       
   221     void writeObject(uint32_t numProperties)
       
   222     {
       
   223         append(ObjectTag);
       
   224         doWriteUint32(numProperties);
       
   225     }
       
   226 
       
   227     void writeSparseArray(uint32_t numProperties, uint32_t length)
       
   228     {
       
   229         append(SparseArrayTag);
       
   230         doWriteUint32(numProperties);
       
   231         doWriteUint32(length);
       
   232     }
       
   233 
       
   234     Vector<BufferValueType>& data()
       
   235     {
       
   236         fillHole();
       
   237         return m_buffer;
       
   238     }
       
   239 
       
   240 private:
       
   241     void doWriteString(const char* data, int length)
       
   242     {
       
   243         doWriteUint32(static_cast<uint32_t>(length));
       
   244         append(reinterpret_cast<const uint8_t*>(data), length);
       
   245     }
       
   246 
       
   247     void doWriteWebCoreString(const String& string)
       
   248     {
       
   249         RefPtr<SharedBuffer> buffer = utf8Buffer(string);
       
   250         doWriteString(buffer->data(), buffer->size());
       
   251     }
       
   252 
       
   253     void doWriteUint32(uint32_t value)
       
   254     {
       
   255         while (true) {
       
   256             uint8_t b = (value & varIntMask);
       
   257             value >>= varIntShift;
       
   258             if (!value) {
       
   259                 append(b);
       
   260                 break;
       
   261             }
       
   262             append(b | (1 << varIntShift));
       
   263         }
       
   264     }
       
   265 
       
   266     void doWriteNumber(double number)
       
   267     {
       
   268         append(reinterpret_cast<uint8_t*>(&number), sizeof(number));
       
   269     }
       
   270 
       
   271     void append(SerializationTag tag)
       
   272     {
       
   273         append(static_cast<uint8_t>(tag));
       
   274     }
       
   275 
       
   276     void append(uint8_t b)
       
   277     {
       
   278         ensureSpace(1);
       
   279         *byteAt(m_position++) = b;
       
   280     }
       
   281 
       
   282     void append(const uint8_t* data, int length)
       
   283     {
       
   284         ensureSpace(length);
       
   285         memcpy(byteAt(m_position), data, length);
       
   286         m_position += length;
       
   287     }
       
   288 
       
   289     void ensureSpace(int extra)
       
   290     {
       
   291         COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
       
   292         m_buffer.grow((m_position + extra + 1) / 2); // "+ 1" to round up.
       
   293     }
       
   294 
       
   295     void fillHole()
       
   296     {
       
   297         COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
       
   298         // If the writer is at odd position in the buffer, then one of
       
   299         // the bytes in the last UChar is not initialized.
       
   300         if (m_position % 2)
       
   301             *byteAt(m_position) = static_cast<uint8_t>(PaddingTag);
       
   302     }
       
   303 
       
   304     uint8_t* byteAt(int position) { return reinterpret_cast<uint8_t*>(m_buffer.data()) + position; }
       
   305 
       
   306     Vector<BufferValueType> m_buffer;
       
   307     unsigned m_position;
       
   308 };
       
   309 
       
   310 class Serializer {
       
   311     class StateBase;
       
   312 public:
       
   313     explicit Serializer(Writer& writer)
       
   314         : m_writer(writer)
       
   315         , m_depth(0)
       
   316         , m_hasError(false)
       
   317     {
       
   318     }
       
   319 
       
   320     bool serialize(v8::Handle<v8::Value> value)
       
   321     {
       
   322         v8::HandleScope scope;
       
   323         StateBase* state = doSerialize(value, 0);
       
   324         while (state)
       
   325             state = state->advance(*this);
       
   326         return !m_hasError;
       
   327     }
       
   328 
       
   329     // Functions used by serialization states.
       
   330 
       
   331     StateBase* doSerialize(v8::Handle<v8::Value> value, StateBase* next);
       
   332 
       
   333     StateBase* writeArray(uint32_t length, StateBase* state)
       
   334     {
       
   335         m_writer.writeArray(length);
       
   336         return pop(state);
       
   337     }
       
   338 
       
   339     StateBase* writeObject(uint32_t numProperties, StateBase* state)
       
   340     {
       
   341         m_writer.writeObject(numProperties);
       
   342         return pop(state);
       
   343     }
       
   344 
       
   345     StateBase* writeSparseArray(uint32_t numProperties, uint32_t length, StateBase* state)
       
   346     {
       
   347         m_writer.writeSparseArray(numProperties, length);
       
   348         return pop(state);
       
   349     }
       
   350 
       
   351 private:
       
   352     class StateBase : public Noncopyable {
       
   353     public:
       
   354         virtual ~StateBase() { }
       
   355 
       
   356         // Link to the next state to form a stack.
       
   357         StateBase* nextState() { return m_next; }
       
   358 
       
   359         // Composite object we're processing in this state.
       
   360         v8::Handle<v8::Value> composite() { return m_composite; }
       
   361 
       
   362         // Serializes (a part of) the current composite and returns
       
   363         // the next state to process or null when this is the final
       
   364         // state.
       
   365         virtual StateBase* advance(Serializer&) = 0;
       
   366 
       
   367     protected:
       
   368         StateBase(v8::Handle<v8::Value> composite, StateBase* next)
       
   369             : m_composite(composite)
       
   370             , m_next(next)
       
   371         {
       
   372         }
       
   373 
       
   374     private:
       
   375         v8::Handle<v8::Value> m_composite;
       
   376         StateBase* m_next;
       
   377     };
       
   378 
       
   379     // Dummy state that is used to signal serialization errors.
       
   380     class ErrorState : public StateBase {
       
   381     public:
       
   382         ErrorState()
       
   383             : StateBase(v8::Handle<v8::Value>(), 0)
       
   384         {
       
   385         }
       
   386 
       
   387         virtual StateBase* advance(Serializer&)
       
   388         {
       
   389             delete this;
       
   390             return 0;
       
   391         }
       
   392     };
       
   393 
       
   394     template <typename T>
       
   395     class State : public StateBase {
       
   396     public:
       
   397         v8::Handle<T> composite() { return v8::Handle<T>::Cast(StateBase::composite()); }
       
   398 
       
   399     protected:
       
   400         State(v8::Handle<T> composite, StateBase* next)
       
   401             : StateBase(composite, next)
       
   402         {
       
   403         }
       
   404     };
       
   405 
       
   406 #if 0
       
   407     // Currently unused, see comment in newArrayState.
       
   408     class ArrayState : public State<v8::Array> {
       
   409     public:
       
   410         ArrayState(v8::Handle<v8::Array> array, StateBase* next)
       
   411             : State<v8::Array>(array, next)
       
   412             , m_index(-1)
       
   413         {
       
   414         }
       
   415 
       
   416         virtual StateBase* advance(Serializer& serializer)
       
   417         {
       
   418             ++m_index;
       
   419             for (; m_index < composite()->Length(); ++m_index) {
       
   420                 if (StateBase* newState = serializer.doSerialize(composite()->Get(m_index), this))
       
   421                     return newState;
       
   422             }
       
   423             return serializer.writeArray(composite()->Length(), this);
       
   424         }
       
   425 
       
   426     private:
       
   427         unsigned m_index;
       
   428     };
       
   429 #endif
       
   430 
       
   431     class AbstractObjectState : public State<v8::Object> {
       
   432     public:
       
   433         AbstractObjectState(v8::Handle<v8::Object> object, StateBase* next)
       
   434             : State<v8::Object>(object, next)
       
   435             , m_propertyNames(object->GetPropertyNames())
       
   436             , m_index(-1)
       
   437             , m_numSerializedProperties(0)
       
   438             , m_nameDone(false)
       
   439         {
       
   440         }
       
   441 
       
   442         virtual StateBase* advance(Serializer& serializer)
       
   443         {
       
   444             ++m_index;
       
   445             for (; m_index < m_propertyNames->Length(); ++m_index) {
       
   446                 if (m_propertyName.IsEmpty()) {
       
   447                     v8::Local<v8::Value> propertyName = m_propertyNames->Get(m_index);
       
   448                     if ((propertyName->IsString() && composite()->HasRealNamedProperty(propertyName.As<v8::String>()))
       
   449                         || (propertyName->IsUint32() && composite()->HasRealIndexedProperty(propertyName->Uint32Value()))) {
       
   450                         m_propertyName = propertyName;
       
   451                     } else
       
   452                         continue;
       
   453                 }
       
   454                 ASSERT(!m_propertyName.IsEmpty());
       
   455                 if (!m_nameDone) {
       
   456                     m_nameDone = true;
       
   457                     if (StateBase* newState = serializer.doSerialize(m_propertyName, this))
       
   458                         return newState;
       
   459                 }
       
   460                 v8::Local<v8::Value> value = composite()->Get(m_propertyName);
       
   461                 m_nameDone = false;
       
   462                 m_propertyName.Clear();
       
   463                 ++m_numSerializedProperties;
       
   464                 if (StateBase* newState = serializer.doSerialize(value, this))
       
   465                     return newState;
       
   466             }
       
   467             return objectDone(m_numSerializedProperties, serializer);
       
   468         }
       
   469 
       
   470     protected:
       
   471         virtual StateBase* objectDone(unsigned numProperties, Serializer&) = 0;
       
   472 
       
   473     private:
       
   474         v8::Local<v8::Array> m_propertyNames;
       
   475         v8::Local<v8::Value> m_propertyName;
       
   476         unsigned m_index;
       
   477         unsigned m_numSerializedProperties;
       
   478         bool m_nameDone;
       
   479     };
       
   480 
       
   481     class ObjectState : public AbstractObjectState {
       
   482     public:
       
   483         ObjectState(v8::Handle<v8::Object> object, StateBase* next)
       
   484             : AbstractObjectState(object, next)
       
   485         {
       
   486         }
       
   487 
       
   488     protected:
       
   489         virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer)
       
   490         {
       
   491             return serializer.writeObject(numProperties, this);
       
   492         }
       
   493     };
       
   494 
       
   495     class SparseArrayState : public AbstractObjectState {
       
   496     public:
       
   497         SparseArrayState(v8::Handle<v8::Array> array, StateBase* next)
       
   498             : AbstractObjectState(array, next)
       
   499         {
       
   500         }
       
   501 
       
   502     protected:
       
   503         virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer)
       
   504         {
       
   505             return serializer.writeSparseArray(numProperties, composite().As<v8::Array>()->Length(), this);
       
   506         }
       
   507     };
       
   508 
       
   509     StateBase* push(StateBase* state)
       
   510     {
       
   511         ASSERT(state);
       
   512         ++m_depth;
       
   513         return checkComposite(state) ? state : handleError(state);
       
   514     }
       
   515 
       
   516     StateBase* pop(StateBase* state)
       
   517     {
       
   518         ASSERT(state);
       
   519         --m_depth;
       
   520         StateBase* next = state->nextState();
       
   521         delete state;
       
   522         return next;
       
   523     }
       
   524 
       
   525     StateBase* handleError(StateBase* state)
       
   526     {
       
   527         m_hasError = true;
       
   528         while (state) {
       
   529             StateBase* tmp = state->nextState();
       
   530             delete state;
       
   531             state = tmp;
       
   532         }
       
   533         return new ErrorState;
       
   534     }
       
   535 
       
   536     bool checkComposite(StateBase* top)
       
   537     {
       
   538         ASSERT(top);
       
   539         if (m_depth > maxDepth)
       
   540             return false;
       
   541         if (!shouldCheckForCycles(m_depth))
       
   542             return true;
       
   543         v8::Handle<v8::Value> composite = top->composite();
       
   544         for (StateBase* state = top->nextState(); state; state = state->nextState()) {
       
   545             if (state->composite() == composite)
       
   546                 return false;
       
   547         }
       
   548         return true;
       
   549     }
       
   550 
       
   551     void writeString(v8::Handle<v8::Value> value)
       
   552     {
       
   553         v8::String::Utf8Value stringValue(value);
       
   554         m_writer.writeString(*stringValue, stringValue.length());
       
   555     }
       
   556 
       
   557     void writeBlob(v8::Handle<v8::Value> value)
       
   558     {
       
   559         Blob* blob = V8Blob::toNative(value.As<v8::Object>());
       
   560         if (!blob)
       
   561             return;
       
   562         m_writer.writeBlob(blob->path());
       
   563     }
       
   564 
       
   565     void writeFile(v8::Handle<v8::Value> value)
       
   566     {
       
   567         File* file = V8File::toNative(value.As<v8::Object>());
       
   568         if (!file)
       
   569             return;
       
   570         m_writer.writeFile(file->path());
       
   571     }
       
   572 
       
   573     void writeFileList(v8::Handle<v8::Value> value)
       
   574     {
       
   575         FileList* fileList = V8FileList::toNative(value.As<v8::Object>());
       
   576         if (!fileList)
       
   577             return;
       
   578         m_writer.writeFileList(*fileList);
       
   579     }
       
   580 
       
   581     void writeImageData(v8::Handle<v8::Value> value)
       
   582     {
       
   583         ImageData* imageData = V8ImageData::toNative(value.As<v8::Object>());
       
   584         if (!imageData)
       
   585             return;
       
   586         WTF::ByteArray* pixelArray = imageData->data()->data();
       
   587         m_writer.writeImageData(imageData->width(), imageData->height(), pixelArray->data(), pixelArray->length());
       
   588     }
       
   589 
       
   590     static StateBase* newArrayState(v8::Handle<v8::Array> array, StateBase* next)
       
   591     {
       
   592         // FIXME: use plain Array state when we can quickly check that
       
   593         // an array is not sparse and has only indexed properties.
       
   594         return new SparseArrayState(array, next);
       
   595     }
       
   596 
       
   597     static StateBase* newObjectState(v8::Handle<v8::Object> object, StateBase* next)
       
   598     {
       
   599         // FIXME:
       
   600         // - check not a wrapper
       
   601         // - support File, etc.
       
   602         return new ObjectState(object, next);
       
   603     }
       
   604 
       
   605     Writer& m_writer;
       
   606     int m_depth;
       
   607     bool m_hasError;
       
   608 };
       
   609 
       
   610 Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, StateBase* next)
       
   611 {
       
   612     if (value->IsUndefined())
       
   613         m_writer.writeUndefined();
       
   614     else if (value->IsNull())
       
   615         m_writer.writeNull();
       
   616     else if (value->IsTrue())
       
   617         m_writer.writeTrue();
       
   618     else if (value->IsFalse())
       
   619         m_writer.writeFalse();
       
   620     else if (value->IsInt32())
       
   621         m_writer.writeInt32(value->Int32Value());
       
   622     else if (value->IsUint32())
       
   623         m_writer.writeUint32(value->Uint32Value());
       
   624     else if (value->IsDate())
       
   625         m_writer.writeDate(value->NumberValue());
       
   626     else if (value->IsNumber())
       
   627         m_writer.writeNumber(value.As<v8::Number>()->Value());
       
   628     else if (value->IsString())
       
   629         writeString(value);
       
   630     else if (value->IsArray())
       
   631         return push(newArrayState(value.As<v8::Array>(), next));
       
   632     else if (V8File::HasInstance(value))
       
   633         writeFile(value);
       
   634     else if (V8Blob::HasInstance(value))
       
   635         writeBlob(value);
       
   636     else if (V8FileList::HasInstance(value))
       
   637         writeFileList(value);
       
   638     else if (V8ImageData::HasInstance(value))
       
   639         writeImageData(value);
       
   640     else if (value->IsObject())
       
   641         return push(newObjectState(value.As<v8::Object>(), next));
       
   642     return 0;
       
   643 }
       
   644 
       
   645 // Interface used by Reader to create objects of composite types.
       
   646 class CompositeCreator {
       
   647 public:
       
   648     virtual ~CompositeCreator() { }
       
   649 
       
   650     virtual bool createArray(uint32_t length, v8::Handle<v8::Value>* value) = 0;
       
   651     virtual bool createObject(uint32_t numProperties, v8::Handle<v8::Value>* value) = 0;
       
   652     virtual bool createSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) = 0;
       
   653 };
       
   654 
       
   655 // Reader is responsible for deserializing primitive types and
       
   656 // restoring information about saved objects of composite types.
       
   657 class Reader {
       
   658 public:
       
   659     Reader(const uint8_t* buffer, int length)
       
   660         : m_buffer(buffer)
       
   661         , m_length(length)
       
   662         , m_position(0)
       
   663     {
       
   664         ASSERT(length >= 0);
       
   665     }
       
   666 
       
   667     bool isEof() const { return m_position >= m_length; }
       
   668 
       
   669     bool read(v8::Handle<v8::Value>* value, CompositeCreator& creator)
       
   670     {
       
   671         SerializationTag tag;
       
   672         if (!readTag(&tag))
       
   673             return false;
       
   674         switch (tag) {
       
   675         case InvalidTag:
       
   676             return false;
       
   677         case PaddingTag:
       
   678             return true;
       
   679         case UndefinedTag:
       
   680             *value = v8::Undefined();
       
   681             break;
       
   682         case NullTag:
       
   683             *value = v8::Null();
       
   684             break;
       
   685         case TrueTag:
       
   686             *value = v8::True();
       
   687             break;
       
   688         case FalseTag:
       
   689             *value = v8::False();
       
   690             break;
       
   691         case StringTag:
       
   692             if (!readString(value))
       
   693                 return false;
       
   694             break;
       
   695         case Int32Tag:
       
   696             if (!readInt32(value))
       
   697                 return false;
       
   698             break;
       
   699         case Uint32Tag:
       
   700             if (!readUint32(value))
       
   701                 return false;
       
   702             break;
       
   703         case DateTag:
       
   704             if (!readDate(value))
       
   705                 return false;
       
   706             break;
       
   707         case NumberTag:
       
   708             if (!readNumber(value))
       
   709                 return false;
       
   710             break;
       
   711         case BlobTag:
       
   712             if (!readBlob(value))
       
   713                 return false;
       
   714             break;
       
   715         case FileTag:
       
   716             if (!readFile(value))
       
   717                 return false;
       
   718             break;
       
   719         case FileListTag:
       
   720             if (!readFileList(value))
       
   721                 return false;
       
   722             break;
       
   723         case ImageDataTag:
       
   724             if (!readImageData(value))
       
   725                 return false;
       
   726             break;
       
   727         case ArrayTag: {
       
   728             uint32_t length;
       
   729             if (!doReadUint32(&length))
       
   730                 return false;
       
   731             if (!creator.createArray(length, value))
       
   732                 return false;
       
   733             break;
       
   734         }
       
   735         case ObjectTag: {
       
   736             uint32_t numProperties;
       
   737             if (!doReadUint32(&numProperties))
       
   738                 return false;
       
   739             if (!creator.createObject(numProperties, value))
       
   740                 return false;
       
   741             break;
       
   742         }
       
   743         case SparseArrayTag: {
       
   744             uint32_t numProperties;
       
   745             uint32_t length;
       
   746             if (!doReadUint32(&numProperties))
       
   747                 return false;
       
   748             if (!doReadUint32(&length))
       
   749                 return false;
       
   750             if (!creator.createSparseArray(numProperties, length, value))
       
   751                 return false;
       
   752             break;
       
   753         }
       
   754         default:
       
   755             return false;
       
   756         }
       
   757         return !value->IsEmpty();
       
   758     }
       
   759 
       
   760 private:
       
   761     bool readTag(SerializationTag* tag)
       
   762     {
       
   763         if (m_position >= m_length)
       
   764             return false;
       
   765         *tag = static_cast<SerializationTag>(m_buffer[m_position++]);
       
   766         return true;
       
   767     }
       
   768 
       
   769     bool readString(v8::Handle<v8::Value>* value)
       
   770     {
       
   771         uint32_t length;
       
   772         if (!doReadUint32(&length))
       
   773             return false;
       
   774         if (m_position + length > m_length)
       
   775             return false;
       
   776         *value = v8::String::New(reinterpret_cast<const char*>(m_buffer + m_position), length);
       
   777         m_position += length;
       
   778         return true;
       
   779     }
       
   780 
       
   781     bool readWebCoreString(String* string)
       
   782     {
       
   783         uint32_t length;
       
   784         if (!doReadUint32(&length))
       
   785             return false;
       
   786         if (m_position + length > m_length)
       
   787             return false;
       
   788         *string = String::fromUTF8(reinterpret_cast<const char*>(m_buffer + m_position), length);
       
   789         m_position += length;
       
   790         return true;
       
   791     }
       
   792 
       
   793     bool readInt32(v8::Handle<v8::Value>* value)
       
   794     {
       
   795         uint32_t rawValue;
       
   796         if (!doReadUint32(&rawValue))
       
   797             return false;
       
   798         *value = v8::Integer::New(static_cast<int32_t>(ZigZag::decode(rawValue)));
       
   799         return true;
       
   800     }
       
   801 
       
   802     bool readUint32(v8::Handle<v8::Value>* value)
       
   803     {
       
   804         uint32_t rawValue;
       
   805         if (!doReadUint32(&rawValue))
       
   806             return false;
       
   807         *value = v8::Integer::New(rawValue);
       
   808         return true;
       
   809     }
       
   810 
       
   811     bool readDate(v8::Handle<v8::Value>* value)
       
   812     {
       
   813         double numberValue;
       
   814         if (!doReadNumber(&numberValue))
       
   815             return false;
       
   816         *value = v8::Date::New(numberValue);
       
   817         return true;
       
   818     }
       
   819 
       
   820     bool readNumber(v8::Handle<v8::Value>* value)
       
   821     {
       
   822         double number;
       
   823         if (!doReadNumber(&number))
       
   824             return false;
       
   825         *value = v8::Number::New(number);
       
   826         return true;
       
   827     }
       
   828 
       
   829     bool readImageData(v8::Handle<v8::Value>* value)
       
   830     {
       
   831         uint32_t width;
       
   832         uint32_t height;
       
   833         uint32_t pixelDataLength;
       
   834         if (!doReadUint32(&width))
       
   835             return false;
       
   836         if (!doReadUint32(&height))
       
   837             return false;
       
   838         if (!doReadUint32(&pixelDataLength))
       
   839             return false;
       
   840         if (m_position + pixelDataLength > m_length)
       
   841             return false;
       
   842         PassRefPtr<ImageData> imageData = ImageData::create(width, height);
       
   843         WTF::ByteArray* pixelArray = imageData->data()->data();
       
   844         ASSERT(pixelArray);
       
   845         ASSERT(pixelArray->length() >= pixelDataLength);
       
   846         memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength);
       
   847         m_position += pixelDataLength;
       
   848         *value = toV8(imageData);
       
   849         return true;
       
   850     }
       
   851 
       
   852     bool readBlob(v8::Handle<v8::Value>* value)
       
   853     {
       
   854         String path;
       
   855         if (!readWebCoreString(&path))
       
   856             return false;
       
   857         PassRefPtr<Blob> blob = Blob::create(path);
       
   858         *value = toV8(blob);
       
   859         return true;
       
   860     }
       
   861 
       
   862     bool readFile(v8::Handle<v8::Value>* value)
       
   863     {
       
   864         String path;
       
   865         if (!readWebCoreString(&path))
       
   866             return false;
       
   867         PassRefPtr<File> file = File::create(path);
       
   868         *value = toV8(file);
       
   869         return true;
       
   870     }
       
   871 
       
   872     bool readFileList(v8::Handle<v8::Value>* value)
       
   873     {
       
   874         uint32_t length;
       
   875         if (!doReadUint32(&length))
       
   876             return false;
       
   877         PassRefPtr<FileList> fileList = FileList::create();
       
   878         for (unsigned i = 0; i < length; ++i) {
       
   879             String path;
       
   880             if (!readWebCoreString(&path))
       
   881                 return false;
       
   882             fileList->append(File::create(path));
       
   883         }
       
   884         *value = toV8(fileList);
       
   885         return true;
       
   886     }
       
   887 
       
   888     bool doReadUint32(uint32_t* value)
       
   889     {
       
   890         *value = 0;
       
   891         uint8_t currentByte;
       
   892         int shift = 0;
       
   893         do {
       
   894             if (m_position >= m_length)
       
   895                 return false;
       
   896             currentByte = m_buffer[m_position++];
       
   897             *value |= ((currentByte & varIntMask) << shift);
       
   898             shift += varIntShift;
       
   899         } while (currentByte & (1 << varIntShift));
       
   900         return true;
       
   901     }
       
   902 
       
   903     bool doReadNumber(double* number)
       
   904     {
       
   905         if (m_position + sizeof(double) > m_length)
       
   906             return false;
       
   907         uint8_t* numberAsByteArray = reinterpret_cast<uint8_t*>(number);
       
   908         for (unsigned i = 0; i < sizeof(double); ++i)
       
   909             numberAsByteArray[i] = m_buffer[m_position++];
       
   910         return true;
       
   911     }
       
   912 
       
   913     const uint8_t* m_buffer;
       
   914     const unsigned m_length;
       
   915     unsigned m_position;
       
   916 };
       
   917 
       
   918 class Deserializer : public CompositeCreator {
       
   919 public:
       
   920     explicit Deserializer(Reader& reader)
       
   921         : m_reader(reader)
       
   922     {
       
   923     }
       
   924 
       
   925     v8::Handle<v8::Value> deserialize()
       
   926     {
       
   927         v8::HandleScope scope;
       
   928         while (!m_reader.isEof()) {
       
   929             if (!doDeserialize())
       
   930                 return v8::Null();
       
   931         }
       
   932         if (stackDepth() != 1)
       
   933             return v8::Null();
       
   934         return scope.Close(element(0));
       
   935     }
       
   936 
       
   937     virtual bool createArray(uint32_t length, v8::Handle<v8::Value>* value)
       
   938     {
       
   939         if (length > stackDepth())
       
   940             return false;
       
   941         v8::Local<v8::Array> array = v8::Array::New(length);
       
   942         if (array.IsEmpty())
       
   943             return false;
       
   944         const int depth = stackDepth() - length;
       
   945         for (unsigned i = 0; i < length; ++i)
       
   946             array->Set(i, element(depth + i));
       
   947         pop(length);
       
   948         *value = array;
       
   949         return true;
       
   950     }
       
   951 
       
   952     virtual bool createObject(uint32_t numProperties, v8::Handle<v8::Value>* value)
       
   953     {
       
   954         v8::Local<v8::Object> object = v8::Object::New();
       
   955         if (object.IsEmpty())
       
   956             return false;
       
   957         return initializeObject(object, numProperties, value);
       
   958     }
       
   959 
       
   960     virtual bool createSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value)
       
   961     {
       
   962         v8::Local<v8::Array> array = v8::Array::New(length);
       
   963         if (array.IsEmpty())
       
   964             return false;
       
   965         return initializeObject(array, numProperties, value);
       
   966     }
       
   967 
       
   968 private:
       
   969     bool initializeObject(v8::Handle<v8::Object> object, uint32_t numProperties, v8::Handle<v8::Value>* value)
       
   970     {
       
   971         unsigned length = 2 * numProperties;
       
   972         if (length > stackDepth())
       
   973             return false;
       
   974         for (unsigned i = stackDepth() - length; i < stackDepth(); i += 2) {
       
   975             v8::Local<v8::Value> propertyName = element(i);
       
   976             v8::Local<v8::Value> propertyValue = element(i + 1);
       
   977             object->Set(propertyName, propertyValue);
       
   978         }
       
   979         pop(length);
       
   980         *value = object;
       
   981         return true;
       
   982     }
       
   983 
       
   984     bool doDeserialize()
       
   985     {
       
   986         v8::Local<v8::Value> value;
       
   987         if (!m_reader.read(&value, *this))
       
   988             return false;
       
   989         if (!value.IsEmpty())
       
   990             push(value);
       
   991         return true;
       
   992     }
       
   993 
       
   994     void push(v8::Local<v8::Value> value) { m_stack.append(value); }
       
   995 
       
   996     void pop(unsigned length)
       
   997     {
       
   998         ASSERT(length <= m_stack.size());
       
   999         m_stack.shrink(m_stack.size() - length);
       
  1000     }
       
  1001 
       
  1002     unsigned stackDepth() const { return m_stack.size(); }
       
  1003 
       
  1004     v8::Local<v8::Value> element(unsigned index)
       
  1005     {
       
  1006         ASSERT(index < m_stack.size());
       
  1007         return m_stack[index];
       
  1008     }
       
  1009 
       
  1010     Reader& m_reader;
       
  1011     Vector<v8::Local<v8::Value> > m_stack;
       
  1012 };
       
  1013 
       
  1014 } // namespace
       
  1015 
       
  1016 void SerializedScriptValue::deserializeAndSetProperty(v8::Handle<v8::Object> object, const char* propertyName,
       
  1017                                                       v8::PropertyAttribute attribute, SerializedScriptValue* value)
       
  1018 {
       
  1019     if (!value)
       
  1020         return;
       
  1021     v8::Handle<v8::Value> deserialized = value->deserialize();
       
  1022     object->ForceSet(v8::String::NewSymbol(propertyName), deserialized, attribute);
       
  1023 }
       
  1024 
       
  1025 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value, bool& didThrow)
       
  1026 {
       
  1027     return adoptRef(new SerializedScriptValue(value, didThrow));
       
  1028 }
       
  1029 
       
  1030 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value)
       
  1031 {
       
  1032     bool didThrow;
       
  1033     return adoptRef(new SerializedScriptValue(value, didThrow));
       
  1034 }
       
  1035 
       
  1036 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWire(String data)
       
  1037 {
       
  1038     return adoptRef(new SerializedScriptValue(data, WireData));
       
  1039 }
       
  1040 
       
  1041 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(String data)
       
  1042 {
       
  1043     return adoptRef(new SerializedScriptValue(data, StringValue));
       
  1044 }
       
  1045 
       
  1046 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create()
       
  1047 {
       
  1048     return adoptRef(new SerializedScriptValue());
       
  1049 }
       
  1050 
       
  1051 PassRefPtr<SerializedScriptValue> SerializedScriptValue::release()
       
  1052 {
       
  1053     RefPtr<SerializedScriptValue> result = adoptRef(new SerializedScriptValue(m_data, WireData));
       
  1054     m_data = String();
       
  1055     return result.release();
       
  1056 }
       
  1057 
       
  1058 SerializedScriptValue::SerializedScriptValue()
       
  1059 {
       
  1060 }
       
  1061 
       
  1062 SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, bool& didThrow)
       
  1063 {
       
  1064     didThrow = false;
       
  1065     Writer writer;
       
  1066     Serializer serializer(writer);
       
  1067     if (!serializer.serialize(value)) {
       
  1068         throwError(NOT_SUPPORTED_ERR);
       
  1069         didThrow = true;
       
  1070         return;
       
  1071     }
       
  1072     m_data = StringImpl::adopt(writer.data());
       
  1073 }
       
  1074 
       
  1075 SerializedScriptValue::SerializedScriptValue(String data, StringDataMode mode)
       
  1076 {
       
  1077     if (mode == WireData)
       
  1078         m_data = data;
       
  1079     else {
       
  1080         ASSERT(mode == StringValue);
       
  1081         Writer writer;
       
  1082         writer.writeWebCoreString(data);
       
  1083         m_data = StringImpl::adopt(writer.data());
       
  1084     }
       
  1085 }
       
  1086 
       
  1087 v8::Handle<v8::Value> SerializedScriptValue::deserialize()
       
  1088 {
       
  1089     if (!m_data.impl())
       
  1090         return v8::Null();
       
  1091     COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
       
  1092     Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->characters()), 2 * m_data.length());
       
  1093     Deserializer deserializer(reader);
       
  1094     return deserializer.deserialize();
       
  1095 }
       
  1096 
       
  1097 } // namespace WebCore