Fossil SCM
Merged in diff context loading fixes from Florian: off-by-one error for the single-line context case and a race condition for the click-queue.
Commit
36bec9adac0849789cace9a4eac911d2f893c1f4cd33b93228fbdfaf93da5115
Parent
fb752a04f5cb974…
1 file changed
+11
-2
+11
-2
| --- src/fossil.diff.js | ||
| +++ src/fossil.diff.js | ||
| @@ -448,11 +448,11 @@ | ||
| 448 | 448 | const selector = '.difflnr > pre'; |
| 449 | 449 | td = tr.querySelector(selector); |
| 450 | 450 | const lineNoTxt = lineno.join('\n')+'\n'; |
| 451 | 451 | lineno.length = 0; |
| 452 | 452 | td.innerHTML = lineNoTxt + td.innerHTML; |
| 453 | - if(this.pos.endLhs<=1 | |
| 453 | + if(this.pos.endLhs<1 | |
| 454 | 454 | || lines.length < (urlParam.to - urlParam.from)){ |
| 455 | 455 | /* No more data. */ |
| 456 | 456 | this.destroy(); |
| 457 | 457 | }else{ |
| 458 | 458 | this.maybeReplaceButtons(); |
| @@ -504,19 +504,25 @@ | ||
| 504 | 504 | a warning. Returns this object. |
| 505 | 505 | */ |
| 506 | 506 | fetchChunk: function(fetchType){ |
| 507 | 507 | if( !this.$fetchQueue ) return this; // HACKHACK: are we destroyed? |
| 508 | 508 | if( fetchType==this.FetchType.ProcessQueue ){ |
| 509 | + this.$fetchQueue.shift(); | |
| 509 | 510 | if( this.$fetchQueue.length==0 ) return this; |
| 510 | 511 | //console.log('fetchChunk: processing queue ...'); |
| 511 | 512 | } |
| 512 | 513 | else{ |
| 513 | 514 | this.$fetchQueue.push(fetchType); |
| 514 | 515 | if( this.$fetchQueue.length!=1 ) return this; |
| 515 | 516 | //console.log('fetchChunk: processing user input ...'); |
| 516 | 517 | } |
| 517 | 518 | fetchType = this.$fetchQueue[0]; |
| 519 | + if( fetchType==this.FetchType.ProcessQueue ){ | |
| 520 | + /* Unexpected! Clear queue so recovery (manual restart) is possible. */ | |
| 521 | + this.$fetchQueue.length = 0; | |
| 522 | + return this; | |
| 523 | + } | |
| 518 | 524 | /* Forewarning, this is a bit confusing: when fetching the |
| 519 | 525 | previous lines, we're doing so on behalf of the *next* diff |
| 520 | 526 | chunk (this.pos.next), and vice versa. */ |
| 521 | 527 | if(fetchType===this.FetchType.NextUp && !this.pos.next |
| 522 | 528 | || fetchType===this.FetchType.PrevDown && !this.pos.prev){ |
| @@ -531,11 +537,14 @@ | ||
| 531 | 537 | }, |
| 532 | 538 | aftersend: ()=>this.msg(false), |
| 533 | 539 | onload: function(list){ |
| 534 | 540 | self.injectResponse(fetchType,up,list); |
| 535 | 541 | if( !self.$fetchQueue || self.$fetchQueue.length==0 ) return; |
| 536 | - self.$fetchQueue.shift(); | |
| 542 | + /* Keep queue length > 0, or clicks stalled during (unusually lengthy) | |
| 543 | + injectResponse() may sneak in as soon as setTimeout() allows, find | |
| 544 | + an empty queue, and therefore start over with queue processing. */ | |
| 545 | + self.$fetchQueue[0] = self.FetchType.ProcessQueue; | |
| 537 | 546 | setTimeout(self.fetchChunk.bind(self,self.FetchType.ProcessQueue)); |
| 538 | 547 | } |
| 539 | 548 | }; |
| 540 | 549 | const up = fOpt.urlParams; |
| 541 | 550 | if(fetchType===this.FetchType.FillGap){ |
| 542 | 551 |
| --- src/fossil.diff.js | |
| +++ src/fossil.diff.js | |
| @@ -448,11 +448,11 @@ | |
| 448 | const selector = '.difflnr > pre'; |
| 449 | td = tr.querySelector(selector); |
| 450 | const lineNoTxt = lineno.join('\n')+'\n'; |
| 451 | lineno.length = 0; |
| 452 | td.innerHTML = lineNoTxt + td.innerHTML; |
| 453 | if(this.pos.endLhs<=1 |
| 454 | || lines.length < (urlParam.to - urlParam.from)){ |
| 455 | /* No more data. */ |
| 456 | this.destroy(); |
| 457 | }else{ |
| 458 | this.maybeReplaceButtons(); |
| @@ -504,19 +504,25 @@ | |
| 504 | a warning. Returns this object. |
| 505 | */ |
| 506 | fetchChunk: function(fetchType){ |
| 507 | if( !this.$fetchQueue ) return this; // HACKHACK: are we destroyed? |
| 508 | if( fetchType==this.FetchType.ProcessQueue ){ |
| 509 | if( this.$fetchQueue.length==0 ) return this; |
| 510 | //console.log('fetchChunk: processing queue ...'); |
| 511 | } |
| 512 | else{ |
| 513 | this.$fetchQueue.push(fetchType); |
| 514 | if( this.$fetchQueue.length!=1 ) return this; |
| 515 | //console.log('fetchChunk: processing user input ...'); |
| 516 | } |
| 517 | fetchType = this.$fetchQueue[0]; |
| 518 | /* Forewarning, this is a bit confusing: when fetching the |
| 519 | previous lines, we're doing so on behalf of the *next* diff |
| 520 | chunk (this.pos.next), and vice versa. */ |
| 521 | if(fetchType===this.FetchType.NextUp && !this.pos.next |
| 522 | || fetchType===this.FetchType.PrevDown && !this.pos.prev){ |
| @@ -531,11 +537,14 @@ | |
| 531 | }, |
| 532 | aftersend: ()=>this.msg(false), |
| 533 | onload: function(list){ |
| 534 | self.injectResponse(fetchType,up,list); |
| 535 | if( !self.$fetchQueue || self.$fetchQueue.length==0 ) return; |
| 536 | self.$fetchQueue.shift(); |
| 537 | setTimeout(self.fetchChunk.bind(self,self.FetchType.ProcessQueue)); |
| 538 | } |
| 539 | }; |
| 540 | const up = fOpt.urlParams; |
| 541 | if(fetchType===this.FetchType.FillGap){ |
| 542 |
| --- src/fossil.diff.js | |
| +++ src/fossil.diff.js | |
| @@ -448,11 +448,11 @@ | |
| 448 | const selector = '.difflnr > pre'; |
| 449 | td = tr.querySelector(selector); |
| 450 | const lineNoTxt = lineno.join('\n')+'\n'; |
| 451 | lineno.length = 0; |
| 452 | td.innerHTML = lineNoTxt + td.innerHTML; |
| 453 | if(this.pos.endLhs<1 |
| 454 | || lines.length < (urlParam.to - urlParam.from)){ |
| 455 | /* No more data. */ |
| 456 | this.destroy(); |
| 457 | }else{ |
| 458 | this.maybeReplaceButtons(); |
| @@ -504,19 +504,25 @@ | |
| 504 | a warning. Returns this object. |
| 505 | */ |
| 506 | fetchChunk: function(fetchType){ |
| 507 | if( !this.$fetchQueue ) return this; // HACKHACK: are we destroyed? |
| 508 | if( fetchType==this.FetchType.ProcessQueue ){ |
| 509 | this.$fetchQueue.shift(); |
| 510 | if( this.$fetchQueue.length==0 ) return this; |
| 511 | //console.log('fetchChunk: processing queue ...'); |
| 512 | } |
| 513 | else{ |
| 514 | this.$fetchQueue.push(fetchType); |
| 515 | if( this.$fetchQueue.length!=1 ) return this; |
| 516 | //console.log('fetchChunk: processing user input ...'); |
| 517 | } |
| 518 | fetchType = this.$fetchQueue[0]; |
| 519 | if( fetchType==this.FetchType.ProcessQueue ){ |
| 520 | /* Unexpected! Clear queue so recovery (manual restart) is possible. */ |
| 521 | this.$fetchQueue.length = 0; |
| 522 | return this; |
| 523 | } |
| 524 | /* Forewarning, this is a bit confusing: when fetching the |
| 525 | previous lines, we're doing so on behalf of the *next* diff |
| 526 | chunk (this.pos.next), and vice versa. */ |
| 527 | if(fetchType===this.FetchType.NextUp && !this.pos.next |
| 528 | || fetchType===this.FetchType.PrevDown && !this.pos.prev){ |
| @@ -531,11 +537,14 @@ | |
| 537 | }, |
| 538 | aftersend: ()=>this.msg(false), |
| 539 | onload: function(list){ |
| 540 | self.injectResponse(fetchType,up,list); |
| 541 | if( !self.$fetchQueue || self.$fetchQueue.length==0 ) return; |
| 542 | /* Keep queue length > 0, or clicks stalled during (unusually lengthy) |
| 543 | injectResponse() may sneak in as soon as setTimeout() allows, find |
| 544 | an empty queue, and therefore start over with queue processing. */ |
| 545 | self.$fetchQueue[0] = self.FetchType.ProcessQueue; |
| 546 | setTimeout(self.fetchChunk.bind(self,self.FetchType.ProcessQueue)); |
| 547 | } |
| 548 | }; |
| 549 | const up = fOpt.urlParams; |
| 550 | if(fetchType===this.FetchType.FillGap){ |
| 551 |