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 "bindings/v8/SerializedScriptValue.h" 33 34 #include "V8Blob.h" 35 #include "V8DOMFileSystem.h" 36 #include "V8File.h" 37 #include "V8FileList.h" 38 #include "V8ImageData.h" 39 #include "V8MessagePort.h" 40 #include "bindings/v8/ScriptScope.h" 41 #include "bindings/v8/ScriptState.h" 42 #include "bindings/v8/V8Binding.h" 43 #include "bindings/v8/V8Utilities.h" 44 #include "bindings/v8/custom/V8ArrayBufferCustom.h" 45 #include "bindings/v8/custom/V8ArrayBufferViewCustom.h" 46 #include "bindings/v8/custom/V8DataViewCustom.h" 47 #include "bindings/v8/custom/V8Float32ArrayCustom.h" 48 #include "bindings/v8/custom/V8Float64ArrayCustom.h" 49 #include "bindings/v8/custom/V8Int16ArrayCustom.h" 50 #include "bindings/v8/custom/V8Int32ArrayCustom.h" 51 #include "bindings/v8/custom/V8Int8ArrayCustom.h" 52 #include "bindings/v8/custom/V8Uint16ArrayCustom.h" 53 #include "bindings/v8/custom/V8Uint32ArrayCustom.h" 54 #include "bindings/v8/custom/V8Uint8ArrayCustom.h" 55 #include "bindings/v8/custom/V8Uint8ClampedArrayCustom.h" 56 #include "core/dom/ExceptionCode.h" 57 #include "core/dom/MessagePort.h" 58 #include "core/fileapi/Blob.h" 59 #include "core/fileapi/File.h" 60 #include "core/fileapi/FileList.h" 61 #include "core/html/ImageData.h" 62 #include "core/html/canvas/DataView.h" 63 #include "platform/SharedBuffer.h" 64 #include "wtf/ArrayBuffer.h" 65 #include "wtf/ArrayBufferContents.h" 66 #include "wtf/ArrayBufferView.h" 67 #include "wtf/Assertions.h" 68 #include "wtf/ByteOrder.h" 69 #include "wtf/Float32Array.h" 70 #include "wtf/Float64Array.h" 71 #include "wtf/Int16Array.h" 72 #include "wtf/Int32Array.h" 73 #include "wtf/Int8Array.h" 74 #include "wtf/RefCounted.h" 75 #include "wtf/Uint16Array.h" 76 #include "wtf/Uint32Array.h" 77 #include "wtf/Uint8Array.h" 78 #include "wtf/Uint8ClampedArray.h" 79 #include "wtf/Vector.h" 80 #include "wtf/text/StringBuffer.h" 81 #include "wtf/text/StringUTF8Adaptor.h" 82 83 // FIXME: consider crashing in debug mode on deserialization errors 84 // NOTE: be sure to change wireFormatVersion as necessary! 85 86 namespace WebCore { 87 88 namespace { 89 90 // This code implements the HTML5 Structured Clone algorithm: 91 // http://www.whatwg.org/specs/web-apps/current-work/multipage/urls.html#safe-passing-of-structured-data 92 93 // V8ObjectMap is a map from V8 objects to arbitrary values of type T. 94 // V8 objects (or handles to V8 objects) cannot be used as keys in ordinary wtf::HashMaps; 95 // this class should be used instead. GCObject must be a subtype of v8::Object. 96 // Suggested usage: 97 // V8ObjectMap<v8::Object, int> map; 98 // v8::Handle<v8::Object> obj = ...; 99 // map.set(obj, 42); 100 template<typename GCObject, typename T> 101 class V8ObjectMap { 102 public: 103 bool contains(const v8::Handle<GCObject>& handle) 104 { 105 return m_map.contains(*handle); 106 } 107 108 bool tryGet(const v8::Handle<GCObject>& handle, T* valueOut) 109 { 110 typename HandleToT::iterator result = m_map.find(*handle); 111 if (result != m_map.end()) { 112 *valueOut = result->value; 113 return true; 114 } 115 return false; 116 } 117 118 void set(const v8::Handle<GCObject>& handle, const T& value) 119 { 120 m_map.set(*handle, value); 121 } 122 123 private: 124 // This implementation uses GetIdentityHash(), which sets a hidden property on the object containing 125 // a random integer (or returns the one that had been previously set). This ensures that the table 126 // never needs to be rebuilt across garbage collections at the expense of doing additional allocation 127 // and making more round trips into V8. Note that since GetIdentityHash() is defined only on 128 // v8::Objects, this V8ObjectMap cannot be used to map v8::Strings to T (because the public V8 API 129 // considers a v8::String to be a v8::Primitive). 130 131 // If V8 exposes a way to get at the address of the object held by a handle, then we can produce 132 // an alternate implementation that does not need to do any V8-side allocation; however, it will 133 // need to rehash after every garbage collection because a key object may have been moved. 134 template<typename G> 135 struct V8HandlePtrHash { 136 static unsigned hash(const G* key) 137 { 138 return static_cast<unsigned>(unsafeHandleFromRawValue(key)->GetIdentityHash()); 139 } 140 static bool equal(const G* a, const G* b) 141 { 142 return unsafeHandleFromRawValue(a) == unsafeHandleFromRawValue(b); 143 } 144 // For HashArg. 145 static const bool safeToCompareToEmptyOrDeleted = false; 146 }; 147 148 typedef WTF::HashMap<GCObject*, T, V8HandlePtrHash<GCObject> > HandleToT; 149 HandleToT m_map; 150 }; 151 152 typedef UChar BufferValueType; 153 154 // Serialization format is a sequence of tags followed by zero or more data arguments. 155 // Tags always take exactly one byte. A serialized stream first begins with 156 // a complete VersionTag. If the stream does not begin with a VersionTag, we assume that 157 // the stream is in format 0. 158 159 // This format is private to the implementation of SerializedScriptValue. Do not rely on it 160 // externally. It is safe to persist a SerializedScriptValue as a binary blob, but this 161 // code should always be used to interpret it. 162 163 // WebCoreStrings are read as (length:uint32_t, string:UTF8[length]). 164 // RawStrings are read as (length:uint32_t, string:UTF8[length]). 165 // RawUCharStrings are read as (length:uint32_t, string:UChar[length/sizeof(UChar)]). 166 // RawFiles are read as (path:WebCoreString, url:WebCoreStrng, type:WebCoreString). 167 // There is a reference table that maps object references (uint32_t) to v8::Values. 168 // Tokens marked with (ref) are inserted into the reference table and given the next object reference ID after decoding. 169 // All tags except InvalidTag, PaddingTag, ReferenceCountTag, VersionTag, GenerateFreshObjectTag 170 // and GenerateFreshArrayTag push their results to the deserialization stack. 171 // There is also an 'open' stack that is used to resolve circular references. Objects or arrays may 172 // contain self-references. Before we begin to deserialize the contents of these values, they 173 // are first given object reference IDs (by GenerateFreshObjectTag/GenerateFreshArrayTag); 174 // these reference IDs are then used with ObjectReferenceTag to tie the recursive knot. 175 enum SerializationTag { 176 InvalidTag = '!', // Causes deserialization to fail. 177 PaddingTag = '\0', // Is ignored (but consumed). 178 UndefinedTag = '_', // -> <undefined> 179 NullTag = '0', // -> <null> 180 TrueTag = 'T', // -> <true> 181 FalseTag = 'F', // -> <false> 182 StringTag = 'S', // string:RawString -> string 183 StringUCharTag = 'c', // string:RawUCharString -> string 184 Int32Tag = 'I', // value:ZigZag-encoded int32 -> Integer 185 Uint32Tag = 'U', // value:uint32_t -> Integer 186 DateTag = 'D', // value:double -> Date (ref) 187 MessagePortTag = 'M', // index:int -> MessagePort. Fills the result with transferred MessagePort. 188 NumberTag = 'N', // value:double -> Number 189 BlobTag = 'b', // url:WebCoreString, type:WebCoreString, size:uint64_t -> Blob (ref) 190 FileTag = 'f', // file:RawFile -> File (ref) 191 DOMFileSystemTag = 'd', // type:int32_t, name:WebCoreString, url:WebCoreString -> FileSystem (ref) 192 FileListTag = 'l', // length:uint32_t, files:RawFile[length] -> FileList (ref) 193 ImageDataTag = '#', // width:uint32_t, height:uint32_t, pixelDataLength:uint32_t, data:byte[pixelDataLength] -> ImageData (ref) 194 ObjectTag = '{', // numProperties:uint32_t -> pops the last object from the open stack; 195 // fills it with the last numProperties name,value pairs pushed onto the deserialization stack 196 SparseArrayTag = '@', // numProperties:uint32_t, length:uint32_t -> pops the last object from the open stack; 197 // fills it with the last numProperties name,value pairs pushed onto the deserialization stack 198 DenseArrayTag = '$', // numProperties:uint32_t, length:uint32_t -> pops the last object from the open stack; 199 // fills it with the last length elements and numProperties name,value pairs pushed onto deserialization stack 200 RegExpTag = 'R', // pattern:RawString, flags:uint32_t -> RegExp (ref) 201 ArrayBufferTag = 'B', // byteLength:uint32_t, data:byte[byteLength] -> ArrayBuffer (ref) 202 ArrayBufferTransferTag = 't', // index:uint32_t -> ArrayBuffer. For ArrayBuffer transfer 203 ArrayBufferViewTag = 'V', // subtag:byte, byteOffset:uint32_t, byteLength:uint32_t -> ArrayBufferView (ref). Consumes an ArrayBuffer from the top of the deserialization stack. 204 ObjectReferenceTag = '^', // ref:uint32_t -> reference table[ref] 205 GenerateFreshObjectTag = 'o', // -> empty object allocated an object ID and pushed onto the open stack (ref) 206 GenerateFreshSparseArrayTag = 'a', // length:uint32_t -> empty array[length] allocated an object ID and pushed onto the open stack (ref) 207 GenerateFreshDenseArrayTag = 'A', // length:uint32_t -> empty array[length] allocated an object ID and pushed onto the open stack (ref) 208 ReferenceCountTag = '?', // refTableSize:uint32_t -> If the reference table is not refTableSize big, fails. 209 StringObjectTag = 's', // string:RawString -> new String(string) (ref) 210 NumberObjectTag = 'n', // value:double -> new Number(value) (ref) 211 TrueObjectTag = 'y', // new Boolean(true) (ref) 212 FalseObjectTag = 'x', // new Boolean(false) (ref) 213 VersionTag = 0xFF // version:uint32_t -> Uses this as the file version. 214 }; 215 216 enum ArrayBufferViewSubTag { 217 ByteArrayTag = 'b', 218 UnsignedByteArrayTag = 'B', 219 UnsignedByteClampedArrayTag = 'C', 220 ShortArrayTag = 'w', 221 UnsignedShortArrayTag = 'W', 222 IntArrayTag = 'd', 223 UnsignedIntArrayTag = 'D', 224 FloatArrayTag = 'f', 225 DoubleArrayTag = 'F', 226 DataViewTag = '?' 227 }; 228 229 static bool shouldCheckForCycles(int depth) 230 { 231 ASSERT(depth >= 0); 232 // Since we are not required to spot the cycle as soon as it 233 // happens we can check for cycles only when the current depth 234 // is a power of two. 235 return !(depth & (depth - 1)); 236 } 237 238 static const int maxDepth = 20000; 239 240 // VarInt encoding constants. 241 static const int varIntShift = 7; 242 static const int varIntMask = (1 << varIntShift) - 1; 243 244 // ZigZag encoding helps VarInt encoding stay small for negative 245 // numbers with small absolute values. 246 class ZigZag { 247 public: 248 static uint32_t encode(uint32_t value) 249 { 250 if (value & (1U << 31)) 251 value = ((~value) << 1) + 1; 252 else 253 value <<= 1; 254 return value; 255 } 256 257 static uint32_t decode(uint32_t value) 258 { 259 if (value & 1) 260 value = ~(value >> 1); 261 else 262 value >>= 1; 263 return value; 264 } 265 266 private: 267 ZigZag(); 268 }; 269 270 // Writer is responsible for serializing primitive types and storing 271 // information used to reconstruct composite types. 272 class Writer { 273 WTF_MAKE_NONCOPYABLE(Writer); 274 public: 275 explicit Writer(v8::Isolate* isolate) 276 : m_position(0) 277 , m_isolate(isolate) 278 { 279 } 280 281 // Write functions for primitive types. 282 283 void writeUndefined() { append(UndefinedTag); } 284 285 void writeNull() { append(NullTag); } 286 287 void writeTrue() { append(TrueTag); } 288 289 void writeFalse() { append(FalseTag); } 290 291 void writeBooleanObject(bool value) 292 { 293 append(value ? TrueObjectTag : FalseObjectTag); 294 } 295 296 void writeOneByteString(v8::Handle<v8::String>& string) 297 { 298 int stringLength = string->Length(); 299 int utf8Length = string->Utf8Length(); 300 ASSERT(stringLength >= 0 && utf8Length >= 0); 301 302 append(StringTag); 303 doWriteUint32(static_cast<uint32_t>(utf8Length)); 304 ensureSpace(utf8Length); 305 306 // ASCII fast path. 307 if (stringLength == utf8Length) 308 string->WriteOneByte(byteAt(m_position), 0, utf8Length, v8StringWriteOptions()); 309 else { 310 char* buffer = reinterpret_cast<char*>(byteAt(m_position)); 311 string->WriteUtf8(buffer, utf8Length, 0, v8StringWriteOptions()); 312 } 313 m_position += utf8Length; 314 } 315 316 void writeUCharString(v8::Handle<v8::String>& string) 317 { 318 int length = string->Length(); 319 ASSERT(length >= 0); 320 321 int size = length * sizeof(UChar); 322 int bytes = bytesNeededToWireEncode(static_cast<uint32_t>(size)); 323 if ((m_position + 1 + bytes) & 1) 324 append(PaddingTag); 325 326 append(StringUCharTag); 327 doWriteUint32(static_cast<uint32_t>(size)); 328 ensureSpace(size); 329 330 ASSERT(!(m_position & 1)); 331 uint16_t* buffer = reinterpret_cast<uint16_t*>(byteAt(m_position)); 332 string->Write(buffer, 0, length, v8StringWriteOptions()); 333 m_position += size; 334 } 335 336 void writeStringObject(const char* data, int length) 337 { 338 ASSERT(length >= 0); 339 append(StringObjectTag); 340 doWriteString(data, length); 341 } 342 343 void writeWebCoreString(const String& string) 344 { 345 // Uses UTF8 encoding so we can read it back as either V8 or 346 // WebCore string. 347 append(StringTag); 348 doWriteWebCoreString(string); 349 } 350 351 void writeVersion() 352 { 353 append(VersionTag); 354 doWriteUint32(SerializedScriptValue::wireFormatVersion); 355 } 356 357 void writeInt32(int32_t value) 358 { 359 append(Int32Tag); 360 doWriteUint32(ZigZag::encode(static_cast<uint32_t>(value))); 361 } 362 363 void writeUint32(uint32_t value) 364 { 365 append(Uint32Tag); 366 doWriteUint32(value); 367 } 368 369 void writeDate(double numberValue) 370 { 371 append(DateTag); 372 doWriteNumber(numberValue); 373 } 374 375 void writeNumber(double number) 376 { 377 append(NumberTag); 378 doWriteNumber(number); 379 } 380 381 void writeNumberObject(double number) 382 { 383 append(NumberObjectTag); 384 doWriteNumber(number); 385 } 386 387 void writeBlob(const String& uuid, const String& type, unsigned long long size) 388 { 389 append(BlobTag); 390 doWriteWebCoreString(uuid); 391 doWriteWebCoreString(type); 392 doWriteUint64(size); 393 } 394 395 void writeDOMFileSystem(int type, const String& name, const String& url) 396 { 397 append(DOMFileSystemTag); 398 doWriteUint32(type); 399 doWriteWebCoreString(name); 400 doWriteWebCoreString(url); 401 } 402 403 void writeFile(const File& file) 404 { 405 append(FileTag); 406 doWriteFile(file); 407 } 408 409 void writeFileList(const FileList& fileList) 410 { 411 append(FileListTag); 412 uint32_t length = fileList.length(); 413 doWriteUint32(length); 414 for (unsigned i = 0; i < length; ++i) 415 doWriteFile(*fileList.item(i)); 416 } 417 418 void writeArrayBuffer(const ArrayBuffer& arrayBuffer) 419 { 420 append(ArrayBufferTag); 421 doWriteArrayBuffer(arrayBuffer); 422 } 423 424 void writeArrayBufferView(const ArrayBufferView& arrayBufferView) 425 { 426 append(ArrayBufferViewTag); 427 #ifndef NDEBUG 428 const ArrayBuffer& arrayBuffer = *arrayBufferView.buffer(); 429 ASSERT(static_cast<const uint8_t*>(arrayBuffer.data()) + arrayBufferView.byteOffset() == 430 static_cast<const uint8_t*>(arrayBufferView.baseAddress())); 431 #endif 432 ArrayBufferView::ViewType type = arrayBufferView.getType(); 433 434 if (type == ArrayBufferView::TypeInt8) 435 append(ByteArrayTag); 436 else if (type == ArrayBufferView::TypeUint8Clamped) 437 append(UnsignedByteClampedArrayTag); 438 else if (type == ArrayBufferView::TypeUint8) 439 append(UnsignedByteArrayTag); 440 else if (type == ArrayBufferView::TypeInt16) 441 append(ShortArrayTag); 442 else if (type == ArrayBufferView::TypeUint16) 443 append(UnsignedShortArrayTag); 444 else if (type == ArrayBufferView::TypeInt32) 445 append(IntArrayTag); 446 else if (type == ArrayBufferView::TypeUint32) 447 append(UnsignedIntArrayTag); 448 else if (type == ArrayBufferView::TypeFloat32) 449 append(FloatArrayTag); 450 else if (type == ArrayBufferView::TypeFloat64) 451 append(DoubleArrayTag); 452 else if (type == ArrayBufferView::TypeDataView) 453 append(DataViewTag); 454 else 455 ASSERT_NOT_REACHED(); 456 doWriteUint32(arrayBufferView.byteOffset()); 457 doWriteUint32(arrayBufferView.byteLength()); 458 } 459 460 void writeImageData(uint32_t width, uint32_t height, const uint8_t* pixelData, uint32_t pixelDataLength) 461 { 462 append(ImageDataTag); 463 doWriteUint32(width); 464 doWriteUint32(height); 465 doWriteUint32(pixelDataLength); 466 append(pixelData, pixelDataLength); 467 } 468 469 void writeRegExp(v8::Local<v8::String> pattern, v8::RegExp::Flags flags) 470 { 471 append(RegExpTag); 472 v8::String::Utf8Value patternUtf8Value(pattern); 473 doWriteString(*patternUtf8Value, patternUtf8Value.length()); 474 doWriteUint32(static_cast<uint32_t>(flags)); 475 } 476 477 void writeTransferredMessagePort(uint32_t index) 478 { 479 append(MessagePortTag); 480 doWriteUint32(index); 481 } 482 483 void writeTransferredArrayBuffer(uint32_t index) 484 { 485 append(ArrayBufferTransferTag); 486 doWriteUint32(index); 487 } 488 489 void writeObjectReference(uint32_t reference) 490 { 491 append(ObjectReferenceTag); 492 doWriteUint32(reference); 493 } 494 495 void writeObject(uint32_t numProperties) 496 { 497 append(ObjectTag); 498 doWriteUint32(numProperties); 499 } 500 501 void writeSparseArray(uint32_t numProperties, uint32_t length) 502 { 503 append(SparseArrayTag); 504 doWriteUint32(numProperties); 505 doWriteUint32(length); 506 } 507 508 void writeDenseArray(uint32_t numProperties, uint32_t length) 509 { 510 append(DenseArrayTag); 511 doWriteUint32(numProperties); 512 doWriteUint32(length); 513 } 514 515 String takeWireString() 516 { 517 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes); 518 fillHole(); 519 String data = String(m_buffer.data(), m_buffer.size()); 520 data.impl()->truncateAssumingIsolated((m_position + 1) / sizeof(BufferValueType)); 521 return data; 522 } 523 524 void writeReferenceCount(uint32_t numberOfReferences) 525 { 526 append(ReferenceCountTag); 527 doWriteUint32(numberOfReferences); 528 } 529 530 void writeGenerateFreshObject() 531 { 532 append(GenerateFreshObjectTag); 533 } 534 535 void writeGenerateFreshSparseArray(uint32_t length) 536 { 537 append(GenerateFreshSparseArrayTag); 538 doWriteUint32(length); 539 } 540 541 void writeGenerateFreshDenseArray(uint32_t length) 542 { 543 append(GenerateFreshDenseArrayTag); 544 doWriteUint32(length); 545 } 546 547 v8::Isolate* getIsolate() { return m_isolate; } 548 549 private: 550 void doWriteFile(const File& file) 551 { 552 doWriteWebCoreString(file.hasBackingFile() ? file.path() : ""); 553 doWriteWebCoreString(file.name()); 554 doWriteWebCoreString(file.webkitRelativePath()); 555 doWriteWebCoreString(file.uuid()); 556 doWriteWebCoreString(file.type()); 557 558 // FIXME don't use 4 bytes to encode a flag. 559 if (file.hasValidSnapshotMetadata()) { 560 doWriteUint32(static_cast<uint8_t>(1)); 561 562 long long size; 563 double lastModified; 564 file.captureSnapshot(size, lastModified); 565 doWriteUint64(static_cast<uint64_t>(size)); 566 doWriteNumber(lastModified); 567 } else { 568 append(static_cast<uint8_t>(0)); 569 } 570 } 571 572 void doWriteArrayBuffer(const ArrayBuffer& arrayBuffer) 573 { 574 uint32_t byteLength = arrayBuffer.byteLength(); 575 doWriteUint32(byteLength); 576 append(static_cast<const uint8_t*>(arrayBuffer.data()), byteLength); 577 } 578 579 void doWriteString(const char* data, int length) 580 { 581 doWriteUint32(static_cast<uint32_t>(length)); 582 append(reinterpret_cast<const uint8_t*>(data), length); 583 } 584 585 void doWriteWebCoreString(const String& string) 586 { 587 StringUTF8Adaptor stringUTF8(string); 588 doWriteString(stringUTF8.data(), stringUTF8.length()); 589 } 590 591 int bytesNeededToWireEncode(uint32_t value) 592 { 593 int bytes = 1; 594 while (true) { 595 value >>= varIntShift; 596 if (!value) 597 break; 598 ++bytes; 599 } 600 601 return bytes; 602 } 603 604 template<class T> 605 void doWriteUintHelper(T value) 606 { 607 while (true) { 608 uint8_t b = (value & varIntMask); 609 value >>= varIntShift; 610 if (!value) { 611 append(b); 612 break; 613 } 614 append(b | (1 << varIntShift)); 615 } 616 } 617 618 void doWriteUint32(uint32_t value) 619 { 620 doWriteUintHelper(value); 621 } 622 623 void doWriteUint64(uint64_t value) 624 { 625 doWriteUintHelper(value); 626 } 627 628 void doWriteNumber(double number) 629 { 630 append(reinterpret_cast<uint8_t*>(&number), sizeof(number)); 631 } 632 633 void append(SerializationTag tag) 634 { 635 append(static_cast<uint8_t>(tag)); 636 } 637 638 void append(uint8_t b) 639 { 640 ensureSpace(1); 641 *byteAt(m_position++) = b; 642 } 643 644 void append(const uint8_t* data, int length) 645 { 646 ensureSpace(length); 647 memcpy(byteAt(m_position), data, length); 648 m_position += length; 649 } 650 651 void ensureSpace(unsigned extra) 652 { 653 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes); 654 m_buffer.resize((m_position + extra + 1) / sizeof(BufferValueType)); // "+ 1" to round up. 655 } 656 657 void fillHole() 658 { 659 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes); 660 // If the writer is at odd position in the buffer, then one of 661 // the bytes in the last UChar is not initialized. 662 if (m_position % 2) 663 *byteAt(m_position) = static_cast<uint8_t>(PaddingTag); 664 } 665 666 uint8_t* byteAt(int position) 667 { 668 return reinterpret_cast<uint8_t*>(m_buffer.data()) + position; 669 } 670 671 int v8StringWriteOptions() 672 { 673 return v8::String::NO_NULL_TERMINATION; 674 } 675 676 Vector<BufferValueType> m_buffer; 677 unsigned m_position; 678 v8::Isolate* m_isolate; 679 }; 680 681 static v8::Handle<v8::Object> toV8Object(MessagePort* impl, v8::Isolate* isolate) 682 { 683 if (!impl) 684 return v8::Handle<v8::Object>(); 685 v8::Handle<v8::Value> wrapper = toV8(impl, v8::Handle<v8::Object>(), isolate); 686 ASSERT(wrapper->IsObject()); 687 return wrapper.As<v8::Object>(); 688 } 689 690 static v8::Handle<v8::ArrayBuffer> toV8Object(ArrayBuffer* impl, v8::Isolate* isolate) 691 { 692 if (!impl) 693 return v8::Handle<v8::ArrayBuffer>(); 694 v8::Handle<v8::Value> wrapper = toV8(impl, v8::Handle<v8::Object>(), isolate); 695 ASSERT(wrapper->IsArrayBuffer()); 696 return wrapper.As<v8::ArrayBuffer>(); 697 } 698 699 class Serializer { 700 class StateBase; 701 public: 702 enum Status { 703 Success, 704 InputError, 705 DataCloneError, 706 InvalidStateError, 707 JSException, 708 JSFailure 709 }; 710 711 Serializer(Writer& writer, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, v8::Isolate* isolate) 712 : m_writer(writer) 713 , m_tryCatch(tryCatch) 714 , m_depth(0) 715 , m_status(Success) 716 , m_nextObjectReference(0) 717 , m_blobDataHandles(blobDataHandles) 718 , m_isolate(isolate) 719 { 720 ASSERT(!tryCatch.HasCaught()); 721 if (messagePorts) { 722 for (size_t i = 0; i < messagePorts->size(); i++) 723 m_transferredMessagePorts.set(toV8Object(messagePorts->at(i).get(), m_writer.getIsolate()), i); 724 } 725 if (arrayBuffers) { 726 for (size_t i = 0; i < arrayBuffers->size(); i++) { 727 v8::Handle<v8::Object> v8ArrayBuffer = toV8Object(arrayBuffers->at(i).get(), m_writer.getIsolate()); 728 // Coalesce multiple occurences of the same buffer to the first index. 729 if (!m_transferredArrayBuffers.contains(v8ArrayBuffer)) 730 m_transferredArrayBuffers.set(v8ArrayBuffer, i); 731 } 732 } 733 } 734 735 Status serialize(v8::Handle<v8::Value> value) 736 { 737 v8::HandleScope scope(m_isolate); 738 m_writer.writeVersion(); 739 StateBase* state = doSerialize(value, 0); 740 while (state) 741 state = state->advance(*this); 742 return m_status; 743 } 744 745 // Functions used by serialization states. 746 StateBase* doSerialize(v8::Handle<v8::Value>, StateBase* next); 747 748 StateBase* doSerializeArrayBuffer(v8::Handle<v8::Value> arrayBuffer, StateBase* next) 749 { 750 return doSerialize(arrayBuffer, next); 751 } 752 753 StateBase* checkException(StateBase* state) 754 { 755 return m_tryCatch.HasCaught() ? handleError(JSException, state) : 0; 756 } 757 758 StateBase* reportFailure(StateBase* state) 759 { 760 return handleError(JSFailure, state); 761 } 762 763 StateBase* writeObject(uint32_t numProperties, StateBase* state) 764 { 765 m_writer.writeObject(numProperties); 766 return pop(state); 767 } 768 769 StateBase* writeSparseArray(uint32_t numProperties, uint32_t length, StateBase* state) 770 { 771 m_writer.writeSparseArray(numProperties, length); 772 return pop(state); 773 } 774 775 StateBase* writeDenseArray(uint32_t numProperties, uint32_t length, StateBase* state) 776 { 777 m_writer.writeDenseArray(numProperties, length); 778 return pop(state); 779 } 780 781 782 private: 783 class StateBase { 784 WTF_MAKE_NONCOPYABLE(StateBase); 785 public: 786 virtual ~StateBase() { } 787 788 // Link to the next state to form a stack. 789 StateBase* nextState() { return m_next; } 790 791 // Composite object we're processing in this state. 792 v8::Handle<v8::Value> composite() { return m_composite; } 793 794 // Serializes (a part of) the current composite and returns 795 // the next state to process or null when this is the final 796 // state. 797 virtual StateBase* advance(Serializer&) = 0; 798 799 // Returns 1 if this state is currently serializing a property 800 // via an accessor and 0 otherwise. 801 virtual uint32_t execDepth() const { return 0; } 802 803 protected: 804 StateBase(v8::Handle<v8::Value> composite, StateBase* next) 805 : m_composite(composite) 806 , m_next(next) 807 { 808 } 809 810 private: 811 v8::Handle<v8::Value> m_composite; 812 StateBase* m_next; 813 }; 814 815 // Dummy state that is used to signal serialization errors. 816 class ErrorState : public StateBase { 817 public: 818 ErrorState() 819 : StateBase(v8Undefined(), 0) 820 { 821 } 822 823 virtual StateBase* advance(Serializer&) 824 { 825 delete this; 826 return 0; 827 } 828 }; 829 830 template <typename T> 831 class State : public StateBase { 832 public: 833 v8::Handle<T> composite() { return v8::Handle<T>::Cast(StateBase::composite()); } 834 835 protected: 836 State(v8::Handle<T> composite, StateBase* next) 837 : StateBase(composite, next) 838 { 839 } 840 }; 841 842 class AbstractObjectState : public State<v8::Object> { 843 public: 844 AbstractObjectState(v8::Handle<v8::Object> object, StateBase* next) 845 : State<v8::Object>(object, next) 846 , m_index(0) 847 , m_numSerializedProperties(0) 848 , m_nameDone(false) 849 { 850 } 851 852 protected: 853 virtual StateBase* objectDone(unsigned numProperties, Serializer&) = 0; 854 855 StateBase* serializeProperties(bool ignoreIndexed, Serializer& serializer) 856 { 857 while (m_index < m_propertyNames->Length()) { 858 if (!m_nameDone) { 859 v8::Local<v8::Value> propertyName = m_propertyNames->Get(m_index); 860 if (StateBase* newState = serializer.checkException(this)) 861 return newState; 862 if (propertyName.IsEmpty()) 863 return serializer.reportFailure(this); 864 bool hasStringProperty = propertyName->IsString() && composite()->HasRealNamedProperty(propertyName.As<v8::String>()); 865 if (StateBase* newState = serializer.checkException(this)) 866 return newState; 867 bool hasIndexedProperty = !hasStringProperty && propertyName->IsUint32() && composite()->HasRealIndexedProperty(propertyName->Uint32Value()); 868 if (StateBase* newState = serializer.checkException(this)) 869 return newState; 870 if (hasStringProperty || (hasIndexedProperty && !ignoreIndexed)) 871 m_propertyName = propertyName; 872 else { 873 ++m_index; 874 continue; 875 } 876 } 877 ASSERT(!m_propertyName.IsEmpty()); 878 if (!m_nameDone) { 879 m_nameDone = true; 880 if (StateBase* newState = serializer.doSerialize(m_propertyName, this)) 881 return newState; 882 } 883 v8::Local<v8::Value> value = composite()->Get(m_propertyName); 884 if (StateBase* newState = serializer.checkException(this)) 885 return newState; 886 m_nameDone = false; 887 m_propertyName.Clear(); 888 ++m_index; 889 ++m_numSerializedProperties; 890 // If we return early here, it's either because we have pushed a new state onto the 891 // serialization state stack or because we have encountered an error (and in both cases 892 // we are unwinding the native stack). 893 if (StateBase* newState = serializer.doSerialize(value, this)) 894 return newState; 895 } 896 return objectDone(m_numSerializedProperties, serializer); 897 } 898 899 v8::Local<v8::Array> m_propertyNames; 900 901 private: 902 v8::Local<v8::Value> m_propertyName; 903 unsigned m_index; 904 unsigned m_numSerializedProperties; 905 bool m_nameDone; 906 }; 907 908 class ObjectState : public AbstractObjectState { 909 public: 910 ObjectState(v8::Handle<v8::Object> object, StateBase* next) 911 : AbstractObjectState(object, next) 912 { 913 } 914 915 virtual StateBase* advance(Serializer& serializer) 916 { 917 if (m_propertyNames.IsEmpty()) { 918 m_propertyNames = composite()->GetPropertyNames(); 919 if (StateBase* newState = serializer.checkException(this)) 920 return newState; 921 if (m_propertyNames.IsEmpty()) 922 return serializer.reportFailure(this); 923 } 924 return serializeProperties(false, serializer); 925 } 926 927 protected: 928 virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) 929 { 930 return serializer.writeObject(numProperties, this); 931 } 932 }; 933 934 class DenseArrayState : public AbstractObjectState { 935 public: 936 DenseArrayState(v8::Handle<v8::Array> array, v8::Handle<v8::Array> propertyNames, StateBase* next, v8::Isolate* isolate) 937 : AbstractObjectState(array, next) 938 , m_arrayIndex(0) 939 , m_arrayLength(array->Length()) 940 { 941 m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames); 942 } 943 944 virtual StateBase* advance(Serializer& serializer) 945 { 946 while (m_arrayIndex < m_arrayLength) { 947 v8::Handle<v8::Value> value = composite().As<v8::Array>()->Get(m_arrayIndex); 948 m_arrayIndex++; 949 if (StateBase* newState = serializer.checkException(this)) 950 return newState; 951 if (StateBase* newState = serializer.doSerialize(value, this)) 952 return newState; 953 } 954 return serializeProperties(true, serializer); 955 } 956 957 protected: 958 virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) 959 { 960 return serializer.writeDenseArray(numProperties, m_arrayLength, this); 961 } 962 963 private: 964 uint32_t m_arrayIndex; 965 uint32_t m_arrayLength; 966 }; 967 968 class SparseArrayState : public AbstractObjectState { 969 public: 970 SparseArrayState(v8::Handle<v8::Array> array, v8::Handle<v8::Array> propertyNames, StateBase* next, v8::Isolate* isolate) 971 : AbstractObjectState(array, next) 972 { 973 m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames); 974 } 975 976 virtual StateBase* advance(Serializer& serializer) 977 { 978 return serializeProperties(false, serializer); 979 } 980 981 protected: 982 virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) 983 { 984 return serializer.writeSparseArray(numProperties, composite().As<v8::Array>()->Length(), this); 985 } 986 }; 987 988 StateBase* push(StateBase* state) 989 { 990 ASSERT(state); 991 ++m_depth; 992 return checkComposite(state) ? state : handleError(InputError, state); 993 } 994 995 StateBase* pop(StateBase* state) 996 { 997 ASSERT(state); 998 --m_depth; 999 StateBase* next = state->nextState(); 1000 delete state; 1001 return next; 1002 } 1003 1004 StateBase* handleError(Status errorStatus, StateBase* state) 1005 { 1006 ASSERT(errorStatus != Success); 1007 m_status = errorStatus; 1008 while (state) { 1009 StateBase* tmp = state->nextState(); 1010 delete state; 1011 state = tmp; 1012 } 1013 return new ErrorState; 1014 } 1015 1016 bool checkComposite(StateBase* top) 1017 { 1018 ASSERT(top); 1019 if (m_depth > maxDepth) 1020 return false; 1021 if (!shouldCheckForCycles(m_depth)) 1022 return true; 1023 v8::Handle<v8::Value> composite = top->composite(); 1024 for (StateBase* state = top->nextState(); state; state = state->nextState()) { 1025 if (state->composite() == composite) 1026 return false; 1027 } 1028 return true; 1029 } 1030 1031 void writeString(v8::Handle<v8::Value> value) 1032 { 1033 v8::Handle<v8::String> string = value.As<v8::String>(); 1034 if (!string->Length() || string->IsOneByte()) 1035 m_writer.writeOneByteString(string); 1036 else 1037 m_writer.writeUCharString(string); 1038 } 1039 1040 void writeStringObject(v8::Handle<v8::Value> value) 1041 { 1042 v8::Handle<v8::StringObject> stringObject = value.As<v8::StringObject>(); 1043 v8::String::Utf8Value stringValue(stringObject->ValueOf()); 1044 m_writer.writeStringObject(*stringValue, stringValue.length()); 1045 } 1046 1047 void writeNumberObject(v8::Handle<v8::Value> value) 1048 { 1049 v8::Handle<v8::NumberObject> numberObject = value.As<v8::NumberObject>(); 1050 m_writer.writeNumberObject(numberObject->ValueOf()); 1051 } 1052 1053 void writeBooleanObject(v8::Handle<v8::Value> value) 1054 { 1055 v8::Handle<v8::BooleanObject> booleanObject = value.As<v8::BooleanObject>(); 1056 m_writer.writeBooleanObject(booleanObject->ValueOf()); 1057 } 1058 1059 void writeBlob(v8::Handle<v8::Value> value) 1060 { 1061 Blob* blob = V8Blob::toNative(value.As<v8::Object>()); 1062 if (!blob) 1063 return; 1064 m_writer.writeBlob(blob->uuid(), blob->type(), blob->size()); 1065 m_blobDataHandles.add(blob->uuid(), blob->blobDataHandle()); 1066 } 1067 1068 StateBase* writeDOMFileSystem(v8::Handle<v8::Value> value, StateBase* next) 1069 { 1070 DOMFileSystem* fs = V8DOMFileSystem::toNative(value.As<v8::Object>()); 1071 if (!fs) 1072 return 0; 1073 if (!fs->clonable()) 1074 return handleError(DataCloneError, next); 1075 m_writer.writeDOMFileSystem(fs->type(), fs->name(), fs->rootURL().string()); 1076 return 0; 1077 } 1078 1079 void writeFile(v8::Handle<v8::Value> value) 1080 { 1081 File* file = V8File::toNative(value.As<v8::Object>()); 1082 if (!file) 1083 return; 1084 m_writer.writeFile(*file); 1085 m_blobDataHandles.add(file->uuid(), file->blobDataHandle()); 1086 } 1087 1088 void writeFileList(v8::Handle<v8::Value> value) 1089 { 1090 FileList* fileList = V8FileList::toNative(value.As<v8::Object>()); 1091 if (!fileList) 1092 return; 1093 m_writer.writeFileList(*fileList); 1094 unsigned length = fileList->length(); 1095 for (unsigned i = 0; i < length; ++i) 1096 m_blobDataHandles.add(fileList->item(i)->uuid(), fileList->item(i)->blobDataHandle()); 1097 } 1098 1099 void writeImageData(v8::Handle<v8::Value> value) 1100 { 1101 ImageData* imageData = V8ImageData::toNative(value.As<v8::Object>()); 1102 if (!imageData) 1103 return; 1104 Uint8ClampedArray* pixelArray = imageData->data(); 1105 m_writer.writeImageData(imageData->width(), imageData->height(), pixelArray->data(), pixelArray->length()); 1106 } 1107 1108 void writeRegExp(v8::Handle<v8::Value> value) 1109 { 1110 v8::Handle<v8::RegExp> regExp = value.As<v8::RegExp>(); 1111 m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags()); 1112 } 1113 1114 StateBase* writeAndGreyArrayBufferView(v8::Handle<v8::Object> object, StateBase* next) 1115 { 1116 ASSERT(!object.IsEmpty()); 1117 ArrayBufferView* arrayBufferView = V8ArrayBufferView::toNative(object); 1118 if (!arrayBufferView) 1119 return 0; 1120 if (!arrayBufferView->buffer()) 1121 return handleError(DataCloneError, next); 1122 v8::Handle<v8::Value> underlyingBuffer = toV8(arrayBufferView->buffer(), v8::Handle<v8::Object>(), m_writer.getIsolate()); 1123 if (underlyingBuffer.IsEmpty()) 1124 return handleError(DataCloneError, next); 1125 StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next); 1126 if (stateOut) 1127 return stateOut; 1128 m_writer.writeArrayBufferView(*arrayBufferView); 1129 // This should be safe: we serialize something that we know to be a wrapper (see 1130 // the toV8 call above), so the call to doSerializeArrayBuffer should neither 1131 // cause the system stack to overflow nor should it have potential to reach 1132 // this ArrayBufferView again. 1133 // 1134 // We do need to grey the underlying buffer before we grey its view, however; 1135 // ArrayBuffers may be shared, so they need to be given reference IDs, and an 1136 // ArrayBufferView cannot be constructed without a corresponding ArrayBuffer 1137 // (or without an additional tag that would allow us to do two-stage construction 1138 // like we do for Objects and Arrays). 1139 greyObject(object); 1140 return 0; 1141 } 1142 1143 StateBase* writeArrayBuffer(v8::Handle<v8::Value> value, StateBase* next) 1144 { 1145 ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(value.As<v8::Object>()); 1146 if (!arrayBuffer) 1147 return 0; 1148 if (arrayBuffer->isNeutered()) 1149 return handleError(InvalidStateError, next); 1150 ASSERT(!m_transferredArrayBuffers.contains(value.As<v8::Object>())); 1151 m_writer.writeArrayBuffer(*arrayBuffer); 1152 return 0; 1153 } 1154 1155 StateBase* writeTransferredArrayBuffer(v8::Handle<v8::Value> value, uint32_t index, StateBase* next) 1156 { 1157 ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(value.As<v8::Object>()); 1158 if (!arrayBuffer) 1159 return 0; 1160 if (arrayBuffer->isNeutered()) 1161 return handleError(DataCloneError, next); 1162 m_writer.writeTransferredArrayBuffer(index); 1163 return 0; 1164 } 1165 1166 static bool shouldSerializeDensely(uint32_t length, uint32_t propertyCount) 1167 { 1168 // Let K be the cost of serializing all property values that are there 1169 // Cost of serializing sparsely: 5*propertyCount + K (5 bytes per uint32_t key) 1170 // Cost of serializing densely: K + 1*(length - propertyCount) (1 byte for all properties that are not there) 1171 // so densely is better than sparsly whenever 6*propertyCount > length 1172 return 6 * propertyCount >= length; 1173 } 1174 1175 StateBase* startArrayState(v8::Handle<v8::Array> array, StateBase* next) 1176 { 1177 v8::Handle<v8::Array> propertyNames = array->GetPropertyNames(); 1178 if (StateBase* newState = checkException(next)) 1179 return newState; 1180 uint32_t length = array->Length(); 1181 1182 if (shouldSerializeDensely(length, propertyNames->Length())) { 1183 m_writer.writeGenerateFreshDenseArray(length); 1184 return push(new DenseArrayState(array, propertyNames, next, m_isolate)); 1185 } 1186 1187 m_writer.writeGenerateFreshSparseArray(length); 1188 return push(new SparseArrayState(array, propertyNames, next, m_isolate)); 1189 } 1190 1191 StateBase* startObjectState(v8::Handle<v8::Object> object, StateBase* next) 1192 { 1193 m_writer.writeGenerateFreshObject(); 1194 // FIXME: check not a wrapper 1195 return push(new ObjectState(object, next)); 1196 } 1197 1198 // Marks object as having been visited by the serializer and assigns it a unique object reference ID. 1199 // An object may only be greyed once. 1200 void greyObject(const v8::Handle<v8::Object>& object) 1201 { 1202 ASSERT(!m_objectPool.contains(object)); 1203 uint32_t objectReference = m_nextObjectReference++; 1204 m_objectPool.set(object, objectReference); 1205 } 1206 1207 Writer& m_writer; 1208 v8::TryCatch& m_tryCatch; 1209 int m_depth; 1210 Status m_status; 1211 typedef V8ObjectMap<v8::Object, uint32_t> ObjectPool; 1212 ObjectPool m_objectPool; 1213 ObjectPool m_transferredMessagePorts; 1214 ObjectPool m_transferredArrayBuffers; 1215 uint32_t m_nextObjectReference; 1216 BlobDataHandleMap& m_blobDataHandles; 1217 v8::Isolate* m_isolate; 1218 }; 1219 1220 Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, StateBase* next) 1221 { 1222 m_writer.writeReferenceCount(m_nextObjectReference); 1223 uint32_t objectReference; 1224 uint32_t arrayBufferIndex; 1225 WrapperWorldType currentWorldType = worldType(m_isolate); 1226 if ((value->IsObject() || value->IsDate() || value->IsRegExp()) 1227 && m_objectPool.tryGet(value.As<v8::Object>(), &objectReference)) { 1228 // Note that IsObject() also detects wrappers (eg, it will catch the things 1229 // that we grey and write below). 1230 ASSERT(!value->IsString()); 1231 m_writer.writeObjectReference(objectReference); 1232 } else if (value.IsEmpty()) 1233 return reportFailure(next); 1234 else if (value->IsUndefined()) 1235 m_writer.writeUndefined(); 1236 else if (value->IsNull()) 1237 m_writer.writeNull(); 1238 else if (value->IsTrue()) 1239 m_writer.writeTrue(); 1240 else if (value->IsFalse()) 1241 m_writer.writeFalse(); 1242 else if (value->IsInt32()) 1243 m_writer.writeInt32(value->Int32Value()); 1244 else if (value->IsUint32()) 1245 m_writer.writeUint32(value->Uint32Value()); 1246 else if (value->IsNumber()) 1247 m_writer.writeNumber(value.As<v8::Number>()->Value()); 1248 else if (V8ArrayBufferView::hasInstance(value, m_isolate, currentWorldType)) 1249 return writeAndGreyArrayBufferView(value.As<v8::Object>(), next); 1250 else if (value->IsString()) 1251 writeString(value); 1252 else if (V8MessagePort::hasInstance(value, m_isolate, currentWorldType)) { 1253 uint32_t messagePortIndex; 1254 if (m_transferredMessagePorts.tryGet(value.As<v8::Object>(), &messagePortIndex)) 1255 m_writer.writeTransferredMessagePort(messagePortIndex); 1256 else 1257 return handleError(DataCloneError, next); 1258 } else if (V8ArrayBuffer::hasInstance(value, m_isolate, currentWorldType) && m_transferredArrayBuffers.tryGet(value.As<v8::Object>(), &arrayBufferIndex)) 1259 return writeTransferredArrayBuffer(value, arrayBufferIndex, next); 1260 else { 1261 v8::Handle<v8::Object> jsObject = value.As<v8::Object>(); 1262 if (jsObject.IsEmpty()) 1263 return handleError(DataCloneError, next); 1264 greyObject(jsObject); 1265 if (value->IsDate()) 1266 m_writer.writeDate(value->NumberValue()); 1267 else if (value->IsStringObject()) 1268 writeStringObject(value); 1269 else if (value->IsNumberObject()) 1270 writeNumberObject(value); 1271 else if (value->IsBooleanObject()) 1272 writeBooleanObject(value); 1273 else if (value->IsArray()) { 1274 return startArrayState(value.As<v8::Array>(), next); 1275 } else if (V8File::hasInstance(value, m_isolate, currentWorldType)) 1276 writeFile(value); 1277 else if (V8Blob::hasInstance(value, m_isolate, currentWorldType)) 1278 writeBlob(value); 1279 else if (V8DOMFileSystem::hasInstance(value, m_isolate, currentWorldType)) 1280 return writeDOMFileSystem(value, next); 1281 else if (V8FileList::hasInstance(value, m_isolate, currentWorldType)) 1282 writeFileList(value); 1283 else if (V8ImageData::hasInstance(value, m_isolate, currentWorldType)) 1284 writeImageData(value); 1285 else if (value->IsRegExp()) 1286 writeRegExp(value); 1287 else if (V8ArrayBuffer::hasInstance(value, m_isolate, currentWorldType)) 1288 return writeArrayBuffer(value, next); 1289 else if (value->IsObject()) { 1290 if (isHostObject(jsObject) || jsObject->IsCallable() || value->IsNativeError()) 1291 return handleError(DataCloneError, next); 1292 return startObjectState(jsObject, next); 1293 } else 1294 return handleError(DataCloneError, next); 1295 } 1296 return 0; 1297 } 1298 1299 // Interface used by Reader to create objects of composite types. 1300 class CompositeCreator { 1301 public: 1302 virtual ~CompositeCreator() { } 1303 1304 virtual bool consumeTopOfStack(v8::Handle<v8::Value>*) = 0; 1305 virtual uint32_t objectReferenceCount() = 0; 1306 virtual void pushObjectReference(const v8::Handle<v8::Value>&) = 0; 1307 virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle<v8::Value>*) = 0; 1308 virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Value>*) = 0; 1309 virtual bool tryGetTransferredArrayBuffer(uint32_t index, v8::Handle<v8::Value>*) = 0; 1310 virtual bool newSparseArray(uint32_t length) = 0; 1311 virtual bool newDenseArray(uint32_t length) = 0; 1312 virtual bool newObject() = 0; 1313 virtual bool completeObject(uint32_t numProperties, v8::Handle<v8::Value>*) = 0; 1314 virtual bool completeSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>*) = 0; 1315 virtual bool completeDenseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>*) = 0; 1316 }; 1317 1318 // Reader is responsible for deserializing primitive types and 1319 // restoring information about saved objects of composite types. 1320 class Reader { 1321 public: 1322 Reader(const uint8_t* buffer, int length, v8::Isolate* isolate, const BlobDataHandleMap& blobDataHandles) 1323 : m_buffer(buffer) 1324 , m_length(length) 1325 , m_position(0) 1326 , m_version(0) 1327 , m_isolate(isolate) 1328 , m_blobDataHandles(blobDataHandles) 1329 { 1330 ASSERT(!(reinterpret_cast<size_t>(buffer) & 1)); 1331 ASSERT(length >= 0); 1332 } 1333 1334 bool isEof() const { return m_position >= m_length; } 1335 1336 v8::Isolate* isolate() const { return m_isolate; } 1337 1338 bool read(v8::Handle<v8::Value>* value, CompositeCreator& creator) 1339 { 1340 SerializationTag tag; 1341 if (!readTag(&tag)) 1342 return false; 1343 switch (tag) { 1344 case ReferenceCountTag: { 1345 if (m_version <= 0) 1346 return false; 1347 uint32_t referenceTableSize; 1348 if (!doReadUint32(&referenceTableSize)) 1349 return false; 1350 // If this test fails, then the serializer and deserializer disagree about the assignment 1351 // of object reference IDs. On the deserialization side, this means there are too many or too few 1352 // calls to pushObjectReference. 1353 if (referenceTableSize != creator.objectReferenceCount()) 1354 return false; 1355 return true; 1356 } 1357 case InvalidTag: 1358 return false; 1359 case PaddingTag: 1360 return true; 1361 case UndefinedTag: 1362 *value = v8::Undefined(m_isolate); 1363 break; 1364 case NullTag: 1365 *value = v8::Null(m_isolate); 1366 break; 1367 case TrueTag: 1368 *value = v8BooleanWithCheck(true, m_isolate); 1369 break; 1370 case FalseTag: 1371 *value = v8BooleanWithCheck(false, m_isolate); 1372 break; 1373 case TrueObjectTag: 1374 *value = v8::BooleanObject::New(true); 1375 creator.pushObjectReference(*value); 1376 break; 1377 case FalseObjectTag: 1378 *value = v8::BooleanObject::New(false); 1379 creator.pushObjectReference(*value); 1380 break; 1381 case StringTag: 1382 if (!readString(value)) 1383 return false; 1384 break; 1385 case StringUCharTag: 1386 if (!readUCharString(value)) 1387 return false; 1388 break; 1389 case StringObjectTag: 1390 if (!readStringObject(value)) 1391 return false; 1392 creator.pushObjectReference(*value); 1393 break; 1394 case Int32Tag: 1395 if (!readInt32(value)) 1396 return false; 1397 break; 1398 case Uint32Tag: 1399 if (!readUint32(value)) 1400 return false; 1401 break; 1402 case DateTag: 1403 if (!readDate(value)) 1404 return false; 1405 creator.pushObjectReference(*value); 1406 break; 1407 case NumberTag: 1408 if (!readNumber(value)) 1409 return false; 1410 break; 1411 case NumberObjectTag: 1412 if (!readNumberObject(value)) 1413 return false; 1414 creator.pushObjectReference(*value); 1415 break; 1416 case BlobTag: 1417 if (!readBlob(value)) 1418 return false; 1419 creator.pushObjectReference(*value); 1420 break; 1421 case FileTag: 1422 if (!readFile(value)) 1423 return false; 1424 creator.pushObjectReference(*value); 1425 break; 1426 case DOMFileSystemTag: 1427 if (!readDOMFileSystem(value)) 1428 return false; 1429 creator.pushObjectReference(*value); 1430 break; 1431 case FileListTag: 1432 if (!readFileList(value)) 1433 return false; 1434 creator.pushObjectReference(*value); 1435 break; 1436 case ImageDataTag: 1437 if (!readImageData(value)) 1438 return false; 1439 creator.pushObjectReference(*value); 1440 break; 1441 1442 case RegExpTag: 1443 if (!readRegExp(value)) 1444 return false; 1445 creator.pushObjectReference(*value); 1446 break; 1447 case ObjectTag: { 1448 uint32_t numProperties; 1449 if (!doReadUint32(&numProperties)) 1450 return false; 1451 if (!creator.completeObject(numProperties, value)) 1452 return false; 1453 break; 1454 } 1455 case SparseArrayTag: { 1456 uint32_t numProperties; 1457 uint32_t length; 1458 if (!doReadUint32(&numProperties)) 1459 return false; 1460 if (!doReadUint32(&length)) 1461 return false; 1462 if (!creator.completeSparseArray(numProperties, length, value)) 1463 return false; 1464 break; 1465 } 1466 case DenseArrayTag: { 1467 uint32_t numProperties; 1468 uint32_t length; 1469 if (!doReadUint32(&numProperties)) 1470 return false; 1471 if (!doReadUint32(&length)) 1472 return false; 1473 if (!creator.completeDenseArray(numProperties, length, value)) 1474 return false; 1475 break; 1476 } 1477 case ArrayBufferViewTag: { 1478 if (m_version <= 0) 1479 return false; 1480 if (!readArrayBufferView(value, creator)) 1481 return false; 1482 creator.pushObjectReference(*value); 1483 break; 1484 } 1485 case ArrayBufferTag: { 1486 if (m_version <= 0) 1487 return false; 1488 if (!readArrayBuffer(value)) 1489 return false; 1490 creator.pushObjectReference(*value); 1491 break; 1492 } 1493 case GenerateFreshObjectTag: { 1494 if (m_version <= 0) 1495 return false; 1496 if (!creator.newObject()) 1497 return false; 1498 return true; 1499 } 1500 case GenerateFreshSparseArrayTag: { 1501 if (m_version <= 0) 1502 return false; 1503 uint32_t length; 1504 if (!doReadUint32(&length)) 1505 return false; 1506 if (!creator.newSparseArray(length)) 1507 return false; 1508 return true; 1509 } 1510 case GenerateFreshDenseArrayTag: { 1511 if (m_version <= 0) 1512 return false; 1513 uint32_t length; 1514 if (!doReadUint32(&length)) 1515 return false; 1516 if (!creator.newDenseArray(length)) 1517 return false; 1518 return true; 1519 } 1520 case MessagePortTag: { 1521 if (m_version <= 0) 1522 return false; 1523 uint32_t index; 1524 if (!doReadUint32(&index)) 1525 return false; 1526 if (!creator.tryGetTransferredMessagePort(index, value)) 1527 return false; 1528 break; 1529 } 1530 case ArrayBufferTransferTag: { 1531 if (m_version <= 0) 1532 return false; 1533 uint32_t index; 1534 if (!doReadUint32(&index)) 1535 return false; 1536 if (!creator.tryGetTransferredArrayBuffer(index, value)) 1537 return false; 1538 break; 1539 } 1540 case ObjectReferenceTag: { 1541 if (m_version <= 0) 1542 return false; 1543 uint32_t reference; 1544 if (!doReadUint32(&reference)) 1545 return false; 1546 if (!creator.tryGetObjectFromObjectReference(reference, value)) 1547 return false; 1548 break; 1549 } 1550 default: 1551 return false; 1552 } 1553 return !value->IsEmpty(); 1554 } 1555 1556 bool readVersion(uint32_t& version) 1557 { 1558 SerializationTag tag; 1559 if (!readTag(&tag)) { 1560 // This is a nullary buffer. We're still version 0. 1561 version = 0; 1562 return true; 1563 } 1564 if (tag != VersionTag) { 1565 // Versions of the format past 0 start with the version tag. 1566 version = 0; 1567 // Put back the tag. 1568 undoReadTag(); 1569 return true; 1570 } 1571 // Version-bearing messages are obligated to finish the version tag. 1572 return doReadUint32(&version); 1573 } 1574 1575 void setVersion(uint32_t version) 1576 { 1577 m_version = version; 1578 } 1579 1580 v8::Isolate* getIsolate() { return m_isolate; } 1581 1582 private: 1583 bool readTag(SerializationTag* tag) 1584 { 1585 if (m_position >= m_length) 1586 return false; 1587 *tag = static_cast<SerializationTag>(m_buffer[m_position++]); 1588 return true; 1589 } 1590 1591 void undoReadTag() 1592 { 1593 if (m_position > 0) 1594 --m_position; 1595 } 1596 1597 bool readArrayBufferViewSubTag(ArrayBufferViewSubTag* tag) 1598 { 1599 if (m_position >= m_length) 1600 return false; 1601 *tag = static_cast<ArrayBufferViewSubTag>(m_buffer[m_position++]); 1602 return true; 1603 } 1604 1605 bool readString(v8::Handle<v8::Value>* value) 1606 { 1607 uint32_t length; 1608 if (!doReadUint32(&length)) 1609 return false; 1610 if (m_position + length > m_length) 1611 return false; 1612 *value = v8::String::NewFromUtf8(m_isolate, reinterpret_cast<const char*>(m_buffer + m_position), v8::String::kNormalString, length); 1613 m_position += length; 1614 return true; 1615 } 1616 1617 bool readUCharString(v8::Handle<v8::Value>* value) 1618 { 1619 uint32_t length; 1620 if (!doReadUint32(&length) || (length & 1)) 1621 return false; 1622 if (m_position + length > m_length) 1623 return false; 1624 ASSERT(!(m_position & 1)); 1625 *value = v8::String::NewFromTwoByte(m_isolate, reinterpret_cast<const uint16_t*>(m_buffer + m_position), v8::String::kNormalString, length / sizeof(UChar)); 1626 m_position += length; 1627 return true; 1628 } 1629 1630 bool readStringObject(v8::Handle<v8::Value>* value) 1631 { 1632 v8::Handle<v8::Value> stringValue; 1633 if (!readString(&stringValue) || !stringValue->IsString()) 1634 return false; 1635 *value = v8::StringObject::New(stringValue.As<v8::String>()); 1636 return true; 1637 } 1638 1639 bool readWebCoreString(String* string) 1640 { 1641 uint32_t length; 1642 if (!doReadUint32(&length)) 1643 return false; 1644 if (m_position + length > m_length) 1645 return false; 1646 *string = String::fromUTF8(reinterpret_cast<const char*>(m_buffer + m_position), length); 1647 m_position += length; 1648 return true; 1649 } 1650 1651 bool readInt32(v8::Handle<v8::Value>* value) 1652 { 1653 uint32_t rawValue; 1654 if (!doReadUint32(&rawValue)) 1655 return false; 1656 *value = v8::Integer::New(static_cast<int32_t>(ZigZag::decode(rawValue)), m_isolate); 1657 return true; 1658 } 1659 1660 bool readUint32(v8::Handle<v8::Value>* value) 1661 { 1662 uint32_t rawValue; 1663 if (!doReadUint32(&rawValue)) 1664 return false; 1665 *value = v8::Integer::NewFromUnsigned(rawValue, m_isolate); 1666 return true; 1667 } 1668 1669 bool readDate(v8::Handle<v8::Value>* value) 1670 { 1671 double numberValue; 1672 if (!doReadNumber(&numberValue)) 1673 return false; 1674 *value = v8DateOrNull(numberValue, m_isolate); 1675 return true; 1676 } 1677 1678 bool readNumber(v8::Handle<v8::Value>* value) 1679 { 1680 double number; 1681 if (!doReadNumber(&number)) 1682 return false; 1683 *value = v8::Number::New(m_isolate, number); 1684 return true; 1685 } 1686 1687 bool readNumberObject(v8::Handle<v8::Value>* value) 1688 { 1689 double number; 1690 if (!doReadNumber(&number)) 1691 return false; 1692 *value = v8::NumberObject::New(m_isolate, number); 1693 return true; 1694 } 1695 1696 bool readImageData(v8::Handle<v8::Value>* value) 1697 { 1698 uint32_t width; 1699 uint32_t height; 1700 uint32_t pixelDataLength; 1701 if (!doReadUint32(&width)) 1702 return false; 1703 if (!doReadUint32(&height)) 1704 return false; 1705 if (!doReadUint32(&pixelDataLength)) 1706 return false; 1707 if (m_position + pixelDataLength > m_length) 1708 return false; 1709 RefPtr<ImageData> imageData = ImageData::create(IntSize(width, height)); 1710 Uint8ClampedArray* pixelArray = imageData->data(); 1711 ASSERT(pixelArray); 1712 ASSERT(pixelArray->length() >= pixelDataLength); 1713 memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength); 1714 m_position += pixelDataLength; 1715 *value = toV8(imageData.release(), v8::Handle<v8::Object>(), m_isolate); 1716 return true; 1717 } 1718 1719 PassRefPtr<ArrayBuffer> doReadArrayBuffer() 1720 { 1721 uint32_t byteLength; 1722 if (!doReadUint32(&byteLength)) 1723 return 0; 1724 if (m_position + byteLength > m_length) 1725 return 0; 1726 const void* bufferStart = m_buffer + m_position; 1727 RefPtr<ArrayBuffer> arrayBuffer = ArrayBuffer::create(bufferStart, byteLength); 1728 arrayBuffer->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instanceTemplate()); 1729 m_position += byteLength; 1730 return arrayBuffer.release(); 1731 } 1732 1733 bool readArrayBuffer(v8::Handle<v8::Value>* value) 1734 { 1735 RefPtr<ArrayBuffer> arrayBuffer = doReadArrayBuffer(); 1736 if (!arrayBuffer) 1737 return false; 1738 *value = toV8(arrayBuffer.release(), v8::Handle<v8::Object>(), m_isolate); 1739 return true; 1740 } 1741 1742 bool readArrayBufferView(v8::Handle<v8::Value>* value, CompositeCreator& creator) 1743 { 1744 ArrayBufferViewSubTag subTag; 1745 uint32_t byteOffset; 1746 uint32_t byteLength; 1747 RefPtr<ArrayBuffer> arrayBuffer; 1748 v8::Handle<v8::Value> arrayBufferV8Value; 1749 if (!readArrayBufferViewSubTag(&subTag)) 1750 return false; 1751 if (!doReadUint32(&byteOffset)) 1752 return false; 1753 if (!doReadUint32(&byteLength)) 1754 return false; 1755 if (!creator.consumeTopOfStack(&arrayBufferV8Value)) 1756 return false; 1757 if (arrayBufferV8Value.IsEmpty()) 1758 return false; 1759 arrayBuffer = V8ArrayBuffer::toNative(arrayBufferV8Value.As<v8::Object>()); 1760 if (!arrayBuffer) 1761 return false; 1762 switch (subTag) { 1763 case ByteArrayTag: 1764 *value = toV8(Int8Array::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate); 1765 break; 1766 case UnsignedByteArrayTag: 1767 *value = toV8(Uint8Array::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate); 1768 break; 1769 case UnsignedByteClampedArrayTag: 1770 *value = toV8(Uint8ClampedArray::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate); 1771 break; 1772 case ShortArrayTag: { 1773 uint32_t shortLength = byteLength / sizeof(int16_t); 1774 if (shortLength * sizeof(int16_t) != byteLength) 1775 return false; 1776 *value = toV8(Int16Array::create(arrayBuffer.release(), byteOffset, shortLength), v8::Handle<v8::Object>(), m_isolate); 1777 break; 1778 } 1779 case UnsignedShortArrayTag: { 1780 uint32_t shortLength = byteLength / sizeof(uint16_t); 1781 if (shortLength * sizeof(uint16_t) != byteLength) 1782 return false; 1783 *value = toV8(Uint16Array::create(arrayBuffer.release(), byteOffset, shortLength), v8::Handle<v8::Object>(), m_isolate); 1784 break; 1785 } 1786 case IntArrayTag: { 1787 uint32_t intLength = byteLength / sizeof(int32_t); 1788 if (intLength * sizeof(int32_t) != byteLength) 1789 return false; 1790 *value = toV8(Int32Array::create(arrayBuffer.release(), byteOffset, intLength), v8::Handle<v8::Object>(), m_isolate); 1791 break; 1792 } 1793 case UnsignedIntArrayTag: { 1794 uint32_t intLength = byteLength / sizeof(uint32_t); 1795 if (intLength * sizeof(uint32_t) != byteLength) 1796 return false; 1797 *value = toV8(Uint32Array::create(arrayBuffer.release(), byteOffset, intLength), v8::Handle<v8::Object>(), m_isolate); 1798 break; 1799 } 1800 case FloatArrayTag: { 1801 uint32_t floatLength = byteLength / sizeof(float); 1802 if (floatLength * sizeof(float) != byteLength) 1803 return false; 1804 *value = toV8(Float32Array::create(arrayBuffer.release(), byteOffset, floatLength), v8::Handle<v8::Object>(), m_isolate); 1805 break; 1806 } 1807 case DoubleArrayTag: { 1808 uint32_t floatLength = byteLength / sizeof(double); 1809 if (floatLength * sizeof(double) != byteLength) 1810 return false; 1811 *value = toV8(Float64Array::create(arrayBuffer.release(), byteOffset, floatLength), v8::Handle<v8::Object>(), m_isolate); 1812 break; 1813 } 1814 case DataViewTag: 1815 *value = toV8(DataView::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate); 1816 break; 1817 default: 1818 return false; 1819 } 1820 // The various *Array::create() methods will return null if the range the view expects is 1821 // mismatched with the range the buffer can provide or if the byte offset is not aligned 1822 // to the size of the element type. 1823 return !value->IsEmpty(); 1824 } 1825 1826 bool readRegExp(v8::Handle<v8::Value>* value) 1827 { 1828 v8::Handle<v8::Value> pattern; 1829 if (!readString(&pattern)) 1830 return false; 1831 uint32_t flags; 1832 if (!doReadUint32(&flags)) 1833 return false; 1834 *value = v8::RegExp::New(pattern.As<v8::String>(), static_cast<v8::RegExp::Flags>(flags)); 1835 return true; 1836 } 1837 1838 bool readBlob(v8::Handle<v8::Value>* value) 1839 { 1840 if (m_version < 3) 1841 return false; 1842 String uuid; 1843 String type; 1844 uint64_t size; 1845 if (!readWebCoreString(&uuid)) 1846 return false; 1847 if (!readWebCoreString(&type)) 1848 return false; 1849 if (!doReadUint64(&size)) 1850 return false; 1851 RefPtr<Blob> blob = Blob::create(getOrCreateBlobDataHandle(uuid, type, size)); 1852 *value = toV8(blob.release(), v8::Handle<v8::Object>(), m_isolate); 1853 return true; 1854 } 1855 1856 bool readDOMFileSystem(v8::Handle<v8::Value>* value) 1857 { 1858 uint32_t type; 1859 String name; 1860 String url; 1861 if (!doReadUint32(&type)) 1862 return false; 1863 if (!readWebCoreString(&name)) 1864 return false; 1865 if (!readWebCoreString(&url)) 1866 return false; 1867 RefPtr<DOMFileSystem> fs = DOMFileSystem::create(getExecutionContext(), name, static_cast<WebCore::FileSystemType>(type), KURL(ParsedURLString, url)); 1868 *value = toV8(fs.release(), v8::Handle<v8::Object>(), m_isolate); 1869 return true; 1870 } 1871 1872 bool readFile(v8::Handle<v8::Value>* value) 1873 { 1874 RefPtr<File> file = doReadFileHelper(); 1875 if (!file) 1876 return false; 1877 *value = toV8(file.release(), v8::Handle<v8::Object>(), m_isolate); 1878 return true; 1879 } 1880 1881 bool readFileList(v8::Handle<v8::Value>* value) 1882 { 1883 if (m_version < 3) 1884 return false; 1885 uint32_t length; 1886 if (!doReadUint32(&length)) 1887 return false; 1888 RefPtr<FileList> fileList = FileList::create(); 1889 for (unsigned i = 0; i < length; ++i) { 1890 RefPtr<File> file = doReadFileHelper(); 1891 if (!file) 1892 return false; 1893 fileList->append(file.release()); 1894 } 1895 *value = toV8(fileList.release(), v8::Handle<v8::Object>(), m_isolate); 1896 return true; 1897 } 1898 1899 PassRefPtr<File> doReadFileHelper() 1900 { 1901 if (m_version < 3) 1902 return 0; 1903 String path; 1904 String name; 1905 String relativePath; 1906 String uuid; 1907 String type; 1908 uint32_t hasSnapshot = 0; 1909 uint64_t size = 0; 1910 double lastModified = 0; 1911 if (!readWebCoreString(&path)) 1912 return 0; 1913 if (m_version >= 4 && !readWebCoreString(&name)) 1914 return 0; 1915 if (m_version >= 4 && !readWebCoreString(&relativePath)) 1916 return 0; 1917 if (!readWebCoreString(&uuid)) 1918 return 0; 1919 if (!readWebCoreString(&type)) 1920 return 0; 1921 if (m_version >= 4 && !doReadUint32(&hasSnapshot)) 1922 return 0; 1923 if (hasSnapshot) { 1924 if (!doReadUint64(&size)) 1925 return 0; 1926 if (!doReadNumber(&lastModified)) 1927 return 0; 1928 } 1929 return File::create(path, name, relativePath, hasSnapshot > 0, size, lastModified, getOrCreateBlobDataHandle(uuid, type)); 1930 } 1931 1932 template<class T> 1933 bool doReadUintHelper(T* value) 1934 { 1935 *value = 0; 1936 uint8_t currentByte; 1937 int shift = 0; 1938 do { 1939 if (m_position >= m_length) 1940 return false; 1941 currentByte = m_buffer[m_position++]; 1942 *value |= ((currentByte & varIntMask) << shift); 1943 shift += varIntShift; 1944 } while (currentByte & (1 << varIntShift)); 1945 return true; 1946 } 1947 1948 bool doReadUint32(uint32_t* value) 1949 { 1950 return doReadUintHelper(value); 1951 } 1952 1953 bool doReadUint64(uint64_t* value) 1954 { 1955 return doReadUintHelper(value); 1956 } 1957 1958 bool doReadNumber(double* number) 1959 { 1960 if (m_position + sizeof(double) > m_length) 1961 return false; 1962 uint8_t* numberAsByteArray = reinterpret_cast<uint8_t*>(number); 1963 for (unsigned i = 0; i < sizeof(double); ++i) 1964 numberAsByteArray[i] = m_buffer[m_position++]; 1965 return true; 1966 } 1967 1968 PassRefPtr<BlobDataHandle> getOrCreateBlobDataHandle(const String& uuid, const String& type, long long size = -1) 1969 { 1970 // The containing ssv may have a BDH for this uuid if this ssv is just being 1971 // passed from main to worker thread (for example). We use those values when creating 1972 // the new blob instead of cons'ing up a new BDH. 1973 // 1974 // FIXME: Maybe we should require that it work that way where the ssv must have a BDH for any 1975 // blobs it comes across during deserialization. Would require callers to explicitly populate 1976 // the collection of BDH's for blobs to work, which would encourage lifetimes to be considered 1977 // when passing ssv's around cross process. At present, we get 'lucky' in some cases because 1978 // the blob in the src process happens to still exist at the time the dest process is deserializing. 1979 // For example in sharedWorker.postMesssage(...). 1980 BlobDataHandleMap::const_iterator it = m_blobDataHandles.find(uuid); 1981 if (it != m_blobDataHandles.end()) { 1982 // make assertions about type and size? 1983 return it->value; 1984 } 1985 return BlobDataHandle::create(uuid, type, size); 1986 } 1987 1988 const uint8_t* m_buffer; 1989 const unsigned m_length; 1990 unsigned m_position; 1991 uint32_t m_version; 1992 v8::Isolate* m_isolate; 1993 const BlobDataHandleMap& m_blobDataHandles; 1994 }; 1995 1996 1997 typedef Vector<WTF::ArrayBufferContents, 1> ArrayBufferContentsArray; 1998 1999 class Deserializer : public CompositeCreator { 2000 public: 2001 Deserializer(Reader& reader, MessagePortArray* messagePorts, ArrayBufferContentsArray* arrayBufferContents) 2002 : m_reader(reader) 2003 , m_transferredMessagePorts(messagePorts) 2004 , m_arrayBufferContents(arrayBufferContents) 2005 , m_arrayBuffers(arrayBufferContents ? arrayBufferContents->size() : 0) 2006 , m_version(0) 2007 { 2008 } 2009 2010 v8::Handle<v8::Value> deserialize() 2011 { 2012 if (!m_reader.readVersion(m_version) || m_version > SerializedScriptValue::wireFormatVersion) 2013 return v8::Null(m_reader.getIsolate()); 2014 m_reader.setVersion(m_version); 2015 v8::EscapableHandleScope scope(m_reader.getIsolate()); 2016 while (!m_reader.isEof()) { 2017 if (!doDeserialize()) 2018 return v8::Null(m_reader.getIsolate()); 2019 } 2020 if (stackDepth() != 1 || m_openCompositeReferenceStack.size()) 2021 return v8::Null(m_reader.getIsolate()); 2022 v8::Handle<v8::Value> result = scope.Escape(element(0)); 2023 return result; 2024 } 2025 2026 virtual bool newSparseArray(uint32_t) 2027 { 2028 v8::Local<v8::Array> array = v8::Array::New(m_reader.isolate(), 0); 2029 openComposite(array); 2030 return true; 2031 } 2032 2033 virtual bool newDenseArray(uint32_t length) 2034 { 2035 v8::Local<v8::Array> array = v8::Array::New(m_reader.isolate(), length); 2036 openComposite(array); 2037 return true; 2038 } 2039 2040 virtual bool consumeTopOfStack(v8::Handle<v8::Value>* object) 2041 { 2042 if (stackDepth() < 1) 2043 return false; 2044 *object = element(stackDepth() - 1); 2045 pop(1); 2046 return true; 2047 } 2048 2049 virtual bool completeArray(uint32_t length, v8::Handle<v8::Value>* value) 2050 { 2051 if (length > stackDepth()) 2052 return false; 2053 v8::Local<v8::Array> array; 2054 if (m_version > 0) { 2055 v8::Local<v8::Value> composite; 2056 if (!closeComposite(&composite)) 2057 return false; 2058 array = composite.As<v8::Array>(); 2059 } else { 2060 array = v8::Array::New(m_reader.isolate(), length); 2061 } 2062 if (array.IsEmpty()) 2063 return false; 2064 const int depth = stackDepth() - length; 2065 // The V8 API ensures space exists for any index argument to Set; it will (eg) resize arrays as necessary. 2066 for (unsigned i = 0; i < length; ++i) 2067 array->Set(i, element(depth + i)); 2068 pop(length); 2069 *value = array; 2070 return true; 2071 } 2072 2073 virtual bool newObject() 2074 { 2075 v8::Local<v8::Object> object = v8::Object::New(); 2076 if (object.IsEmpty()) 2077 return false; 2078 openComposite(object); 2079 return true; 2080 } 2081 2082 virtual bool completeObject(uint32_t numProperties, v8::Handle<v8::Value>* value) 2083 { 2084 v8::Local<v8::Object> object; 2085 if (m_version > 0) { 2086 v8::Local<v8::Value> composite; 2087 if (!closeComposite(&composite)) 2088 return false; 2089 object = composite.As<v8::Object>(); 2090 } else 2091 object = v8::Object::New(); 2092 if (object.IsEmpty()) 2093 return false; 2094 return initializeObject(object, numProperties, value); 2095 } 2096 2097 virtual bool completeSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) 2098 { 2099 v8::Local<v8::Array> array; 2100 if (m_version > 0) { 2101 v8::Local<v8::Value> composite; 2102 if (!closeComposite(&composite)) 2103 return false; 2104 array = composite.As<v8::Array>(); 2105 } else { 2106 array = v8::Array::New(m_reader.isolate()); 2107 } 2108 if (array.IsEmpty()) 2109 return false; 2110 return initializeObject(array, numProperties, value); 2111 } 2112 2113 virtual bool completeDenseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) 2114 { 2115 v8::Local<v8::Array> array; 2116 if (m_version > 0) { 2117 v8::Local<v8::Value> composite; 2118 if (!closeComposite(&composite)) 2119 return false; 2120 array = composite.As<v8::Array>(); 2121 } 2122 if (array.IsEmpty()) 2123 return false; 2124 if (!initializeObject(array, numProperties, value)) 2125 return false; 2126 if (length > stackDepth()) 2127 return false; 2128 for (unsigned i = 0, stackPos = stackDepth() - length; i < length; i++, stackPos++) { 2129 v8::Local<v8::Value> elem = element(stackPos); 2130 if (!elem->IsUndefined()) 2131 array->Set(i, elem); 2132 } 2133 pop(length); 2134 return true; 2135 } 2136 2137 virtual void pushObjectReference(const v8::Handle<v8::Value>& object) 2138 { 2139 m_objectPool.append(object); 2140 } 2141 2142 virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Value>* object) 2143 { 2144 if (!m_transferredMessagePorts) 2145 return false; 2146 if (index >= m_transferredMessagePorts->size()) 2147 return false; 2148 *object = toV8(m_transferredMessagePorts->at(index).get(), v8::Handle<v8::Object>(), m_reader.getIsolate()); 2149 return true; 2150 } 2151 2152 virtual bool tryGetTransferredArrayBuffer(uint32_t index, v8::Handle<v8::Value>* object) 2153 { 2154 if (!m_arrayBufferContents) 2155 return false; 2156 if (index >= m_arrayBuffers.size()) 2157 return false; 2158 v8::Handle<v8::Object> result = m_arrayBuffers.at(index); 2159 if (result.IsEmpty()) { 2160 RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(m_arrayBufferContents->at(index)); 2161 buffer->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instanceTemplate()); 2162 m_reader.isolate()->AdjustAmountOfExternalAllocatedMemory(buffer->byteLength()); 2163 result = toV8Object(buffer.get(), m_reader.getIsolate()); 2164 m_arrayBuffers[index] = result; 2165 } 2166 *object = result; 2167 return true; 2168 } 2169 2170 virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle<v8::Value>* object) 2171 { 2172 if (reference >= m_objectPool.size()) 2173 return false; 2174 *object = m_objectPool[reference]; 2175 return object; 2176 } 2177 2178 virtual uint32_t objectReferenceCount() 2179 { 2180 return m_objectPool.size(); 2181 } 2182 2183 private: 2184 bool initializeObject(v8::Handle<v8::Object> object, uint32_t numProperties, v8::Handle<v8::Value>* value) 2185 { 2186 unsigned length = 2 * numProperties; 2187 if (length > stackDepth()) 2188 return false; 2189 for (unsigned i = stackDepth() - length; i < stackDepth(); i += 2) { 2190 v8::Local<v8::Value> propertyName = element(i); 2191 v8::Local<v8::Value> propertyValue = element(i + 1); 2192 object->Set(propertyName, propertyValue); 2193 } 2194 pop(length); 2195 *value = object; 2196 return true; 2197 } 2198 2199 bool doDeserialize() 2200 { 2201 v8::Local<v8::Value> value; 2202 if (!m_reader.read(&value, *this)) 2203 return false; 2204 if (!value.IsEmpty()) 2205 push(value); 2206 return true; 2207 } 2208 2209 void push(v8::Local<v8::Value> value) { m_stack.append(value); } 2210 2211 void pop(unsigned length) 2212 { 2213 ASSERT(length <= m_stack.size()); 2214 m_stack.shrink(m_stack.size() - length); 2215 } 2216 2217 unsigned stackDepth() const { return m_stack.size(); } 2218 2219 v8::Local<v8::Value> element(unsigned index) 2220 { 2221 ASSERT_WITH_SECURITY_IMPLICATION(index < m_stack.size()); 2222 return m_stack[index]; 2223 } 2224 2225 void openComposite(const v8::Local<v8::Value>& object) 2226 { 2227 uint32_t newObjectReference = m_objectPool.size(); 2228 m_openCompositeReferenceStack.append(newObjectReference); 2229 m_objectPool.append(object); 2230 } 2231 2232 bool closeComposite(v8::Handle<v8::Value>* object) 2233 { 2234 if (!m_openCompositeReferenceStack.size()) 2235 return false; 2236 uint32_t objectReference = m_openCompositeReferenceStack[m_openCompositeReferenceStack.size() - 1]; 2237 m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size() - 1); 2238 if (objectReference >= m_objectPool.size()) 2239 return false; 2240 *object = m_objectPool[objectReference]; 2241 return true; 2242 } 2243 2244 Reader& m_reader; 2245 Vector<v8::Local<v8::Value> > m_stack; 2246 Vector<v8::Handle<v8::Value> > m_objectPool; 2247 Vector<uint32_t> m_openCompositeReferenceStack; 2248 MessagePortArray* m_transferredMessagePorts; 2249 ArrayBufferContentsArray* m_arrayBufferContents; 2250 Vector<v8::Handle<v8::Object> > m_arrayBuffers; 2251 uint32_t m_version; 2252 }; 2253 2254 } // namespace 2255 2256 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, bool& didThrow, v8::Isolate* isolate) 2257 { 2258 return adoptRef(new SerializedScriptValue(value, messagePorts, arrayBuffers, didThrow, isolate)); 2259 } 2260 2261 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createAndSwallowExceptions(v8::Handle<v8::Value> value, v8::Isolate* isolate) 2262 { 2263 bool didThrow; 2264 return adoptRef(new SerializedScriptValue(value, 0, 0, didThrow, isolate, DoNotThrowExceptions)); 2265 } 2266 2267 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const ScriptValue& value, bool& didThrow, ScriptState* state) 2268 { 2269 ScriptScope scope(state); 2270 return adoptRef(new SerializedScriptValue(value.v8Value(), 0, 0, didThrow, state->isolate())); 2271 } 2272 2273 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWire(const String& data) 2274 { 2275 return adoptRef(new SerializedScriptValue(data)); 2276 } 2277 2278 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWireBytes(const Vector<uint8_t>& data) 2279 { 2280 // Decode wire data from big endian to host byte order. 2281 ASSERT(!(data.size() % sizeof(UChar))); 2282 size_t length = data.size() / sizeof(UChar); 2283 StringBuffer<UChar> buffer(length); 2284 const UChar* src = reinterpret_cast<const UChar*>(data.data()); 2285 UChar* dst = buffer.characters(); 2286 for (size_t i = 0; i < length; i++) 2287 dst[i] = ntohs(src[i]); 2288 2289 return createFromWire(String::adopt(buffer)); 2290 } 2291 2292 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& data) 2293 { 2294 return create(data, v8::Isolate::GetCurrent()); 2295 } 2296 2297 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& data, v8::Isolate* isolate) 2298 { 2299 Writer writer(isolate); 2300 writer.writeWebCoreString(data); 2301 String wireData = writer.takeWireString(); 2302 return adoptRef(new SerializedScriptValue(wireData)); 2303 } 2304 2305 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create() 2306 { 2307 return adoptRef(new SerializedScriptValue()); 2308 } 2309 2310 PassRefPtr<SerializedScriptValue> SerializedScriptValue::nullValue() 2311 { 2312 return nullValue(v8::Isolate::GetCurrent()); 2313 } 2314 2315 PassRefPtr<SerializedScriptValue> SerializedScriptValue::nullValue(v8::Isolate* isolate) 2316 { 2317 Writer writer(isolate); 2318 writer.writeNull(); 2319 String wireData = writer.takeWireString(); 2320 return adoptRef(new SerializedScriptValue(wireData)); 2321 } 2322 2323 // Convert serialized string to big endian wire data. 2324 void SerializedScriptValue::toWireBytes(Vector<char>& result) const 2325 { 2326 ASSERT(result.isEmpty()); 2327 size_t length = m_data.length(); 2328 result.resize(length * sizeof(UChar)); 2329 UChar* dst = reinterpret_cast<UChar*>(result.data()); 2330 2331 if (m_data.is8Bit()) { 2332 const LChar* src = m_data.characters8(); 2333 for (size_t i = 0; i < length; i++) 2334 dst[i] = htons(static_cast<UChar>(src[i])); 2335 } else { 2336 const UChar* src = m_data.characters16(); 2337 for (size_t i = 0; i < length; i++) 2338 dst[i] = htons(src[i]); 2339 } 2340 } 2341 2342 SerializedScriptValue::SerializedScriptValue() 2343 : m_externallyAllocatedMemory(0) 2344 { 2345 } 2346 2347 inline void neuterBinding(ArrayBuffer* object) 2348 { 2349 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 2350 Vector<DOMDataStore*>& allStores = V8PerIsolateData::from(isolate)->allStores(); 2351 for (size_t i = 0; i < allStores.size(); i++) { 2352 v8::Handle<v8::Object> wrapper = allStores[i]->get<V8ArrayBuffer>(object, isolate); 2353 if (!wrapper.IsEmpty()) { 2354 ASSERT(wrapper->IsArrayBuffer()); 2355 v8::Handle<v8::ArrayBuffer>::Cast(wrapper)->Neuter(); 2356 } 2357 } 2358 } 2359 2360 inline void neuterBinding(ArrayBufferView* object) 2361 { 2362 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 2363 Vector<DOMDataStore*>& allStores = V8PerIsolateData::from(isolate)->allStores(); 2364 for (size_t i = 0; i < allStores.size(); i++) { 2365 v8::Handle<v8::Object> wrapper = allStores[i]->get<V8ArrayBufferView>(object, isolate); 2366 if (!wrapper.IsEmpty()) 2367 wrapper->SetIndexedPropertiesToExternalArrayData(0, v8::kExternalByteArray, 0); 2368 } 2369 } 2370 2371 PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValue::transferArrayBuffers(ArrayBufferArray& arrayBuffers, bool& didThrow, v8::Isolate* isolate) 2372 { 2373 ASSERT(arrayBuffers.size()); 2374 2375 for (size_t i = 0; i < arrayBuffers.size(); i++) { 2376 if (arrayBuffers[i]->isNeutered()) { 2377 setDOMException(InvalidStateError, isolate); 2378 didThrow = true; 2379 return nullptr; 2380 } 2381 } 2382 2383 OwnPtr<ArrayBufferContentsArray> contents = adoptPtr(new ArrayBufferContentsArray(arrayBuffers.size())); 2384 2385 HashSet<ArrayBuffer*> visited; 2386 for (size_t i = 0; i < arrayBuffers.size(); i++) { 2387 Vector<RefPtr<ArrayBufferView> > neuteredViews; 2388 2389 if (visited.contains(arrayBuffers[i].get())) 2390 continue; 2391 visited.add(arrayBuffers[i].get()); 2392 2393 bool result = arrayBuffers[i]->transfer(contents->at(i), neuteredViews); 2394 if (!result) { 2395 setDOMException(InvalidStateError, isolate); 2396 didThrow = true; 2397 return nullptr; 2398 } 2399 2400 neuterBinding(arrayBuffers[i].get()); 2401 for (size_t j = 0; j < neuteredViews.size(); j++) 2402 neuterBinding(neuteredViews[j].get()); 2403 } 2404 return contents.release(); 2405 } 2406 2407 SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, bool& didThrow, v8::Isolate* isolate, ExceptionPolicy policy) 2408 : m_externallyAllocatedMemory(0) 2409 { 2410 didThrow = false; 2411 Writer writer(isolate); 2412 Serializer::Status status; 2413 { 2414 v8::TryCatch tryCatch; 2415 Serializer serializer(writer, messagePorts, arrayBuffers, m_blobDataHandles, tryCatch, isolate); 2416 status = serializer.serialize(value); 2417 if (status == Serializer::JSException) { 2418 didThrow = true; 2419 // If there was a JS exception thrown, re-throw it. 2420 if (policy == ThrowExceptions) 2421 tryCatch.ReThrow(); 2422 return; 2423 } 2424 } 2425 switch (status) { 2426 case Serializer::InputError: 2427 case Serializer::DataCloneError: 2428 // If there was an input error, throw a new exception outside 2429 // of the TryCatch scope. 2430 didThrow = true; 2431 if (policy == ThrowExceptions) 2432 setDOMException(DataCloneError, isolate); 2433 return; 2434 case Serializer::InvalidStateError: 2435 didThrow = true; 2436 if (policy == ThrowExceptions) 2437 setDOMException(InvalidStateError, isolate); 2438 return; 2439 case Serializer::JSFailure: 2440 // If there was a JS failure (but no exception), there's not 2441 // much we can do except for unwinding the C++ stack by 2442 // pretending there was a JS exception. 2443 didThrow = true; 2444 return; 2445 case Serializer::Success: 2446 m_data = writer.takeWireString(); 2447 ASSERT(m_data.impl()->hasOneRef()); 2448 if (arrayBuffers && arrayBuffers->size()) 2449 m_arrayBufferContentsArray = transferArrayBuffers(*arrayBuffers, didThrow, isolate); 2450 return; 2451 case Serializer::JSException: 2452 // We should never get here because this case was handled above. 2453 break; 2454 } 2455 ASSERT_NOT_REACHED(); 2456 } 2457 2458 SerializedScriptValue::SerializedScriptValue(const String& wireData) 2459 : m_externallyAllocatedMemory(0) 2460 { 2461 m_data = wireData.isolatedCopy(); 2462 } 2463 2464 v8::Handle<v8::Value> SerializedScriptValue::deserialize(MessagePortArray* messagePorts) 2465 { 2466 return deserialize(v8::Isolate::GetCurrent(), messagePorts); 2467 } 2468 2469 v8::Handle<v8::Value> SerializedScriptValue::deserialize(v8::Isolate* isolate, MessagePortArray* messagePorts) 2470 { 2471 if (!m_data.impl()) 2472 return v8::Null(isolate); 2473 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes); 2474 m_data.ensure16Bit(); 2475 // FIXME: SerializedScriptValue shouldn't use String for its underlying 2476 // storage. Instead, it should use SharedBuffer or Vector<uint8_t>. The 2477 // information stored in m_data isn't even encoded in UTF-16. Instead, 2478 // unicode characters are encoded as UTF-8 with two code units per UChar. 2479 Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->characters16()), 2 * m_data.length(), isolate, m_blobDataHandles); 2480 Deserializer deserializer(reader, messagePorts, m_arrayBufferContentsArray.get()); 2481 2482 // deserialize() can run arbitrary script (e.g., setters), which could result in |this| being destroyed. 2483 // Holding a RefPtr ensures we are alive (along with our internal data) throughout the operation. 2484 RefPtr<SerializedScriptValue> protect(this); 2485 return deserializer.deserialize(); 2486 } 2487 2488 void SerializedScriptValue::registerMemoryAllocatedWithCurrentScriptContext() 2489 { 2490 if (m_externallyAllocatedMemory) 2491 return; 2492 m_externallyAllocatedMemory = static_cast<intptr_t>(m_data.length()); 2493 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(m_externallyAllocatedMemory); 2494 } 2495 2496 SerializedScriptValue::~SerializedScriptValue() 2497 { 2498 // If the allocated memory was not registered before, then this class is likely 2499 // used in a context other then Worker's onmessage environment and the presence of 2500 // current v8 context is not guaranteed. Avoid calling v8 then. 2501 if (m_externallyAllocatedMemory) { 2502 ASSERT(v8::Isolate::GetCurrent()); 2503 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-m_externallyAllocatedMemory); 2504 } 2505 } 2506 2507 } // namespace WebCore 2508