| Index: src/value-serializer.cc
|
| diff --git a/src/value-serializer.cc b/src/value-serializer.cc
|
| index 756732043a404595d9412b9079d64678416906e8..bbfb2c77e038e5fe2051ec406e0ae66a15b9f045 100644
|
| --- a/src/value-serializer.cc
|
| +++ b/src/value-serializer.cc
|
| @@ -92,12 +92,15 @@ enum class SerializationTag : uint8_t {
|
| kEndJSSet = ',',
|
| // Array buffer. byteLength:uint32_t, then raw data.
|
| kArrayBuffer = 'B',
|
| + // Array buffer (transferred). transferID:uint32_t
|
| + kArrayBufferTransfer = 't',
|
| };
|
|
|
| ValueSerializer::ValueSerializer(Isolate* isolate)
|
| : isolate_(isolate),
|
| zone_(isolate->allocator()),
|
| - id_map_(isolate->heap(), &zone_) {}
|
| + id_map_(isolate->heap(), &zone_),
|
| + array_buffer_transfer_map_(isolate->heap(), &zone_) {}
|
|
|
| ValueSerializer::~ValueSerializer() {}
|
|
|
| @@ -172,6 +175,12 @@ uint8_t* ValueSerializer::ReserveRawBytes(size_t bytes) {
|
| return &buffer_[old_size];
|
| }
|
|
|
| +void ValueSerializer::TransferArrayBuffer(uint32_t transfer_id,
|
| + Handle<JSArrayBuffer> array_buffer) {
|
| + DCHECK(!array_buffer_transfer_map_.Find(array_buffer));
|
| + array_buffer_transfer_map_.Set(array_buffer, transfer_id);
|
| +}
|
| +
|
| Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) {
|
| if (object->IsSmi()) {
|
| WriteSmi(Smi::cast(*object));
|
| @@ -500,6 +509,14 @@ Maybe<bool> ValueSerializer::WriteJSSet(Handle<JSSet> set) {
|
| }
|
|
|
| Maybe<bool> ValueSerializer::WriteJSArrayBuffer(JSArrayBuffer* array_buffer) {
|
| + uint32_t* transfer_entry = array_buffer_transfer_map_.Find(array_buffer);
|
| + if (transfer_entry) {
|
| + DCHECK(array_buffer->was_neutered());
|
| + WriteTag(SerializationTag::kArrayBufferTransfer);
|
| + WriteVarint(*transfer_entry);
|
| + return Just(true);
|
| + }
|
| +
|
| if (array_buffer->was_neutered()) return Nothing<bool>();
|
| double byte_length = array_buffer->byte_length()->Number();
|
| if (byte_length > std::numeric_limits<uint32_t>::max()) {
|
| @@ -550,6 +567,11 @@ ValueDeserializer::ValueDeserializer(Isolate* isolate,
|
|
|
| ValueDeserializer::~ValueDeserializer() {
|
| GlobalHandles::Destroy(Handle<Object>::cast(id_map_).location());
|
| +
|
| + Handle<Object> transfer_map_handle;
|
| + if (array_buffer_transfer_map_.ToHandle(&transfer_map_handle)) {
|
| + GlobalHandles::Destroy(transfer_map_handle.location());
|
| + }
|
| }
|
|
|
| Maybe<bool> ValueDeserializer::ReadHeader() {
|
| @@ -645,6 +667,26 @@ Maybe<Vector<const uint8_t>> ValueDeserializer::ReadRawBytes(int size) {
|
| return Just(Vector<const uint8_t>(start, size));
|
| }
|
|
|
| +void ValueDeserializer::TransferArrayBuffer(
|
| + uint32_t transfer_id, Handle<JSArrayBuffer> array_buffer) {
|
| + if (array_buffer_transfer_map_.is_null()) {
|
| + array_buffer_transfer_map_ =
|
| + Handle<SeededNumberDictionary>::cast(isolate_->global_handles()->Create(
|
| + *SeededNumberDictionary::New(isolate_, 0)));
|
| + }
|
| + Handle<SeededNumberDictionary> dictionary =
|
| + array_buffer_transfer_map_.ToHandleChecked();
|
| + const bool used_as_prototype = false;
|
| + Handle<SeededNumberDictionary> new_dictionary =
|
| + SeededNumberDictionary::AtNumberPut(dictionary, transfer_id, array_buffer,
|
| + used_as_prototype);
|
| + if (!new_dictionary.is_identical_to(dictionary)) {
|
| + GlobalHandles::Destroy(Handle<Object>::cast(dictionary).location());
|
| + array_buffer_transfer_map_ = Handle<SeededNumberDictionary>::cast(
|
| + isolate_->global_handles()->Create(*new_dictionary));
|
| + }
|
| +}
|
| +
|
| MaybeHandle<Object> ValueDeserializer::ReadObject() {
|
| SerializationTag tag;
|
| if (!ReadTag().To(&tag)) return MaybeHandle<Object>();
|
| @@ -706,6 +748,8 @@ MaybeHandle<Object> ValueDeserializer::ReadObject() {
|
| return ReadJSSet();
|
| case SerializationTag::kArrayBuffer:
|
| return ReadJSArrayBuffer();
|
| + case SerializationTag::kArrayBufferTransfer:
|
| + return ReadTransferredJSArrayBuffer();
|
| default:
|
| return MaybeHandle<Object>();
|
| }
|
| @@ -992,6 +1036,24 @@ MaybeHandle<JSArrayBuffer> ValueDeserializer::ReadJSArrayBuffer() {
|
| return array_buffer;
|
| }
|
|
|
| +MaybeHandle<JSArrayBuffer> ValueDeserializer::ReadTransferredJSArrayBuffer() {
|
| + uint32_t id = next_id_++;
|
| + uint32_t transfer_id;
|
| + Handle<SeededNumberDictionary> transfer_map;
|
| + if (!ReadVarint<uint32_t>().To(&transfer_id) ||
|
| + !array_buffer_transfer_map_.ToHandle(&transfer_map)) {
|
| + return MaybeHandle<JSArrayBuffer>();
|
| + }
|
| + int index = transfer_map->FindEntry(isolate_, transfer_id);
|
| + if (index == SeededNumberDictionary::kNotFound) {
|
| + return MaybeHandle<JSArrayBuffer>();
|
| + }
|
| + Handle<JSArrayBuffer> array_buffer(
|
| + JSArrayBuffer::cast(transfer_map->ValueAt(index)), isolate_);
|
| + AddObjectWithID(id, array_buffer);
|
| + return array_buffer;
|
| +}
|
| +
|
| Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties(
|
| Handle<JSObject> object, SerializationTag end_tag) {
|
| for (uint32_t num_properties = 0;; num_properties++) {
|
|
|