Add an v8::ArrayBuffer::WasDetached method to the C++ API

V8's C++ API does not give a way to tell whether an ArrayBuffer has
been detached from the `v8::ArrayBuffer` class. In fact, as far as can
be told from the C++ API without running JS code, detached
ArrayBuffers behave the same as zero-sized ArrayBuffers and there is
no way to observe the difference. However, this difference can be
observed in JS because constructing a TypedArray from a detached
ArrayBuffer will throw.

This change adds a `WasDetached` method to the `v8::ArrayBuffer` class
to give embedders access to this information without having to run JS
code.

Bug: v8:13159
Change-Id: I2bb1e380cee1cecd31f6d48ec3d9f28c03a8a673
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3810345
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/main@{#83963}
This commit is contained in:
Andreu Botella 2022-10-27 02:15:59 +02:00 committed by V8 LUCI CQ
parent b799750f0a
commit 9df5ef70ff
5 changed files with 45 additions and 0 deletions

View File

@ -60,6 +60,7 @@ Allan Sandfeld Jensen <allan.jensen@qt.io>
Amos Lim <eui-sang.lim@samsung.com>
Andreas Anyuru <andreas.anyuru@gmail.com>
Andrei Kashcha <anvaka@gmail.com>
Andreu Botella <andreu@andreubotella.com>
Andrew Paprocki <andrew@ishiboo.com>
Anna Henningsen <anna@addaleax.net>
Antoine du Hamel <duhamelantoine1995@gmail.com>

View File

@ -240,6 +240,11 @@ class V8_EXPORT ArrayBuffer : public Object {
*/
bool IsDetachable() const;
/**
* Returns true if this ArrayBuffer has been detached.
*/
bool WasDetached() const;
/**
* Detaches this ArrayBuffer and all its views (typed arrays).
* Detaching sets the byte length of the buffer and all typed arrays to zero,
@ -271,6 +276,9 @@ class V8_EXPORT ArrayBuffer : public Object {
* pointer coordinates the lifetime management of the internal storage
* with any live ArrayBuffers on the heap, even across isolates. The embedder
* should not attempt to manage lifetime of the storage through other means.
*
* The returned shared pointer will not be empty, even if the ArrayBuffer has
* been detached. Use |WasDetached| to tell if it has been detached instead.
*/
std::shared_ptr<BackingStore> GetBackingStore();

View File

@ -8100,6 +8100,10 @@ bool v8::ArrayBuffer::IsDetachable() const {
return Utils::OpenHandle(this)->is_detachable();
}
bool v8::ArrayBuffer::WasDetached() const {
return Utils::OpenHandle(this)->was_detached();
}
namespace {
std::shared_ptr<i::BackingStore> ToInternal(
std::shared_ptr<i::BackingStoreBase> backing_store) {

View File

@ -513,6 +513,7 @@
'test-api/WasmI32AtomicWaitCallback': [SKIP],
'test-api/WasmI64AtomicWaitCallback': [SKIP],
'test-api/WasmSetJitCodeEventHandler': [SKIP],
'test-api-array-buffer/ArrayBuffer_NonDetachableWasDetached': [SKIP],
'test-backing-store/Run_WasmModule_Buffer_Externalized_Regression_UseAfterFree': [SKIP],
'test-c-wasm-entry/*': [SKIP],
'test-compilation-cache/*': [SKIP],

View File

@ -245,6 +245,37 @@ THREADED_TEST(ArrayBuffer_DetachingScript) {
CheckDataViewIsDetached(dv);
}
THREADED_TEST(ArrayBuffer_WasDetached) {
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope handle_scope(isolate);
Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 0);
CHECK(!ab->WasDetached());
ab->Detach(v8::Local<v8::Value>()).Check();
CHECK(ab->WasDetached());
}
THREADED_TEST(ArrayBuffer_NonDetachableWasDetached) {
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope handle_scope(isolate);
CompileRun(R"JS(
var wasmMemory = new WebAssembly.Memory({initial: 1, maximum: 2});
)JS");
Local<v8::ArrayBuffer> non_detachable =
CompileRun("wasmMemory.buffer").As<v8::ArrayBuffer>();
CHECK(!non_detachable->IsDetachable());
CHECK(!non_detachable->WasDetached());
CompileRun("wasmMemory.grow(1)");
CHECK(!non_detachable->IsDetachable());
CHECK(non_detachable->WasDetached());
}
THREADED_TEST(ArrayBuffer_ExternalizeEmpty) {
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();