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