summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.cc
blob: e4e9c0a05eb36d04ea604ba4d8079393471192f2 (plain)
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
95
96
97
98
99
100
101
// 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->IsNeuterable();

  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::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