| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "config.h" | 5 #include "config.h" |
| 6 #include "bindings/core/v8/ScriptValueSerializer.h" | 6 #include "bindings/core/v8/ScriptValueSerializer.h" |
| 7 | 7 |
| 8 #include "bindings/core/v8/V8ArrayBuffer.h" | 8 #include "bindings/core/v8/V8ArrayBuffer.h" |
| 9 #include "bindings/core/v8/V8ArrayBufferView.h" | 9 #include "bindings/core/v8/V8ArrayBufferView.h" |
| 10 #include "bindings/core/v8/V8Blob.h" | 10 #include "bindings/core/v8/V8Blob.h" |
| 11 #include "bindings/core/v8/V8CompositorProxy.h" | 11 #include "bindings/core/v8/V8CompositorProxy.h" |
| 12 #include "bindings/core/v8/V8File.h" | 12 #include "bindings/core/v8/V8File.h" |
| 13 #include "bindings/core/v8/V8FileList.h" | 13 #include "bindings/core/v8/V8FileList.h" |
| 14 #include "bindings/core/v8/V8ImageData.h" | 14 #include "bindings/core/v8/V8ImageData.h" |
| 15 #include "bindings/core/v8/V8MessagePort.h" | 15 #include "bindings/core/v8/V8MessagePort.h" |
| 16 #include "bindings/core/v8/V8SharedArrayBuffer.h" |
| 16 #include "core/dom/CompositorProxy.h" | 17 #include "core/dom/CompositorProxy.h" |
| 17 #include "core/dom/DOMDataView.h" | 18 #include "core/dom/DOMDataView.h" |
| 19 #include "core/dom/DOMSharedArrayBuffer.h" |
| 20 #include "core/dom/DOMTypedArray.h" |
| 18 #include "core/fileapi/Blob.h" | 21 #include "core/fileapi/Blob.h" |
| 19 #include "core/fileapi/File.h" | 22 #include "core/fileapi/File.h" |
| 20 #include "core/fileapi/FileList.h" | 23 #include "core/fileapi/FileList.h" |
| 24 #include "platform/RuntimeEnabledFeatures.h" |
| 21 #include "public/platform/Platform.h" | 25 #include "public/platform/Platform.h" |
| 22 #include "public/platform/WebBlobInfo.h" | 26 #include "public/platform/WebBlobInfo.h" |
| 23 #include "wtf/DateMath.h" | 27 #include "wtf/DateMath.h" |
| 24 #include "wtf/text/StringHash.h" | 28 #include "wtf/text/StringHash.h" |
| 25 #include "wtf/text/StringUTF8Adaptor.h" | 29 #include "wtf/text/StringUTF8Adaptor.h" |
| 30 #include <stdio.h> |
| 26 | 31 |
| 27 // FIXME: consider crashing in debug mode on deserialization errors | 32 // FIXME: consider crashing in debug mode on deserialization errors |
| 28 // NOTE: be sure to change wireFormatVersion as necessary! | 33 // NOTE: be sure to change wireFormatVersion as necessary! |
| 29 | 34 |
| 30 namespace blink { | 35 namespace blink { |
| 31 | 36 |
| 32 // This code implements the HTML5 Structured Clone algorithm: | 37 // This code implements the HTML5 Structured Clone algorithm: |
| 33 // http://www.whatwg.org/specs/web-apps/current-work/multipage/urls.html#safe-pa
ssing-of-structured-data | 38 // http://www.whatwg.org/specs/web-apps/current-work/multipage/urls.html#safe-pa
ssing-of-structured-data |
| 34 | 39 |
| 35 // ZigZag encoding helps VarInt encoding stay small for negative | 40 // ZigZag encoding helps VarInt encoding stay small for negative |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 void SerializedScriptValueWriter::writeArrayBuffer(const DOMArrayBuffer& arrayBu
ffer) | 245 void SerializedScriptValueWriter::writeArrayBuffer(const DOMArrayBuffer& arrayBu
ffer) |
| 241 { | 246 { |
| 242 append(ArrayBufferTag); | 247 append(ArrayBufferTag); |
| 243 doWriteArrayBuffer(arrayBuffer); | 248 doWriteArrayBuffer(arrayBuffer); |
| 244 } | 249 } |
| 245 | 250 |
| 246 void SerializedScriptValueWriter::writeArrayBufferView(const DOMArrayBufferView&
arrayBufferView) | 251 void SerializedScriptValueWriter::writeArrayBufferView(const DOMArrayBufferView&
arrayBufferView) |
| 247 { | 252 { |
| 248 append(ArrayBufferViewTag); | 253 append(ArrayBufferViewTag); |
| 249 #if ENABLE(ASSERT) | 254 #if ENABLE(ASSERT) |
| 250 const DOMArrayBuffer& arrayBuffer = *arrayBufferView.buffer(); | 255 ASSERT(static_cast<const uint8_t*>(arrayBufferView.bufferBase()->data()) + a
rrayBufferView.byteOffset() == |
| 251 ASSERT(static_cast<const uint8_t*>(arrayBuffer.data()) + arrayBufferView.byt
eOffset() == | |
| 252 static_cast<const uint8_t*>(arrayBufferView.baseAddress())); | 256 static_cast<const uint8_t*>(arrayBufferView.baseAddress())); |
| 253 #endif | 257 #endif |
| 254 DOMArrayBufferView::ViewType type = arrayBufferView.type(); | 258 DOMArrayBufferView::ViewType type = arrayBufferView.type(); |
| 255 | 259 |
| 256 switch (type) { | 260 switch (type) { |
| 257 case DOMArrayBufferView::TypeInt8: | 261 case DOMArrayBufferView::TypeInt8: |
| 258 append(ByteArrayTag); | 262 append(ByteArrayTag); |
| 259 break; | 263 break; |
| 260 case DOMArrayBufferView::TypeUint8Clamped: | 264 case DOMArrayBufferView::TypeUint8Clamped: |
| 261 append(UnsignedByteClampedArrayTag); | 265 append(UnsignedByteClampedArrayTag); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 append(MessagePortTag); | 317 append(MessagePortTag); |
| 314 doWriteUint32(index); | 318 doWriteUint32(index); |
| 315 } | 319 } |
| 316 | 320 |
| 317 void SerializedScriptValueWriter::writeTransferredArrayBuffer(uint32_t index) | 321 void SerializedScriptValueWriter::writeTransferredArrayBuffer(uint32_t index) |
| 318 { | 322 { |
| 319 append(ArrayBufferTransferTag); | 323 append(ArrayBufferTransferTag); |
| 320 doWriteUint32(index); | 324 doWriteUint32(index); |
| 321 } | 325 } |
| 322 | 326 |
| 327 void SerializedScriptValueWriter::writeTransferredSharedArrayBuffer(uint32_t ind
ex) |
| 328 { |
| 329 ASSERT(RuntimeEnabledFeatures::sharedArrayBufferEnabled()); |
| 330 append(SharedArrayBufferTransferTag); |
| 331 doWriteUint32(index); |
| 332 } |
| 333 |
| 323 void SerializedScriptValueWriter::writeObjectReference(uint32_t reference) | 334 void SerializedScriptValueWriter::writeObjectReference(uint32_t reference) |
| 324 { | 335 { |
| 325 append(ObjectReferenceTag); | 336 append(ObjectReferenceTag); |
| 326 doWriteUint32(reference); | 337 doWriteUint32(reference); |
| 327 } | 338 } |
| 328 | 339 |
| 329 void SerializedScriptValueWriter::writeObject(uint32_t numProperties) | 340 void SerializedScriptValueWriter::writeObject(uint32_t numProperties) |
| 330 { | 341 { |
| 331 append(ObjectTag); | 342 append(ObjectTag); |
| 332 doWriteUint32(numProperties); | 343 doWriteUint32(numProperties); |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 { | 604 { |
| 594 if (!impl) | 605 if (!impl) |
| 595 return v8::Local<v8::ArrayBuffer>(); | 606 return v8::Local<v8::ArrayBuffer>(); |
| 596 v8::Local<v8::Value> wrapper = toV8(impl, creationContext, isolate); | 607 v8::Local<v8::Value> wrapper = toV8(impl, creationContext, isolate); |
| 597 if (wrapper.IsEmpty()) | 608 if (wrapper.IsEmpty()) |
| 598 return v8::Local<v8::ArrayBuffer>(); | 609 return v8::Local<v8::ArrayBuffer>(); |
| 599 ASSERT(wrapper->IsArrayBuffer()); | 610 ASSERT(wrapper->IsArrayBuffer()); |
| 600 return wrapper.As<v8::ArrayBuffer>(); | 611 return wrapper.As<v8::ArrayBuffer>(); |
| 601 } | 612 } |
| 602 | 613 |
| 614 static v8::Local<v8::SharedArrayBuffer> toV8Object(DOMSharedArrayBuffer* impl, v
8::Local<v8::Object> creationContext, v8::Isolate* isolate) |
| 615 { |
| 616 ASSERT(RuntimeEnabledFeatures::sharedArrayBufferEnabled()); |
| 617 if (!impl) |
| 618 return v8::Local<v8::SharedArrayBuffer>(); |
| 619 v8::Local<v8::Value> wrapper = toV8(impl, creationContext, isolate); |
| 620 ASSERT(wrapper->IsSharedArrayBuffer()); |
| 621 return wrapper.As<v8::SharedArrayBuffer>(); |
| 622 } |
| 623 |
| 603 // Returns true if the provided object is to be considered a 'host object', as u
sed in the | 624 // Returns true if the provided object is to be considered a 'host object', as u
sed in the |
| 604 // HTML5 structured clone algorithm. | 625 // HTML5 structured clone algorithm. |
| 605 static bool isHostObject(v8::Local<v8::Object> object) | 626 static bool isHostObject(v8::Local<v8::Object> object) |
| 606 { | 627 { |
| 607 // If the object has any internal fields, then we won't be able to serialize
or deserialize | 628 // If the object has any internal fields, then we won't be able to serialize
or deserialize |
| 608 // them; conveniently, this is also a quick way to detect DOM wrapper object
s, because | 629 // them; conveniently, this is also a quick way to detect DOM wrapper object
s, because |
| 609 // the mechanism for these relies on data stored in these fields. We should | 630 // the mechanism for these relies on data stored in these fields. We should |
| 610 // catch external array data as a special case. | 631 // catch external array data as a special case. |
| 611 return object->InternalFieldCount(); | 632 return object->InternalFieldCount(); |
| 612 } | 633 } |
| 613 | 634 |
| 614 ScriptValueSerializer::ScriptValueSerializer(SerializedScriptValueWriter& writer
, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, WebBlobInfoArr
ay* blobInfo, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, Script
State* scriptState) | 635 ScriptValueSerializer::ScriptValueSerializer(SerializedScriptValueWriter& writer
, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, SharedArrayBuf
ferArray* sharedArrayBuffers, WebBlobInfoArray* blobInfo, BlobDataHandleMap& blo
bDataHandles, v8::TryCatch& tryCatch, ScriptState* scriptState) |
| 615 : m_scriptState(scriptState) | 636 : m_scriptState(scriptState) |
| 616 , m_writer(writer) | 637 , m_writer(writer) |
| 617 , m_tryCatch(tryCatch) | 638 , m_tryCatch(tryCatch) |
| 618 , m_depth(0) | 639 , m_depth(0) |
| 619 , m_status(Success) | 640 , m_status(Success) |
| 620 , m_nextObjectReference(0) | 641 , m_nextObjectReference(0) |
| 621 , m_blobInfo(blobInfo) | 642 , m_blobInfo(blobInfo) |
| 622 , m_blobDataHandles(blobDataHandles) | 643 , m_blobDataHandles(blobDataHandles) |
| 623 { | 644 { |
| 624 ASSERT(!tryCatch.HasCaught()); | 645 ASSERT(!tryCatch.HasCaught()); |
| 625 v8::Local<v8::Object> creationContext = m_scriptState->context()->Global(); | 646 v8::Local<v8::Object> creationContext = m_scriptState->context()->Global(); |
| 626 if (messagePorts) { | 647 if (messagePorts) { |
| 627 for (size_t i = 0; i < messagePorts->size(); i++) | 648 for (size_t i = 0; i < messagePorts->size(); i++) |
| 628 m_transferredMessagePorts.set(toV8Object(messagePorts->at(i).get(),
creationContext, isolate()), i); | 649 m_transferredMessagePorts.set(toV8Object(messagePorts->at(i).get(),
creationContext, isolate()), i); |
| 629 } | 650 } |
| 630 if (arrayBuffers) { | 651 if (arrayBuffers) { |
| 631 for (size_t i = 0; i < arrayBuffers->size(); i++) { | 652 for (size_t i = 0; i < arrayBuffers->size(); i++) { |
| 632 v8::Local<v8::Object> v8ArrayBuffer = toV8Object(arrayBuffers->at(i)
.get(), creationContext, isolate()); | 653 v8::Local<v8::Object> v8ArrayBuffer = toV8Object(arrayBuffers->at(i)
.get(), creationContext, isolate()); |
| 633 // Coalesce multiple occurences of the same buffer to the first inde
x. | 654 // Coalesce multiple occurences of the same buffer to the first inde
x. |
| 634 if (!m_transferredArrayBuffers.contains(v8ArrayBuffer)) | 655 if (!m_transferredArrayBuffers.contains(v8ArrayBuffer)) |
| 635 m_transferredArrayBuffers.set(v8ArrayBuffer, i); | 656 m_transferredArrayBuffers.set(v8ArrayBuffer, i); |
| 636 } | 657 } |
| 637 } | 658 } |
| 659 if (sharedArrayBuffers) { |
| 660 ASSERT(sharedArrayBuffers->size() == 0 || RuntimeEnabledFeatures::shared
ArrayBufferEnabled()); |
| 661 for (size_t i = 0; i < sharedArrayBuffers->size(); i++) { |
| 662 v8::Local<v8::Object> v8SharedArrayBuffer = toV8Object(sharedArrayBu
ffers->at(i).get(), creationContext, isolate()); |
| 663 // Coalesce multiple occurences of the same buffer to the first inde
x. |
| 664 if (!m_transferredSharedArrayBuffers.contains(v8SharedArrayBuffer)) |
| 665 m_transferredSharedArrayBuffers.set(v8SharedArrayBuffer, i); |
| 666 } |
| 667 } |
| 638 } | 668 } |
| 639 | 669 |
| 640 ScriptValueSerializer::Status ScriptValueSerializer::serialize(v8::Local<v8::Val
ue> value) | 670 ScriptValueSerializer::Status ScriptValueSerializer::serialize(v8::Local<v8::Val
ue> value) |
| 641 { | 671 { |
| 642 v8::HandleScope scope(isolate()); | 672 v8::HandleScope scope(isolate()); |
| 643 m_writer.writeVersion(); | 673 m_writer.writeVersion(); |
| 644 StateBase* state = doSerialize(value, 0); | 674 StateBase* state = doSerialize(value, 0); |
| 645 while (state) | 675 while (state) |
| 646 state = state->advance(*this); | 676 state = state->advance(*this); |
| 647 return m_status; | 677 return m_status; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 659 m_writer.writeObjectReference(objectReference); | 689 m_writer.writeObjectReference(objectReference); |
| 660 } else { | 690 } else { |
| 661 return doSerializeValue(value, next); | 691 return doSerializeValue(value, next); |
| 662 } | 692 } |
| 663 return 0; | 693 return 0; |
| 664 } | 694 } |
| 665 | 695 |
| 666 ScriptValueSerializer::StateBase* ScriptValueSerializer::doSerializeValue(v8::Lo
cal<v8::Value> value, ScriptValueSerializer::StateBase* next) | 696 ScriptValueSerializer::StateBase* ScriptValueSerializer::doSerializeValue(v8::Lo
cal<v8::Value> value, ScriptValueSerializer::StateBase* next) |
| 667 { | 697 { |
| 668 uint32_t arrayBufferIndex; | 698 uint32_t arrayBufferIndex; |
| 699 uint32_t sharedArrayBufferIndex; |
| 669 if (value.IsEmpty()) | 700 if (value.IsEmpty()) |
| 670 return handleError(InputError, "The empty property name cannot be cloned
.", next); | 701 return handleError(InputError, "The empty property name cannot be cloned
.", next); |
| 671 if (value->IsUndefined()) { | 702 if (value->IsUndefined()) { |
| 672 m_writer.writeUndefined(); | 703 m_writer.writeUndefined(); |
| 673 } else if (value->IsNull()) { | 704 } else if (value->IsNull()) { |
| 674 m_writer.writeNull(); | 705 m_writer.writeNull(); |
| 675 } else if (value->IsTrue()) { | 706 } else if (value->IsTrue()) { |
| 676 m_writer.writeTrue(); | 707 m_writer.writeTrue(); |
| 677 } else if (value->IsFalse()) { | 708 } else if (value->IsFalse()) { |
| 678 m_writer.writeFalse(); | 709 m_writer.writeFalse(); |
| 679 } else if (value->IsInt32()) { | 710 } else if (value->IsInt32()) { |
| 680 m_writer.writeInt32(value.As<v8::Int32>()->Value()); | 711 m_writer.writeInt32(value.As<v8::Int32>()->Value()); |
| 681 } else if (value->IsUint32()) { | 712 } else if (value->IsUint32()) { |
| 682 m_writer.writeUint32(value.As<v8::Uint32>()->Value()); | 713 m_writer.writeUint32(value.As<v8::Uint32>()->Value()); |
| 683 } else if (value->IsNumber()) { | 714 } else if (value->IsNumber()) { |
| 684 m_writer.writeNumber(value.As<v8::Number>()->Value()); | 715 m_writer.writeNumber(value.As<v8::Number>()->Value()); |
| 685 } else if (V8ArrayBufferView::hasInstance(value, isolate())) { | 716 } else if (V8ArrayBufferView::hasInstance(value, isolate())) { |
| 686 return writeAndGreyArrayBufferView(value.As<v8::Object>(), next); | 717 return writeAndGreyArrayBufferView(value.As<v8::Object>(), next); |
| 687 } else if (value->IsString()) { | 718 } else if (value->IsString()) { |
| 688 writeString(value); | 719 writeString(value); |
| 689 } else if (V8MessagePort::hasInstance(value, isolate())) { | 720 } else if (V8MessagePort::hasInstance(value, isolate())) { |
| 690 uint32_t messagePortIndex; | 721 uint32_t messagePortIndex; |
| 691 if (m_transferredMessagePorts.tryGet(value.As<v8::Object>(), &messagePor
tIndex)) { | 722 if (m_transferredMessagePorts.tryGet(value.As<v8::Object>(), &messagePor
tIndex)) { |
| 692 m_writer.writeTransferredMessagePort(messagePortIndex); | 723 m_writer.writeTransferredMessagePort(messagePortIndex); |
| 693 } else { | 724 } else { |
| 694 return handleError(DataCloneError, "A MessagePort could not be clone
d.", next); | 725 return handleError(DataCloneError, "A MessagePort could not be clone
d.", next); |
| 695 } | 726 } |
| 696 } else if (V8ArrayBuffer::hasInstance(value, isolate()) && m_transferredArra
yBuffers.tryGet(value.As<v8::Object>(), &arrayBufferIndex)) { | 727 } else if (V8ArrayBuffer::hasInstance(value, isolate()) && m_transferredArra
yBuffers.tryGet(value.As<v8::Object>(), &arrayBufferIndex)) { |
| 697 return writeTransferredArrayBuffer(value, arrayBufferIndex, next); | 728 return writeTransferredArrayBuffer(value, arrayBufferIndex, next); |
| 729 } else if (V8SharedArrayBuffer::hasInstance(value, isolate()) && m_transferr
edSharedArrayBuffers.tryGet(value.As<v8::Object>(), &sharedArrayBufferIndex)) { |
| 730 return writeTransferredSharedArrayBuffer(value, sharedArrayBufferIndex,
next); |
| 698 } else { | 731 } else { |
| 699 v8::Local<v8::Object> jsObject = value.As<v8::Object>(); | 732 v8::Local<v8::Object> jsObject = value.As<v8::Object>(); |
| 700 if (jsObject.IsEmpty()) | 733 if (jsObject.IsEmpty()) |
| 701 return handleError(DataCloneError, "An object could not be cloned.",
next); | 734 return handleError(DataCloneError, "An object could not be cloned.",
next); |
| 702 greyObject(jsObject); | 735 greyObject(jsObject); |
| 703 if (value->IsDate()) { | 736 if (value->IsDate()) { |
| 704 m_writer.writeDate(value.As<v8::Date>()->ValueOf()); | 737 m_writer.writeDate(value.As<v8::Date>()->ValueOf()); |
| 705 } else if (value->IsStringObject()) { | 738 } else if (value->IsStringObject()) { |
| 706 writeStringObject(value); | 739 writeStringObject(value); |
| 707 } else if (value->IsNumberObject()) { | 740 } else if (value->IsNumberObject()) { |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 904 v8::Local<v8::RegExp> regExp = value.As<v8::RegExp>(); | 937 v8::Local<v8::RegExp> regExp = value.As<v8::RegExp>(); |
| 905 m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags()); | 938 m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags()); |
| 906 } | 939 } |
| 907 | 940 |
| 908 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeAndGreyArrayBuffer
View(v8::Local<v8::Object> object, ScriptValueSerializer::StateBase* next) | 941 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeAndGreyArrayBuffer
View(v8::Local<v8::Object> object, ScriptValueSerializer::StateBase* next) |
| 909 { | 942 { |
| 910 ASSERT(!object.IsEmpty()); | 943 ASSERT(!object.IsEmpty()); |
| 911 DOMArrayBufferView* arrayBufferView = V8ArrayBufferView::toImpl(object); | 944 DOMArrayBufferView* arrayBufferView = V8ArrayBufferView::toImpl(object); |
| 912 if (!arrayBufferView) | 945 if (!arrayBufferView) |
| 913 return 0; | 946 return 0; |
| 914 if (!arrayBufferView->buffer()) | 947 v8::Local<v8::Value> underlyingBuffer; |
| 915 return handleError(DataCloneError, "An ArrayBuffer could not be cloned."
, next); | 948 if (arrayBufferView->isShared()) { |
| 916 v8::Local<v8::Value> underlyingBuffer = toV8(arrayBufferView->buffer(), m_sc
riptState->context()->Global(), isolate()); | 949 if (!arrayBufferView->bufferShared()) |
| 950 return handleError(DataCloneError, "A SharedArrayBuffer could not be
cloned.", next); |
| 951 underlyingBuffer = toV8(arrayBufferView->bufferShared(), m_scriptState->
context()->Global(), isolate()); |
| 952 } else { |
| 953 if (!arrayBufferView->buffer()) |
| 954 return handleError(DataCloneError, "An ArrayBuffer could not be clon
ed.", next); |
| 955 underlyingBuffer = toV8(arrayBufferView->buffer(), m_scriptState->contex
t()->Global(), isolate()); |
| 956 } |
| 917 if (underlyingBuffer.IsEmpty()) | 957 if (underlyingBuffer.IsEmpty()) |
| 918 return handleError(DataCloneError, "An ArrayBuffer could not be cloned."
, next); | 958 return handleError(DataCloneError, "An ArrayBuffer could not be cloned."
, next); |
| 919 StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next); | 959 StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next); |
| 920 if (stateOut) | 960 if (stateOut) |
| 921 return stateOut; | 961 return stateOut; |
| 922 m_writer.writeArrayBufferView(*arrayBufferView); | 962 m_writer.writeArrayBufferView(*arrayBufferView); |
| 923 // This should be safe: we serialize something that we know to be a wrapper
(see | 963 // This should be safe: we serialize something that we know to be a wrapper
(see |
| 924 // the toV8 call above), so the call to doSerializeArrayBuffer should neithe
r | 964 // the toV8 call above), so the call to doSerializeArrayBuffer should neithe
r |
| 925 // cause the system stack to overflow nor should it have potential to reach | 965 // cause the system stack to overflow nor should it have potential to reach |
| 926 // this ArrayBufferView again. | 966 // this ArrayBufferView again. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 950 { | 990 { |
| 951 DOMArrayBuffer* arrayBuffer = V8ArrayBuffer::toImpl(value.As<v8::Object>()); | 991 DOMArrayBuffer* arrayBuffer = V8ArrayBuffer::toImpl(value.As<v8::Object>()); |
| 952 if (!arrayBuffer) | 992 if (!arrayBuffer) |
| 953 return 0; | 993 return 0; |
| 954 if (arrayBuffer->isNeutered()) | 994 if (arrayBuffer->isNeutered()) |
| 955 return handleError(DataCloneError, "An ArrayBuffer is neutered and could
not be cloned.", next); | 995 return handleError(DataCloneError, "An ArrayBuffer is neutered and could
not be cloned.", next); |
| 956 m_writer.writeTransferredArrayBuffer(index); | 996 m_writer.writeTransferredArrayBuffer(index); |
| 957 return 0; | 997 return 0; |
| 958 } | 998 } |
| 959 | 999 |
| 1000 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeTransferredSharedA
rrayBuffer(v8::Local<v8::Value> value, uint32_t index, ScriptValueSerializer::St
ateBase* next) |
| 1001 { |
| 1002 ASSERT(RuntimeEnabledFeatures::sharedArrayBufferEnabled()); |
| 1003 DOMSharedArrayBuffer* sharedArrayBuffer = V8SharedArrayBuffer::toImpl(value.
As<v8::Object>()); |
| 1004 if (!sharedArrayBuffer) |
| 1005 return 0; |
| 1006 m_writer.writeTransferredSharedArrayBuffer(index); |
| 1007 return 0; |
| 1008 } |
| 1009 |
| 960 bool ScriptValueSerializer::shouldSerializeDensely(uint32_t length, uint32_t pro
pertyCount) | 1010 bool ScriptValueSerializer::shouldSerializeDensely(uint32_t length, uint32_t pro
pertyCount) |
| 961 { | 1011 { |
| 962 // Let K be the cost of serializing all property values that are there | 1012 // Let K be the cost of serializing all property values that are there |
| 963 // Cost of serializing sparsely: 5*propertyCount + K (5 bytes per uint32_t k
ey) | 1013 // Cost of serializing sparsely: 5*propertyCount + K (5 bytes per uint32_t k
ey) |
| 964 // Cost of serializing densely: K + 1*(length - propertyCount) (1 byte for a
ll properties that are not there) | 1014 // Cost of serializing densely: K + 1*(length - propertyCount) (1 byte for a
ll properties that are not there) |
| 965 // so densely is better than sparsly whenever 6*propertyCount > length | 1015 // so densely is better than sparsly whenever 6*propertyCount > length |
| 966 return 6 * propertyCount >= length; | 1016 return 6 * propertyCount >= length; |
| 967 } | 1017 } |
| 968 | 1018 |
| 969 ScriptValueSerializer::StateBase* ScriptValueSerializer::startArrayState(v8::Loc
al<v8::Array> array, ScriptValueSerializer::StateBase* next) | 1019 ScriptValueSerializer::StateBase* ScriptValueSerializer::startArrayState(v8::Loc
al<v8::Array> array, ScriptValueSerializer::StateBase* next) |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1226 case ArrayBufferTransferTag: { | 1276 case ArrayBufferTransferTag: { |
| 1227 if (!m_version) | 1277 if (!m_version) |
| 1228 return false; | 1278 return false; |
| 1229 uint32_t index; | 1279 uint32_t index; |
| 1230 if (!doReadUint32(&index)) | 1280 if (!doReadUint32(&index)) |
| 1231 return false; | 1281 return false; |
| 1232 if (!creator.tryGetTransferredArrayBuffer(index, value)) | 1282 if (!creator.tryGetTransferredArrayBuffer(index, value)) |
| 1233 return false; | 1283 return false; |
| 1234 break; | 1284 break; |
| 1235 } | 1285 } |
| 1286 case SharedArrayBufferTransferTag: { |
| 1287 if (!m_version) |
| 1288 return false; |
| 1289 uint32_t index; |
| 1290 if (!doReadUint32(&index)) |
| 1291 return false; |
| 1292 if (!creator.tryGetTransferredSharedArrayBuffer(index, value)) |
| 1293 return false; |
| 1294 break; |
| 1295 } |
| 1236 case ObjectReferenceTag: { | 1296 case ObjectReferenceTag: { |
| 1237 if (!m_version) | 1297 if (!m_version) |
| 1238 return false; | 1298 return false; |
| 1239 uint32_t reference; | 1299 uint32_t reference; |
| 1240 if (!doReadUint32(&reference)) | 1300 if (!doReadUint32(&reference)) |
| 1241 return false; | 1301 return false; |
| 1242 if (!creator.tryGetObjectFromObjectReference(reference, value)) | 1302 if (!creator.tryGetObjectFromObjectReference(reference, value)) |
| 1243 return false; | 1303 return false; |
| 1244 break; | 1304 break; |
| 1245 } | 1305 } |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1447 return false; | 1507 return false; |
| 1448 *value = toV8(arrayBuffer.release(), m_scriptState->context()->Global(), iso
late()); | 1508 *value = toV8(arrayBuffer.release(), m_scriptState->context()->Global(), iso
late()); |
| 1449 return !value->IsEmpty(); | 1509 return !value->IsEmpty(); |
| 1450 } | 1510 } |
| 1451 | 1511 |
| 1452 bool SerializedScriptValueReader::readArrayBufferView(v8::Local<v8::Value>* valu
e, ScriptValueCompositeCreator& creator) | 1512 bool SerializedScriptValueReader::readArrayBufferView(v8::Local<v8::Value>* valu
e, ScriptValueCompositeCreator& creator) |
| 1453 { | 1513 { |
| 1454 ArrayBufferViewSubTag subTag; | 1514 ArrayBufferViewSubTag subTag; |
| 1455 uint32_t byteOffset; | 1515 uint32_t byteOffset; |
| 1456 uint32_t byteLength; | 1516 uint32_t byteLength; |
| 1457 RefPtr<DOMArrayBuffer> arrayBuffer; | 1517 RefPtr<DOMArrayBufferBase> arrayBuffer; |
| 1458 v8::Local<v8::Value> arrayBufferV8Value; | 1518 v8::Local<v8::Value> arrayBufferV8Value; |
| 1459 if (!readArrayBufferViewSubTag(&subTag)) | 1519 if (!readArrayBufferViewSubTag(&subTag)) |
| 1460 return false; | 1520 return false; |
| 1461 if (!doReadUint32(&byteOffset)) | 1521 if (!doReadUint32(&byteOffset)) |
| 1462 return false; | 1522 return false; |
| 1463 if (!doReadUint32(&byteLength)) | 1523 if (!doReadUint32(&byteLength)) |
| 1464 return false; | 1524 return false; |
| 1465 if (!creator.consumeTopOfStack(&arrayBufferV8Value)) | 1525 if (!creator.consumeTopOfStack(&arrayBufferV8Value)) |
| 1466 return false; | 1526 return false; |
| 1467 if (arrayBufferV8Value.IsEmpty()) | 1527 if (arrayBufferV8Value.IsEmpty()) |
| 1468 return false; | 1528 return false; |
| 1469 arrayBuffer = V8ArrayBuffer::toImpl(arrayBufferV8Value.As<v8::Object>()); | 1529 if (arrayBufferV8Value->IsArrayBuffer()) { |
| 1470 if (!arrayBuffer) | 1530 arrayBuffer = V8ArrayBuffer::toImpl(arrayBufferV8Value.As<v8::Object>())
; |
| 1471 return false; | 1531 if (!arrayBuffer) |
| 1532 return false; |
| 1533 } else if (arrayBufferV8Value->IsSharedArrayBuffer()) { |
| 1534 arrayBuffer = V8SharedArrayBuffer::toImpl(arrayBufferV8Value.As<v8::Obje
ct>()); |
| 1535 if (!arrayBuffer) |
| 1536 return false; |
| 1537 } else { |
| 1538 ASSERT_NOT_REACHED(); |
| 1539 } |
| 1472 | 1540 |
| 1473 // Check the offset, length and alignment. | 1541 // Check the offset, length and alignment. |
| 1474 int elementByteSize; | 1542 int elementByteSize; |
| 1475 switch (subTag) { | 1543 switch (subTag) { |
| 1476 case ByteArrayTag: | 1544 case ByteArrayTag: |
| 1477 elementByteSize = sizeof(DOMInt8Array::ValueType); | 1545 elementByteSize = sizeof(DOMInt8Array::ValueType); |
| 1478 break; | 1546 break; |
| 1479 case UnsignedByteArrayTag: | 1547 case UnsignedByteArrayTag: |
| 1480 elementByteSize = sizeof(DOMUint8Array::ValueType); | 1548 elementByteSize = sizeof(DOMUint8Array::ValueType); |
| 1481 break; | 1549 break; |
| (...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1868 v8::Local<v8::Object> creationContext = m_reader.scriptState()->context(
)->Global(); | 1936 v8::Local<v8::Object> creationContext = m_reader.scriptState()->context(
)->Global(); |
| 1869 result = toV8(buffer.get(), creationContext, isolate); | 1937 result = toV8(buffer.get(), creationContext, isolate); |
| 1870 if (result.IsEmpty()) | 1938 if (result.IsEmpty()) |
| 1871 return false; | 1939 return false; |
| 1872 m_arrayBuffers[index] = result; | 1940 m_arrayBuffers[index] = result; |
| 1873 } | 1941 } |
| 1874 *object = result; | 1942 *object = result; |
| 1875 return true; | 1943 return true; |
| 1876 } | 1944 } |
| 1877 | 1945 |
| 1946 bool ScriptValueDeserializer::tryGetTransferredSharedArrayBuffer(uint32_t index,
v8::Local<v8::Value>* object) |
| 1947 { |
| 1948 ASSERT(RuntimeEnabledFeatures::sharedArrayBufferEnabled()); |
| 1949 if (!m_arrayBufferContents) |
| 1950 return false; |
| 1951 if (index >= m_arrayBuffers.size()) |
| 1952 return false; |
| 1953 v8::Local<v8::Value> result = m_arrayBuffers.at(index); |
| 1954 if (result.IsEmpty()) { |
| 1955 RefPtr<DOMSharedArrayBuffer> buffer = DOMSharedArrayBuffer::create(m_arr
ayBufferContents->at(index)); |
| 1956 v8::Isolate* isolate = m_reader.scriptState()->isolate(); |
| 1957 v8::Local<v8::Object> creationContext = m_reader.scriptState()->context(
)->Global(); |
| 1958 result = toV8(buffer.get(), creationContext, isolate); |
| 1959 m_arrayBuffers[index] = result; |
| 1960 } |
| 1961 *object = result; |
| 1962 return true; |
| 1963 } |
| 1964 |
| 1878 bool ScriptValueDeserializer::tryGetObjectFromObjectReference(uint32_t reference
, v8::Local<v8::Value>* object) | 1965 bool ScriptValueDeserializer::tryGetObjectFromObjectReference(uint32_t reference
, v8::Local<v8::Value>* object) |
| 1879 { | 1966 { |
| 1880 if (reference >= m_objectPool.size()) | 1967 if (reference >= m_objectPool.size()) |
| 1881 return false; | 1968 return false; |
| 1882 *object = m_objectPool[reference]; | 1969 *object = m_objectPool[reference]; |
| 1883 return object; | 1970 return object; |
| 1884 } | 1971 } |
| 1885 | 1972 |
| 1886 uint32_t ScriptValueDeserializer::objectReferenceCount() | 1973 uint32_t ScriptValueDeserializer::objectReferenceCount() |
| 1887 { | 1974 { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1940 return false; | 2027 return false; |
| 1941 uint32_t objectReference = m_openCompositeReferenceStack[m_openCompositeRefe
renceStack.size() - 1]; | 2028 uint32_t objectReference = m_openCompositeReferenceStack[m_openCompositeRefe
renceStack.size() - 1]; |
| 1942 m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size() -
1); | 2029 m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size() -
1); |
| 1943 if (objectReference >= m_objectPool.size()) | 2030 if (objectReference >= m_objectPool.size()) |
| 1944 return false; | 2031 return false; |
| 1945 *object = m_objectPool[objectReference]; | 2032 *object = m_objectPool[objectReference]; |
| 1946 return true; | 2033 return true; |
| 1947 } | 2034 } |
| 1948 | 2035 |
| 1949 } // namespace blink | 2036 } // namespace blink |
| OLD | NEW |