| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent ef2ce9a commit 7bcce26
2 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -102,8 +102,7 @@ export class IdleScheduler implements OnDestroy { | |||
| 102 | 102 | ||
| 103 | 103 | const key = getIdleRequestKey(options); | |
| 104 | 104 | const callback = (deadline?: IdleDeadline) => { | |
| 105 | - this.cancelBucket(bucket); | ||
| 106 | - | ||
| 105 | + // Keep idleId set during the drain to prevent re-entrant add() from scheduling redundant callbacks. | ||
| 107 | 106 | for (const cb of bucket.queue) { | |
| 108 | 107 | cb(); | |
| 109 | 108 | // _tick here is an optimized change detection check and is safe to call here. | |
@@ -118,6 +117,8 @@ export class IdleScheduler implements OnDestroy { | |||
| 118 | 117 | } | |
| 119 | 118 | } | |
| 120 | 119 | ||
| 120 | + bucket.idleId = null; | ||
| 121 | + | ||
| 121 | 122 | if (bucket.queue.size > 0) { | |
| 122 | 123 | this.scheduleBucket(bucket, options); | |
| 123 | 124 | } else { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5502,4 +5502,158 @@ describe('IdleScheduler', () => { | |||
| 5502 | 5502 | capturedCbs[0]({didTimeout: false, timeRemaining: () => 10}); | |
| 5503 | 5503 | expect(cb1).toHaveBeenCalledTimes(1); | |
| 5504 | 5504 | }); | |
| 5505 | + | ||
| 5506 | + it('should not register a spurious requestOnIdle when a callback re-entrantly adds to the same bucket', () => { | ||
| 5507 | + let capturedCb: ((deadline: any) => void) | null = null; | ||
| 5508 | + let ricCount = 0; | ||
| 5509 | + | ||
| 5510 | + customIdleService.requestOnIdleSpy.and.callFake((cb: any) => { | ||
| 5511 | + ricCount++; | ||
| 5512 | + capturedCb = cb; | ||
| 5513 | + return 100 + ricCount; | ||
| 5514 | + }); | ||
| 5515 | + | ||
| 5516 | + const cbB = jasmine.createSpy('cbB'); | ||
| 5517 | + const cbA = jasmine.createSpy('cbA').and.callFake(() => { | ||
| 5518 | + scheduler.add(cbB); | ||
| 5519 | + }); | ||
| 5520 | + | ||
| 5521 | + scheduler.add(cbA); | ||
| 5522 | + expect(ricCount).toBe(1); | ||
| 5523 | + | ||
| 5524 | + capturedCb!({didTimeout: false, timeRemaining: () => 9999}); | ||
| 5525 | + | ||
| 5526 | + expect(cbA).toHaveBeenCalledTimes(1); | ||
| 5527 | + expect(cbB).toHaveBeenCalledTimes(1); | ||
| 5528 | + expect(ricCount).toBe(1); | ||
| 5529 | + }); | ||
| 5530 | + | ||
| 5531 | + it('should defer a re-entrantly-added same-bucket callback to the next idle period when the deadline expires', () => { | ||
| 5532 | + let capturedCbs: Array<(deadline: any) => void> = []; | ||
| 5533 | + let ricCount = 0; | ||
| 5534 | + | ||
| 5535 | + customIdleService.requestOnIdleSpy.and.callFake((cb: any) => { | ||
| 5536 | + ricCount++; | ||
| 5537 | + capturedCbs.push(cb); | ||
| 5538 | + return 100 + ricCount; | ||
| 5539 | + }); | ||
| 5540 | + | ||
| 5541 | + const cbB = jasmine.createSpy('cbB'); | ||
| 5542 | + const cbA = jasmine.createSpy('cbA').and.callFake(() => { | ||
| 5543 | + scheduler.add(cbB); | ||
| 5544 | + }); | ||
| 5545 | + | ||
| 5546 | + scheduler.add(cbA); | ||
| 5547 | + capturedCbs[0]({didTimeout: false, timeRemaining: () => 0}); | ||
| 5548 | + | ||
| 5549 | + expect(cbA).toHaveBeenCalledTimes(1); | ||
| 5550 | + expect(cbB).toHaveBeenCalledTimes(0); | ||
| 5551 | + expect(ricCount).toBe(2); | ||
| 5552 | + capturedCbs[1]({didTimeout: false, timeRemaining: () => 10}); | ||
| 5553 | + expect(cbB).toHaveBeenCalledTimes(1); | ||
| 5554 | + }); | ||
| 5555 | + | ||
| 5556 | + it('should isolate a re-entrantly-added callback in a different bucket from the current drain', () => { | ||
| 5557 | + let capturedCbs: Array<(deadline: any) => void> = []; | ||
| 5558 | + let ricCount = 0; | ||
| 5559 | + | ||
| 5560 | + customIdleService.requestOnIdleSpy.and.callFake((cb: any) => { | ||
| 5561 | + ricCount++; | ||
| 5562 | + capturedCbs.push(cb); | ||
| 5563 | + return 100 + ricCount; | ||
| 5564 | + }); | ||
| 5565 | + | ||
| 5566 | + const cbB = jasmine.createSpy('cbB'); | ||
| 5567 | + const cbA = jasmine.createSpy('cbA').and.callFake(() => { | ||
| 5568 | + scheduler.add(cbB, {timeout: 500}); | ||
| 5569 | + }); | ||
| 5570 | + | ||
| 5571 | + scheduler.add(cbA); | ||
| 5572 | + capturedCbs[0]({didTimeout: false, timeRemaining: () => 10}); | ||
| 5573 | + | ||
| 5574 | + expect(cbA).toHaveBeenCalledTimes(1); | ||
| 5575 | + expect(cbB).toHaveBeenCalledTimes(0); | ||
| 5576 | + expect(ricCount).toBe(2); | ||
| 5577 | + | ||
| 5578 | + capturedCbs[1]({didTimeout: false, timeRemaining: () => 10}); | ||
| 5579 | + expect(cbB).toHaveBeenCalledTimes(1); | ||
| 5580 | + }); | ||
| 5581 | + | ||
| 5582 | + it('should skip a same-bucket sibling that is removed during a drain', () => { | ||
| 5583 | + let capturedCb: ((deadline: any) => void) | null = null; | ||
| 5584 | + let ricCount = 0; | ||
| 5585 | + | ||
| 5586 | + customIdleService.requestOnIdleSpy.and.callFake((cb: any) => { | ||
| 5587 | + ricCount++; | ||
| 5588 | + capturedCb = cb; | ||
| 5589 | + return 100 + ricCount; | ||
| 5590 | + }); | ||
| 5591 | + | ||
| 5592 | + const cbC = jasmine.createSpy('cbC'); | ||
| 5593 | + const cbB = jasmine.createSpy('cbB'); | ||
| 5594 | + const cbA = jasmine.createSpy('cbA').and.callFake(() => { | ||
| 5595 | + scheduler.remove(cbC); | ||
| 5596 | + }); | ||
| 5597 | + | ||
| 5598 | + scheduler.add(cbA); | ||
| 5599 | + scheduler.add(cbB); | ||
| 5600 | + scheduler.add(cbC); | ||
| 5601 | + | ||
| 5602 | + capturedCb!({didTimeout: false, timeRemaining: () => 10}); | ||
| 5603 | + | ||
| 5604 | + expect(cbA).toHaveBeenCalledTimes(1); | ||
| 5605 | + expect(cbB).toHaveBeenCalledTimes(1); | ||
| 5606 | + expect(cbC).toHaveBeenCalledTimes(0); | ||
| 5607 | + expect(ricCount).toBe(1); | ||
| 5608 | + }); | ||
| 5609 | + | ||
| 5610 | + it('should skip the immediately-next callback when it is removed during a drain', () => { | ||
| 5611 | + let capturedCb: ((deadline: any) => void) | null = null; | ||
| 5612 | + let ricCount = 0; | ||
| 5613 | + | ||
| 5614 | + customIdleService.requestOnIdleSpy.and.callFake((cb: any) => { | ||
| 5615 | + ricCount++; | ||
| 5616 | + capturedCb = cb; | ||
| 5617 | + return 100 + ricCount; | ||
| 5618 | + }); | ||
| 5619 | + | ||
| 5620 | + const cbB = jasmine.createSpy('cbB'); | ||
| 5621 | + const cbA = jasmine.createSpy('cbA').and.callFake(() => { | ||
| 5622 | + scheduler.remove(cbB); | ||
| 5623 | + }); | ||
| 5624 | + | ||
| 5625 | + scheduler.add(cbA); | ||
| 5626 | + scheduler.add(cbB); | ||
| 5627 | + | ||
| 5628 | + capturedCb!({didTimeout: false, timeRemaining: () => 10}); | ||
| 5629 | + | ||
| 5630 | + expect(cbA).toHaveBeenCalledTimes(1); | ||
| 5631 | + expect(cbB).toHaveBeenCalledTimes(0); | ||
| 5632 | + expect(ricCount).toBe(1); | ||
| 5633 | + }); | ||
| 5634 | + | ||
| 5635 | + it('should ignore re-entrant remove() calls for callbacks already processed in the current drain', () => { | ||
| 5636 | + let capturedCb: ((deadline: any) => void) | null = null; | ||
| 5637 | + let ricCount = 0; | ||
| 5638 | + | ||
| 5639 | + customIdleService.requestOnIdleSpy.and.callFake((cb: any) => { | ||
| 5640 | + ricCount++; | ||
| 5641 | + capturedCb = cb; | ||
| 5642 | + return 100 + ricCount; | ||
| 5643 | + }); | ||
| 5644 | + | ||
| 5645 | + const cbA = jasmine.createSpy('cbA'); | ||
| 5646 | + const cbB = jasmine.createSpy('cbB').and.callFake(() => { | ||
| 5647 | + scheduler.remove(cbA); | ||
| 5648 | + }); | ||
| 5649 | + | ||
| 5650 | + scheduler.add(cbA); | ||
| 5651 | + scheduler.add(cbB); | ||
| 5652 | + | ||
| 5653 | + expect(() => capturedCb!({didTimeout: false, timeRemaining: () => 10})).not.toThrow(); | ||
| 5654 | + | ||
| 5655 | + expect(cbA).toHaveBeenCalledTimes(1); | ||
| 5656 | + expect(cbB).toHaveBeenCalledTimes(1); | ||
| 5657 | + expect(ricCount).toBe(1); | ||
| 5658 | + }); | ||
| 5505 | 5659 | }); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments