diff --git a/blink/renderer/core/typed_arrays/dom_array_buffer.cc b/blink/renderer/core/typed_arrays/dom_array_buffer.cc index c195e28b442626b693063a3f5b6ad1bc4ceecbed..bbf87ad0314be98b90ddf509d458261411d4178b 100644 --- a/blink/renderer/core/typed_arrays/dom_array_buffer.cc +++ b/blink/renderer/core/typed_arrays/dom_array_buffer.cc @@ -46,12 +46,21 @@ const WrapperTypeInfo& DOMArrayBuffer::wrapper_type_info_ = static void AccumulateArrayBuffersForAllWorlds( v8::Isolate* isolate, - DOMArrayBuffer* object, + const DOMArrayBuffer* object, Vector, 4>& buffers) { + if (!object->has_non_main_world_wrappers() && IsMainThread()) { + const DOMWrapperWorld& world = DOMWrapperWorld::MainWorld(); + v8::Local wrapper = world.DomDataStore().Get(const_cast(object), isolate); + if (!wrapper.IsEmpty()){ + buffers.push_back(v8::Local::Cast(wrapper)); + } + return; + } + Vector> worlds; DOMWrapperWorld::AllWorldsInCurrentThread(worlds); for (const auto& world : worlds) { - v8::Local wrapper = world->DomDataStore().Get(object, isolate); + v8::Local wrapper = world->DomDataStore().Get(const_cast(object), isolate); if (!wrapper.IsEmpty()) buffers.push_back(v8::Local::Cast(wrapper)); } @@ -256,6 +265,47 @@ v8::MaybeLocal DOMArrayBuffer::Wrap(ScriptState* script_state) { wrapper); } +bool DOMArrayBuffer::IsDetached() const { + if (contents_.BackingStore() == nullptr) { + return is_detached_; + } + if (is_detached_) { + return true; + } + + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope handle_scope(isolate); + Vector, 4> buffer_handles; + AccumulateArrayBuffersForAllWorlds(isolate, this, buffer_handles); + + // There may be several v8::ArrayBuffers corresponding to the DOMArrayBuffer, + // but at most one of them may be non-detached. + int nondetached_count = 0; + int detached_count = 0; + + for (const auto& buffer_handle : buffer_handles) { + if (buffer_handle->WasDetached()) { + ++detached_count; + } else { + ++nondetached_count; + } + } + CHECK_LE(nondetached_count, 1); + + return nondetached_count == 0 && detached_count > 0; +} + +v8::Local DOMArrayBuffer::AssociateWithWrapper( + v8::Isolate* isolate, + const WrapperTypeInfo* wrapper_type_info, + v8::Local wrapper) { + if (!DOMWrapperWorld::Current(isolate).IsMainWorld()) { + has_non_main_world_wrappers_ = true; + } + return ScriptWrappable::AssociateWithWrapper(isolate, wrapper_type_info, + wrapper); +} + DOMArrayBuffer* DOMArrayBuffer::Slice(size_t begin, size_t end) const { begin = std::min(begin, ByteLength()); end = std::min(end, ByteLength()); diff --git a/blink/renderer/core/typed_arrays/dom_array_buffer.h b/blink/renderer/core/typed_arrays/dom_array_buffer.h index 87881af878749bc374ca6dc46f4d6ae457e0d4f0..84322ff31fcc85e26e76dd1662d555a9ecea875e 100644 --- a/blink/renderer/core/typed_arrays/dom_array_buffer.h +++ b/blink/renderer/core/typed_arrays/dom_array_buffer.h @@ -87,6 +87,17 @@ class CORE_EXPORT DOMArrayBuffer : public DOMArrayBufferBase { void Trace(Visitor*) const override; + bool IsDetached() const override; + + v8::Local AssociateWithWrapper( + v8::Isolate* isolate, + const WrapperTypeInfo* wrapper_type_info, + v8::Local wrapper) override; + + bool has_non_main_world_wrappers() const { + return has_non_main_world_wrappers_; + } + private: v8::Maybe TransferDetachable(v8::Isolate*, v8::Local detach_key, @@ -97,6 +108,8 @@ class CORE_EXPORT DOMArrayBuffer : public DOMArrayBufferBase { // support only v8::String as the detach key type. It's also convenient that // we can write `array_buffer->SetDetachKey(isolate, "my key")`. TraceWrapperV8Reference detach_key_; + + bool has_non_main_world_wrappers_ = false; }; } // namespace blink diff --git a/blink/renderer/core/typed_arrays/dom_array_buffer_base.h b/blink/renderer/core/typed_arrays/dom_array_buffer_base.h index 95511438595715d030e5f18760b210cf7e58311a..985044ccc1de97dca903b22e5f41e55be52f2533 100644 --- a/blink/renderer/core/typed_arrays/dom_array_buffer_base.h +++ b/blink/renderer/core/typed_arrays/dom_array_buffer_base.h @@ -27,7 +27,9 @@ class CORE_EXPORT DOMArrayBufferBase : public ScriptWrappable { size_t ByteLength() const { return contents_.DataLength(); } - bool IsDetached() const { return is_detached_; } + // TODO(331348222): It doesn't make sense to detach DomSharedArrayBuffers, + // remove that possibility. + virtual bool IsDetached() const { return is_detached_; } void Detach() { is_detached_ = true; }