From 85fba3f107a4a03bdac43f06c81ab2f2a3c2fea5 Mon Sep 17 00:00:00 2001 From: Josep Sanz Date: Mon, 8 Nov 2021 11:53:45 +0100 Subject: [PATCH] Tooltip: Don't crash on empty content MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 1f2011ece removed a `try-catch` around triggering the `remove` handlers in the `jQuery.cleanData` override. The `try-catch` was meant for old IE but it was also catching an error coming from the tooltip `remove` handler depending on being able to find a relevant tooltip. The `_find` method returns `null`, though, when the tooltip cotent is empty. Instead of restoring the `try-catch`, handle the `null` case in the `remove` handler. Fixes gh-1990 Closes gh-1994 Co-authored-by: Claas Augner Co-authored-by: Michał Gołębiowski-Owczarek --- tests/unit/tooltip/core.js | 70 ++++++++++++++++++++++++++++++++++++++ ui/widgets/tooltip.js | 5 ++- 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/tests/unit/tooltip/core.js b/tests/unit/tooltip/core.js index 5ce49aeb7..a3eedbd6a 100644 --- a/tests/unit/tooltip/core.js +++ b/tests/unit/tooltip/core.js @@ -254,4 +254,74 @@ QUnit.test( "remove conflicting attributes from live region", function( assert ) .tooltip( "open" ); } ); +// gh-1990 +QUnit.test( "don't crash on empty tooltip content", function( assert ) { + var ready = assert.async(); + assert.expect( 1 ); + + var anchor = $( "#tooltipped1" ), + input = anchor.next(), + actions = []; + + $( document ).tooltip( { + show: false, + hide: false, + content: function() { + var title = $( this ).attr( "title" ); + if ( title === "inputtitle" ) { + return ""; + } + return title; + }, + open: function( event, ui ) { + actions.push( "open:" + ui.tooltip.text() ); + }, + close: function( event, ui ) { + actions.push( "close:" + ui.tooltip.text() ); + } + } ); + + function step1() { + anchor.simulate( "mouseover" ); + setTimeout( step2 ); + } + + function step2() { + anchor.simulate( "mouseout" ); + setTimeout( step3 ); + } + + function step3() { + input.simulate( "focus" ); + setTimeout( step4 ); + } + + function step4() { + input.simulate( "blur" ); + setTimeout( step5 ); + } + + function step5() { + anchor.simulate( "mouseover" ); + setTimeout( step6 ); + } + + function step6() { + anchor.simulate( "mouseout" ); + setTimeout( step7 ); + } + + function step7() { + assert.deepEqual( actions, [ + "open:anchortitle", + "close:anchortitle", + "open:anchortitle", + "close:anchortitle" + ], "Tooltip opens and closes without crashing" ); + ready(); + } + + step1(); +} ); + } ); diff --git a/ui/widgets/tooltip.js b/ui/widgets/tooltip.js index f1cea47d1..06282338a 100644 --- a/ui/widgets/tooltip.js +++ b/ui/widgets/tooltip.js @@ -352,7 +352,10 @@ $.widget( "ui.tooltip", { // tooltips will handle this in destroy. if ( target[ 0 ] !== this.element[ 0 ] ) { events.remove = function() { - this._removeTooltip( this._find( target ).tooltip ); + var targetElement = this._find( target ); + if ( targetElement ) { + this._removeTooltip( targetElement.tooltip ); + } }; }