Revert "fix(core): NgZone coaleascing options should trigger onStable correctly (#40540)"

This reverts commit 22f9e454a4.
This commit is contained in:
Misko Hevery 2021-01-29 15:09:37 -08:00
parent bd0d19141b
commit d754cc1ea5
2 changed files with 2 additions and 72 deletions

View File

@ -148,7 +148,6 @@ export class NgZone {
!shouldCoalesceRunChangeDetection && shouldCoalesceEventChangeDetection; !shouldCoalesceRunChangeDetection && shouldCoalesceEventChangeDetection;
self.shouldCoalesceRunChangeDetection = shouldCoalesceRunChangeDetection; self.shouldCoalesceRunChangeDetection = shouldCoalesceRunChangeDetection;
self.lastRequestAnimationFrameId = -1; self.lastRequestAnimationFrameId = -1;
self.isCheckStableRunning = false;
self.nativeRequestAnimationFrame = getNativeRequestAnimationFrame().nativeRequestAnimationFrame; self.nativeRequestAnimationFrame = getNativeRequestAnimationFrame().nativeRequestAnimationFrame;
forkInnerZoneWithAngularBehavior(self); forkInnerZoneWithAngularBehavior(self);
} }
@ -244,17 +243,6 @@ interface NgZonePrivate extends NgZone {
hasPendingMacrotasks: boolean; hasPendingMacrotasks: boolean;
hasPendingMicrotasks: boolean; hasPendingMicrotasks: boolean;
lastRequestAnimationFrameId: number; lastRequestAnimationFrameId: number;
/**
* A flag to indicate if NgZone is currently inside
* checkStable and to prevent re-entry. The flag is
* needed because it is possible to invoke the change
* detection from within change detection leading to
* incorrect behavior.
*
* For detail, please refer here,
* https://github.com/angular/angular/pull/40540
*/
isCheckStableRunning: boolean;
isStable: boolean; isStable: boolean;
/** /**
* Optionally specify coalescing event change detections or not. * Optionally specify coalescing event change detections or not.
@ -303,9 +291,7 @@ interface NgZonePrivate extends NgZone {
} }
function checkStable(zone: NgZonePrivate) { function checkStable(zone: NgZonePrivate) {
if (!zone.isCheckStableRunning && zone._nesting == 0 && !zone.hasPendingMicrotasks && if (zone._nesting == 0 && !zone.hasPendingMicrotasks && !zone.isStable) {
!zone.isStable) {
zone.isCheckStableRunning = true;
try { try {
zone._nesting++; zone._nesting++;
zone.onMicrotaskEmpty.emit(null); zone.onMicrotaskEmpty.emit(null);
@ -318,26 +304,12 @@ function checkStable(zone: NgZonePrivate) {
zone.isStable = true; zone.isStable = true;
} }
} }
zone.isCheckStableRunning = false;
} }
} }
} }
function delayChangeDetectionForEvents(zone: NgZonePrivate) { function delayChangeDetectionForEvents(zone: NgZonePrivate) {
/** if (zone.lastRequestAnimationFrameId !== -1) {
* We also need to check isCheckStableRunning here
* Consider the following case with shouldCoalesceRunChangeDetection = true
*
* ngZone.run(() => {});
* ngZone.run(() => {});
*
* We want the two `ngZone.run()` only trigger one change detection
* when shouldCoalesceRunChangeDetection is true.
* And because in this case, change detection run in async way(requestAnimationFrame),
* so we also need to check the isCheckStableRunning here to prevent multiple
* change detections.
*/
if (zone.isCheckStableRunning || zone.lastRequestAnimationFrameId !== -1) {
return; return;
} }
zone.lastRequestAnimationFrameId = zone.nativeRequestAnimationFrame.call(global, () => { zone.lastRequestAnimationFrameId = zone.nativeRequestAnimationFrame.call(global, () => {

View File

@ -982,7 +982,6 @@ function commonTests() {
describe('shouldCoalesceEventChangeDetection = true, shouldCoalesceRunChangeDetection = false', () => { describe('shouldCoalesceEventChangeDetection = true, shouldCoalesceRunChangeDetection = false', () => {
let nativeRequestAnimationFrame: (fn: FrameRequestCallback) => void; let nativeRequestAnimationFrame: (fn: FrameRequestCallback) => void;
let nativeSetTimeout: any = (global as any)[Zone.__symbol__('setTimeout')];
if (!(global as any).requestAnimationFrame) { if (!(global as any).requestAnimationFrame) {
nativeRequestAnimationFrame = function(fn: Function) { nativeRequestAnimationFrame = function(fn: Function) {
(global as any)[Zone.__symbol__('setTimeout')](fn, 16); (global as any)[Zone.__symbol__('setTimeout')](fn, 16);
@ -1043,32 +1042,6 @@ function commonTests() {
}); });
}); });
it('should only emit onMicroTaskEmpty once within the same event loop for ngZone.run in onMicrotaskEmpty subscription',
(done: DoneFn) => {
const tasks: Task[] = [];
coalesceZone.onMicrotaskEmpty.subscribe(() => {
coalesceZone.run(() => {});
});
coalesceZone.run(() => {
tasks.push(Zone.current.scheduleEventTask('myEvent', () => {
logs.push('eventTask1');
}, undefined, () => {}));
});
coalesceZone.run(() => {
tasks.push(Zone.current.scheduleEventTask('myEvent', () => {
logs.push('eventTask2');
}, undefined, () => {}));
});
tasks.forEach(t => t.invoke());
expect(logs).toEqual(['microTask empty', 'microTask empty', 'eventTask1', 'eventTask2']);
nativeSetTimeout(() => {
expect(logs).toEqual([
'microTask empty', 'microTask empty', 'eventTask1', 'eventTask2', 'microTask empty'
]);
done();
}, 100);
});
it('should emit onMicroTaskEmpty once within the same event loop for not only event tasks, but event tasks are before other tasks', it('should emit onMicroTaskEmpty once within the same event loop for not only event tasks, but event tasks are before other tasks',
(done: DoneFn) => { (done: DoneFn) => {
const tasks: Task[] = []; const tasks: Task[] = [];
@ -1121,7 +1094,6 @@ function commonTests() {
describe('shouldCoalesceRunChangeDetection = true', () => { describe('shouldCoalesceRunChangeDetection = true', () => {
let nativeRequestAnimationFrame: (fn: FrameRequestCallback) => void; let nativeRequestAnimationFrame: (fn: FrameRequestCallback) => void;
let nativeSetTimeout: any = (global as any)[Zone.__symbol__('setTimeout')];
if (!(global as any).requestAnimationFrame) { if (!(global as any).requestAnimationFrame) {
nativeRequestAnimationFrame = function(fn: Function) { nativeRequestAnimationFrame = function(fn: Function) {
(global as any)[Zone.__symbol__('setTimeout')](fn, 16); (global as any)[Zone.__symbol__('setTimeout')](fn, 16);
@ -1167,20 +1139,6 @@ function commonTests() {
}); });
}); });
it('should only emit onMicroTaskEmpty once within the same event loop for ngZone.run in onMicrotaskEmpty subscription',
(done: DoneFn) => {
coalesceZone.onMicrotaskEmpty.subscribe(() => {
coalesceZone.run(() => {});
});
coalesceZone.run(() => {});
coalesceZone.run(() => {});
expect(logs).toEqual([]);
nativeSetTimeout(() => {
expect(logs).toEqual(['microTask empty']);
done();
}, 100);
});
it('should only emit onMicroTaskEmpty once within the same event loop for multiple tasks', it('should only emit onMicroTaskEmpty once within the same event loop for multiple tasks',
(done: DoneFn) => { (done: DoneFn) => {
const tasks: Task[] = []; const tasks: Task[] = [];