blob: 524bb4d4ec85b6a732161c88290e06710faa927c [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// 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/core/typed_arrays/dom_array_buffer.h"
#include <algorithm>
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/bindings/dom_data_store.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
static void AccumulateArrayBuffersForAllWorlds(
v8::Isolate* isolate,
DOMArrayBuffer* object,
Vector<v8::Local<v8::ArrayBuffer>, 4>& buffers) {
Vector<scoped_refptr<DOMWrapperWorld>> worlds;
DOMWrapperWorld::AllWorldsInCurrentThread(worlds);
for (const auto& world : worlds) {
v8::Local<v8::Object> wrapper = world->DomDataStore().Get(object, isolate);
if (!wrapper.IsEmpty())
buffers.push_back(v8::Local<v8::ArrayBuffer>::Cast(wrapper));
}
}
bool DOMArrayBuffer::IsDetachable(v8::Isolate* isolate) {
Vector<v8::Local<v8::ArrayBuffer>, 4> buffer_handles;
v8::HandleScope handle_scope(isolate);
AccumulateArrayBuffersForAllWorlds(isolate, this, buffer_handles);
bool is_detachable = true;
for (const auto& buffer_handle : buffer_handles)
is_detachable &= buffer_handle->IsDetachable();
return is_detachable;
}
bool DOMArrayBuffer::Transfer(v8::Isolate* isolate,
ArrayBufferContents& result) {
DOMArrayBuffer* to_transfer = this;
if (!IsDetachable(isolate)) {
to_transfer =
DOMArrayBuffer::Create(Buffer()->Data(), Buffer()->ByteLengthAsSizeT());
}
if (!to_transfer->Buffer()->Transfer(result))
return false;
Vector<v8::Local<v8::ArrayBuffer>, 4> buffer_handles;
v8::HandleScope handle_scope(isolate);
AccumulateArrayBuffersForAllWorlds(isolate, to_transfer, buffer_handles);
for (const auto& buffer_handle : buffer_handles)
buffer_handle->Detach();
return true;
}
DOMArrayBuffer* DOMArrayBuffer::CreateUninitializedOrNull(
size_t num_elements,
size_t element_byte_size) {
scoped_refptr<ArrayBuffer> buffer =
ArrayBuffer::CreateUninitializedOrNull(num_elements, element_byte_size);
if (!buffer)
return nullptr;
return Create(std::move(buffer));
}
v8::Local<v8::Value> DOMArrayBuffer::Wrap(
v8::Isolate* isolate,
v8::Local<v8::Object> creation_context) {
DCHECK(!DOMDataStore::ContainsWrapper(this, isolate));
const WrapperTypeInfo* wrapper_type_info = this->GetWrapperTypeInfo();
v8::Local<v8::ArrayBuffer> wrapper;
{
v8::Context::Scope context_scope(creation_context->CreationContext());
wrapper =
v8::ArrayBuffer::New(isolate, Buffer()->Content()->BackingStore());
wrapper->Externalize(Buffer()->Content()->BackingStore());
}
return AssociateWithWrapper(isolate, wrapper_type_info, wrapper);
}
DOMArrayBuffer* DOMArrayBuffer::Create(
scoped_refptr<SharedBuffer> shared_buffer) {
ArrayBufferContents contents(shared_buffer->size(), 1,
ArrayBufferContents::kNotShared,
ArrayBufferContents::kDontInitialize);
uint8_t* data = static_cast<uint8_t*>(contents.Data());
if (UNLIKELY(!data))
OOM_CRASH(shared_buffer->size());
for (const auto& span : *shared_buffer) {
memcpy(data, span.data(), span.size());
data += span.size();
}
return Create(ArrayBuffer::Create(contents));
}
DOMArrayBuffer* DOMArrayBuffer::Create(
const Vector<base::span<const char>>& data) {
size_t size = 0;
for (const auto& span : data) {
size += span.size();
}
ArrayBufferContents contents(size, 1, ArrayBufferContents::kNotShared,
ArrayBufferContents::kDontInitialize);
uint8_t* ptr = static_cast<uint8_t*>(contents.Data());
if (UNLIKELY(!ptr))
OOM_CRASH(size);
for (const auto& span : data) {
memcpy(ptr, span.data(), span.size());
ptr += span.size();
}
return Create(ArrayBuffer::Create(contents));
}
DOMArrayBuffer* DOMArrayBuffer::Slice(size_t begin, size_t end) const {
begin = std::min(begin, ByteLengthAsSizeT());
end = std::min(end, ByteLengthAsSizeT());
size_t size = begin <= end ? end - begin : 0;
return Create(static_cast<const char*>(Data()) + begin, size);
}
} // namespace blink