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