| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project 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 "src/value-serializer.h" | 5 #include "src/value-serializer.h" |
| 6 | 6 |
| 7 #include <type_traits> | 7 #include <type_traits> |
| 8 | 8 |
| 9 #include "src/base/logging.h" | 9 #include "src/base/logging.h" |
| 10 #include "src/conversions.h" | 10 #include "src/conversions.h" |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 // Array buffer (transferred). transferID:uint32_t | 103 // Array buffer (transferred). transferID:uint32_t |
| 104 kArrayBufferTransfer = 't', | 104 kArrayBufferTransfer = 't', |
| 105 // View into an array buffer. | 105 // View into an array buffer. |
| 106 // subtag:ArrayBufferViewTag, byteOffset:uint32_t, byteLength:uint32_t | 106 // subtag:ArrayBufferViewTag, byteOffset:uint32_t, byteLength:uint32_t |
| 107 // For typed arrays, byteOffset and byteLength must be divisible by the size | 107 // For typed arrays, byteOffset and byteLength must be divisible by the size |
| 108 // of the element. | 108 // of the element. |
| 109 // Note: kArrayBufferView is special, and should have an ArrayBuffer (or an | 109 // Note: kArrayBufferView is special, and should have an ArrayBuffer (or an |
| 110 // ObjectReference to one) serialized just before it. This is a quirk arising | 110 // ObjectReference to one) serialized just before it. This is a quirk arising |
| 111 // from the previous stack-based implementation. | 111 // from the previous stack-based implementation. |
| 112 kArrayBufferView = 'V', | 112 kArrayBufferView = 'V', |
| 113 // Shared array buffer. transferID:uint32_t | 113 // Shared array buffer (transferred). transferID:uint32_t |
| 114 kSharedArrayBuffer = 'u', | 114 kSharedArrayBufferTransfer = 'u', |
| 115 // Compiled WebAssembly module. encodingType:(one-byte tag). | 115 // Compiled WebAssembly module. encodingType:(one-byte tag). |
| 116 // If encodingType == 'y' (raw bytes): | 116 // If encodingType == 'y' (raw bytes): |
| 117 // wasmWireByteLength:uint32_t, then raw data | 117 // wasmWireByteLength:uint32_t, then raw data |
| 118 // compiledDataLength:uint32_t, then raw data | 118 // compiledDataLength:uint32_t, then raw data |
| 119 kWasmModule = 'W', | 119 kWasmModule = 'W', |
| 120 }; | 120 }; |
| 121 | 121 |
| 122 namespace { | 122 namespace { |
| 123 | 123 |
| 124 enum class ArrayBufferViewTag : uint8_t { | 124 enum class ArrayBufferViewTag : uint8_t { |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 auto result = std::make_pair(buffer_, buffer_size_); | 262 auto result = std::make_pair(buffer_, buffer_size_); |
| 263 buffer_ = nullptr; | 263 buffer_ = nullptr; |
| 264 buffer_size_ = 0; | 264 buffer_size_ = 0; |
| 265 buffer_capacity_ = 0; | 265 buffer_capacity_ = 0; |
| 266 return result; | 266 return result; |
| 267 } | 267 } |
| 268 | 268 |
| 269 void ValueSerializer::TransferArrayBuffer(uint32_t transfer_id, | 269 void ValueSerializer::TransferArrayBuffer(uint32_t transfer_id, |
| 270 Handle<JSArrayBuffer> array_buffer) { | 270 Handle<JSArrayBuffer> array_buffer) { |
| 271 DCHECK(!array_buffer_transfer_map_.Find(array_buffer)); | 271 DCHECK(!array_buffer_transfer_map_.Find(array_buffer)); |
| 272 DCHECK(!array_buffer->is_shared()); | |
| 273 array_buffer_transfer_map_.Set(array_buffer, transfer_id); | 272 array_buffer_transfer_map_.Set(array_buffer, transfer_id); |
| 274 } | 273 } |
| 275 | 274 |
| 276 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) { | 275 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) { |
| 277 if (object->IsSmi()) { | 276 if (object->IsSmi()) { |
| 278 WriteSmi(Smi::cast(*object)); | 277 WriteSmi(Smi::cast(*object)); |
| 279 return Just(true); | 278 return Just(true); |
| 280 } | 279 } |
| 281 | 280 |
| 282 DCHECK(object->IsHeapObject()); | 281 DCHECK(object->IsHeapObject()); |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 436 case JS_VALUE_TYPE: | 435 case JS_VALUE_TYPE: |
| 437 return WriteJSValue(Handle<JSValue>::cast(receiver)); | 436 return WriteJSValue(Handle<JSValue>::cast(receiver)); |
| 438 case JS_REGEXP_TYPE: | 437 case JS_REGEXP_TYPE: |
| 439 WriteJSRegExp(JSRegExp::cast(*receiver)); | 438 WriteJSRegExp(JSRegExp::cast(*receiver)); |
| 440 return Just(true); | 439 return Just(true); |
| 441 case JS_MAP_TYPE: | 440 case JS_MAP_TYPE: |
| 442 return WriteJSMap(Handle<JSMap>::cast(receiver)); | 441 return WriteJSMap(Handle<JSMap>::cast(receiver)); |
| 443 case JS_SET_TYPE: | 442 case JS_SET_TYPE: |
| 444 return WriteJSSet(Handle<JSSet>::cast(receiver)); | 443 return WriteJSSet(Handle<JSSet>::cast(receiver)); |
| 445 case JS_ARRAY_BUFFER_TYPE: | 444 case JS_ARRAY_BUFFER_TYPE: |
| 446 return WriteJSArrayBuffer(Handle<JSArrayBuffer>::cast(receiver)); | 445 return WriteJSArrayBuffer(JSArrayBuffer::cast(*receiver)); |
| 447 case JS_TYPED_ARRAY_TYPE: | 446 case JS_TYPED_ARRAY_TYPE: |
| 448 case JS_DATA_VIEW_TYPE: | 447 case JS_DATA_VIEW_TYPE: |
| 449 return WriteJSArrayBufferView(JSArrayBufferView::cast(*receiver)); | 448 return WriteJSArrayBufferView(JSArrayBufferView::cast(*receiver)); |
| 450 default: | 449 default: |
| 451 ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver); | 450 ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver); |
| 452 return Nothing<bool>(); | 451 return Nothing<bool>(); |
| 453 } | 452 } |
| 454 return Nothing<bool>(); | 453 return Nothing<bool>(); |
| 455 } | 454 } |
| 456 | 455 |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 718 for (int i = 0; i < length; i++) { | 717 for (int i = 0; i < length; i++) { |
| 719 if (!WriteObject(handle(entries->get(i), isolate_)).FromMaybe(false)) { | 718 if (!WriteObject(handle(entries->get(i), isolate_)).FromMaybe(false)) { |
| 720 return Nothing<bool>(); | 719 return Nothing<bool>(); |
| 721 } | 720 } |
| 722 } | 721 } |
| 723 WriteTag(SerializationTag::kEndJSSet); | 722 WriteTag(SerializationTag::kEndJSSet); |
| 724 WriteVarint<uint32_t>(length); | 723 WriteVarint<uint32_t>(length); |
| 725 return Just(true); | 724 return Just(true); |
| 726 } | 725 } |
| 727 | 726 |
| 728 Maybe<bool> ValueSerializer::WriteJSArrayBuffer( | 727 Maybe<bool> ValueSerializer::WriteJSArrayBuffer(JSArrayBuffer* array_buffer) { |
| 729 Handle<JSArrayBuffer> array_buffer) { | 728 uint32_t* transfer_entry = array_buffer_transfer_map_.Find(array_buffer); |
| 730 if (array_buffer->is_shared()) { | 729 if (transfer_entry) { |
| 731 if (!delegate_) { | 730 WriteTag(array_buffer->is_shared() |
| 732 ThrowDataCloneError(MessageTemplate::kDataCloneError, array_buffer); | 731 ? SerializationTag::kSharedArrayBufferTransfer |
| 733 return Nothing<bool>(); | 732 : SerializationTag::kArrayBufferTransfer); |
| 734 } | 733 WriteVarint(*transfer_entry); |
| 735 | |
| 736 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_); | |
| 737 Maybe<uint32_t> index = delegate_->GetSharedArrayBufferId( | |
| 738 v8_isolate, Utils::ToLocalShared(array_buffer)); | |
| 739 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate_, Nothing<bool>()); | |
| 740 | |
| 741 WriteTag(SerializationTag::kSharedArrayBuffer); | |
| 742 WriteVarint(index.FromJust()); | |
| 743 return Just(true); | 734 return Just(true); |
| 744 } | 735 } |
| 745 | 736 |
| 746 uint32_t* transfer_entry = array_buffer_transfer_map_.Find(array_buffer); | 737 if (array_buffer->is_shared()) { |
| 747 if (transfer_entry) { | 738 ThrowDataCloneError( |
| 748 WriteTag(SerializationTag::kArrayBufferTransfer); | 739 MessageTemplate::kDataCloneErrorSharedArrayBufferNotTransferred); |
| 749 WriteVarint(*transfer_entry); | 740 return Nothing<bool>(); |
| 750 return Just(true); | |
| 751 } | 741 } |
| 752 if (array_buffer->was_neutered()) { | 742 if (array_buffer->was_neutered()) { |
| 753 ThrowDataCloneError(MessageTemplate::kDataCloneErrorNeuteredArrayBuffer); | 743 ThrowDataCloneError(MessageTemplate::kDataCloneErrorNeuteredArrayBuffer); |
| 754 return Nothing<bool>(); | 744 return Nothing<bool>(); |
| 755 } | 745 } |
| 756 double byte_length = array_buffer->byte_length()->Number(); | 746 double byte_length = array_buffer->byte_length()->Number(); |
| 757 if (byte_length > std::numeric_limits<uint32_t>::max()) { | 747 if (byte_length > std::numeric_limits<uint32_t>::max()) { |
| 758 ThrowDataCloneError(MessageTemplate::kDataCloneError, array_buffer); | 748 ThrowDataCloneError(MessageTemplate::kDataCloneError, handle(array_buffer)); |
| 759 return Nothing<bool>(); | 749 return Nothing<bool>(); |
| 760 } | 750 } |
| 761 WriteTag(SerializationTag::kArrayBuffer); | 751 WriteTag(SerializationTag::kArrayBuffer); |
| 762 WriteVarint<uint32_t>(byte_length); | 752 WriteVarint<uint32_t>(byte_length); |
| 763 WriteRawBytes(array_buffer->backing_store(), byte_length); | 753 WriteRawBytes(array_buffer->backing_store(), byte_length); |
| 764 return Just(true); | 754 return Just(true); |
| 765 } | 755 } |
| 766 | 756 |
| 767 Maybe<bool> ValueSerializer::WriteJSArrayBufferView(JSArrayBufferView* view) { | 757 Maybe<bool> ValueSerializer::WriteJSArrayBufferView(JSArrayBufferView* view) { |
| 768 WriteTag(SerializationTag::kArrayBufferView); | 758 WriteTag(SerializationTag::kArrayBufferView); |
| (...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1108 case SerializationTag::kBeginJSMap: | 1098 case SerializationTag::kBeginJSMap: |
| 1109 return ReadJSMap(); | 1099 return ReadJSMap(); |
| 1110 case SerializationTag::kBeginJSSet: | 1100 case SerializationTag::kBeginJSSet: |
| 1111 return ReadJSSet(); | 1101 return ReadJSSet(); |
| 1112 case SerializationTag::kArrayBuffer: | 1102 case SerializationTag::kArrayBuffer: |
| 1113 return ReadJSArrayBuffer(); | 1103 return ReadJSArrayBuffer(); |
| 1114 case SerializationTag::kArrayBufferTransfer: { | 1104 case SerializationTag::kArrayBufferTransfer: { |
| 1115 const bool is_shared = false; | 1105 const bool is_shared = false; |
| 1116 return ReadTransferredJSArrayBuffer(is_shared); | 1106 return ReadTransferredJSArrayBuffer(is_shared); |
| 1117 } | 1107 } |
| 1118 case SerializationTag::kSharedArrayBuffer: { | 1108 case SerializationTag::kSharedArrayBufferTransfer: { |
| 1119 const bool is_shared = true; | 1109 const bool is_shared = true; |
| 1120 return ReadTransferredJSArrayBuffer(is_shared); | 1110 return ReadTransferredJSArrayBuffer(is_shared); |
| 1121 } | 1111 } |
| 1122 case SerializationTag::kWasmModule: | 1112 case SerializationTag::kWasmModule: |
| 1123 return ReadWasmModule(); | 1113 return ReadWasmModule(); |
| 1124 default: | 1114 default: |
| 1125 // TODO(jbroman): Introduce an explicit tag for host objects to avoid | 1115 // TODO(jbroman): Introduce an explicit tag for host objects to avoid |
| 1126 // having to treat every unknown tag as a potential host object. | 1116 // having to treat every unknown tag as a potential host object. |
| 1127 position_--; | 1117 position_--; |
| 1128 return ReadHostObject(); | 1118 return ReadHostObject(); |
| (...skipping 741 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1870 if (stack.size() != 1) { | 1860 if (stack.size() != 1) { |
| 1871 isolate_->Throw(*isolate_->factory()->NewError( | 1861 isolate_->Throw(*isolate_->factory()->NewError( |
| 1872 MessageTemplate::kDataCloneDeserializationError)); | 1862 MessageTemplate::kDataCloneDeserializationError)); |
| 1873 return MaybeHandle<Object>(); | 1863 return MaybeHandle<Object>(); |
| 1874 } | 1864 } |
| 1875 return scope.CloseAndEscape(stack[0]); | 1865 return scope.CloseAndEscape(stack[0]); |
| 1876 } | 1866 } |
| 1877 | 1867 |
| 1878 } // namespace internal | 1868 } // namespace internal |
| 1879 } // namespace v8 | 1869 } // namespace v8 |
| OLD | NEW |