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 (transferred). transferID:uint32_t | 113 // Shared array buffer. transferID:uint32_t |
114 kSharedArrayBufferTransfer = 'u', | 114 kSharedArrayBuffer = '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()); | |
272 array_buffer_transfer_map_.Set(array_buffer, transfer_id); | 273 array_buffer_transfer_map_.Set(array_buffer, transfer_id); |
273 } | 274 } |
274 | 275 |
275 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) { | 276 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) { |
276 if (object->IsSmi()) { | 277 if (object->IsSmi()) { |
277 WriteSmi(Smi::cast(*object)); | 278 WriteSmi(Smi::cast(*object)); |
278 return Just(true); | 279 return Just(true); |
279 } | 280 } |
280 | 281 |
281 DCHECK(object->IsHeapObject()); | 282 DCHECK(object->IsHeapObject()); |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
435 case JS_VALUE_TYPE: | 436 case JS_VALUE_TYPE: |
436 return WriteJSValue(Handle<JSValue>::cast(receiver)); | 437 return WriteJSValue(Handle<JSValue>::cast(receiver)); |
437 case JS_REGEXP_TYPE: | 438 case JS_REGEXP_TYPE: |
438 WriteJSRegExp(JSRegExp::cast(*receiver)); | 439 WriteJSRegExp(JSRegExp::cast(*receiver)); |
439 return Just(true); | 440 return Just(true); |
440 case JS_MAP_TYPE: | 441 case JS_MAP_TYPE: |
441 return WriteJSMap(Handle<JSMap>::cast(receiver)); | 442 return WriteJSMap(Handle<JSMap>::cast(receiver)); |
442 case JS_SET_TYPE: | 443 case JS_SET_TYPE: |
443 return WriteJSSet(Handle<JSSet>::cast(receiver)); | 444 return WriteJSSet(Handle<JSSet>::cast(receiver)); |
444 case JS_ARRAY_BUFFER_TYPE: | 445 case JS_ARRAY_BUFFER_TYPE: |
445 return WriteJSArrayBuffer(JSArrayBuffer::cast(*receiver)); | 446 return WriteJSArrayBuffer(Handle<JSArrayBuffer>::cast(receiver)); |
446 case JS_TYPED_ARRAY_TYPE: | 447 case JS_TYPED_ARRAY_TYPE: |
447 case JS_DATA_VIEW_TYPE: | 448 case JS_DATA_VIEW_TYPE: |
448 return WriteJSArrayBufferView(JSArrayBufferView::cast(*receiver)); | 449 return WriteJSArrayBufferView(JSArrayBufferView::cast(*receiver)); |
449 default: | 450 default: |
450 ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver); | 451 ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver); |
451 return Nothing<bool>(); | 452 return Nothing<bool>(); |
452 } | 453 } |
453 return Nothing<bool>(); | 454 return Nothing<bool>(); |
454 } | 455 } |
455 | 456 |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
717 for (int i = 0; i < length; i++) { | 718 for (int i = 0; i < length; i++) { |
718 if (!WriteObject(handle(entries->get(i), isolate_)).FromMaybe(false)) { | 719 if (!WriteObject(handle(entries->get(i), isolate_)).FromMaybe(false)) { |
719 return Nothing<bool>(); | 720 return Nothing<bool>(); |
720 } | 721 } |
721 } | 722 } |
722 WriteTag(SerializationTag::kEndJSSet); | 723 WriteTag(SerializationTag::kEndJSSet); |
723 WriteVarint<uint32_t>(length); | 724 WriteVarint<uint32_t>(length); |
724 return Just(true); | 725 return Just(true); |
725 } | 726 } |
726 | 727 |
727 Maybe<bool> ValueSerializer::WriteJSArrayBuffer(JSArrayBuffer* array_buffer) { | 728 Maybe<bool> ValueSerializer::WriteJSArrayBuffer( |
728 uint32_t* transfer_entry = array_buffer_transfer_map_.Find(array_buffer); | 729 Handle<JSArrayBuffer> array_buffer) { |
729 if (transfer_entry) { | 730 if (array_buffer->is_shared()) { |
730 WriteTag(array_buffer->is_shared() | 731 if (!delegate_) { |
731 ? SerializationTag::kSharedArrayBufferTransfer | 732 ThrowDataCloneError(MessageTemplate::kDataCloneError, array_buffer); |
732 : SerializationTag::kArrayBufferTransfer); | 733 return Nothing<bool>(); |
733 WriteVarint(*transfer_entry); | 734 } |
735 | |
736 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_); | |
737 Maybe<uint32_t> index = delegate_->TransferSharedArrayBuffer( | |
738 v8_isolate, Utils::ToLocalShared(array_buffer)); | |
739 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate_, Nothing<bool>()); | |
740 DCHECK(!index.IsNothing()); | |
jbroman
2016/12/15 16:15:33
super-nit: index.FromJust() will already crash in
binji
2016/12/15 19:31:20
Done.
| |
741 | |
742 WriteTag(SerializationTag::kSharedArrayBuffer); | |
743 WriteVarint(index.FromJust()); | |
734 return Just(true); | 744 return Just(true); |
735 } | 745 } |
736 | 746 |
737 if (array_buffer->is_shared()) { | 747 uint32_t* transfer_entry = array_buffer_transfer_map_.Find(array_buffer); |
738 ThrowDataCloneError( | 748 if (transfer_entry) { |
739 MessageTemplate::kDataCloneErrorSharedArrayBufferNotTransferred); | 749 WriteTag(SerializationTag::kArrayBufferTransfer); |
740 return Nothing<bool>(); | 750 WriteVarint(*transfer_entry); |
751 return Just(true); | |
741 } | 752 } |
742 if (array_buffer->was_neutered()) { | 753 if (array_buffer->was_neutered()) { |
743 ThrowDataCloneError(MessageTemplate::kDataCloneErrorNeuteredArrayBuffer); | 754 ThrowDataCloneError(MessageTemplate::kDataCloneErrorNeuteredArrayBuffer); |
744 return Nothing<bool>(); | 755 return Nothing<bool>(); |
745 } | 756 } |
746 double byte_length = array_buffer->byte_length()->Number(); | 757 double byte_length = array_buffer->byte_length()->Number(); |
747 if (byte_length > std::numeric_limits<uint32_t>::max()) { | 758 if (byte_length > std::numeric_limits<uint32_t>::max()) { |
748 ThrowDataCloneError(MessageTemplate::kDataCloneError, handle(array_buffer)); | 759 ThrowDataCloneError(MessageTemplate::kDataCloneError, array_buffer); |
749 return Nothing<bool>(); | 760 return Nothing<bool>(); |
750 } | 761 } |
751 WriteTag(SerializationTag::kArrayBuffer); | 762 WriteTag(SerializationTag::kArrayBuffer); |
752 WriteVarint<uint32_t>(byte_length); | 763 WriteVarint<uint32_t>(byte_length); |
753 WriteRawBytes(array_buffer->backing_store(), byte_length); | 764 WriteRawBytes(array_buffer->backing_store(), byte_length); |
754 return Just(true); | 765 return Just(true); |
755 } | 766 } |
756 | 767 |
757 Maybe<bool> ValueSerializer::WriteJSArrayBufferView(JSArrayBufferView* view) { | 768 Maybe<bool> ValueSerializer::WriteJSArrayBufferView(JSArrayBufferView* view) { |
758 WriteTag(SerializationTag::kArrayBufferView); | 769 WriteTag(SerializationTag::kArrayBufferView); |
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1098 case SerializationTag::kBeginJSMap: | 1109 case SerializationTag::kBeginJSMap: |
1099 return ReadJSMap(); | 1110 return ReadJSMap(); |
1100 case SerializationTag::kBeginJSSet: | 1111 case SerializationTag::kBeginJSSet: |
1101 return ReadJSSet(); | 1112 return ReadJSSet(); |
1102 case SerializationTag::kArrayBuffer: | 1113 case SerializationTag::kArrayBuffer: |
1103 return ReadJSArrayBuffer(); | 1114 return ReadJSArrayBuffer(); |
1104 case SerializationTag::kArrayBufferTransfer: { | 1115 case SerializationTag::kArrayBufferTransfer: { |
1105 const bool is_shared = false; | 1116 const bool is_shared = false; |
1106 return ReadTransferredJSArrayBuffer(is_shared); | 1117 return ReadTransferredJSArrayBuffer(is_shared); |
1107 } | 1118 } |
1108 case SerializationTag::kSharedArrayBufferTransfer: { | 1119 case SerializationTag::kSharedArrayBuffer: { |
1109 const bool is_shared = true; | 1120 const bool is_shared = true; |
1110 return ReadTransferredJSArrayBuffer(is_shared); | 1121 return ReadTransferredJSArrayBuffer(is_shared); |
1111 } | 1122 } |
1112 case SerializationTag::kWasmModule: | 1123 case SerializationTag::kWasmModule: |
1113 return ReadWasmModule(); | 1124 return ReadWasmModule(); |
1114 default: | 1125 default: |
1115 // TODO(jbroman): Introduce an explicit tag for host objects to avoid | 1126 // TODO(jbroman): Introduce an explicit tag for host objects to avoid |
1116 // having to treat every unknown tag as a potential host object. | 1127 // having to treat every unknown tag as a potential host object. |
1117 position_--; | 1128 position_--; |
1118 return ReadHostObject(); | 1129 return ReadHostObject(); |
(...skipping 741 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1860 if (stack.size() != 1) { | 1871 if (stack.size() != 1) { |
1861 isolate_->Throw(*isolate_->factory()->NewError( | 1872 isolate_->Throw(*isolate_->factory()->NewError( |
1862 MessageTemplate::kDataCloneDeserializationError)); | 1873 MessageTemplate::kDataCloneDeserializationError)); |
1863 return MaybeHandle<Object>(); | 1874 return MaybeHandle<Object>(); |
1864 } | 1875 } |
1865 return scope.CloseAndEscape(stack[0]); | 1876 return scope.CloseAndEscape(stack[0]); |
1866 } | 1877 } |
1867 | 1878 |
1868 } // namespace internal | 1879 } // namespace internal |
1869 } // namespace v8 | 1880 } // namespace v8 |
OLD | NEW |