1/* 2 * Copyright (C) 2009, 2013 Apple 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 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * 25 */ 26 27#include "config.h" 28#include "SerializedScriptValue.h" 29 30#include "Blob.h" 31#include "ExceptionCode.h" 32#include "File.h" 33#include "FileList.h" 34#include "ImageData.h" 35#include "JSArrayBuffer.h" 36#include "JSArrayBufferView.h" 37#include "JSBlob.h" 38#include "JSDataView.h" 39#include "JSDOMGlobalObject.h" 40#include "JSFile.h" 41#include "JSFileList.h" 42#include "JSFloat32Array.h" 43#include "JSFloat64Array.h" 44#include "JSImageData.h" 45#include "JSInt16Array.h" 46#include "JSInt32Array.h" 47#include "JSInt8Array.h" 48#include "JSMessagePort.h" 49#include "JSNavigator.h" 50#include "JSUint16Array.h" 51#include "JSUint32Array.h" 52#include "JSUint8Array.h" 53#include "JSUint8ClampedArray.h" 54#include "NotImplemented.h" 55#include "ScriptValue.h" 56#include "SharedBuffer.h" 57#include "WebCoreJSClientData.h" 58#include <limits> 59#include <JavaScriptCore/APICast.h> 60#include <JavaScriptCore/APIShims.h> 61#include <runtime/BooleanObject.h> 62#include <runtime/DateInstance.h> 63#include <runtime/Error.h> 64#include <runtime/ExceptionHelpers.h> 65#include <runtime/ObjectConstructor.h> 66#include <runtime/Operations.h> 67#include <runtime/PropertyNameArray.h> 68#include <runtime/RegExp.h> 69#include <runtime/RegExpObject.h> 70#include <wtf/ArrayBuffer.h> 71#include <wtf/HashTraits.h> 72#include <wtf/Uint8ClampedArray.h> 73#include <wtf/Vector.h> 74 75using namespace JSC; 76using namespace std; 77 78#if CPU(BIG_ENDIAN) || CPU(MIDDLE_ENDIAN) || CPU(NEEDS_ALIGNED_ACCESS) 79#define ASSUME_LITTLE_ENDIAN 0 80#else 81#define ASSUME_LITTLE_ENDIAN 1 82#endif 83 84namespace WebCore { 85 86static const unsigned maximumFilterRecursion = 40000; 87 88enum WalkerState { StateUnknown, ArrayStartState, ArrayStartVisitMember, ArrayEndVisitMember, 89 ObjectStartState, ObjectStartVisitMember, ObjectEndVisitMember }; 90 91// These can't be reordered, and any new types must be added to the end of the list 92enum SerializationTag { 93 ArrayTag = 1, 94 ObjectTag = 2, 95 UndefinedTag = 3, 96 NullTag = 4, 97 IntTag = 5, 98 ZeroTag = 6, 99 OneTag = 7, 100 FalseTag = 8, 101 TrueTag = 9, 102 DoubleTag = 10, 103 DateTag = 11, 104 FileTag = 12, 105 FileListTag = 13, 106 ImageDataTag = 14, 107 BlobTag = 15, 108 StringTag = 16, 109 EmptyStringTag = 17, 110 RegExpTag = 18, 111 ObjectReferenceTag = 19, 112 MessagePortReferenceTag = 20, 113 ArrayBufferTag = 21, 114 ArrayBufferViewTag = 22, 115 ArrayBufferTransferTag = 23, 116 TrueObjectTag = 24, 117 FalseObjectTag = 25, 118 StringObjectTag = 26, 119 EmptyStringObjectTag = 27, 120 NumberObjectTag = 28, 121 ErrorTag = 255 122}; 123 124enum ArrayBufferViewSubtag { 125 DataViewTag = 0, 126 Int8ArrayTag = 1, 127 Uint8ArrayTag = 2, 128 Uint8ClampedArrayTag = 3, 129 Int16ArrayTag = 4, 130 Uint16ArrayTag = 5, 131 Int32ArrayTag = 6, 132 Uint32ArrayTag = 7, 133 Float32ArrayTag = 8, 134 Float64ArrayTag = 9 135}; 136 137static unsigned typedArrayElementSize(ArrayBufferViewSubtag tag) 138{ 139 switch (tag) { 140 case DataViewTag: 141 case Int8ArrayTag: 142 case Uint8ArrayTag: 143 case Uint8ClampedArrayTag: 144 return 1; 145 case Int16ArrayTag: 146 case Uint16ArrayTag: 147 return 2; 148 case Int32ArrayTag: 149 case Uint32ArrayTag: 150 case Float32ArrayTag: 151 return 4; 152 case Float64ArrayTag: 153 return 8; 154 default: 155 return 0; 156 } 157 158} 159 160/* CurrentVersion tracks the serialization version so that persistant stores 161 * are able to correctly bail out in the case of encountering newer formats. 162 * 163 * Initial version was 1. 164 * Version 2. added the ObjectReferenceTag and support for serialization of cyclic graphs. 165 * Version 3. added the FalseObjectTag, TrueObjectTag, NumberObjectTag, StringObjectTag 166 * and EmptyStringObjectTag for serialization of Boolean, Number and String objects. 167 * Version 4. added support for serializing non-index properties of arrays. 168 */ 169static const unsigned CurrentVersion = 4; 170static const unsigned TerminatorTag = 0xFFFFFFFF; 171static const unsigned StringPoolTag = 0xFFFFFFFE; 172static const unsigned NonIndexPropertiesTag = 0xFFFFFFFD; 173 174/* 175 * Object serialization is performed according to the following grammar, all tags 176 * are recorded as a single uint8_t. 177 * 178 * IndexType (used for the object pool and StringData's constant pool) is the 179 * minimum sized unsigned integer type required to represent the maximum index 180 * in the constant pool. 181 * 182 * SerializedValue :- <CurrentVersion:uint32_t> Value 183 * Value :- Array | Object | Terminal 184 * 185 * Array :- 186 * ArrayTag <length:uint32_t>(<index:uint32_t><value:Value>)* TerminatorTag 187 * 188 * Object :- 189 * ObjectTag (<name:StringData><value:Value>)* TerminatorTag 190 * 191 * Terminal :- 192 * UndefinedTag 193 * | NullTag 194 * | IntTag <value:int32_t> 195 * | ZeroTag 196 * | OneTag 197 * | FalseTag 198 * | TrueTag 199 * | FalseObjectTag 200 * | TrueObjectTag 201 * | DoubleTag <value:double> 202 * | NumberObjectTag <value:double> 203 * | DateTag <value:double> 204 * | String 205 * | EmptyStringTag 206 * | EmptyStringObjectTag 207 * | File 208 * | FileList 209 * | ImageData 210 * | Blob 211 * | ObjectReference 212 * | MessagePortReferenceTag <value:uint32_t> 213 * | ArrayBuffer 214 * | ArrayBufferViewTag ArrayBufferViewSubtag <byteOffset:uint32_t> <byteLenght:uint32_t> (ArrayBuffer | ObjectReference) 215 * | ArrayBufferTransferTag <value:uint32_t> 216 * 217 * String :- 218 * EmptyStringTag 219 * StringTag StringData 220 * 221 * StringObject: 222 * EmptyStringObjectTag 223 * StringObjectTag StringData 224 * 225 * StringData :- 226 * StringPoolTag <cpIndex:IndexType> 227 * (not (TerminatorTag | StringPoolTag))<length:uint32_t><characters:UChar{length}> // Added to constant pool when seen, string length 0xFFFFFFFF is disallowed 228 * 229 * File :- 230 * FileTag FileData 231 * 232 * FileData :- 233 * <path:StringData> <url:StringData> <type:StringData> 234 * 235 * FileList :- 236 * FileListTag <length:uint32_t>(<file:FileData>){length} 237 * 238 * ImageData :- 239 * ImageDataTag <width:int32_t><height:int32_t><length:uint32_t><data:uint8_t{length}> 240 * 241 * Blob :- 242 * BlobTag <url:StringData><type:StringData><size:long long> 243 * 244 * RegExp :- 245 * RegExpTag <pattern:StringData><flags:StringData> 246 * 247 * ObjectReference :- 248 * ObjectReferenceTag <opIndex:IndexType> 249 * 250 * ArrayBuffer :- 251 * ArrayBufferTag <length:uint32_t> <contents:byte{length}> 252 */ 253 254typedef pair<JSC::JSValue, SerializationReturnCode> DeserializationResult; 255 256class CloneBase { 257protected: 258 CloneBase(ExecState* exec) 259 : m_exec(exec) 260 , m_failed(false) 261 { 262 } 263 264 bool shouldTerminate() 265 { 266 return m_exec->hadException(); 267 } 268 269 void throwStackOverflow() 270 { 271 throwError(m_exec, createStackOverflowError(m_exec)); 272 } 273 274 NO_RETURN_DUE_TO_ASSERT 275 void fail() 276 { 277 ASSERT_NOT_REACHED(); 278 m_failed = true; 279 } 280 281 ExecState* m_exec; 282 bool m_failed; 283 MarkedArgumentBuffer m_gcBuffer; 284}; 285 286#if ASSUME_LITTLE_ENDIAN 287template <typename T> static void writeLittleEndian(Vector<uint8_t>& buffer, T value) 288{ 289 buffer.append(reinterpret_cast<uint8_t*>(&value), sizeof(value)); 290} 291#else 292template <typename T> static void writeLittleEndian(Vector<uint8_t>& buffer, T value) 293{ 294 for (unsigned i = 0; i < sizeof(T); i++) { 295 buffer.append(value & 0xFF); 296 value >>= 8; 297 } 298} 299#endif 300 301template <> void writeLittleEndian<uint8_t>(Vector<uint8_t>& buffer, uint8_t value) 302{ 303 buffer.append(value); 304} 305 306template <typename T> static bool writeLittleEndian(Vector<uint8_t>& buffer, const T* values, uint32_t length) 307{ 308 if (length > numeric_limits<uint32_t>::max() / sizeof(T)) 309 return false; 310 311#if ASSUME_LITTLE_ENDIAN 312 buffer.append(reinterpret_cast<const uint8_t*>(values), length * sizeof(T)); 313#else 314 for (unsigned i = 0; i < length; i++) { 315 T value = values[i]; 316 for (unsigned j = 0; j < sizeof(T); j++) { 317 buffer.append(static_cast<uint8_t>(value & 0xFF)); 318 value >>= 8; 319 } 320 } 321#endif 322 return true; 323} 324 325class CloneSerializer : CloneBase { 326public: 327 static SerializationReturnCode serialize(ExecState* exec, JSValue value, 328 MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, 329 Vector<String>& blobURLs, Vector<uint8_t>& out) 330 { 331 CloneSerializer serializer(exec, messagePorts, arrayBuffers, blobURLs, out); 332 return serializer.serialize(value); 333 } 334 335 static bool serialize(const String& s, Vector<uint8_t>& out) 336 { 337 writeLittleEndian(out, CurrentVersion); 338 if (s.isEmpty()) { 339 writeLittleEndian<uint8_t>(out, EmptyStringTag); 340 return true; 341 } 342 writeLittleEndian<uint8_t>(out, StringTag); 343 writeLittleEndian(out, s.length()); 344 return writeLittleEndian(out, s.impl()->characters(), s.length()); 345 } 346 347 static void serializeUndefined(Vector<uint8_t>& out) 348 { 349 writeLittleEndian(out, CurrentVersion); 350 writeLittleEndian<uint8_t>(out, UndefinedTag); 351 } 352 353 static void serializeBoolean(bool value, Vector<uint8_t>& out) 354 { 355 writeLittleEndian(out, CurrentVersion); 356 writeLittleEndian<uint8_t>(out, value ? TrueTag : FalseTag); 357 } 358 359 static void serializeNumber(double value, Vector<uint8_t>& out) 360 { 361 writeLittleEndian(out, CurrentVersion); 362 writeLittleEndian<uint8_t>(out, DoubleTag); 363 union { 364 double d; 365 int64_t i; 366 } u; 367 u.d = value; 368 writeLittleEndian(out, u.i); 369 } 370 371private: 372 typedef HashMap<JSObject*, uint32_t> ObjectPool; 373 374 CloneSerializer(ExecState* exec, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, Vector<String>& blobURLs, Vector<uint8_t>& out) 375 : CloneBase(exec) 376 , m_buffer(out) 377 , m_blobURLs(blobURLs) 378 , m_emptyIdentifier(exec, emptyString()) 379 { 380 write(CurrentVersion); 381 fillTransferMap(messagePorts, m_transferredMessagePorts); 382 fillTransferMap(arrayBuffers, m_transferredArrayBuffers); 383 } 384 385 template <class T> 386 void fillTransferMap(Vector<RefPtr<T>, 1>* input, ObjectPool& result) 387 { 388 if (!input) 389 return; 390 JSDOMGlobalObject* globalObject = jsCast<JSDOMGlobalObject*>(m_exec->lexicalGlobalObject()); 391 for (size_t i = 0; i < input->size(); i++) { 392 JSC::JSValue value = toJS(m_exec, globalObject, input->at(i).get()); 393 JSC::JSObject* obj = value.getObject(); 394 if (obj && !result.contains(obj)) 395 result.add(obj, i); 396 } 397 } 398 399 SerializationReturnCode serialize(JSValue in); 400 401 bool isArray(JSValue value) 402 { 403 if (!value.isObject()) 404 return false; 405 JSObject* object = asObject(value); 406 return isJSArray(object) || object->inherits(&JSArray::s_info); 407 } 408 409 bool checkForDuplicate(JSObject* object) 410 { 411 // Record object for graph reconstruction 412 ObjectPool::const_iterator found = m_objectPool.find(object); 413 414 // Handle duplicate references 415 if (found != m_objectPool.end()) { 416 write(ObjectReferenceTag); 417 ASSERT(static_cast<int32_t>(found->value) < m_objectPool.size()); 418 writeObjectIndex(found->value); 419 return true; 420 } 421 422 return false; 423 } 424 425 void recordObject(JSObject* object) 426 { 427 m_objectPool.add(object, m_objectPool.size()); 428 m_gcBuffer.append(object); 429 } 430 431 bool startObjectInternal(JSObject* object) 432 { 433 if (checkForDuplicate(object)) 434 return false; 435 recordObject(object); 436 return true; 437 } 438 439 bool startObject(JSObject* object) 440 { 441 if (!startObjectInternal(object)) 442 return false; 443 write(ObjectTag); 444 return true; 445 } 446 447 bool startArray(JSArray* array) 448 { 449 if (!startObjectInternal(array)) 450 return false; 451 452 unsigned length = array->length(); 453 write(ArrayTag); 454 write(length); 455 return true; 456 } 457 458 void endObject() 459 { 460 write(TerminatorTag); 461 } 462 463 JSValue getProperty(JSObject* object, const Identifier& propertyName) 464 { 465 PropertySlot slot(object); 466 if (object->methodTable()->getOwnPropertySlot(object, m_exec, propertyName, slot)) 467 return slot.getValue(m_exec, propertyName); 468 return JSValue(); 469 } 470 471 void dumpImmediate(JSValue value) 472 { 473 if (value.isNull()) 474 write(NullTag); 475 else if (value.isUndefined()) 476 write(UndefinedTag); 477 else if (value.isNumber()) { 478 if (value.isInt32()) { 479 if (!value.asInt32()) 480 write(ZeroTag); 481 else if (value.asInt32() == 1) 482 write(OneTag); 483 else { 484 write(IntTag); 485 write(static_cast<uint32_t>(value.asInt32())); 486 } 487 } else { 488 write(DoubleTag); 489 write(value.asDouble()); 490 } 491 } else if (value.isBoolean()) { 492 if (value.isTrue()) 493 write(TrueTag); 494 else 495 write(FalseTag); 496 } 497 } 498 499 void dumpString(String str) 500 { 501 if (str.isEmpty()) 502 write(EmptyStringTag); 503 else { 504 write(StringTag); 505 write(str); 506 } 507 } 508 509 void dumpStringObject(String str) 510 { 511 if (str.isEmpty()) 512 write(EmptyStringObjectTag); 513 else { 514 write(StringObjectTag); 515 write(str); 516 } 517 } 518 519 bool dumpArrayBufferView(JSObject* obj, SerializationReturnCode& code) 520 { 521 write(ArrayBufferViewTag); 522 if (obj->inherits(&JSDataView::s_info)) 523 write(DataViewTag); 524 else if (obj->inherits(&JSUint8ClampedArray::s_info)) 525 write(Uint8ClampedArrayTag); 526 else if (obj->inherits(&JSInt8Array::s_info)) 527 write(Int8ArrayTag); 528 else if (obj->inherits(&JSUint8Array::s_info)) 529 write(Uint8ArrayTag); 530 else if (obj->inherits(&JSInt16Array::s_info)) 531 write(Int16ArrayTag); 532 else if (obj->inherits(&JSUint16Array::s_info)) 533 write(Uint16ArrayTag); 534 else if (obj->inherits(&JSInt32Array::s_info)) 535 write(Int32ArrayTag); 536 else if (obj->inherits(&JSUint32Array::s_info)) 537 write(Uint32ArrayTag); 538 else if (obj->inherits(&JSFloat32Array::s_info)) 539 write(Float32ArrayTag); 540 else if (obj->inherits(&JSFloat64Array::s_info)) 541 write(Float64ArrayTag); 542 else 543 return false; 544 545 RefPtr<ArrayBufferView> arrayBufferView = toArrayBufferView(obj); 546 write(static_cast<uint32_t>(arrayBufferView->byteOffset())); 547 write(static_cast<uint32_t>(arrayBufferView->byteLength())); 548 RefPtr<ArrayBuffer> arrayBuffer = arrayBufferView->buffer(); 549 if (!arrayBuffer) { 550 code = ValidationError; 551 return true; 552 } 553 JSValue bufferObj = toJS(m_exec, jsCast<JSDOMGlobalObject*>(m_exec->lexicalGlobalObject()), arrayBuffer.get()); 554 return dumpIfTerminal(bufferObj, code); 555 } 556 557 bool dumpIfTerminal(JSValue value, SerializationReturnCode& code) 558 { 559 if (!value.isCell()) { 560 dumpImmediate(value); 561 return true; 562 } 563 564 if (value.isString()) { 565 String str = asString(value)->value(m_exec); 566 dumpString(str); 567 return true; 568 } 569 570 if (value.isNumber()) { 571 write(DoubleTag); 572 write(value.asNumber()); 573 return true; 574 } 575 576 if (value.isObject() && asObject(value)->inherits(&DateInstance::s_info)) { 577 write(DateTag); 578 write(asDateInstance(value)->internalNumber()); 579 return true; 580 } 581 582 if (isArray(value)) 583 return false; 584 585 if (value.isObject()) { 586 JSObject* obj = asObject(value); 587 if (obj->inherits(&BooleanObject::s_info)) { 588 if (!startObjectInternal(obj)) // handle duplicates 589 return true; 590 write(asBooleanObject(value)->internalValue().toBoolean(m_exec) ? TrueObjectTag : FalseObjectTag); 591 return true; 592 } 593 if (obj->inherits(&StringObject::s_info)) { 594 if (!startObjectInternal(obj)) // handle duplicates 595 return true; 596 String str = asString(asStringObject(value)->internalValue())->value(m_exec); 597 dumpStringObject(str); 598 return true; 599 } 600 if (obj->inherits(&NumberObject::s_info)) { 601 if (!startObjectInternal(obj)) // handle duplicates 602 return true; 603 write(NumberObjectTag); 604 NumberObject* obj = static_cast<NumberObject*>(asObject(value)); 605 write(obj->internalValue().asNumber()); 606 return true; 607 } 608 if (obj->inherits(&JSFile::s_info)) { 609 write(FileTag); 610 write(toFile(obj)); 611 return true; 612 } 613 if (obj->inherits(&JSFileList::s_info)) { 614 FileList* list = toFileList(obj); 615 write(FileListTag); 616 unsigned length = list->length(); 617 write(length); 618 for (unsigned i = 0; i < length; i++) 619 write(list->item(i)); 620 return true; 621 } 622 if (obj->inherits(&JSBlob::s_info)) { 623 write(BlobTag); 624 Blob* blob = toBlob(obj); 625 m_blobURLs.append(blob->url()); 626 write(blob->url()); 627 write(blob->type()); 628 write(blob->size()); 629 return true; 630 } 631 if (obj->inherits(&JSImageData::s_info)) { 632 ImageData* data = toImageData(obj); 633 write(ImageDataTag); 634 write(data->width()); 635 write(data->height()); 636 write(data->data()->length()); 637 write(data->data()->data(), data->data()->length()); 638 return true; 639 } 640 if (obj->inherits(&RegExpObject::s_info)) { 641 RegExpObject* regExp = asRegExpObject(obj); 642 char flags[3]; 643 int flagCount = 0; 644 if (regExp->regExp()->global()) 645 flags[flagCount++] = 'g'; 646 if (regExp->regExp()->ignoreCase()) 647 flags[flagCount++] = 'i'; 648 if (regExp->regExp()->multiline()) 649 flags[flagCount++] = 'm'; 650 write(RegExpTag); 651 write(regExp->regExp()->pattern()); 652 write(String(flags, flagCount)); 653 return true; 654 } 655 if (obj->inherits(&JSMessagePort::s_info)) { 656 ObjectPool::iterator index = m_transferredMessagePorts.find(obj); 657 if (index != m_transferredMessagePorts.end()) { 658 write(MessagePortReferenceTag); 659 write(index->value); 660 return true; 661 } 662 // MessagePort object could not be found in transferred message ports 663 code = ValidationError; 664 return true; 665 } 666 if (obj->inherits(&JSArrayBuffer::s_info)) { 667 RefPtr<ArrayBuffer> arrayBuffer = toArrayBuffer(obj); 668 if (arrayBuffer->isNeutered()) { 669 code = ValidationError; 670 return true; 671 } 672 ObjectPool::iterator index = m_transferredArrayBuffers.find(obj); 673 if (index != m_transferredArrayBuffers.end()) { 674 write(ArrayBufferTransferTag); 675 write(index->value); 676 return true; 677 } 678 if (!startObjectInternal(obj)) // handle duplicates 679 return true; 680 write(ArrayBufferTag); 681 write(arrayBuffer->byteLength()); 682 write(static_cast<const uint8_t *>(arrayBuffer->data()), arrayBuffer->byteLength()); 683 return true; 684 } 685 if (obj->inherits(&JSArrayBufferView::s_info)) { 686 if (checkForDuplicate(obj)) 687 return true; 688 bool success = dumpArrayBufferView(obj, code); 689 recordObject(obj); 690 return success; 691 } 692 693 return false; 694 } 695 // Any other types are expected to serialize as null. 696 write(NullTag); 697 return true; 698 } 699 700 void write(SerializationTag tag) 701 { 702 writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag)); 703 } 704 705 void write(ArrayBufferViewSubtag tag) 706 { 707 writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag)); 708 } 709 710 void write(uint8_t c) 711 { 712 writeLittleEndian(m_buffer, c); 713 } 714 715 void write(uint32_t i) 716 { 717 writeLittleEndian(m_buffer, i); 718 } 719 720 void write(double d) 721 { 722 union { 723 double d; 724 int64_t i; 725 } u; 726 u.d = d; 727 writeLittleEndian(m_buffer, u.i); 728 } 729 730 void write(int32_t i) 731 { 732 writeLittleEndian(m_buffer, i); 733 } 734 735 void write(unsigned long long i) 736 { 737 writeLittleEndian(m_buffer, i); 738 } 739 740 void write(uint16_t ch) 741 { 742 writeLittleEndian(m_buffer, ch); 743 } 744 745 void writeStringIndex(unsigned i) 746 { 747 writeConstantPoolIndex(m_constantPool, i); 748 } 749 750 void writeObjectIndex(unsigned i) 751 { 752 writeConstantPoolIndex(m_objectPool, i); 753 } 754 755 template <class T> void writeConstantPoolIndex(const T& constantPool, unsigned i) 756 { 757 ASSERT(static_cast<int32_t>(i) < constantPool.size()); 758 if (constantPool.size() <= 0xFF) 759 write(static_cast<uint8_t>(i)); 760 else if (constantPool.size() <= 0xFFFF) 761 write(static_cast<uint16_t>(i)); 762 else 763 write(static_cast<uint32_t>(i)); 764 } 765 766 void write(const Identifier& ident) 767 { 768 const String& str = ident.string(); 769 StringConstantPool::AddResult addResult = m_constantPool.add(str.impl(), m_constantPool.size()); 770 if (!addResult.isNewEntry) { 771 write(StringPoolTag); 772 writeStringIndex(addResult.iterator->value); 773 return; 774 } 775 776 // This condition is unlikely to happen as they would imply an ~8gb 777 // string but we should guard against it anyway 778 if (str.length() >= StringPoolTag) { 779 fail(); 780 return; 781 } 782 783 // Guard against overflow 784 if (str.length() > (numeric_limits<uint32_t>::max() - sizeof(uint32_t)) / sizeof(UChar)) { 785 fail(); 786 return; 787 } 788 789 writeLittleEndian<uint32_t>(m_buffer, str.length()); 790 if (!writeLittleEndian<uint16_t>(m_buffer, reinterpret_cast<const uint16_t*>(str.characters()), str.length())) 791 fail(); 792 } 793 794 void write(const String& str) 795 { 796 if (str.isNull()) 797 write(m_emptyIdentifier); 798 else 799 write(Identifier(m_exec, str)); 800 } 801 802 void write(const File* file) 803 { 804 m_blobURLs.append(file->url()); 805 write(file->path()); 806 write(file->url()); 807 write(file->type()); 808 } 809 810 void write(const uint8_t* data, unsigned length) 811 { 812 m_buffer.append(data, length); 813 } 814 815 Vector<uint8_t>& m_buffer; 816 Vector<String>& m_blobURLs; 817 ObjectPool m_objectPool; 818 ObjectPool m_transferredMessagePorts; 819 ObjectPool m_transferredArrayBuffers; 820 typedef HashMap<RefPtr<StringImpl>, uint32_t, IdentifierRepHash> StringConstantPool; 821 StringConstantPool m_constantPool; 822 Identifier m_emptyIdentifier; 823}; 824 825SerializationReturnCode CloneSerializer::serialize(JSValue in) 826{ 827 Vector<uint32_t, 16> indexStack; 828 Vector<uint32_t, 16> lengthStack; 829 Vector<PropertyNameArray, 16> propertyStack; 830 Vector<JSObject*, 32> inputObjectStack; 831 Vector<WalkerState, 16> stateStack; 832 WalkerState state = StateUnknown; 833 JSValue inValue = in; 834 while (1) { 835 switch (state) { 836 arrayStartState: 837 case ArrayStartState: { 838 ASSERT(isArray(inValue)); 839 if (inputObjectStack.size() > maximumFilterRecursion) 840 return StackOverflowError; 841 842 JSArray* inArray = asArray(inValue); 843 unsigned length = inArray->length(); 844 if (!startArray(inArray)) 845 break; 846 inputObjectStack.append(inArray); 847 indexStack.append(0); 848 lengthStack.append(length); 849 // fallthrough 850 } 851 arrayStartVisitMember: 852 case ArrayStartVisitMember: { 853 JSObject* array = inputObjectStack.last(); 854 uint32_t index = indexStack.last(); 855 if (index == lengthStack.last()) { 856 indexStack.removeLast(); 857 lengthStack.removeLast(); 858 859 propertyStack.append(PropertyNameArray(m_exec)); 860 array->methodTable()->getOwnNonIndexPropertyNames(array, m_exec, propertyStack.last(), ExcludeDontEnumProperties); 861 if (propertyStack.last().size()) { 862 write(NonIndexPropertiesTag); 863 indexStack.append(0); 864 goto objectStartVisitMember; 865 } 866 propertyStack.removeLast(); 867 868 endObject(); 869 inputObjectStack.removeLast(); 870 break; 871 } 872 inValue = array->getDirectIndex(m_exec, index); 873 if (!inValue) { 874 indexStack.last()++; 875 goto arrayStartVisitMember; 876 } 877 878 write(index); 879 SerializationReturnCode terminalCode = SuccessfullyCompleted; 880 if (dumpIfTerminal(inValue, terminalCode)) { 881 if (terminalCode != SuccessfullyCompleted) 882 return terminalCode; 883 indexStack.last()++; 884 goto arrayStartVisitMember; 885 } 886 stateStack.append(ArrayEndVisitMember); 887 goto stateUnknown; 888 } 889 case ArrayEndVisitMember: { 890 indexStack.last()++; 891 goto arrayStartVisitMember; 892 } 893 objectStartState: 894 case ObjectStartState: { 895 ASSERT(inValue.isObject()); 896 if (inputObjectStack.size() > maximumFilterRecursion) 897 return StackOverflowError; 898 JSObject* inObject = asObject(inValue); 899 if (!startObject(inObject)) 900 break; 901 // At this point, all supported objects other than Object 902 // objects have been handled. If we reach this point and 903 // the input is not an Object object then we should throw 904 // a DataCloneError. 905 if (inObject->classInfo() != &JSFinalObject::s_info) 906 return DataCloneError; 907 inputObjectStack.append(inObject); 908 indexStack.append(0); 909 propertyStack.append(PropertyNameArray(m_exec)); 910 inObject->methodTable()->getOwnPropertyNames(inObject, m_exec, propertyStack.last(), ExcludeDontEnumProperties); 911 // fallthrough 912 } 913 objectStartVisitMember: 914 case ObjectStartVisitMember: { 915 JSObject* object = inputObjectStack.last(); 916 uint32_t index = indexStack.last(); 917 PropertyNameArray& properties = propertyStack.last(); 918 if (index == properties.size()) { 919 endObject(); 920 inputObjectStack.removeLast(); 921 indexStack.removeLast(); 922 propertyStack.removeLast(); 923 break; 924 } 925 inValue = getProperty(object, properties[index]); 926 if (shouldTerminate()) 927 return ExistingExceptionError; 928 929 if (!inValue) { 930 // Property was removed during serialisation 931 indexStack.last()++; 932 goto objectStartVisitMember; 933 } 934 write(properties[index]); 935 936 if (shouldTerminate()) 937 return ExistingExceptionError; 938 939 SerializationReturnCode terminalCode = SuccessfullyCompleted; 940 if (!dumpIfTerminal(inValue, terminalCode)) { 941 stateStack.append(ObjectEndVisitMember); 942 goto stateUnknown; 943 } 944 if (terminalCode != SuccessfullyCompleted) 945 return terminalCode; 946 // fallthrough 947 } 948 case ObjectEndVisitMember: { 949 if (shouldTerminate()) 950 return ExistingExceptionError; 951 952 indexStack.last()++; 953 goto objectStartVisitMember; 954 } 955 stateUnknown: 956 case StateUnknown: { 957 SerializationReturnCode terminalCode = SuccessfullyCompleted; 958 if (dumpIfTerminal(inValue, terminalCode)) { 959 if (terminalCode != SuccessfullyCompleted) 960 return terminalCode; 961 break; 962 } 963 964 if (isArray(inValue)) 965 goto arrayStartState; 966 goto objectStartState; 967 } 968 } 969 if (stateStack.isEmpty()) 970 break; 971 972 state = stateStack.last(); 973 stateStack.removeLast(); 974 } 975 if (m_failed) 976 return UnspecifiedError; 977 978 return SuccessfullyCompleted; 979} 980 981typedef Vector<WTF::ArrayBufferContents> ArrayBufferContentsArray; 982 983class CloneDeserializer : CloneBase { 984public: 985 static String deserializeString(const Vector<uint8_t>& buffer) 986 { 987 if (buffer.isEmpty()) 988 return String(); 989 const uint8_t* ptr = buffer.begin(); 990 const uint8_t* end = buffer.end(); 991 uint32_t version; 992 if (!readLittleEndian(ptr, end, version) || version > CurrentVersion) 993 return String(); 994 uint8_t tag; 995 if (!readLittleEndian(ptr, end, tag) || tag != StringTag) 996 return String(); 997 uint32_t length; 998 if (!readLittleEndian(ptr, end, length) || length >= StringPoolTag) 999 return String(); 1000 String str; 1001 if (!readString(ptr, end, str, length)) 1002 return String(); 1003 return String(str.impl()); 1004 } 1005 1006 static DeserializationResult deserialize(ExecState* exec, JSGlobalObject* globalObject, 1007 MessagePortArray* messagePorts, ArrayBufferContentsArray* arrayBufferContentsArray, 1008 const Vector<uint8_t>& buffer) 1009 { 1010 if (!buffer.size()) 1011 return make_pair(jsNull(), UnspecifiedError); 1012 CloneDeserializer deserializer(exec, globalObject, messagePorts, arrayBufferContentsArray, buffer); 1013 if (!deserializer.isValid()) 1014 return make_pair(JSValue(), ValidationError); 1015 return deserializer.deserialize(); 1016 } 1017 1018private: 1019 struct CachedString { 1020 CachedString(const String& string) 1021 : m_string(string) 1022 { 1023 } 1024 1025 JSValue jsString(ExecState* exec) 1026 { 1027 if (!m_jsString) 1028 m_jsString = JSC::jsString(exec, m_string); 1029 return m_jsString; 1030 } 1031 const String& string() { return m_string; } 1032 1033 private: 1034 String m_string; 1035 JSValue m_jsString; 1036 }; 1037 1038 struct CachedStringRef { 1039 CachedStringRef() 1040 : m_base(0) 1041 , m_index(0) 1042 { 1043 } 1044 CachedStringRef(Vector<CachedString>* base, size_t index) 1045 : m_base(base) 1046 , m_index(index) 1047 { 1048 } 1049 1050 CachedString* operator->() { ASSERT(m_base); return &m_base->at(m_index); } 1051 1052 private: 1053 Vector<CachedString>* m_base; 1054 size_t m_index; 1055 }; 1056 1057 CloneDeserializer(ExecState* exec, JSGlobalObject* globalObject, 1058 MessagePortArray* messagePorts, ArrayBufferContentsArray* arrayBufferContents, 1059 const Vector<uint8_t>& buffer) 1060 : CloneBase(exec) 1061 , m_globalObject(globalObject) 1062 , m_isDOMGlobalObject(globalObject->inherits(&JSDOMGlobalObject::s_info)) 1063 , m_ptr(buffer.data()) 1064 , m_end(buffer.data() + buffer.size()) 1065 , m_version(0xFFFFFFFF) 1066 , m_messagePorts(messagePorts) 1067 , m_arrayBufferContents(arrayBufferContents) 1068 , m_arrayBuffers(arrayBufferContents ? arrayBufferContents->size() : 0) 1069 { 1070 if (!read(m_version)) 1071 m_version = 0xFFFFFFFF; 1072 } 1073 1074 DeserializationResult deserialize(); 1075 1076 void throwValidationError() 1077 { 1078 throwError(m_exec, createTypeError(m_exec, "Unable to deserialize data.")); 1079 } 1080 1081 bool isValid() const { return m_version <= CurrentVersion; } 1082 1083 template <typename T> bool readLittleEndian(T& value) 1084 { 1085 if (m_failed || !readLittleEndian(m_ptr, m_end, value)) { 1086 fail(); 1087 return false; 1088 } 1089 return true; 1090 } 1091#if ASSUME_LITTLE_ENDIAN 1092 template <typename T> static bool readLittleEndian(const uint8_t*& ptr, const uint8_t* end, T& value) 1093 { 1094 if (ptr > end - sizeof(value)) 1095 return false; 1096 1097 if (sizeof(T) == 1) 1098 value = *ptr++; 1099 else { 1100 value = *reinterpret_cast<const T*>(ptr); 1101 ptr += sizeof(T); 1102 } 1103 return true; 1104 } 1105#else 1106 template <typename T> static bool readLittleEndian(const uint8_t*& ptr, const uint8_t* end, T& value) 1107 { 1108 if (ptr > end - sizeof(value)) 1109 return false; 1110 1111 if (sizeof(T) == 1) 1112 value = *ptr++; 1113 else { 1114 value = 0; 1115 for (unsigned i = 0; i < sizeof(T); i++) 1116 value += ((T)*ptr++) << (i * 8); 1117 } 1118 return true; 1119 } 1120#endif 1121 1122 bool read(uint32_t& i) 1123 { 1124 return readLittleEndian(i); 1125 } 1126 1127 bool read(int32_t& i) 1128 { 1129 return readLittleEndian(*reinterpret_cast<uint32_t*>(&i)); 1130 } 1131 1132 bool read(uint16_t& i) 1133 { 1134 return readLittleEndian(i); 1135 } 1136 1137 bool read(uint8_t& i) 1138 { 1139 return readLittleEndian(i); 1140 } 1141 1142 bool read(double& d) 1143 { 1144 union { 1145 double d; 1146 uint64_t i64; 1147 } u; 1148 if (!readLittleEndian(u.i64)) 1149 return false; 1150 d = u.d; 1151 return true; 1152 } 1153 1154 bool read(unsigned long long& i) 1155 { 1156 return readLittleEndian(i); 1157 } 1158 1159 bool readStringIndex(uint32_t& i) 1160 { 1161 return readConstantPoolIndex(m_constantPool, i); 1162 } 1163 1164 template <class T> bool readConstantPoolIndex(const T& constantPool, uint32_t& i) 1165 { 1166 if (constantPool.size() <= 0xFF) { 1167 uint8_t i8; 1168 if (!read(i8)) 1169 return false; 1170 i = i8; 1171 return true; 1172 } 1173 if (constantPool.size() <= 0xFFFF) { 1174 uint16_t i16; 1175 if (!read(i16)) 1176 return false; 1177 i = i16; 1178 return true; 1179 } 1180 return read(i); 1181 } 1182 1183 static bool readString(const uint8_t*& ptr, const uint8_t* end, String& str, unsigned length) 1184 { 1185 if (length >= numeric_limits<int32_t>::max() / sizeof(UChar)) 1186 return false; 1187 1188 unsigned size = length * sizeof(UChar); 1189 if ((end - ptr) < static_cast<int>(size)) 1190 return false; 1191 1192#if ASSUME_LITTLE_ENDIAN 1193 str = String(reinterpret_cast<const UChar*>(ptr), length); 1194 ptr += length * sizeof(UChar); 1195#else 1196 Vector<UChar> buffer; 1197 buffer.reserveCapacity(length); 1198 for (unsigned i = 0; i < length; i++) { 1199 uint16_t ch; 1200 readLittleEndian(ptr, end, ch); 1201 buffer.append(ch); 1202 } 1203 str = String::adopt(buffer); 1204#endif 1205 return true; 1206 } 1207 1208 bool readStringData(CachedStringRef& cachedString) 1209 { 1210 bool scratch; 1211 return readStringData(cachedString, scratch); 1212 } 1213 1214 bool readStringData(CachedStringRef& cachedString, bool& wasTerminator) 1215 { 1216 if (m_failed) 1217 return false; 1218 uint32_t length = 0; 1219 if (!read(length)) 1220 return false; 1221 if (length == TerminatorTag) { 1222 wasTerminator = true; 1223 return false; 1224 } 1225 if (length == StringPoolTag) { 1226 unsigned index = 0; 1227 if (!readStringIndex(index)) { 1228 fail(); 1229 return false; 1230 } 1231 if (index >= m_constantPool.size()) { 1232 fail(); 1233 return false; 1234 } 1235 cachedString = CachedStringRef(&m_constantPool, index); 1236 return true; 1237 } 1238 String str; 1239 if (!readString(m_ptr, m_end, str, length)) { 1240 fail(); 1241 return false; 1242 } 1243 m_constantPool.append(str); 1244 cachedString = CachedStringRef(&m_constantPool, m_constantPool.size() - 1); 1245 return true; 1246 } 1247 1248 SerializationTag readTag() 1249 { 1250 if (m_ptr >= m_end) 1251 return ErrorTag; 1252 return static_cast<SerializationTag>(*m_ptr++); 1253 } 1254 1255 bool readArrayBufferViewSubtag(ArrayBufferViewSubtag& tag) 1256 { 1257 if (m_ptr >= m_end) 1258 return false; 1259 tag = static_cast<ArrayBufferViewSubtag>(*m_ptr++); 1260 return true; 1261 } 1262 1263 void putProperty(JSObject* object, unsigned index, JSValue value) 1264 { 1265 object->putDirectIndex(m_exec, index, value); 1266 } 1267 1268 void putProperty(JSObject* object, const Identifier& property, JSValue value) 1269 { 1270 object->putDirectMayBeIndex(m_exec, property, value); 1271 } 1272 1273 bool readFile(RefPtr<File>& file) 1274 { 1275 CachedStringRef path; 1276 if (!readStringData(path)) 1277 return 0; 1278 CachedStringRef url; 1279 if (!readStringData(url)) 1280 return 0; 1281 CachedStringRef type; 1282 if (!readStringData(type)) 1283 return 0; 1284 if (m_isDOMGlobalObject) 1285 file = File::create(path->string(), KURL(KURL(), url->string()), type->string()); 1286 return true; 1287 } 1288 1289 bool readArrayBuffer(RefPtr<ArrayBuffer>& arrayBuffer) 1290 { 1291 uint32_t length; 1292 if (!read(length)) 1293 return false; 1294 if (m_ptr + length > m_end) 1295 return false; 1296 arrayBuffer = ArrayBuffer::create(m_ptr, length); 1297 m_ptr += length; 1298 return true; 1299 } 1300 1301 bool readArrayBufferView(JSValue& arrayBufferView) 1302 { 1303 ArrayBufferViewSubtag arrayBufferViewSubtag; 1304 if (!readArrayBufferViewSubtag(arrayBufferViewSubtag)) 1305 return false; 1306 uint32_t byteOffset; 1307 if (!read(byteOffset)) 1308 return false; 1309 uint32_t byteLength; 1310 if (!read(byteLength)) 1311 return false; 1312 JSObject* arrayBufferObj = asObject(readTerminal()); 1313 if (!arrayBufferObj || !arrayBufferObj->inherits(&JSArrayBuffer::s_info)) 1314 return false; 1315 1316 unsigned elementSize = typedArrayElementSize(arrayBufferViewSubtag); 1317 if (!elementSize) 1318 return false; 1319 unsigned length = byteLength / elementSize; 1320 if (length * elementSize != byteLength) 1321 return false; 1322 1323 RefPtr<ArrayBuffer> arrayBuffer = toArrayBuffer(arrayBufferObj); 1324 switch (arrayBufferViewSubtag) { 1325 case DataViewTag: 1326 arrayBufferView = getJSValue(DataView::create(arrayBuffer, byteOffset, length).get()); 1327 return true; 1328 case Int8ArrayTag: 1329 arrayBufferView = getJSValue(Int8Array::create(arrayBuffer, byteOffset, length).get()); 1330 return true; 1331 case Uint8ArrayTag: 1332 arrayBufferView = getJSValue(Uint8Array::create(arrayBuffer, byteOffset, length).get()); 1333 return true; 1334 case Uint8ClampedArrayTag: 1335 arrayBufferView = getJSValue(Uint8ClampedArray::create(arrayBuffer, byteOffset, length).get()); 1336 return true; 1337 case Int16ArrayTag: 1338 arrayBufferView = getJSValue(Int16Array::create(arrayBuffer, byteOffset, length).get()); 1339 return true; 1340 case Uint16ArrayTag: 1341 arrayBufferView = getJSValue(Uint16Array::create(arrayBuffer, byteOffset, length).get()); 1342 return true; 1343 case Int32ArrayTag: 1344 arrayBufferView = getJSValue(Int32Array::create(arrayBuffer, byteOffset, length).get()); 1345 return true; 1346 case Uint32ArrayTag: 1347 arrayBufferView = getJSValue(Uint32Array::create(arrayBuffer, byteOffset, length).get()); 1348 return true; 1349 case Float32ArrayTag: 1350 arrayBufferView = getJSValue(Float32Array::create(arrayBuffer, byteOffset, length).get()); 1351 return true; 1352 case Float64ArrayTag: 1353 arrayBufferView = getJSValue(Float64Array::create(arrayBuffer, byteOffset, length).get()); 1354 return true; 1355 default: 1356 return false; 1357 } 1358 } 1359 1360 template<class T> 1361 JSValue getJSValue(T* nativeObj) 1362 { 1363 return toJS(m_exec, jsCast<JSDOMGlobalObject*>(m_globalObject), nativeObj); 1364 } 1365 1366 JSValue readTerminal() 1367 { 1368 SerializationTag tag = readTag(); 1369 switch (tag) { 1370 case UndefinedTag: 1371 return jsUndefined(); 1372 case NullTag: 1373 return jsNull(); 1374 case IntTag: { 1375 int32_t i; 1376 if (!read(i)) 1377 return JSValue(); 1378 return jsNumber(i); 1379 } 1380 case ZeroTag: 1381 return jsNumber(0); 1382 case OneTag: 1383 return jsNumber(1); 1384 case FalseTag: 1385 return jsBoolean(false); 1386 case TrueTag: 1387 return jsBoolean(true); 1388 case FalseObjectTag: { 1389 BooleanObject* obj = BooleanObject::create(m_exec->vm(), m_globalObject->booleanObjectStructure()); 1390 obj->setInternalValue(m_exec->vm(), jsBoolean(false)); 1391 m_gcBuffer.append(obj); 1392 return obj; 1393 } 1394 case TrueObjectTag: { 1395 BooleanObject* obj = BooleanObject::create(m_exec->vm(), m_globalObject->booleanObjectStructure()); 1396 obj->setInternalValue(m_exec->vm(), jsBoolean(true)); 1397 m_gcBuffer.append(obj); 1398 return obj; 1399 } 1400 case DoubleTag: { 1401 double d; 1402 if (!read(d)) 1403 return JSValue(); 1404 return jsNumber(d); 1405 } 1406 case NumberObjectTag: { 1407 double d; 1408 if (!read(d)) 1409 return JSValue(); 1410 NumberObject* obj = constructNumber(m_exec, m_globalObject, jsNumber(d)); 1411 m_gcBuffer.append(obj); 1412 return obj; 1413 } 1414 case DateTag: { 1415 double d; 1416 if (!read(d)) 1417 return JSValue(); 1418 return DateInstance::create(m_exec, m_globalObject->dateStructure(), d); 1419 } 1420 case FileTag: { 1421 RefPtr<File> file; 1422 if (!readFile(file)) 1423 return JSValue(); 1424 if (!m_isDOMGlobalObject) 1425 return jsNull(); 1426 return toJS(m_exec, jsCast<JSDOMGlobalObject*>(m_globalObject), file.get()); 1427 } 1428 case FileListTag: { 1429 unsigned length = 0; 1430 if (!read(length)) 1431 return JSValue(); 1432 RefPtr<FileList> result = FileList::create(); 1433 for (unsigned i = 0; i < length; i++) { 1434 RefPtr<File> file; 1435 if (!readFile(file)) 1436 return JSValue(); 1437 if (m_isDOMGlobalObject) 1438 result->append(file.get()); 1439 } 1440 if (!m_isDOMGlobalObject) 1441 return jsNull(); 1442 return getJSValue(result.get()); 1443 } 1444 case ImageDataTag: { 1445 int32_t width; 1446 if (!read(width)) 1447 return JSValue(); 1448 int32_t height; 1449 if (!read(height)) 1450 return JSValue(); 1451 uint32_t length; 1452 if (!read(length)) 1453 return JSValue(); 1454 if (m_end < ((uint8_t*)0) + length || m_ptr > m_end - length) { 1455 fail(); 1456 return JSValue(); 1457 } 1458 if (!m_isDOMGlobalObject) { 1459 m_ptr += length; 1460 return jsNull(); 1461 } 1462 RefPtr<ImageData> result = ImageData::create(IntSize(width, height)); 1463 memcpy(result->data()->data(), m_ptr, length); 1464 m_ptr += length; 1465 return getJSValue(result.get()); 1466 } 1467 case BlobTag: { 1468 CachedStringRef url; 1469 if (!readStringData(url)) 1470 return JSValue(); 1471 CachedStringRef type; 1472 if (!readStringData(type)) 1473 return JSValue(); 1474 unsigned long long size = 0; 1475 if (!read(size)) 1476 return JSValue(); 1477 if (!m_isDOMGlobalObject) 1478 return jsNull(); 1479 return getJSValue(Blob::create(KURL(KURL(), url->string()), type->string(), size).get()); 1480 } 1481 case StringTag: { 1482 CachedStringRef cachedString; 1483 if (!readStringData(cachedString)) 1484 return JSValue(); 1485 return cachedString->jsString(m_exec); 1486 } 1487 case EmptyStringTag: 1488 return jsEmptyString(&m_exec->vm()); 1489 case StringObjectTag: { 1490 CachedStringRef cachedString; 1491 if (!readStringData(cachedString)) 1492 return JSValue(); 1493 StringObject* obj = constructString(m_exec, m_globalObject, cachedString->jsString(m_exec)); 1494 m_gcBuffer.append(obj); 1495 return obj; 1496 } 1497 case EmptyStringObjectTag: { 1498 StringObject* obj = constructString(m_exec, m_globalObject, jsEmptyString(&m_exec->vm())); 1499 m_gcBuffer.append(obj); 1500 return obj; 1501 } 1502 case RegExpTag: { 1503 CachedStringRef pattern; 1504 if (!readStringData(pattern)) 1505 return JSValue(); 1506 CachedStringRef flags; 1507 if (!readStringData(flags)) 1508 return JSValue(); 1509 RegExpFlags reFlags = regExpFlags(flags->string()); 1510 ASSERT(reFlags != InvalidFlags); 1511 RegExp* regExp = RegExp::create(m_exec->vm(), pattern->string(), reFlags); 1512 return RegExpObject::create(m_exec, m_exec->lexicalGlobalObject(), m_globalObject->regExpStructure(), regExp); 1513 } 1514 case ObjectReferenceTag: { 1515 unsigned index = 0; 1516 if (!readConstantPoolIndex(m_gcBuffer, index)) { 1517 fail(); 1518 return JSValue(); 1519 } 1520 return m_gcBuffer.at(index); 1521 } 1522 case MessagePortReferenceTag: { 1523 uint32_t index; 1524 bool indexSuccessfullyRead = read(index); 1525 if (!indexSuccessfullyRead || !m_messagePorts || index >= m_messagePorts->size()) { 1526 fail(); 1527 return JSValue(); 1528 } 1529 return getJSValue(m_messagePorts->at(index).get()); 1530 } 1531 case ArrayBufferTag: { 1532 RefPtr<ArrayBuffer> arrayBuffer; 1533 if (!readArrayBuffer(arrayBuffer)) { 1534 fail(); 1535 return JSValue(); 1536 } 1537 JSValue result = getJSValue(arrayBuffer.get()); 1538 m_gcBuffer.append(result); 1539 return result; 1540 } 1541 case ArrayBufferTransferTag: { 1542 uint32_t index; 1543 bool indexSuccessfullyRead = read(index); 1544 if (!indexSuccessfullyRead || index >= m_arrayBuffers.size()) { 1545 fail(); 1546 return JSValue(); 1547 } 1548 1549 if (!m_arrayBuffers[index]) 1550 m_arrayBuffers[index] = ArrayBuffer::create(m_arrayBufferContents->at(index)); 1551 1552 return getJSValue(m_arrayBuffers[index].get()); 1553 } 1554 case ArrayBufferViewTag: { 1555 JSValue arrayBufferView; 1556 if (!readArrayBufferView(arrayBufferView)) { 1557 fail(); 1558 return JSValue(); 1559 } 1560 m_gcBuffer.append(arrayBufferView); 1561 return arrayBufferView; 1562 } 1563 default: 1564 m_ptr--; // Push the tag back 1565 return JSValue(); 1566 } 1567 } 1568 1569 JSGlobalObject* m_globalObject; 1570 bool m_isDOMGlobalObject; 1571 const uint8_t* m_ptr; 1572 const uint8_t* m_end; 1573 unsigned m_version; 1574 Vector<CachedString> m_constantPool; 1575 MessagePortArray* m_messagePorts; 1576 ArrayBufferContentsArray* m_arrayBufferContents; 1577 ArrayBufferArray m_arrayBuffers; 1578}; 1579 1580DeserializationResult CloneDeserializer::deserialize() 1581{ 1582 Vector<uint32_t, 16> indexStack; 1583 Vector<Identifier, 16> propertyNameStack; 1584 Vector<JSObject*, 32> outputObjectStack; 1585 Vector<WalkerState, 16> stateStack; 1586 WalkerState state = StateUnknown; 1587 JSValue outValue; 1588 1589 while (1) { 1590 switch (state) { 1591 arrayStartState: 1592 case ArrayStartState: { 1593 uint32_t length; 1594 if (!read(length)) { 1595 fail(); 1596 goto error; 1597 } 1598 JSArray* outArray = constructEmptyArray(m_exec, 0, m_globalObject, length); 1599 m_gcBuffer.append(outArray); 1600 outputObjectStack.append(outArray); 1601 // fallthrough 1602 } 1603 arrayStartVisitMember: 1604 case ArrayStartVisitMember: { 1605 uint32_t index; 1606 if (!read(index)) { 1607 fail(); 1608 goto error; 1609 } 1610 if (index == TerminatorTag) { 1611 JSObject* outArray = outputObjectStack.last(); 1612 outValue = outArray; 1613 outputObjectStack.removeLast(); 1614 break; 1615 } else if (index == NonIndexPropertiesTag) { 1616 goto objectStartVisitMember; 1617 } 1618 1619 if (JSValue terminal = readTerminal()) { 1620 putProperty(outputObjectStack.last(), index, terminal); 1621 goto arrayStartVisitMember; 1622 } 1623 if (m_failed) 1624 goto error; 1625 indexStack.append(index); 1626 stateStack.append(ArrayEndVisitMember); 1627 goto stateUnknown; 1628 } 1629 case ArrayEndVisitMember: { 1630 JSObject* outArray = outputObjectStack.last(); 1631 putProperty(outArray, indexStack.last(), outValue); 1632 indexStack.removeLast(); 1633 goto arrayStartVisitMember; 1634 } 1635 objectStartState: 1636 case ObjectStartState: { 1637 if (outputObjectStack.size() > maximumFilterRecursion) 1638 return make_pair(JSValue(), StackOverflowError); 1639 JSObject* outObject = constructEmptyObject(m_exec, m_globalObject->objectPrototype()); 1640 m_gcBuffer.append(outObject); 1641 outputObjectStack.append(outObject); 1642 // fallthrough 1643 } 1644 objectStartVisitMember: 1645 case ObjectStartVisitMember: { 1646 CachedStringRef cachedString; 1647 bool wasTerminator = false; 1648 if (!readStringData(cachedString, wasTerminator)) { 1649 if (!wasTerminator) 1650 goto error; 1651 1652 JSObject* outObject = outputObjectStack.last(); 1653 outValue = outObject; 1654 outputObjectStack.removeLast(); 1655 break; 1656 } 1657 1658 if (JSValue terminal = readTerminal()) { 1659 putProperty(outputObjectStack.last(), Identifier(m_exec, cachedString->string()), terminal); 1660 goto objectStartVisitMember; 1661 } 1662 stateStack.append(ObjectEndVisitMember); 1663 propertyNameStack.append(Identifier(m_exec, cachedString->string())); 1664 goto stateUnknown; 1665 } 1666 case ObjectEndVisitMember: { 1667 putProperty(outputObjectStack.last(), propertyNameStack.last(), outValue); 1668 propertyNameStack.removeLast(); 1669 goto objectStartVisitMember; 1670 } 1671 stateUnknown: 1672 case StateUnknown: 1673 if (JSValue terminal = readTerminal()) { 1674 outValue = terminal; 1675 break; 1676 } 1677 SerializationTag tag = readTag(); 1678 if (tag == ArrayTag) 1679 goto arrayStartState; 1680 if (tag == ObjectTag) 1681 goto objectStartState; 1682 goto error; 1683 } 1684 if (stateStack.isEmpty()) 1685 break; 1686 1687 state = stateStack.last(); 1688 stateStack.removeLast(); 1689 } 1690 ASSERT(outValue); 1691 ASSERT(!m_failed); 1692 return make_pair(outValue, SuccessfullyCompleted); 1693error: 1694 fail(); 1695 return make_pair(JSValue(), ValidationError); 1696} 1697 1698void SerializedScriptValue::addBlobURL(const String& string) 1699{ 1700 m_blobURLs.append(Vector<uint16_t>()); 1701 m_blobURLs.last().reserveCapacity(string.length()); 1702 for (size_t i = 0; i < string.length(); i++) 1703 m_blobURLs.last().append(string.characterAt(i)); 1704 m_blobURLs.last().resize(m_blobURLs.last().size()); 1705} 1706 1707SerializedScriptValue::~SerializedScriptValue() 1708{ 1709} 1710 1711SerializedScriptValue::SerializedScriptValue(const Vector<uint8_t>& buffer) 1712 : m_data(buffer) 1713{ 1714} 1715 1716SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer) 1717{ 1718 m_data.swap(buffer); 1719} 1720 1721SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer, Vector<String>& blobURLs) 1722{ 1723 m_data.swap(buffer); 1724 for (auto blobIter = blobURLs.begin(); blobIter != blobURLs.end(); ++blobIter) 1725 addBlobURL(*blobIter); 1726} 1727 1728SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer, Vector<String>& blobURLs, PassOwnPtr<ArrayBufferContentsArray> arrayBufferContentsArray) 1729 : m_arrayBufferContentsArray(arrayBufferContentsArray) 1730{ 1731 m_data.swap(buffer); 1732 for (auto blobIter = blobURLs.begin(); blobIter != blobURLs.end(); ++blobIter) 1733 addBlobURL(*blobIter); 1734} 1735 1736static void neuterView(JSCell* jsView) 1737{ 1738 if (!jsView) 1739 return; 1740 1741 switch (jsView->classInfo()->typedArrayStorageType) { 1742 case TypedArrayNone: 1743 // This could be a DataView, for example. Assume that there are views that the 1744 // DFG doesn't care about. 1745 return; 1746 case TypedArrayInt8: 1747 jsCast<JSInt8Array*>(jsView)->m_storageLength = 0; 1748 return; 1749 case TypedArrayInt16: 1750 jsCast<JSInt16Array*>(jsView)->m_storageLength = 0; 1751 return; 1752 case TypedArrayInt32: 1753 jsCast<JSInt32Array*>(jsView)->m_storageLength = 0; 1754 return; 1755 case TypedArrayUint8: 1756 jsCast<JSUint8Array*>(jsView)->m_storageLength = 0; 1757 return; 1758 case TypedArrayUint8Clamped: 1759 jsCast<JSUint8ClampedArray*>(jsView)->m_storageLength = 0; 1760 return; 1761 case TypedArrayUint16: 1762 jsCast<JSUint16Array*>(jsView)->m_storageLength = 0; 1763 return; 1764 case TypedArrayUint32: 1765 jsCast<JSUint32Array*>(jsView)->m_storageLength = 0; 1766 return; 1767 case TypedArrayFloat32: 1768 jsCast<JSFloat32Array*>(jsView)->m_storageLength = 0; 1769 return; 1770 case TypedArrayFloat64: 1771 jsCast<JSFloat64Array*>(jsView)->m_storageLength = 0; 1772 return; 1773 } 1774 RELEASE_ASSERT_NOT_REACHED(); 1775} 1776 1777PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValue::transferArrayBuffers( 1778 ExecState* exec, ArrayBufferArray& arrayBuffers, SerializationReturnCode& code) 1779{ 1780 for (size_t i = 0; i < arrayBuffers.size(); i++) { 1781 if (arrayBuffers[i]->isNeutered()) { 1782 code = ValidationError; 1783 return nullptr; 1784 } 1785 } 1786 1787 OwnPtr<ArrayBufferContentsArray> contents = adoptPtr(new ArrayBufferContentsArray(arrayBuffers.size())); 1788 Vector<RefPtr<DOMWrapperWorld> > worlds; 1789 static_cast<WebCoreJSClientData*>(exec->vm().clientData)->getAllWorlds(worlds); 1790 1791 HashSet<WTF::ArrayBuffer*> visited; 1792 for (size_t arrayBufferIndex = 0; arrayBufferIndex < arrayBuffers.size(); arrayBufferIndex++) { 1793 Vector<RefPtr<ArrayBufferView> > neuteredViews; 1794 1795 if (visited.contains(arrayBuffers[arrayBufferIndex].get())) 1796 continue; 1797 visited.add(arrayBuffers[arrayBufferIndex].get()); 1798 1799 bool result = arrayBuffers[arrayBufferIndex]->transfer(contents->at(arrayBufferIndex), neuteredViews); 1800 if (!result) { 1801 code = ValidationError; 1802 return nullptr; 1803 } 1804 1805 // The views may have been neutered, but their wrappers also need to be neutered, too. 1806 for (size_t viewIndex = neuteredViews.size(); viewIndex--;) { 1807 ArrayBufferView* view = neuteredViews[viewIndex].get(); 1808 for (size_t worldIndex = worlds.size(); worldIndex--;) { 1809 DOMWrapperWorld* world = worlds[worldIndex].get(); 1810 neuterView(getCachedWrapper(world, view)); 1811 } 1812 } 1813 } 1814 return contents.release(); 1815} 1816 1817 1818PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(ExecState* exec, JSValue value, 1819 MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, 1820 SerializationErrorMode throwExceptions) 1821{ 1822 Vector<uint8_t> buffer; 1823 Vector<String> blobURLs; 1824 SerializationReturnCode code = CloneSerializer::serialize(exec, value, messagePorts, arrayBuffers, blobURLs, buffer); 1825 1826 OwnPtr<ArrayBufferContentsArray> arrayBufferContentsArray; 1827 1828 if (arrayBuffers && serializationDidCompleteSuccessfully(code)) 1829 arrayBufferContentsArray = transferArrayBuffers(exec, *arrayBuffers, code); 1830 1831 if (throwExceptions == Throwing) 1832 maybeThrowExceptionIfSerializationFailed(exec, code); 1833 1834 if (!serializationDidCompleteSuccessfully(code)) 1835 return 0; 1836 1837 return adoptRef(new SerializedScriptValue(buffer, blobURLs, arrayBufferContentsArray.release())); 1838} 1839 1840PassRefPtr<SerializedScriptValue> SerializedScriptValue::create() 1841{ 1842 Vector<uint8_t> buffer; 1843 return adoptRef(new SerializedScriptValue(buffer)); 1844} 1845 1846PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& string) 1847{ 1848 Vector<uint8_t> buffer; 1849 if (!CloneSerializer::serialize(string, buffer)) 1850 return 0; 1851 return adoptRef(new SerializedScriptValue(buffer)); 1852} 1853 1854#if ENABLE(INDEXED_DATABASE) 1855PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(JSC::ExecState* exec, JSC::JSValue value) 1856{ 1857 return SerializedScriptValue::create(exec, value, 0, 0); 1858} 1859 1860PassRefPtr<SerializedScriptValue> SerializedScriptValue::numberValue(double value) 1861{ 1862 Vector<uint8_t> buffer; 1863 CloneSerializer::serializeNumber(value, buffer); 1864 return adoptRef(new SerializedScriptValue(buffer)); 1865} 1866 1867JSValue SerializedScriptValue::deserialize(JSC::ExecState* exec, JSC::JSGlobalObject* globalObject) 1868{ 1869 return deserialize(exec, globalObject, 0); 1870} 1871#endif 1872 1873PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(JSContextRef originContext, JSValueRef apiValue, 1874 MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, 1875 JSValueRef* exception) 1876{ 1877 ExecState* exec = toJS(originContext); 1878 APIEntryShim entryShim(exec); 1879 JSValue value = toJS(exec, apiValue); 1880 RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::create(exec, value, messagePorts, arrayBuffers); 1881 if (exec->hadException()) { 1882 if (exception) 1883 *exception = toRef(exec, exec->exception()); 1884 exec->clearException(); 1885 return 0; 1886 } 1887 ASSERT(serializedValue); 1888 return serializedValue.release(); 1889} 1890 1891PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(JSContextRef originContext, JSValueRef apiValue, 1892 JSValueRef* exception) 1893{ 1894 return create(originContext, apiValue, 0, 0, exception); 1895} 1896 1897String SerializedScriptValue::toString() 1898{ 1899 return CloneDeserializer::deserializeString(m_data); 1900} 1901 1902JSValue SerializedScriptValue::deserialize(ExecState* exec, JSGlobalObject* globalObject, 1903 MessagePortArray* messagePorts, SerializationErrorMode throwExceptions) 1904{ 1905 DeserializationResult result = CloneDeserializer::deserialize(exec, globalObject, messagePorts, 1906 m_arrayBufferContentsArray.get(), m_data); 1907 if (throwExceptions == Throwing) 1908 maybeThrowExceptionIfSerializationFailed(exec, result.second); 1909 return result.first; 1910} 1911 1912#if ENABLE(INSPECTOR) 1913ScriptValue SerializedScriptValue::deserializeForInspector(ScriptState* scriptState) 1914{ 1915 JSValue value = deserialize(scriptState, scriptState->lexicalGlobalObject(), 0); 1916 return ScriptValue(scriptState->vm(), value); 1917} 1918#endif 1919 1920JSValueRef SerializedScriptValue::deserialize(JSContextRef destinationContext, JSValueRef* exception, MessagePortArray* messagePorts) 1921{ 1922 ExecState* exec = toJS(destinationContext); 1923 APIEntryShim entryShim(exec); 1924 JSValue value = deserialize(exec, exec->lexicalGlobalObject(), messagePorts); 1925 if (exec->hadException()) { 1926 if (exception) 1927 *exception = toRef(exec, exec->exception()); 1928 exec->clearException(); 1929 return 0; 1930 } 1931 ASSERT(value); 1932 return toRef(exec, value); 1933} 1934 1935 1936JSValueRef SerializedScriptValue::deserialize(JSContextRef destinationContext, JSValueRef* exception) 1937{ 1938 return deserialize(destinationContext, exception, 0); 1939} 1940 1941PassRefPtr<SerializedScriptValue> SerializedScriptValue::nullValue() 1942{ 1943 return SerializedScriptValue::create(); 1944} 1945 1946PassRefPtr<SerializedScriptValue> SerializedScriptValue::undefinedValue() 1947{ 1948 Vector<uint8_t> buffer; 1949 CloneSerializer::serializeUndefined(buffer); 1950 return adoptRef(new SerializedScriptValue(buffer)); 1951} 1952 1953PassRefPtr<SerializedScriptValue> SerializedScriptValue::booleanValue(bool value) 1954{ 1955 Vector<uint8_t> buffer; 1956 CloneSerializer::serializeBoolean(value, buffer); 1957 return adoptRef(new SerializedScriptValue(buffer)); 1958} 1959 1960void SerializedScriptValue::maybeThrowExceptionIfSerializationFailed(ExecState* exec, SerializationReturnCode code) 1961{ 1962 if (code == SuccessfullyCompleted) 1963 return; 1964 1965 switch (code) { 1966 case StackOverflowError: 1967 throwError(exec, createStackOverflowError(exec)); 1968 break; 1969 case ValidationError: 1970 throwError(exec, createTypeError(exec, "Unable to deserialize data.")); 1971 break; 1972 case DataCloneError: 1973 setDOMException(exec, DATA_CLONE_ERR); 1974 break; 1975 case ExistingExceptionError: 1976 break; 1977 case UnspecifiedError: 1978 break; 1979 default: 1980 ASSERT_NOT_REACHED(); 1981 } 1982} 1983 1984bool SerializedScriptValue::serializationDidCompleteSuccessfully(SerializationReturnCode code) 1985{ 1986 return (code == SuccessfullyCompleted); 1987} 1988 1989uint32_t SerializedScriptValue::wireFormatVersion() 1990{ 1991 return CurrentVersion; 1992} 1993 1994} 1995