1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
|
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/modules/webcodecs/array_buffer_util.h"
#include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h"
namespace blink {
ArrayBufferContents PinSharedArrayBufferContent(
const AllowSharedBufferSource* buffer_union) {
ArrayBufferContents result;
switch (buffer_union->GetContentType()) {
case AllowSharedBufferSource::ContentType::kArrayBufferAllowShared: {
auto* buffer = buffer_union->GetAsArrayBufferAllowShared();
if (buffer && !buffer->IsDetached() && buffer->IsShared()) {
buffer->Content()->ShareWith(result);
}
break;
}
case AllowSharedBufferSource::ContentType::kArrayBufferViewAllowShared: {
auto* view = buffer_union->GetAsArrayBufferViewAllowShared().Get();
if (view && !view->IsDetached() && view->IsShared()) {
view->BufferShared()->Content()->ShareWith(result);
}
break;
}
}
return result;
}
ArrayBufferContents TransferArrayBufferForSpan(
const HeapVector<Member<DOMArrayBuffer>>& transfer_list,
base::span<const uint8_t> data_range,
ExceptionState& exception_state,
v8::Isolate* isolate) {
// Before transferring anything, we check that all the arraybuffers in the
// list are transferable and there are no duplicates.
HeapHashSet<Member<DOMArrayBuffer>> seen_buffers;
for (const Member<DOMArrayBuffer>& array_buffer : transfer_list) {
if (!array_buffer) {
continue;
}
if (!array_buffer->IsDetachable(isolate) || array_buffer->IsDetached()) {
exception_state.ThrowDOMException(DOMExceptionCode::kDataCloneError,
"Cannot detach ArrayBuffer");
return {};
}
if (!seen_buffers.insert(array_buffer).is_new_entry) {
// While inserting we found that the buffer has already been seen.
exception_state.ThrowDOMException(
DOMExceptionCode::kDataCloneError,
"Duplicate ArrayBuffers in the transfer list");
return {};
}
}
// Transfer all arraybuffers and check if any of them encompass given
// `data_range`.
ArrayBufferContents result;
for (const Member<DOMArrayBuffer>& array_buffer : transfer_list) {
if (!array_buffer) {
continue;
}
ArrayBufferContents contents;
if (!array_buffer->Transfer(isolate, contents, exception_state) ||
!contents.IsValid()) {
if (exception_state.HadException()) {
return {};
}
continue;
}
auto contents_data = contents.ByteSpan();
if (contents_data.empty() || data_range.empty() ||
data_range.data() < contents_data.data() ||
&data_range.back() > &contents_data.back()) {
// This array buffer doesn't contain `data_range`. Let's ignore it.
continue;
}
if (!result.IsValid()) {
// We haven't found a matching arraybuffer yet, and this one meets
// all the criteria. It is our result.
contents.Transfer(result);
}
}
return result;
}
} // namespace blink
|