Index: third_party/WebKit/Source/core/fetch/Resource.cpp |
diff --git a/third_party/WebKit/Source/core/fetch/Resource.cpp b/third_party/WebKit/Source/core/fetch/Resource.cpp |
index a88e43c79f3cd47a0321c0f9c034fee86bcf72e2..52b4cf5c160cc96b1beb0269ed89b86856872ad6 100644 |
--- a/third_party/WebKit/Source/core/fetch/Resource.cpp |
+++ b/third_party/WebKit/Source/core/fetch/Resource.cpp |
@@ -28,7 +28,7 @@ |
#include "core/fetch/FetchInitiatorTypeNames.h" |
#include "core/fetch/MemoryCache.h" |
#include "core/fetch/ResourceClient.h" |
-#include "core/fetch/ResourceClientOrObserverWalker.h" |
+#include "core/fetch/ResourceClientWalker.h" |
#include "core/fetch/ResourceLoader.h" |
#include "core/inspector/InstanceCounters.h" |
#include "platform/Histogram.h" |
@@ -308,6 +308,7 @@ Resource::Resource(const ResourceRequest& request, Type type, const ResourceLoad |
, m_needsSynchronousCacheHit(false) |
, m_linkPreload(false) |
, m_isRevalidating(false) |
+ , m_isAlive(false) |
, m_options(options) |
, m_responseTimestamp(currentTime()) |
, m_cancelTimer(this, &Resource::cancelTimerFired) |
@@ -331,6 +332,9 @@ DEFINE_TRACE(Resource) |
{ |
visitor->trace(m_loader); |
visitor->trace(m_cacheHandler); |
+ visitor->trace(m_clients); |
+ visitor->trace(m_clientsAwaitingCallback); |
+ visitor->trace(m_finishedClients); |
MemoryCoordinatorClient::trace(visitor); |
} |
@@ -677,8 +681,10 @@ void Resource::willAddClientOrObserver(PreloadReferencePolicy policy) |
preloadDiscoveryHistogram.count(timeSinceDiscovery); |
} |
} |
- if (!hasClientsOrObservers()) |
+ if (!hasClientsOrObservers()) { |
+ m_isAlive = true; |
memoryCache()->makeLive(this); |
+ } |
} |
void Resource::addClient(ResourceClient* client, PreloadReferencePolicy policy) |
@@ -704,7 +710,9 @@ void Resource::addClient(ResourceClient* client, PreloadReferencePolicy policy) |
void Resource::removeClient(ResourceClient* client) |
{ |
- ASSERT(hasClient(client)); |
+ // This code may be called in a pre-finalizer, where weak members in the |
+ // HashCountedSet are already swept out. |
+ |
if (m_finishedClients.contains(client)) |
m_finishedClients.remove(client); |
else if (m_clientsAwaitingCallback.contains(client)) |
@@ -716,12 +724,12 @@ void Resource::removeClient(ResourceClient* client) |
ResourceCallback::callbackHandler().cancel(this); |
didRemoveClientOrObserver(); |
- // This object may be dead here. |
} |
void Resource::didRemoveClientOrObserver() |
{ |
- if (!hasClientsOrObservers()) { |
+ if (!hasClientsOrObservers() && m_isAlive) { |
+ m_isAlive = false; |
memoryCache()->makeDead(this); |
allClientsAndObserversRemoved(); |
@@ -792,7 +800,7 @@ void Resource::finishPendingClients() |
// Handle case (1) by saving a list of clients to notify. A separate list also ensure |
// a client is either in m_clients or m_clientsAwaitingCallback. |
- Vector<ResourceClient*> clientsToNotify; |
+ HeapVector<Member<ResourceClient>> clientsToNotify; |
copyToVector(m_clientsAwaitingCallback, clientsToNotify); |
for (const auto& client : clientsToNotify) { |