[api] Add resizable getters to ArrayBuffer APIs

Adds v8::[Shared]ArrayBuffer::MaxByteLength and
v8::BackingStore::IsResizableByUserJavaScript.

This is needed for embedders who need to check if a buffer is resizable
by user JS, like blink, to check for the [AllowResizable] WebIDL
extended attribute.

Bug: v8:11111
Change-Id: Ie7e03979ef3884123df8a3eeb5c3516c4a6967c2
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4082276
Reviewed-by: Marja Hölttä <marja@chromium.org>
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Commit-Queue: Shu-yu Guo <syg@chromium.org>
Cr-Commit-Position: refs/heads/main@{#84715}
This commit is contained in:
Shu-yu Guo 2022-12-06 17:29:09 -08:00 committed by V8 LUCI CQ
parent e8a22c8eaa
commit 90742c6040
3 changed files with 75 additions and 0 deletions

View File

@ -59,6 +59,13 @@ class V8_EXPORT BackingStore : public v8::internal::BackingStoreBase {
*/
bool IsShared() const;
/**
* Indicates whether the backing store was created for a resizable ArrayBuffer
* or a growable SharedArrayBuffer, and thus may be resized by user JavaScript
* code.
*/
bool IsResizableByUserJavaScript() const;
/**
* Prevent implicit instantiation of operator delete with size_t argument.
* The size_t argument would be incorrect because ptr points to the
@ -189,6 +196,11 @@ class V8_EXPORT ArrayBuffer : public Object {
*/
size_t ByteLength() const;
/**
* Maximum length in bytes.
*/
size_t MaxByteLength() const;
/**
* Create a new ArrayBuffer. Allocate |byte_length| bytes.
* Allocated memory will be owned by a created ArrayBuffer and
@ -392,6 +404,11 @@ class V8_EXPORT SharedArrayBuffer : public Object {
*/
size_t ByteLength() const;
/**
* Maximum length in bytes.
*/
size_t MaxByteLength() const;
/**
* Create a new SharedArrayBuffer. Allocate |byte_length| bytes.
* Allocated memory will be owned by a created SharedArrayBuffer and

View File

@ -4195,6 +4195,10 @@ bool v8::BackingStore::IsShared() const {
return reinterpret_cast<const i::BackingStore*>(this)->is_shared();
}
bool v8::BackingStore::IsResizableByUserJavaScript() const {
return reinterpret_cast<const i::BackingStore*>(this)->is_resizable_by_js();
}
// static
std::unique_ptr<v8::BackingStore> v8::BackingStore::Reallocate(
v8::Isolate* v8_isolate, std::unique_ptr<v8::BackingStore> backing_store,
@ -8263,6 +8267,11 @@ size_t v8::ArrayBuffer::ByteLength() const {
return obj->GetByteLength();
}
size_t v8::ArrayBuffer::MaxByteLength() const {
i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
return obj->max_byte_length();
}
Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* v8_isolate,
size_t byte_length) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
@ -8478,6 +8487,11 @@ size_t v8::SharedArrayBuffer::ByteLength() const {
return obj->GetByteLength();
}
size_t v8::SharedArrayBuffer::MaxByteLength() const {
i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
return obj->max_byte_length();
}
Local<SharedArrayBuffer> v8::SharedArrayBuffer::New(Isolate* v8_isolate,
size_t byte_length) {
CHECK(i::v8_flags.harmony_sharedarraybuffer);

View File

@ -6,6 +6,7 @@
#include "src/base/strings.h"
#include "src/objects/js-array-buffer-inl.h"
#include "test/cctest/test-api.h"
#include "test/common/flag-utils.h"
using ::v8::Array;
using ::v8::Context;
@ -810,3 +811,46 @@ TEST(BackingStore_ReallocateShared) {
v8::BackingStore::Reallocate(isolate, std::move(backing_store), 10);
CHECK(new_backing_store->IsShared());
}
TEST(ArrayBuffer_Resizable) {
FLAG_SCOPE(harmony_rab_gsab);
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope handle_scope(isolate);
// TODO(v8:11111): Expose ability to create resizable buffers to API?
const char rab_source[] = "new ArrayBuffer(32, { maxByteLength: 1024 });";
v8::Local<v8::ArrayBuffer> rab = CompileRun(rab_source).As<v8::ArrayBuffer>();
CHECK(rab->GetBackingStore()->IsResizableByUserJavaScript());
CHECK_EQ(32, rab->ByteLength());
CHECK_EQ(1024, rab->MaxByteLength());
const char gsab_source[] =
"new SharedArrayBuffer(32, { maxByteLength: 1024 });";
v8::Local<v8::SharedArrayBuffer> gsab =
CompileRun(gsab_source).As<v8::SharedArrayBuffer>();
CHECK(gsab->GetBackingStore()->IsResizableByUserJavaScript());
CHECK_EQ(32, gsab->ByteLength());
CHECK_EQ(1024, gsab->MaxByteLength());
}
TEST(ArrayBuffer_FixedLength) {
FLAG_SCOPE(harmony_rab_gsab);
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope handle_scope(isolate);
// Fixed-length ArrayBuffers' byte length are equal to their max byte length.
v8::Local<v8::ArrayBuffer> ab =
CompileRun("new ArrayBuffer(32);").As<v8::ArrayBuffer>();
CHECK(!ab->GetBackingStore()->IsResizableByUserJavaScript());
CHECK_EQ(32, ab->ByteLength());
CHECK_EQ(32, ab->MaxByteLength());
v8::Local<v8::SharedArrayBuffer> sab =
CompileRun("new SharedArrayBuffer(32);").As<v8::SharedArrayBuffer>();
CHECK(!sab->GetBackingStore()->IsResizableByUserJavaScript());
CHECK_EQ(32, sab->ByteLength());
CHECK_EQ(32, sab->MaxByteLength());
}