From b6cae489e050036a5c025c51c524b16bff416c7b Mon Sep 17 00:00:00 2001 From: Sukhendu Sekhar Guria Date: Mon, 18 May 2026 13:12:40 +0530 Subject: [PATCH] Comments: Prevent concurrent AJAX requests on the same comment in wp-lists --- src/js/_enqueues/admin/edit-comments.js | 6 ++++ src/js/_enqueues/lib/lists.js | 44 +++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/js/_enqueues/admin/edit-comments.js b/src/js/_enqueues/admin/edit-comments.js index 78ee78de759ff..0b8ebd175f9fd 100644 --- a/src/js/_enqueues/admin/edit-comments.js +++ b/src/js/_enqueues/admin/edit-comments.js @@ -449,6 +449,12 @@ window.setCommentsList = function() { a.on( 'click', function( e ){ e.preventDefault(); e.stopPropagation(); // Ticket #35904. + + // Abort undo if there is an unfinished AJAX request on this comment. See #35501. + if ( list.wpList.xhrs.inProgress( 'comment-' + id ) ) { + return false; + } + list.wpList.del(this); $('#undo-' + id).css( {backgroundColor:'#ceb'} ).fadeOut(350, function(){ $(this).remove(); diff --git a/src/js/_enqueues/lib/lists.js b/src/js/_enqueues/lib/lists.js index d7e888c85b9ab..9cc54dff55240 100644 --- a/src/js/_enqueues/lib/lists.js +++ b/src/js/_enqueues/lib/lists.js @@ -16,6 +16,27 @@ var functions = { recolor: 'recolor' }, wpList; +/** + * Tracks in-progress XHR requests per element to prevent concurrent calls. + * + * @since x.x.x + * @private + */ +var xhrs = {}; + +/** + * Checks if an element has an in-progress XHR request. + * + * @since x.x.x + * @private + * + * @param {string} element Element ID to check. + * @return {boolean} True if a request is in progress for this element. + */ +function isXhrInProgress( element ) { + return Object.prototype.hasOwnProperty.call( xhrs, element ) && 4 !== xhrs[ element ].readyState; +} + /** * @namespace */ @@ -414,6 +435,11 @@ wpList = { settings.element = data[2] || settings.element || null; settings.delColor = data[3] ? '#' + data[3] : settings.delColor; + // Prevent concurrent AJAX requests on the same element. + if ( isXhrInProgress( settings.element ) ) { + return false; + } + if ( ! settings || ! settings.element ) { return false; } @@ -466,6 +492,8 @@ wpList = { }; settings.complete = function( jqXHR, status ) { + delete xhrs[ settings.element ]; + if ( typeof settings.delAfter === 'function' ) { $eventTarget.queue( function() { settings.delAfter( returnedResponse, $.extend( { @@ -477,7 +505,7 @@ wpList = { } }; - $.ajax( settings ); + xhrs[ settings.element ] = $.ajax( settings ); return false; }, @@ -508,6 +536,11 @@ wpList = { settings.dimAddColor = data[4] ? '#' + data[4] : settings.dimAddColor; settings.dimDelColor = data[5] ? '#' + data[5] : settings.dimDelColor; + // Prevent concurrent AJAX requests on the same element. + if ( isXhrInProgress( settings.element ) ) { + return false; + } + if ( ! settings || ! settings.element || ! settings.dimClass ) { return true; } @@ -591,6 +624,8 @@ wpList = { }; settings.complete = function( jqXHR, status ) { + delete xhrs[ settings.element ]; + if ( typeof settings.dimAfter === 'function' ) { $eventTarget.queue( function() { settings.dimAfter( returnedResponse, $.extend( { @@ -602,7 +637,7 @@ wpList = { } }; - $.ajax( settings ); + xhrs[ settings.element ] = $.ajax( settings ); return false; }, @@ -840,7 +875,10 @@ wpList = { $.fn.wpList = function( settings ) { this.each( function( index, list ) { list.wpList = { - settings: $.extend( {}, wpList.settings, { what: wpList.parseData( list, 'list' )[1] || '' }, settings ) + settings: $.extend( {}, wpList.settings, { what: wpList.parseData( list, 'list' )[1] || '' }, settings ), + xhrs: { + inProgress: isXhrInProgress + } }; $.each( functions, function( func, callback ) {