Home | History | Annotate | Download | only in v8
      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 #include "V8Utilities.h"
     49 
     50 #include <wtf/Assertions.h>
     51 #include <wtf/RefCounted.h>
     52 #include <wtf/Vector.h>
     53 
     54 // FIXME: consider crashing in debug mode on deserialization errors
     55 
     56 namespace WebCore {
     57 
     58 namespace {
     59 
     60 typedef UChar BufferValueType;
     61 
     62 // Serialization format is a sequence of (tag, optional data)
     63 // pairs. Tag always takes exactly one byte.
     64 enum SerializationTag {
     65     InvalidTag = '!',
     66     PaddingTag = '\0',
     67     UndefinedTag = '_',
     68     NullTag = '0',
     69     TrueTag = 'T',
     70     FalseTag = 'F',
     71     StringTag = 'S',
     72     Int32Tag = 'I',
     73     Uint32Tag = 'U',
     74     DateTag = 'D',
     75     NumberTag = 'N',
     76     BlobTag = 'b',
     77     FileTag = 'f',
     78     FileListTag = 'l',
     79     ImageDataTag = '#',
     80     ArrayTag = '[',
     81     ObjectTag = '{',
     82     SparseArrayTag = '@',
     83     RegExpTag = 'R',
     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 {
    130     WTF_MAKE_NONCOPYABLE(Writer);
    131 public:
    132     Writer()
    133         : m_position(0)
    134     {
    135     }
    136 
    137     // Write functions for primitive types.
    138 
    139     void writeUndefined() { append(UndefinedTag); }
    140 
    141     void writeNull() { append(NullTag); }
    142 
    143     void writeTrue() { append(TrueTag); }
    144 
    145     void writeFalse() { append(FalseTag); }
    146 
    147     void writeString(const char* data, int length)
    148     {
    149         ASSERT(length >= 0);
    150         append(StringTag);
    151         doWriteString(data, length);
    152     }
    153 
    154     void writeWebCoreString(const String& string)
    155     {
    156         // Uses UTF8 encoding so we can read it back as either V8 or
    157         // WebCore string.
    158         append(StringTag);
    159         doWriteWebCoreString(string);
    160     }
    161 
    162     void writeInt32(int32_t value)
    163     {
    164         append(Int32Tag);
    165         doWriteUint32(ZigZag::encode(static_cast<uint32_t>(value)));
    166     }
    167 
    168     void writeUint32(uint32_t value)
    169     {
    170         append(Uint32Tag);
    171         doWriteUint32(value);
    172     }
    173 
    174     void writeDate(double numberValue)
    175     {
    176         append(DateTag);
    177         doWriteNumber(numberValue);
    178     }
    179 
    180     void writeNumber(double number)
    181     {
    182         append(NumberTag);
    183         doWriteNumber(number);
    184     }
    185 
    186     void writeBlob(const String& url, const String& type, unsigned long long size)
    187     {
    188         append(BlobTag);
    189         doWriteWebCoreString(url);
    190         doWriteWebCoreString(type);
    191         doWriteUint64(size);
    192     }
    193 
    194     void writeFile(const String& path, const String& url, const String& type)
    195     {
    196         append(FileTag);
    197         doWriteWebCoreString(path);
    198         doWriteWebCoreString(url);
    199         doWriteWebCoreString(type);
    200     }
    201 
    202     void writeFileList(const FileList& fileList)
    203     {
    204         append(FileListTag);
    205         uint32_t length = fileList.length();
    206         doWriteUint32(length);
    207         for (unsigned i = 0; i < length; ++i) {
    208             doWriteWebCoreString(fileList.item(i)->path());
    209             doWriteWebCoreString(fileList.item(i)->url().string());
    210             doWriteWebCoreString(fileList.item(i)->type());
    211         }
    212     }
    213 
    214     void writeImageData(uint32_t width, uint32_t height, const uint8_t* pixelData, uint32_t pixelDataLength)
    215     {
    216         append(ImageDataTag);
    217         doWriteUint32(width);
    218         doWriteUint32(height);
    219         doWriteUint32(pixelDataLength);
    220         append(pixelData, pixelDataLength);
    221     }
    222 
    223     void writeRegExp(v8::Local<v8::String> pattern, v8::RegExp::Flags flags)
    224     {
    225         append(RegExpTag);
    226         v8::String::Utf8Value patternUtf8Value(pattern);
    227         doWriteString(*patternUtf8Value, patternUtf8Value.length());
    228         doWriteUint32(static_cast<uint32_t>(flags));
    229     }
    230 
    231     void writeArray(uint32_t length)
    232     {
    233         append(ArrayTag);
    234         doWriteUint32(length);
    235     }
    236 
    237     void writeObject(uint32_t numProperties)
    238     {
    239         append(ObjectTag);
    240         doWriteUint32(numProperties);
    241     }
    242 
    243     void writeSparseArray(uint32_t numProperties, uint32_t length)
    244     {
    245         append(SparseArrayTag);
    246         doWriteUint32(numProperties);
    247         doWriteUint32(length);
    248     }
    249 
    250     Vector<BufferValueType>& data()
    251     {
    252         fillHole();
    253         return m_buffer;
    254     }
    255 
    256 private:
    257     void doWriteString(const char* data, int length)
    258     {
    259         doWriteUint32(static_cast<uint32_t>(length));
    260         append(reinterpret_cast<const uint8_t*>(data), length);
    261     }
    262 
    263     void doWriteWebCoreString(const String& string)
    264     {
    265         RefPtr<SharedBuffer> buffer = utf8Buffer(string);
    266         doWriteString(buffer->data(), buffer->size());
    267     }
    268 
    269     template<class T>
    270     void doWriteUintHelper(T value)
    271     {
    272         while (true) {
    273             uint8_t b = (value & varIntMask);
    274             value >>= varIntShift;
    275             if (!value) {
    276                 append(b);
    277                 break;
    278             }
    279             append(b | (1 << varIntShift));
    280         }
    281     }
    282 
    283     void doWriteUint32(uint32_t value)
    284     {
    285         doWriteUintHelper(value);
    286     }
    287 
    288     void doWriteUint64(uint64_t value)
    289     {
    290         doWriteUintHelper(value);
    291     }
    292 
    293     void doWriteNumber(double number)
    294     {
    295         append(reinterpret_cast<uint8_t*>(&number), sizeof(number));
    296     }
    297 
    298     void append(SerializationTag tag)
    299     {
    300         append(static_cast<uint8_t>(tag));
    301     }
    302 
    303     void append(uint8_t b)
    304     {
    305         ensureSpace(1);
    306         *byteAt(m_position++) = b;
    307     }
    308 
    309     void append(const uint8_t* data, int length)
    310     {
    311         ensureSpace(length);
    312         memcpy(byteAt(m_position), data, length);
    313         m_position += length;
    314     }
    315 
    316     void ensureSpace(int extra)
    317     {
    318         COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
    319         m_buffer.grow((m_position + extra + 1) / 2); // "+ 1" to round up.
    320     }
    321 
    322     void fillHole()
    323     {
    324         COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
    325         // If the writer is at odd position in the buffer, then one of
    326         // the bytes in the last UChar is not initialized.
    327         if (m_position % 2)
    328             *byteAt(m_position) = static_cast<uint8_t>(PaddingTag);
    329     }
    330 
    331     uint8_t* byteAt(int position) { return reinterpret_cast<uint8_t*>(m_buffer.data()) + position; }
    332 
    333     Vector<BufferValueType> m_buffer;
    334     unsigned m_position;
    335 };
    336 
    337 class Serializer {
    338     class StateBase;
    339 public:
    340     enum Status {
    341         Success,
    342         InputError,
    343         JSException,
    344         JSFailure
    345     };
    346 
    347     Serializer(Writer& writer, v8::TryCatch& tryCatch)
    348         : m_writer(writer)
    349         , m_tryCatch(tryCatch)
    350         , m_depth(0)
    351         , m_status(Success)
    352     {
    353         ASSERT(!tryCatch.HasCaught());
    354     }
    355 
    356     Status serialize(v8::Handle<v8::Value> value)
    357     {
    358         v8::HandleScope scope;
    359         StateBase* state = doSerialize(value, 0);
    360         while (state)
    361             state = state->advance(*this);
    362         return m_status;
    363     }
    364 
    365     // Functions used by serialization states.
    366 
    367     StateBase* doSerialize(v8::Handle<v8::Value> value, StateBase* next);
    368 
    369     StateBase* checkException(StateBase* state)
    370     {
    371         return m_tryCatch.HasCaught() ? handleError(JSException, state) : 0;
    372     }
    373 
    374     StateBase* reportFailure(StateBase* state)
    375     {
    376         return handleError(JSFailure, state);
    377     }
    378 
    379     StateBase* writeArray(uint32_t length, StateBase* state)
    380     {
    381         m_writer.writeArray(length);
    382         return pop(state);
    383     }
    384 
    385     StateBase* writeObject(uint32_t numProperties, StateBase* state)
    386     {
    387         m_writer.writeObject(numProperties);
    388         return pop(state);
    389     }
    390 
    391     StateBase* writeSparseArray(uint32_t numProperties, uint32_t length, StateBase* state)
    392     {
    393         m_writer.writeSparseArray(numProperties, length);
    394         return pop(state);
    395     }
    396 
    397 private:
    398     class StateBase {
    399         WTF_MAKE_NONCOPYABLE(StateBase);
    400     public:
    401         virtual ~StateBase() { }
    402 
    403         // Link to the next state to form a stack.
    404         StateBase* nextState() { return m_next; }
    405 
    406         // Composite object we're processing in this state.
    407         v8::Handle<v8::Value> composite() { return m_composite; }
    408 
    409         // Serializes (a part of) the current composite and returns
    410         // the next state to process or null when this is the final
    411         // state.
    412         virtual StateBase* advance(Serializer&) = 0;
    413 
    414     protected:
    415         StateBase(v8::Handle<v8::Value> composite, StateBase* next)
    416             : m_composite(composite)
    417             , m_next(next)
    418         {
    419         }
    420 
    421     private:
    422         v8::Handle<v8::Value> m_composite;
    423         StateBase* m_next;
    424     };
    425 
    426     // Dummy state that is used to signal serialization errors.
    427     class ErrorState : public StateBase {
    428     public:
    429         ErrorState()
    430             : StateBase(v8::Handle<v8::Value>(), 0)
    431         {
    432         }
    433 
    434         virtual StateBase* advance(Serializer&)
    435         {
    436             delete this;
    437             return 0;
    438         }
    439     };
    440 
    441     template <typename T>
    442     class State : public StateBase {
    443     public:
    444         v8::Handle<T> composite() { return v8::Handle<T>::Cast(StateBase::composite()); }
    445 
    446     protected:
    447         State(v8::Handle<T> composite, StateBase* next)
    448             : StateBase(composite, next)
    449         {
    450         }
    451     };
    452 
    453 #if 0
    454     // Currently unused, see comment in newArrayState.
    455     class ArrayState : public State<v8::Array> {
    456     public:
    457         ArrayState(v8::Handle<v8::Array> array, StateBase* next)
    458             : State<v8::Array>(array, next)
    459             , m_index(-1)
    460         {
    461         }
    462 
    463         virtual StateBase* advance(Serializer& serializer)
    464         {
    465             ++m_index;
    466             for (; m_index < composite()->Length(); ++m_index) {
    467                 v8::Handle<v8::Value> value = composite()->Get(m_index);
    468                 if (StateBase* newState = serializer.checkException(this))
    469                     return newState;
    470                 if (StateBase* newState = serializer.doSerialize(value, this))
    471                     return newState;
    472             }
    473             return serializer.writeArray(composite()->Length(), this);
    474         }
    475 
    476     private:
    477         unsigned m_index;
    478     };
    479 #endif
    480 
    481     class AbstractObjectState : public State<v8::Object> {
    482     public:
    483         AbstractObjectState(v8::Handle<v8::Object> object, StateBase* next)
    484             : State<v8::Object>(object, next)
    485             , m_index(0)
    486             , m_numSerializedProperties(0)
    487             , m_nameDone(false)
    488         {
    489         }
    490 
    491         virtual StateBase* advance(Serializer& serializer)
    492         {
    493             if (!m_index) {
    494                 m_propertyNames = composite()->GetPropertyNames();
    495                 if (StateBase* newState = serializer.checkException(this))
    496                     return newState;
    497                 if (m_propertyNames.IsEmpty())
    498                     return serializer.reportFailure(this);
    499             }
    500             while (m_index < m_propertyNames->Length()) {
    501                 if (!m_nameDone) {
    502                     v8::Local<v8::Value> propertyName = m_propertyNames->Get(m_index);
    503                     if (StateBase* newState = serializer.checkException(this))
    504                         return newState;
    505                     if (propertyName.IsEmpty())
    506                         return serializer.reportFailure(this);
    507                     bool hasStringProperty = propertyName->IsString() && composite()->HasRealNamedProperty(propertyName.As<v8::String>());
    508                     if (StateBase* newState = serializer.checkException(this))
    509                         return newState;
    510                     bool hasIndexedProperty = !hasStringProperty && propertyName->IsUint32() && composite()->HasRealIndexedProperty(propertyName->Uint32Value());
    511                     if (StateBase* newState = serializer.checkException(this))
    512                         return newState;
    513                     if (hasStringProperty || hasIndexedProperty)
    514                         m_propertyName = propertyName;
    515                     else {
    516                         ++m_index;
    517                         continue;
    518                     }
    519                 }
    520                 ASSERT(!m_propertyName.IsEmpty());
    521                 if (!m_nameDone) {
    522                     m_nameDone = true;
    523                     if (StateBase* newState = serializer.doSerialize(m_propertyName, this))
    524                         return newState;
    525                 }
    526                 v8::Local<v8::Value> value = composite()->Get(m_propertyName);
    527                 if (StateBase* newState = serializer.checkException(this))
    528                     return newState;
    529                 m_nameDone = false;
    530                 m_propertyName.Clear();
    531                 ++m_index;
    532                 ++m_numSerializedProperties;
    533                 if (StateBase* newState = serializer.doSerialize(value, this))
    534                     return newState;
    535             }
    536             return objectDone(m_numSerializedProperties, serializer);
    537         }
    538 
    539     protected:
    540         virtual StateBase* objectDone(unsigned numProperties, Serializer&) = 0;
    541 
    542     private:
    543         v8::Local<v8::Array> m_propertyNames;
    544         v8::Local<v8::Value> m_propertyName;
    545         unsigned m_index;
    546         unsigned m_numSerializedProperties;
    547         bool m_nameDone;
    548     };
    549 
    550     class ObjectState : public AbstractObjectState {
    551     public:
    552         ObjectState(v8::Handle<v8::Object> object, StateBase* next)
    553             : AbstractObjectState(object, next)
    554         {
    555         }
    556 
    557     protected:
    558         virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer)
    559         {
    560             return serializer.writeObject(numProperties, this);
    561         }
    562     };
    563 
    564     class SparseArrayState : public AbstractObjectState {
    565     public:
    566         SparseArrayState(v8::Handle<v8::Array> array, StateBase* next)
    567             : AbstractObjectState(array, next)
    568         {
    569         }
    570 
    571     protected:
    572         virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer)
    573         {
    574             return serializer.writeSparseArray(numProperties, composite().As<v8::Array>()->Length(), this);
    575         }
    576     };
    577 
    578     StateBase* push(StateBase* state)
    579     {
    580         ASSERT(state);
    581         ++m_depth;
    582         return checkComposite(state) ? state : handleError(InputError, state);
    583     }
    584 
    585     StateBase* pop(StateBase* state)
    586     {
    587         ASSERT(state);
    588         --m_depth;
    589         StateBase* next = state->nextState();
    590         delete state;
    591         return next;
    592     }
    593 
    594     StateBase* handleError(Status errorStatus, StateBase* state)
    595     {
    596         ASSERT(errorStatus != Success);
    597         m_status = errorStatus;
    598         while (state) {
    599             StateBase* tmp = state->nextState();
    600             delete state;
    601             state = tmp;
    602         }
    603         return new ErrorState;
    604     }
    605 
    606     bool checkComposite(StateBase* top)
    607     {
    608         ASSERT(top);
    609         if (m_depth > maxDepth)
    610             return false;
    611         if (!shouldCheckForCycles(m_depth))
    612             return true;
    613         v8::Handle<v8::Value> composite = top->composite();
    614         for (StateBase* state = top->nextState(); state; state = state->nextState()) {
    615             if (state->composite() == composite)
    616                 return false;
    617         }
    618         return true;
    619     }
    620 
    621     void writeString(v8::Handle<v8::Value> value)
    622     {
    623         v8::String::Utf8Value stringValue(value);
    624         m_writer.writeString(*stringValue, stringValue.length());
    625     }
    626 
    627     void writeBlob(v8::Handle<v8::Value> value)
    628     {
    629         Blob* blob = V8Blob::toNative(value.As<v8::Object>());
    630         if (!blob)
    631             return;
    632         m_writer.writeBlob(blob->url().string(), blob->type(), blob->size());
    633     }
    634 
    635     void writeFile(v8::Handle<v8::Value> value)
    636     {
    637         File* file = V8File::toNative(value.As<v8::Object>());
    638         if (!file)
    639             return;
    640         m_writer.writeFile(file->path(), file->url().string(), file->type());
    641     }
    642 
    643     void writeFileList(v8::Handle<v8::Value> value)
    644     {
    645         FileList* fileList = V8FileList::toNative(value.As<v8::Object>());
    646         if (!fileList)
    647             return;
    648         m_writer.writeFileList(*fileList);
    649     }
    650 
    651     void writeImageData(v8::Handle<v8::Value> value)
    652     {
    653         ImageData* imageData = V8ImageData::toNative(value.As<v8::Object>());
    654         if (!imageData)
    655             return;
    656         WTF::ByteArray* pixelArray = imageData->data()->data();
    657         m_writer.writeImageData(imageData->width(), imageData->height(), pixelArray->data(), pixelArray->length());
    658     }
    659 
    660     void writeRegExp(v8::Handle<v8::Value> value)
    661     {
    662         v8::Handle<v8::RegExp> regExp = value.As<v8::RegExp>();
    663         m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags());
    664     }
    665 
    666     static StateBase* newArrayState(v8::Handle<v8::Array> array, StateBase* next)
    667     {
    668         // FIXME: use plain Array state when we can quickly check that
    669         // an array is not sparse and has only indexed properties.
    670         return new SparseArrayState(array, next);
    671     }
    672 
    673     static StateBase* newObjectState(v8::Handle<v8::Object> object, StateBase* next)
    674     {
    675         // FIXME: check not a wrapper
    676         return new ObjectState(object, next);
    677     }
    678 
    679     Writer& m_writer;
    680     v8::TryCatch& m_tryCatch;
    681     int m_depth;
    682     Status m_status;
    683 };
    684 
    685 Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, StateBase* next)
    686 {
    687     if (value.IsEmpty())
    688         return reportFailure(next);
    689     if (value->IsUndefined())
    690         m_writer.writeUndefined();
    691     else if (value->IsNull())
    692         m_writer.writeNull();
    693     else if (value->IsTrue())
    694         m_writer.writeTrue();
    695     else if (value->IsFalse())
    696         m_writer.writeFalse();
    697     else if (value->IsInt32())
    698         m_writer.writeInt32(value->Int32Value());
    699     else if (value->IsUint32())
    700         m_writer.writeUint32(value->Uint32Value());
    701     else if (value->IsDate())
    702         m_writer.writeDate(value->NumberValue());
    703     else if (value->IsNumber())
    704         m_writer.writeNumber(value.As<v8::Number>()->Value());
    705     else if (value->IsString())
    706         writeString(value);
    707     else if (value->IsArray())
    708         return push(newArrayState(value.As<v8::Array>(), next));
    709     else if (V8File::HasInstance(value))
    710         writeFile(value);
    711     else if (V8Blob::HasInstance(value))
    712         writeBlob(value);
    713     else if (V8FileList::HasInstance(value))
    714         writeFileList(value);
    715     else if (V8ImageData::HasInstance(value))
    716         writeImageData(value);
    717     else if (value->IsRegExp())
    718         writeRegExp(value);
    719     else if (value->IsObject())
    720         return push(newObjectState(value.As<v8::Object>(), next));
    721     return 0;
    722 }
    723 
    724 // Interface used by Reader to create objects of composite types.
    725 class CompositeCreator {
    726 public:
    727     virtual ~CompositeCreator() { }
    728 
    729     virtual bool createArray(uint32_t length, v8::Handle<v8::Value>* value) = 0;
    730     virtual bool createObject(uint32_t numProperties, v8::Handle<v8::Value>* value) = 0;
    731     virtual bool createSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) = 0;
    732 };
    733 
    734 // Reader is responsible for deserializing primitive types and
    735 // restoring information about saved objects of composite types.
    736 class Reader {
    737 public:
    738     Reader(const uint8_t* buffer, int length)
    739         : m_buffer(buffer)
    740         , m_length(length)
    741         , m_position(0)
    742     {
    743         ASSERT(length >= 0);
    744     }
    745 
    746     bool isEof() const { return m_position >= m_length; }
    747 
    748     bool read(v8::Handle<v8::Value>* value, CompositeCreator& creator)
    749     {
    750         SerializationTag tag;
    751         if (!readTag(&tag))
    752             return false;
    753         switch (tag) {
    754         case InvalidTag:
    755             return false;
    756         case PaddingTag:
    757             return true;
    758         case UndefinedTag:
    759             *value = v8::Undefined();
    760             break;
    761         case NullTag:
    762             *value = v8::Null();
    763             break;
    764         case TrueTag:
    765             *value = v8::True();
    766             break;
    767         case FalseTag:
    768             *value = v8::False();
    769             break;
    770         case StringTag:
    771             if (!readString(value))
    772                 return false;
    773             break;
    774         case Int32Tag:
    775             if (!readInt32(value))
    776                 return false;
    777             break;
    778         case Uint32Tag:
    779             if (!readUint32(value))
    780                 return false;
    781             break;
    782         case DateTag:
    783             if (!readDate(value))
    784                 return false;
    785             break;
    786         case NumberTag:
    787             if (!readNumber(value))
    788                 return false;
    789             break;
    790         case BlobTag:
    791             if (!readBlob(value))
    792                 return false;
    793             break;
    794         case FileTag:
    795             if (!readFile(value))
    796                 return false;
    797             break;
    798         case FileListTag:
    799             if (!readFileList(value))
    800                 return false;
    801             break;
    802         case ImageDataTag:
    803             if (!readImageData(value))
    804                 return false;
    805             break;
    806         case ArrayTag: {
    807             uint32_t length;
    808             if (!doReadUint32(&length))
    809                 return false;
    810             if (!creator.createArray(length, value))
    811                 return false;
    812             break;
    813         }
    814         case RegExpTag:
    815             if (!readRegExp(value))
    816                 return false;
    817             break;
    818         case ObjectTag: {
    819             uint32_t numProperties;
    820             if (!doReadUint32(&numProperties))
    821                 return false;
    822             if (!creator.createObject(numProperties, value))
    823                 return false;
    824             break;
    825         }
    826         case SparseArrayTag: {
    827             uint32_t numProperties;
    828             uint32_t length;
    829             if (!doReadUint32(&numProperties))
    830                 return false;
    831             if (!doReadUint32(&length))
    832                 return false;
    833             if (!creator.createSparseArray(numProperties, length, value))
    834                 return false;
    835             break;
    836         }
    837         default:
    838             return false;
    839         }
    840         return !value->IsEmpty();
    841     }
    842 
    843 private:
    844     bool readTag(SerializationTag* tag)
    845     {
    846         if (m_position >= m_length)
    847             return false;
    848         *tag = static_cast<SerializationTag>(m_buffer[m_position++]);
    849         return true;
    850     }
    851 
    852     bool readString(v8::Handle<v8::Value>* value)
    853     {
    854         uint32_t length;
    855         if (!doReadUint32(&length))
    856             return false;
    857         if (m_position + length > m_length)
    858             return false;
    859         *value = v8::String::New(reinterpret_cast<const char*>(m_buffer + m_position), length);
    860         m_position += length;
    861         return true;
    862     }
    863 
    864     bool readWebCoreString(String* string)
    865     {
    866         uint32_t length;
    867         if (!doReadUint32(&length))
    868             return false;
    869         if (m_position + length > m_length)
    870             return false;
    871         *string = String::fromUTF8(reinterpret_cast<const char*>(m_buffer + m_position), length);
    872         m_position += length;
    873         return true;
    874     }
    875 
    876     bool readInt32(v8::Handle<v8::Value>* value)
    877     {
    878         uint32_t rawValue;
    879         if (!doReadUint32(&rawValue))
    880             return false;
    881         *value = v8::Integer::New(static_cast<int32_t>(ZigZag::decode(rawValue)));
    882         return true;
    883     }
    884 
    885     bool readUint32(v8::Handle<v8::Value>* value)
    886     {
    887         uint32_t rawValue;
    888         if (!doReadUint32(&rawValue))
    889             return false;
    890         *value = v8::Integer::NewFromUnsigned(rawValue);
    891         return true;
    892     }
    893 
    894     bool readDate(v8::Handle<v8::Value>* value)
    895     {
    896         double numberValue;
    897         if (!doReadNumber(&numberValue))
    898             return false;
    899         *value = v8::Date::New(numberValue);
    900         return true;
    901     }
    902 
    903     bool readNumber(v8::Handle<v8::Value>* value)
    904     {
    905         double number;
    906         if (!doReadNumber(&number))
    907             return false;
    908         *value = v8::Number::New(number);
    909         return true;
    910     }
    911 
    912     bool readImageData(v8::Handle<v8::Value>* value)
    913     {
    914         uint32_t width;
    915         uint32_t height;
    916         uint32_t pixelDataLength;
    917         if (!doReadUint32(&width))
    918             return false;
    919         if (!doReadUint32(&height))
    920             return false;
    921         if (!doReadUint32(&pixelDataLength))
    922             return false;
    923         if (m_position + pixelDataLength > m_length)
    924             return false;
    925         RefPtr<ImageData> imageData = ImageData::create(IntSize(width, height));
    926         WTF::ByteArray* pixelArray = imageData->data()->data();
    927         ASSERT(pixelArray);
    928         ASSERT(pixelArray->length() >= pixelDataLength);
    929         memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength);
    930         m_position += pixelDataLength;
    931         *value = toV8(imageData.release());
    932         return true;
    933     }
    934 
    935     bool readRegExp(v8::Handle<v8::Value>* value)
    936     {
    937         v8::Handle<v8::Value> pattern;
    938         if (!readString(&pattern))
    939             return false;
    940         uint32_t flags;
    941         if (!doReadUint32(&flags))
    942             return false;
    943         *value = v8::RegExp::New(pattern.As<v8::String>(), static_cast<v8::RegExp::Flags>(flags));
    944         return true;
    945     }
    946 
    947     bool readBlob(v8::Handle<v8::Value>* value)
    948     {
    949         String url;
    950         String type;
    951         uint64_t size;
    952         if (!readWebCoreString(&url))
    953             return false;
    954         if (!readWebCoreString(&type))
    955             return false;
    956         if (!doReadUint64(&size))
    957             return false;
    958         PassRefPtr<Blob> blob = Blob::create(KURL(ParsedURLString, url), type, size);
    959         *value = toV8(blob);
    960         return true;
    961     }
    962 
    963     bool readFile(v8::Handle<v8::Value>* value)
    964     {
    965         String path;
    966         String url;
    967         String type;
    968         if (!readWebCoreString(&path))
    969             return false;
    970         if (!readWebCoreString(&url))
    971             return false;
    972         if (!readWebCoreString(&type))
    973             return false;
    974         PassRefPtr<File> file = File::create(path, KURL(ParsedURLString, url), type);
    975         *value = toV8(file);
    976         return true;
    977     }
    978 
    979     bool readFileList(v8::Handle<v8::Value>* value)
    980     {
    981         uint32_t length;
    982         if (!doReadUint32(&length))
    983             return false;
    984         PassRefPtr<FileList> fileList = FileList::create();
    985         for (unsigned i = 0; i < length; ++i) {
    986             String path;
    987             String urlString;
    988             String type;
    989             if (!readWebCoreString(&path))
    990                 return false;
    991             if (!readWebCoreString(&urlString))
    992                 return false;
    993             if (!readWebCoreString(&type))
    994                 return false;
    995             fileList->append(File::create(path, KURL(ParsedURLString, urlString), type));
    996         }
    997         *value = toV8(fileList);
    998         return true;
    999     }
   1000 
   1001     template<class T>
   1002     bool doReadUintHelper(T* value)
   1003     {
   1004         *value = 0;
   1005         uint8_t currentByte;
   1006         int shift = 0;
   1007         do {
   1008             if (m_position >= m_length)
   1009                 return false;
   1010             currentByte = m_buffer[m_position++];
   1011             *value |= ((currentByte & varIntMask) << shift);
   1012             shift += varIntShift;
   1013         } while (currentByte & (1 << varIntShift));
   1014         return true;
   1015     }
   1016 
   1017     bool doReadUint32(uint32_t* value)
   1018     {
   1019         return doReadUintHelper(value);
   1020     }
   1021 
   1022     bool doReadUint64(uint64_t* value)
   1023     {
   1024         return doReadUintHelper(value);
   1025     }
   1026 
   1027     bool doReadNumber(double* number)
   1028     {
   1029         if (m_position + sizeof(double) > m_length)
   1030             return false;
   1031         uint8_t* numberAsByteArray = reinterpret_cast<uint8_t*>(number);
   1032         for (unsigned i = 0; i < sizeof(double); ++i)
   1033             numberAsByteArray[i] = m_buffer[m_position++];
   1034         return true;
   1035     }
   1036 
   1037     const uint8_t* m_buffer;
   1038     const unsigned m_length;
   1039     unsigned m_position;
   1040 };
   1041 
   1042 class Deserializer : public CompositeCreator {
   1043 public:
   1044     explicit Deserializer(Reader& reader)
   1045         : m_reader(reader)
   1046     {
   1047     }
   1048 
   1049     v8::Handle<v8::Value> deserialize()
   1050     {
   1051         v8::HandleScope scope;
   1052         while (!m_reader.isEof()) {
   1053             if (!doDeserialize())
   1054                 return v8::Null();
   1055         }
   1056         if (stackDepth() != 1)
   1057             return v8::Null();
   1058         return scope.Close(element(0));
   1059     }
   1060 
   1061     virtual bool createArray(uint32_t length, v8::Handle<v8::Value>* value)
   1062     {
   1063         if (length > stackDepth())
   1064             return false;
   1065         v8::Local<v8::Array> array = v8::Array::New(length);
   1066         if (array.IsEmpty())
   1067             return false;
   1068         const int depth = stackDepth() - length;
   1069         for (unsigned i = 0; i < length; ++i)
   1070             array->Set(i, element(depth + i));
   1071         pop(length);
   1072         *value = array;
   1073         return true;
   1074     }
   1075 
   1076     virtual bool createObject(uint32_t numProperties, v8::Handle<v8::Value>* value)
   1077     {
   1078         v8::Local<v8::Object> object = v8::Object::New();
   1079         if (object.IsEmpty())
   1080             return false;
   1081         return initializeObject(object, numProperties, value);
   1082     }
   1083 
   1084     virtual bool createSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value)
   1085     {
   1086         v8::Local<v8::Array> array = v8::Array::New(length);
   1087         if (array.IsEmpty())
   1088             return false;
   1089         return initializeObject(array, numProperties, value);
   1090     }
   1091 
   1092 private:
   1093     bool initializeObject(v8::Handle<v8::Object> object, uint32_t numProperties, v8::Handle<v8::Value>* value)
   1094     {
   1095         unsigned length = 2 * numProperties;
   1096         if (length > stackDepth())
   1097             return false;
   1098         for (unsigned i = stackDepth() - length; i < stackDepth(); i += 2) {
   1099             v8::Local<v8::Value> propertyName = element(i);
   1100             v8::Local<v8::Value> propertyValue = element(i + 1);
   1101             object->Set(propertyName, propertyValue);
   1102         }
   1103         pop(length);
   1104         *value = object;
   1105         return true;
   1106     }
   1107 
   1108     bool doDeserialize()
   1109     {
   1110         v8::Local<v8::Value> value;
   1111         if (!m_reader.read(&value, *this))
   1112             return false;
   1113         if (!value.IsEmpty())
   1114             push(value);
   1115         return true;
   1116     }
   1117 
   1118     void push(v8::Local<v8::Value> value) { m_stack.append(value); }
   1119 
   1120     void pop(unsigned length)
   1121     {
   1122         ASSERT(length <= m_stack.size());
   1123         m_stack.shrink(m_stack.size() - length);
   1124     }
   1125 
   1126     unsigned stackDepth() const { return m_stack.size(); }
   1127 
   1128     v8::Local<v8::Value> element(unsigned index)
   1129     {
   1130         ASSERT(index < m_stack.size());
   1131         return m_stack[index];
   1132     }
   1133 
   1134     Reader& m_reader;
   1135     Vector<v8::Local<v8::Value> > m_stack;
   1136 };
   1137 
   1138 } // namespace
   1139 
   1140 void SerializedScriptValue::deserializeAndSetProperty(v8::Handle<v8::Object> object, const char* propertyName,
   1141                                                       v8::PropertyAttribute attribute, SerializedScriptValue* value)
   1142 {
   1143     if (!value)
   1144         return;
   1145     v8::Handle<v8::Value> deserialized = value->deserialize();
   1146     object->ForceSet(v8::String::NewSymbol(propertyName), deserialized, attribute);
   1147 }
   1148 
   1149 void SerializedScriptValue::deserializeAndSetProperty(v8::Handle<v8::Object> object, const char* propertyName,
   1150                                                       v8::PropertyAttribute attribute, PassRefPtr<SerializedScriptValue> value)
   1151 {
   1152     deserializeAndSetProperty(object, propertyName, attribute, value.get());
   1153 }
   1154 
   1155 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value, bool& didThrow)
   1156 {
   1157     return adoptRef(new SerializedScriptValue(value, didThrow));
   1158 }
   1159 
   1160 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value)
   1161 {
   1162     bool didThrow;
   1163     return adoptRef(new SerializedScriptValue(value, didThrow));
   1164 }
   1165 
   1166 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWire(String data)
   1167 {
   1168     return adoptRef(new SerializedScriptValue(data));
   1169 }
   1170 
   1171 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(String data)
   1172 {
   1173     Writer writer;
   1174     writer.writeWebCoreString(data);
   1175     String wireData = StringImpl::adopt(writer.data());
   1176     return adoptRef(new SerializedScriptValue(wireData));
   1177 }
   1178 
   1179 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create()
   1180 {
   1181     return adoptRef(new SerializedScriptValue());
   1182 }
   1183 
   1184 SerializedScriptValue* SerializedScriptValue::nullValue()
   1185 {
   1186     DEFINE_STATIC_LOCAL(RefPtr<SerializedScriptValue>, nullValue, (0));
   1187     if (!nullValue) {
   1188         Writer writer;
   1189         writer.writeNull();
   1190         String wireData = StringImpl::adopt(writer.data());
   1191         nullValue = adoptRef(new SerializedScriptValue(wireData));
   1192     }
   1193     return nullValue.get();
   1194 }
   1195 
   1196 SerializedScriptValue* SerializedScriptValue::undefinedValue()
   1197 {
   1198     DEFINE_STATIC_LOCAL(RefPtr<SerializedScriptValue>, undefinedValue, (0));
   1199     if (!undefinedValue) {
   1200         Writer writer;
   1201         writer.writeUndefined();
   1202         String wireData = StringImpl::adopt(writer.data());
   1203         undefinedValue = adoptRef(new SerializedScriptValue(wireData));
   1204     }
   1205     return undefinedValue.get();
   1206 }
   1207 
   1208 PassRefPtr<SerializedScriptValue> SerializedScriptValue::release()
   1209 {
   1210     RefPtr<SerializedScriptValue> result = adoptRef(new SerializedScriptValue(m_data));
   1211     m_data = String().crossThreadString();
   1212     return result.release();
   1213 }
   1214 
   1215 SerializedScriptValue::SerializedScriptValue()
   1216 {
   1217 }
   1218 
   1219 SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, bool& didThrow)
   1220 {
   1221     didThrow = false;
   1222     Writer writer;
   1223     Serializer::Status status;
   1224     {
   1225         v8::TryCatch tryCatch;
   1226         Serializer serializer(writer, tryCatch);
   1227         status = serializer.serialize(value);
   1228         if (status == Serializer::JSException) {
   1229             // If there was a JS exception thrown, re-throw it.
   1230             didThrow = true;
   1231             tryCatch.ReThrow();
   1232             return;
   1233         }
   1234     }
   1235     if (status == Serializer::InputError) {
   1236         // If there was an input error, throw a new exception outside
   1237         // of the TryCatch scope.
   1238         didThrow = true;
   1239         throwError(NOT_SUPPORTED_ERR);
   1240         return;
   1241     }
   1242     if (status == Serializer::JSFailure) {
   1243         // If there was a JS failure (but no exception), there's not
   1244         // much we can do except for unwinding the C++ stack by
   1245         // pretending there was a JS exception.
   1246         didThrow = true;
   1247         return;
   1248     }
   1249     ASSERT(status == Serializer::Success);
   1250     m_data = String(StringImpl::adopt(writer.data())).crossThreadString();
   1251 }
   1252 
   1253 SerializedScriptValue::SerializedScriptValue(String wireData)
   1254 {
   1255     m_data = wireData.crossThreadString();
   1256 }
   1257 
   1258 v8::Handle<v8::Value> SerializedScriptValue::deserialize()
   1259 {
   1260     if (!m_data.impl())
   1261         return v8::Null();
   1262     COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
   1263     Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->characters()), 2 * m_data.length());
   1264     Deserializer deserializer(reader);
   1265     return deserializer.deserialize();
   1266 }
   1267 
   1268 } // namespace WebCore
   1269