• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
shouldCheckForCycles(int depth)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:
encode(uint32_t value)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 
decode(uint32_t value)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:
Writer()132     Writer()
133         : m_position(0)
134     {
135     }
136 
137     // Write functions for primitive types.
138 
writeUndefined()139     void writeUndefined() { append(UndefinedTag); }
140 
writeNull()141     void writeNull() { append(NullTag); }
142 
writeTrue()143     void writeTrue() { append(TrueTag); }
144 
writeFalse()145     void writeFalse() { append(FalseTag); }
146 
writeString(const char * data,int length)147     void writeString(const char* data, int length)
148     {
149         ASSERT(length >= 0);
150         append(StringTag);
151         doWriteString(data, length);
152     }
153 
writeWebCoreString(const String & string)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 
writeInt32(int32_t value)162     void writeInt32(int32_t value)
163     {
164         append(Int32Tag);
165         doWriteUint32(ZigZag::encode(static_cast<uint32_t>(value)));
166     }
167 
writeUint32(uint32_t value)168     void writeUint32(uint32_t value)
169     {
170         append(Uint32Tag);
171         doWriteUint32(value);
172     }
173 
writeDate(double numberValue)174     void writeDate(double numberValue)
175     {
176         append(DateTag);
177         doWriteNumber(numberValue);
178     }
179 
writeNumber(double number)180     void writeNumber(double number)
181     {
182         append(NumberTag);
183         doWriteNumber(number);
184     }
185 
writeBlob(const String & url,const String & type,unsigned long long size)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 
writeFile(const String & path,const String & url,const String & type)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 
writeFileList(const FileList & fileList)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 
writeImageData(uint32_t width,uint32_t height,const uint8_t * pixelData,uint32_t pixelDataLength)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 
writeRegExp(v8::Local<v8::String> pattern,v8::RegExp::Flags flags)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 
writeArray(uint32_t length)231     void writeArray(uint32_t length)
232     {
233         append(ArrayTag);
234         doWriteUint32(length);
235     }
236 
writeObject(uint32_t numProperties)237     void writeObject(uint32_t numProperties)
238     {
239         append(ObjectTag);
240         doWriteUint32(numProperties);
241     }
242 
writeSparseArray(uint32_t numProperties,uint32_t length)243     void writeSparseArray(uint32_t numProperties, uint32_t length)
244     {
245         append(SparseArrayTag);
246         doWriteUint32(numProperties);
247         doWriteUint32(length);
248     }
249 
data()250     Vector<BufferValueType>& data()
251     {
252         fillHole();
253         return m_buffer;
254     }
255 
256 private:
doWriteString(const char * data,int length)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 
doWriteWebCoreString(const String & string)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>
doWriteUintHelper(T value)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 
doWriteUint32(uint32_t value)283     void doWriteUint32(uint32_t value)
284     {
285         doWriteUintHelper(value);
286     }
287 
doWriteUint64(uint64_t value)288     void doWriteUint64(uint64_t value)
289     {
290         doWriteUintHelper(value);
291     }
292 
doWriteNumber(double number)293     void doWriteNumber(double number)
294     {
295         append(reinterpret_cast<uint8_t*>(&number), sizeof(number));
296     }
297 
append(SerializationTag tag)298     void append(SerializationTag tag)
299     {
300         append(static_cast<uint8_t>(tag));
301     }
302 
append(uint8_t b)303     void append(uint8_t b)
304     {
305         ensureSpace(1);
306         *byteAt(m_position++) = b;
307     }
308 
append(const uint8_t * data,int length)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 
ensureSpace(int extra)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 
fillHole()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 
byteAt(int position)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 
Serializer(Writer & writer,v8::TryCatch & tryCatch)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 
serialize(v8::Handle<v8::Value> value)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 
checkException(StateBase * state)369     StateBase* checkException(StateBase* state)
370     {
371         return m_tryCatch.HasCaught() ? handleError(JSException, state) : 0;
372     }
373 
reportFailure(StateBase * state)374     StateBase* reportFailure(StateBase* state)
375     {
376         return handleError(JSFailure, state);
377     }
378 
writeArray(uint32_t length,StateBase * state)379     StateBase* writeArray(uint32_t length, StateBase* state)
380     {
381         m_writer.writeArray(length);
382         return pop(state);
383     }
384 
writeObject(uint32_t numProperties,StateBase * state)385     StateBase* writeObject(uint32_t numProperties, StateBase* state)
386     {
387         m_writer.writeObject(numProperties);
388         return pop(state);
389     }
390 
writeSparseArray(uint32_t numProperties,uint32_t length,StateBase * state)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:
~StateBase()401         virtual ~StateBase() { }
402 
403         // Link to the next state to form a stack.
nextState()404         StateBase* nextState() { return m_next; }
405 
406         // Composite object we're processing in this state.
composite()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:
StateBase(v8::Handle<v8::Value> composite,StateBase * next)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:
ErrorState()429         ErrorState()
430             : StateBase(v8::Handle<v8::Value>(), 0)
431         {
432         }
433 
advance(Serializer &)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:
composite()444         v8::Handle<T> composite() { return v8::Handle<T>::Cast(StateBase::composite()); }
445 
446     protected:
State(v8::Handle<T> composite,StateBase * next)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:
AbstractObjectState(v8::Handle<v8::Object> object,StateBase * next)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 
advance(Serializer & serializer)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:
ObjectState(v8::Handle<v8::Object> object,StateBase * next)552         ObjectState(v8::Handle<v8::Object> object, StateBase* next)
553             : AbstractObjectState(object, next)
554         {
555         }
556 
557     protected:
objectDone(unsigned numProperties,Serializer & serializer)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:
SparseArrayState(v8::Handle<v8::Array> array,StateBase * next)566         SparseArrayState(v8::Handle<v8::Array> array, StateBase* next)
567             : AbstractObjectState(array, next)
568         {
569         }
570 
571     protected:
objectDone(unsigned numProperties,Serializer & serializer)572         virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer)
573         {
574             return serializer.writeSparseArray(numProperties, composite().As<v8::Array>()->Length(), this);
575         }
576     };
577 
push(StateBase * state)578     StateBase* push(StateBase* state)
579     {
580         ASSERT(state);
581         ++m_depth;
582         return checkComposite(state) ? state : handleError(InputError, state);
583     }
584 
pop(StateBase * state)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 
handleError(Status errorStatus,StateBase * state)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 
checkComposite(StateBase * top)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 
writeString(v8::Handle<v8::Value> value)621     void writeString(v8::Handle<v8::Value> value)
622     {
623         v8::String::Utf8Value stringValue(value);
624         m_writer.writeString(*stringValue, stringValue.length());
625     }
626 
writeBlob(v8::Handle<v8::Value> value)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 
writeFile(v8::Handle<v8::Value> value)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 
writeFileList(v8::Handle<v8::Value> value)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 
writeImageData(v8::Handle<v8::Value> value)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 
writeRegExp(v8::Handle<v8::Value> value)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 
newArrayState(v8::Handle<v8::Array> array,StateBase * next)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 
newObjectState(v8::Handle<v8::Object> object,StateBase * next)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 
doSerialize(v8::Handle<v8::Value> value,StateBase * next)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:
~CompositeCreator()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:
Reader(const uint8_t * buffer,int length)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 
isEof() const746     bool isEof() const { return m_position >= m_length; }
747 
read(v8::Handle<v8::Value> * value,CompositeCreator & creator)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:
readTag(SerializationTag * tag)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 
readString(v8::Handle<v8::Value> * value)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 
readWebCoreString(String * string)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 
readInt32(v8::Handle<v8::Value> * value)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 
readUint32(v8::Handle<v8::Value> * value)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 
readDate(v8::Handle<v8::Value> * value)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 
readNumber(v8::Handle<v8::Value> * value)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 
readImageData(v8::Handle<v8::Value> * value)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 
readRegExp(v8::Handle<v8::Value> * value)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 
readBlob(v8::Handle<v8::Value> * value)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 
readFile(v8::Handle<v8::Value> * value)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 
readFileList(v8::Handle<v8::Value> * value)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>
doReadUintHelper(T * value)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 
doReadUint32(uint32_t * value)1017     bool doReadUint32(uint32_t* value)
1018     {
1019         return doReadUintHelper(value);
1020     }
1021 
doReadUint64(uint64_t * value)1022     bool doReadUint64(uint64_t* value)
1023     {
1024         return doReadUintHelper(value);
1025     }
1026 
doReadNumber(double * number)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:
Deserializer(Reader & reader)1044     explicit Deserializer(Reader& reader)
1045         : m_reader(reader)
1046     {
1047     }
1048 
deserialize()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 
createArray(uint32_t length,v8::Handle<v8::Value> * value)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 
createObject(uint32_t numProperties,v8::Handle<v8::Value> * value)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 
createSparseArray(uint32_t numProperties,uint32_t length,v8::Handle<v8::Value> * value)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:
initializeObject(v8::Handle<v8::Object> object,uint32_t numProperties,v8::Handle<v8::Value> * value)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 
doDeserialize()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 
push(v8::Local<v8::Value> value)1118     void push(v8::Local<v8::Value> value) { m_stack.append(value); }
1119 
pop(unsigned length)1120     void pop(unsigned length)
1121     {
1122         ASSERT(length <= m_stack.size());
1123         m_stack.shrink(m_stack.size() - length);
1124     }
1125 
stackDepth() const1126     unsigned stackDepth() const { return m_stack.size(); }
1127 
element(unsigned index)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 
deserializeAndSetProperty(v8::Handle<v8::Object> object,const char * propertyName,v8::PropertyAttribute attribute,SerializedScriptValue * value)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 
deserializeAndSetProperty(v8::Handle<v8::Object> object,const char * propertyName,v8::PropertyAttribute attribute,PassRefPtr<SerializedScriptValue> value)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 
create(v8::Handle<v8::Value> value,bool & didThrow)1155 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value, bool& didThrow)
1156 {
1157     return adoptRef(new SerializedScriptValue(value, didThrow));
1158 }
1159 
create(v8::Handle<v8::Value> value)1160 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value)
1161 {
1162     bool didThrow;
1163     return adoptRef(new SerializedScriptValue(value, didThrow));
1164 }
1165 
createFromWire(String data)1166 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWire(String data)
1167 {
1168     return adoptRef(new SerializedScriptValue(data));
1169 }
1170 
create(String data)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 
create()1179 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create()
1180 {
1181     return adoptRef(new SerializedScriptValue());
1182 }
1183 
nullValue()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 
undefinedValue()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 
release()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 
SerializedScriptValue()1215 SerializedScriptValue::SerializedScriptValue()
1216 {
1217 }
1218 
SerializedScriptValue(v8::Handle<v8::Value> value,bool & didThrow)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 
SerializedScriptValue(String wireData)1253 SerializedScriptValue::SerializedScriptValue(String wireData)
1254 {
1255     m_data = wireData.crossThreadString();
1256 }
1257 
deserialize()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