diff --git a/third_party/blink/renderer/core/svg/svg_tree_scope_resources.cc b/third_party/blink/renderer/core/svg/svg_tree_scope_resources.cc index 2d2ab9b48ee03d..96f1b7d042c76f 100644 --- a/third_party/blink/renderer/core/svg/svg_tree_scope_resources.cc +++ b/third_party/blink/renderer/core/svg/svg_tree_scope_resources.cc @@ -17,10 +17,19 @@ SVGTreeScopeResources::SVGTreeScopeResources(TreeScope* tree_scope) LocalSVGResource* SVGTreeScopeResources::ResourceForId(const AtomicString& id) { if (id.empty()) return nullptr; - auto& entry = resources_.insert(id, nullptr).stored_value->value; - if (!entry) - entry = MakeGarbageCollected(*tree_scope_, id); - return entry.Get(); + // MakeGarbageCollected below may run a synchronous major GC at its + // allocation safepoint. That GC invokes ProcessCustomWeakness(), which can + // RemoveAll() dead entries and Shrink() `resources_`, freeing its backing. + // Because `resources_` is a PartitionAlloc-backed HashMap (not a + // HeapHashMap), the shrink is *not* suppressed by the no-allocation scope + // around weak processing. We therefore must not hold any reference or + // iterator into the backing across the allocation. + auto it = resources_.find(id); + if (it != resources_.end() && it->value) + return it->value.Get(); + auto* resource = MakeGarbageCollected(*tree_scope_, id); + resources_.Set(id, resource); + return resource; } LocalSVGResource* SVGTreeScopeResources::ExistingResourceForId(