blob: 769b42719218876f501be63f7594db73234b8b49 [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 "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/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::IsNeuterable(v8::Isolate* isolate) {
Vector<v8::Local<v8::ArrayBuffer>, 4> buffer_handles;
v8::HandleScope handle_scope(isolate);
AccumulateArrayBuffersForAllWorlds(isolate, this, buffer_handles);
bool is_neuterable = true;
for (const auto& buffer_handle : buffer_handles)
is_neuterable &= buffer_handle->IsDetachable();
return is_neuterable;
}
bool DOMArrayBuffer::Transfer(v8::Isolate* isolate,
WTF::ArrayBufferContents& result) {
DOMArrayBuffer* to_transfer = this;
if (!IsNeuterable(isolate)) {
to_transfer =
DOMArrayBuffer::Create(Buffer()->Data(), Buffer()->ByteLength());
}
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->Neuter();
return true;
}
DOMArrayBuffer* DOMArrayBuffer::CreateUninitializedOrNull(
unsigned num_elements,
unsigned element_byte_size) {
scoped_refptr<ArrayBuffer> buffer =
WTF::ArrayBuffer::CreateUninitializedOrNull(num_elements,
element_byte_size);
if (!buffer)
return nullptr;
return Create(std::move(buffer));
}
v8::Local<v8::Object> 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::Object> wrapper;
{
v8::Context::Scope context_scope(creation_context->CreationContext());
wrapper = v8::ArrayBuffer::New(isolate, Data(), ByteLength());
}
return AssociateWithWrapper(isolate, wrapper_type_info, wrapper);
}
DOMArrayBuffer* DOMArrayBuffer::Create(
scoped_refptr<SharedBuffer> shared_buffer) {
WTF::ArrayBufferContents contents(shared_buffer->size(), 1,
WTF::ArrayBufferContents::kNotShared,
WTF::ArrayBufferContents::kDontInitialize);
uint8_t* data = static_cast<uint8_t*>(contents.Data());
if (UNLIKELY(!data))
OOM_CRASH();
for (const auto& span : *shared_buffer) {
memcpy(data, span.data(), span.size());
data += span.size();
}
return Create(ArrayBuffer::Create(contents));
}
} // namespace blink