2222 * THE SOFTWARE.
2323 */
2424import Util from './Util.ts' ;
25+ import LoadingGuard from './LoadingGuard.ts' ;
2526
2627/*
2728 * At the time of writing, requestIdleCallback is still not available in Safari,
@@ -82,6 +83,8 @@ jQuery3.noConflict();
8283 */
8384var UnoChoice = UnoChoice || ( jQuery3 => {
8485 let util = new Util ( jQuery3 ) ;
86+ // Keeps Build disabled while any parameter is updating (JENKINS-73556).
87+ let loadingGuard = new LoadingGuard ( document ) ;
8588 // The final public object
8689 let instance = { } ;
8790 let SEPARATOR = '__LESEP__' ;
@@ -102,6 +105,7 @@ var UnoChoice = UnoChoice || (jQuery3 => {
102105 this . proxy = proxy ;
103106 this . referencedParameters = [ ] ;
104107 this . filterElement = null ;
108+ trackProxy ( proxy ) ;
105109 }
106110 /**
107111 * Gets the parameter name.
@@ -370,9 +374,7 @@ var UnoChoice = UnoChoice || (jQuery3 => {
370374 let other = cascadeParameters [ i ] ;
371375 if ( this . referencesMe ( other ) ) {
372376 console . log ( `[${ this . paramName } ] - CascadeParameter#update - Updating ${ other . getParameterName ( ) } from ${ this . getParameterName ( ) } ` ) ;
373- window . requestIdleCallback ( async ( ) => {
374- await other . update ( other . getParameterName ( ) === this . getParameterName ( ) ) ;
375- } )
377+ scheduleUpdate ( other , other . getParameterName ( ) === this . getParameterName ( ) ) ;
376378 }
377379 }
378380 }
@@ -435,10 +437,9 @@ var UnoChoice = UnoChoice || (jQuery3 => {
435437 //_self.cascadeParameter.loading(true);
436438 jQuery3 ( ".behavior-loading" ) . show ( ) ;
437439 // start updating in separate async function so browser will be able to repaint and show 'loading' animation , see JENKINS-34487
438- window . requestIdleCallback ( async ( ) => {
439- await _self . cascadeParameter . update ( false ) ;
440+ scheduleUpdate ( _self . cascadeParameter , false ) . then ( ( ) => {
440441 jQuery3 ( ".behavior-loading" ) . hide ( ) ;
441- } )
442+ } ) ;
442443 }
443444 } ) ;
444445 cascadeParameter . getReferencedParameters ( ) . push ( this ) ;
@@ -465,6 +466,7 @@ var UnoChoice = UnoChoice || (jQuery3 => {
465466 this . paramElement = paramElement ;
466467 this . proxy = proxy ;
467468 this . referencedParameters = [ ] ;
469+ trackProxy ( proxy ) ;
468470 }
469471 /**
470472 * Extend the cascade parameter.
@@ -556,9 +558,7 @@ var UnoChoice = UnoChoice || (jQuery3 => {
556558 let other = cascadeParameters [ i ] ;
557559 if ( this . referencesMe ( other ) ) {
558560 console . log ( `[${ this . paramName } ] - DynamicReferenceParameter#update - Updating ${ other . paramName } from ${ this . paramName } ` ) ;
559- window . requestIdleCallback ( async ( ) => {
560- await other . update ( true ) ;
561- } )
561+ scheduleUpdate ( other , true ) ;
562562 }
563563 }
564564 }
@@ -847,6 +847,31 @@ var UnoChoice = UnoChoice || (jQuery3 => {
847847 return value ;
848848 }
849849
850+ // Updates the parameter once the browser is idle; Build stays disabled from now until the returned promise settles.
851+ function scheduleUpdate ( parameter , avoidRecursion ) {
852+ let done = loadingGuard . begin ( parameter . getParameterElement ( ) ) ;
853+ return new Promise ( resolve => {
854+ window . requestIdleCallback ( async ( ) => {
855+ try {
856+ await parameter . update ( avoidRecursion ) ;
857+ } catch ( e ) {
858+ loadingGuard . fail ( ) ;
859+ console . error ( `[${ parameter . getParameterName ( ) } ] - scheduleUpdate - Update failed` , e ) ;
860+ } finally {
861+ done ( ) ;
862+ resolve ( ) ;
863+ }
864+ } ) ;
865+ } ) ;
866+ }
867+
868+ // Calls made through this proxy keep Build disabled until their response has been rendered.
869+ function trackProxy ( proxy ) {
870+ if ( proxy ) {
871+ proxy . loadingGuard = loadingGuard ;
872+ }
873+ }
874+
850875 // Hacks in Jenkins core
851876 /**
852877 * <p>This function is the same as makeStaplerProxy available in Jenkins core, but executes calls
@@ -901,6 +926,14 @@ var UnoChoice = UnoChoice || (jQuery3 => {
901926 // what is rendered when, and properly chain certain actions (e.g.
902927 // a dependant parameter is only rendered after its parent/referenced
903928 // parameter).
929+ // JENKINS-73556: the call counts as pending until its callback has rendered the response.
930+ let guard = proxy . loadingGuard ;
931+ let done = guard ? guard . begin ( ) : ( ) => { } ;
932+ let failed = error => {
933+ if ( guard ) guard . fail ( ) ;
934+ done ( ) ;
935+ console . error ( `makeStaplerProxy2 - ${ methodName } failed` , error ) ;
936+ } ;
904937 await fetch ( url + methodName , {
905938 method : 'POST' ,
906939 headers : headers ,
@@ -912,25 +945,32 @@ var UnoChoice = UnoChoice || (jQuery3 => {
912945 status : response . status ,
913946 statusText : response . statusText ,
914947 } ;
948+ // Returned, so that awaiting this call also waits for its callback (JENKINS-75793).
915949 if ( response . headers . has ( 'content-type' ) && response . headers . get ( 'content-type' ) . startsWith ( 'application/json' ) ) {
916- response . json ( ) . then ( function ( responseObject ) {
950+ return response . json ( ) . then ( function ( responseObject ) {
917951 t . responseObject = function ( ) {
918952 return responseObject ;
919953 } ;
920954 t . responseJSON = responseObject ;
921955 if ( callback != null ) {
922956 callback ( t ) ;
923957 }
924- } ) ;
958+ } ) . then ( done , failed ) ;
925959 } else {
926- response . text ( ) . then ( function ( responseText ) {
960+ return response . text ( ) . then ( function ( responseText ) {
927961 t . responseText = responseText ;
928962 if ( callback != null ) {
929963 callback ( t ) ;
930964 }
931- } ) ;
965+ } ) . then ( done , failed ) ;
932966 }
967+ } else {
968+ // The parameter keeps its previous value, so it must not be submitted.
969+ failed ( `HTTP ${ response . status } ${ response . statusText } ` ) ;
933970 }
971+ } , function ( error ) {
972+ failed ( error ) ;
973+ throw error ;
934974 } )
935975 }
936976 } ;
@@ -1019,9 +1059,7 @@ var UnoChoice = UnoChoice || (jQuery3 => {
10191059
10201060 // call update methods in Java passing the HTML values
10211061 console . log ( `[${ name } ] - renderCascadeChoiceParameter - Updating cascade of parameter [${ name } ] ...` ) ;
1022- window . requestIdleCallback ( async ( ) => {
1023- await cascadeParameter . update ( false ) ;
1024- } )
1062+ scheduleUpdate ( cascadeParameter , false ) ;
10251063 } else {
10261064 console . log ( `[${ name } ] - renderCascadeChoiceParameter - Parameter error: Missing parameter [${ paramName } ] HTML element!` ) ;
10271065 }
@@ -1104,9 +1142,7 @@ var UnoChoice = UnoChoice || (jQuery3 => {
11041142
11051143 // call update methods in Java passing the HTML values
11061144 console . log ( `[${ name } ] - renderDynamicRenderParameter - Updating cascade of parameter [${ name } ] ...` ) ;
1107- window . requestIdleCallback ( async ( ) => {
1108- await dynamicParameter . update ( false ) ;
1109- } )
1145+ scheduleUpdate ( dynamicParameter , false ) ;
11101146 } else {
11111147 console . log ( `[${ name } ] - renderDynamicRenderParameter - Parameter error: Missing parameter [${ paramName } ] HTML element!` ) ;
11121148 }
@@ -1120,6 +1156,7 @@ var UnoChoice = UnoChoice || (jQuery3 => {
11201156 instance . ReferencedParameter = ReferencedParameter ;
11211157 instance . FilterElement = FilterElement ;
11221158 instance . makeStaplerProxy2 = makeStaplerProxy2 ;
1159+ instance . loadingGuard = loadingGuard ;
11231160 instance . cascadeParameters = cascadeParameters ;
11241161 instance . renderChoiceParameter = renderChoiceParameter ;
11251162 instance . renderCascadeChoiceParameter = renderCascadeChoiceParameter ;
0 commit comments