diff --git a/include/v8-cppgc.h b/include/v8-cppgc.h index 4a457027c9f7..e0d76f45016e 100644 --- a/include/v8-cppgc.h +++ b/include/v8-cppgc.h @@ -177,6 +177,11 @@ class V8_EXPORT CppHeap { void CollectGarbageInYoungGenerationForTesting( cppgc::EmbedderStackState stack_state); + /** + * \returns the wrapper descriptor of this CppHeap. + */ + v8::WrapperDescriptor wrapper_descriptor() const; + private: CppHeap() = default; diff --git a/src/heap/cppgc-js/cpp-heap.cc b/src/heap/cppgc-js/cpp-heap.cc index 511c2464ae19..cc061f5de532 100644 --- a/src/heap/cppgc-js/cpp-heap.cc +++ b/src/heap/cppgc-js/cpp-heap.cc @@ -147,6 +147,10 @@ void CppHeap::CollectGarbageInYoungGenerationForTesting( internal::CppHeap::CollectionType::kMinor, stack_state); } +v8::WrapperDescriptor CppHeap::wrapper_descriptor() const { + return internal::CppHeap::From(this)->wrapper_descriptor(); +} + namespace internal { namespace { diff --git a/test/unittests/heap/cppgc-js/unified-heap-unittest.cc b/test/unittests/heap/cppgc-js/unified-heap-unittest.cc index 21216f10accf..93f53c0bf8f0 100644 --- a/test/unittests/heap/cppgc-js/unified-heap-unittest.cc +++ b/test/unittests/heap/cppgc-js/unified-heap-unittest.cc @@ -710,4 +710,45 @@ TEST_F(UnifiedHeapTest, TracedReferenceHandlesDoNotLeak) { EXPECT_EQ(initial_count, final_count + 1); } +namespace { +class Wrappable2 final : public cppgc::GarbageCollected { + public: + static size_t destructor_call_count; + void Trace(cppgc::Visitor* visitor) const {} + ~Wrappable2() { destructor_call_count++; } +}; + +size_t Wrappable2::destructor_call_count = 0; +} // namespace + +TEST_F(UnifiedHeapTest, WrapperDescriptorGetter) { + v8::Isolate* isolate = v8_isolate(); + v8::HandleScope scope(isolate); + auto* wrappable_object = + cppgc::MakeGarbageCollected(allocation_handle()); + v8::WrapperDescriptor descriptor = + isolate->GetCppHeap()->wrapper_descriptor(); + v8::Local tmpl = v8::ObjectTemplate::New(isolate); + int size = std::max(descriptor.wrappable_type_index, + descriptor.wrappable_instance_index) + + 1; + tmpl->SetInternalFieldCount(size); + v8::Local api_object = + tmpl->NewInstance(isolate->GetCurrentContext()).ToLocalChecked(); + api_object->SetAlignedPointerInInternalField( + descriptor.wrappable_type_index, + &descriptor.embedder_id_for_garbage_collected); + api_object->SetAlignedPointerInInternalField( + descriptor.wrappable_instance_index, wrappable_object); + + Wrappable2::destructor_call_count = 0; + EXPECT_EQ(0u, Wrappable2::destructor_call_count); + CollectGarbageWithoutEmbedderStack(cppgc::Heap::SweepingType::kAtomic); + EXPECT_EQ(0u, Wrappable2::destructor_call_count); + api_object->SetAlignedPointerInInternalField( + descriptor.wrappable_instance_index, nullptr); + CollectGarbageWithoutEmbedderStack(cppgc::Heap::SweepingType::kAtomic); + EXPECT_EQ(1u, Wrappable2::destructor_call_count); +} + } // namespace v8::internal