Changeset 249594 in webkit
- Timestamp:
- Sep 6, 2019 3:15:51 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r249593 r249594 1 2019-09-06 Said Abou-Hallawa <sabouhallawa@apple.com> 2 3 REGRESSION (r249367): m_decodingPromises grows indefinitely until ImageLoader destruction 4 https://bugs.webkit.org/show_bug.cgi?id=201402 5 6 Reviewed by Youenn Fablet and Daniel Bates. 7 8 * fast/images/decode-resolve-reject-no-leak-expected.txt: Added. 9 * fast/images/decode-resolve-reject-no-leak.html: Added. 10 1 11 2019-09-06 Said Abou-Hallawa <sabouhallawa@apple.com> 2 12 -
trunk/Source/WebCore/ChangeLog
r249593 r249594 1 2019-09-06 Said Abou-Hallawa <sabouhallawa@apple.com> 2 3 REGRESSION (r249367): m_decodingPromises grows indefinitely until ImageLoader destruction 4 https://bugs.webkit.org/show_bug.cgi?id=201402 5 6 Reviewed by Youenn Fablet and Daniel Bates. 7 8 Add the static functions resolvePromises() and rejectPromises(). These 9 functions take an lvalue reference to a Vector of promises. Inside them, 10 the lvalue reference argument are exchanged with an empty Vector of 11 promises then the promises are processed. This clears m_decodingPromises 12 and fixes the leak. 13 14 Add an internal API which returns the count of the pending promises of 15 an HTMLImageElement. This internal API will be used in the attached test. 16 17 Test: fast/images/decode-resolve-reject-no-leak.html 18 19 * html/HTMLImageElement.h: 20 (WebCore::HTMLImageElement::pendingDecodePromisesCountForTesting const): 21 * loader/ImageLoader.cpp: 22 (WebCore::resolvePromises): 23 ImageLoader::decode() calls BitmapImage::decode() and moves m_decodingPromises 24 in capture. When decoding finishes, this function is called to resolve the 25 promises. But ImageLoader might get deleted before the image decoding 26 finishes. So this function has to be static. 27 28 (WebCore::rejectPromises): 29 (WebCore::ImageLoader::resolveDecodePromises): 30 (WebCore::ImageLoader::rejectDecodePromises): 31 (WebCore::ImageLoader::notifyFinished): 32 (WebCore::ImageLoader::decode): 33 (WebCore::resolveDecodePromises): Deleted. 34 (WebCore::rejectDecodePromises): Deleted. 35 * loader/ImageLoader.h: 36 (WebCore::ImageLoader::pendingDecodePromisesCountForTesting const): 37 * testing/Internals.cpp: 38 (WebCore::Internals::imagePendingDecodePromisesCountForTesting): 39 * testing/Internals.h: 40 * testing/Internals.idl: 41 1 42 2019-09-06 Said Abou-Hallawa <sabouhallawa@apple.com> 2 43 -
trunk/Source/WebCore/html/HTMLImageElement.h
r249480 r249594 105 105 106 106 bool hasPendingActivity() const { return m_imageLoader.hasPendingActivity(); } 107 size_t pendingDecodePromisesCountForTesting() const { return m_imageLoader.pendingDecodePromisesCountForTesting(); } 107 108 108 109 bool canContainRangeEndPoint() const override { return false; } -
trunk/Source/WebCore/loader/ImageLoader.cpp
r249367 r249594 276 276 } 277 277 278 static inline void resolve DecodePromises(Vector<RefPtr<DeferredPromise>>&& promises)278 static inline void resolvePromises(Vector<RefPtr<DeferredPromise>>& promises) 279 279 { 280 280 ASSERT(!promises.isEmpty()); 281 for (auto& promise : promises) 281 auto promisesToBeResolved = std::exchange(promises, { }); 282 for (auto& promise : promisesToBeResolved) 282 283 promise->resolve(); 283 284 } 284 285 285 static inline void reject DecodePromises(Vector<RefPtr<DeferredPromise>>&& promises, const char* message)286 static inline void rejectPromises(Vector<RefPtr<DeferredPromise>>& promises, const char* message) 286 287 { 287 288 ASSERT(!promises.isEmpty()); 288 for (auto& promise : promises) 289 auto promisesToBeRejected = std::exchange(promises, { }); 290 for (auto& promise : promisesToBeRejected) 289 291 promise->reject(Exception { EncodingError, message }); 292 } 293 294 inline void ImageLoader::resolveDecodePromises() 295 { 296 resolvePromises(m_decodingPromises); 297 } 298 299 inline void ImageLoader::rejectDecodePromises(const char* message) 300 { 301 rejectPromises(m_decodingPromises, message); 290 302 } 291 303 … … 314 326 315 327 if (hasPendingDecodePromises()) 316 rejectDecodePromises( WTFMove(m_decodingPromises),"Access control error.");328 rejectDecodePromises("Access control error."); 317 329 318 330 ASSERT(!m_hasPendingLoadEvent); … … 326 338 if (m_image->wasCanceled()) { 327 339 if (hasPendingDecodePromises()) 328 rejectDecodePromises( WTFMove(m_decodingPromises),"Loading was canceled.");340 rejectDecodePromises("Loading was canceled."); 329 341 m_hasPendingLoadEvent = false; 330 342 // Only consider updating the protection ref-count of the Element immediately before returning … … 403 415 404 416 if (!element().document().domWindow()) { 405 rejectDecodePromises( WTFMove(m_decodingPromises),"Inactive document.");417 rejectDecodePromises("Inactive document."); 406 418 return; 407 419 } … … 409 421 AtomString attr = element().imageSourceURL(); 410 422 if (stripLeadingAndTrailingHTMLSpaces(attr).isEmpty()) { 411 rejectDecodePromises( WTFMove(m_decodingPromises),"Missing source URL.");423 rejectDecodePromises("Missing source URL."); 412 424 return; 413 425 } … … 422 434 423 435 if (!element().document().domWindow()) { 424 rejectDecodePromises( WTFMove(m_decodingPromises),"Inactive document.");436 rejectDecodePromises("Inactive document."); 425 437 return; 426 438 } 427 439 428 440 if (!m_image || !m_image->image() || m_image->errorOccurred()) { 429 rejectDecodePromises( WTFMove(m_decodingPromises),"Loading error.");441 rejectDecodePromises("Loading error."); 430 442 return; 431 443 } … … 433 445 Image* image = m_image->image(); 434 446 if (!is<BitmapImage>(image)) { 435 resolveDecodePromises( WTFMove(m_decodingPromises));447 resolveDecodePromises(); 436 448 return; 437 449 } … … 439 451 auto& bitmapImage = downcast<BitmapImage>(*image); 440 452 bitmapImage.decode([promises = WTFMove(m_decodingPromises)]() mutable { 441 resolve DecodePromises(WTFMove(promises));453 resolvePromises(promises); 442 454 }); 443 455 } -
trunk/Source/WebCore/loader/ImageLoader.h
r249367 r249594 62 62 void clearImage(); // Cancels pending beforeload and load events, and doesn't dispatch new ones. 63 63 64 size_t pendingDecodePromisesCountForTesting() const { return m_decodingPromises.size(); } 64 65 void decode(Ref<DeferredPromise>&&); 65 66 … … 96 97 97 98 bool hasPendingDecodePromises() const { return !m_decodingPromises.isEmpty(); } 99 void resolveDecodePromises(); 100 void rejectDecodePromises(const char* message); 98 101 void decode(); 99 102 -
trunk/Source/WebCore/testing/Internals.cpp
r249531 r249594 871 871 } 872 872 873 unsigned Internals::imagePendingDecodePromisesCountForTesting(HTMLImageElement& element) 874 { 875 return element.pendingDecodePromisesCountForTesting(); 876 } 877 873 878 void Internals::setClearDecoderAfterAsyncFrameRequestForTesting(HTMLImageElement& element, bool enabled) 874 879 { -
trunk/Source/WebCore/testing/Internals.h
r248373 r249594 155 155 void resetImageAnimation(HTMLImageElement&); 156 156 bool isImageAnimating(HTMLImageElement&); 157 unsigned imagePendingDecodePromisesCountForTesting(HTMLImageElement&); 157 158 void setClearDecoderAfterAsyncFrameRequestForTesting(HTMLImageElement&, bool enabled); 158 159 unsigned imageDecodeCount(HTMLImageElement&); -
trunk/Source/WebCore/testing/Internals.idl
r248373 r249594 370 370 void resetImageAnimation(HTMLImageElement element); 371 371 boolean isImageAnimating(HTMLImageElement element); 372 unsigned long imagePendingDecodePromisesCountForTesting(HTMLImageElement element); 372 373 void setClearDecoderAfterAsyncFrameRequestForTesting(HTMLImageElement element, boolean enabled); 373 374 unsigned long imageDecodeCount(HTMLImageElement element);
Note: See TracChangeset
for help on using the changeset viewer.