refactor(zone.js): rename several internal apis in fake async zone spec (#39127)

In `FakeAsyncZoneSpec`, there are several variables and APIs to identify
different times, and the names are confusing, in this commit, they are
renamed for more clear understandings.

1. currentTickTime, the tick millis advanced.
2. getFakeBaseSystemTime(), return the fake base system time.
3. setFakeBaseSystemTime(), set the fake base system time.
4. getRealSystemTime(), get the underlying native system time.

PR Close #39127
This commit is contained in:
JiaLiPassion 2020-10-06 12:45:16 +09:00 committed by atscott
parent ffc3332dcd
commit c53f19ac47
4 changed files with 51 additions and 43 deletions

View File

@ -127,7 +127,7 @@ Zone.__load_patch('jasmine', (global: any, Zone: ZoneType, api: _ZonePrivate) =>
const fakeAsyncZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); const fakeAsyncZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec');
if (fakeAsyncZoneSpec) { if (fakeAsyncZoneSpec) {
const dateTime = arguments.length > 0 ? arguments[0] : new Date(); const dateTime = arguments.length > 0 ? arguments[0] : new Date();
return fakeAsyncZoneSpec.setCurrentRealTime.apply( return fakeAsyncZoneSpec.setFakeBaseSystemTime.apply(
fakeAsyncZoneSpec, fakeAsyncZoneSpec,
dateTime && typeof dateTime.getTime === 'function' ? [dateTime.getTime()] : dateTime && typeof dateTime.getTime === 'function' ? [dateTime.getTime()] :
arguments); arguments);

View File

@ -188,7 +188,7 @@ Zone.__load_patch('jest', (context: any, Zone: ZoneType, api: _ZonePrivate) => {
return function(self: any, args: any[]) { return function(self: any, args: any[]) {
const fakeAsyncZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); const fakeAsyncZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec');
if (fakeAsyncZoneSpec && isPatchingFakeTimer()) { if (fakeAsyncZoneSpec && isPatchingFakeTimer()) {
fakeAsyncZoneSpec.setCurrentRealTime(args[0]); fakeAsyncZoneSpec.setFakeBaseSystemTime(args[0]);
} else { } else {
return delegate.apply(self, args); return delegate.apply(self, args);
} }

View File

@ -45,16 +45,15 @@ function FakeDate() {
} }
} }
FakeDate.now = FakeDate.now = function(this: unknown) {
function(this: unknown) {
const fakeAsyncTestZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); const fakeAsyncTestZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec');
if (fakeAsyncTestZoneSpec) { if (fakeAsyncTestZoneSpec) {
return fakeAsyncTestZoneSpec.getCurrentRealTime() + fakeAsyncTestZoneSpec.getCurrentTime(); return fakeAsyncTestZoneSpec.getFakeSystemTime();
} }
return OriginalDate.now.apply(this, arguments); return OriginalDate.now.apply(this, arguments);
} };
FakeDate.UTC = OriginalDate.UTC; FakeDate.UTC = OriginalDate.UTC;
FakeDate.parse = OriginalDate.parse; FakeDate.parse = OriginalDate.parse;
// keep a reference for zone patched timer function // keep a reference for zone patched timer function
@ -72,24 +71,24 @@ class Scheduler {
// Scheduler queue with the tuple of end time and callback function - sorted by end time. // Scheduler queue with the tuple of end time and callback function - sorted by end time.
private _schedulerQueue: ScheduledFunction[] = []; private _schedulerQueue: ScheduledFunction[] = [];
// Current simulated time in millis. // Current simulated time in millis.
private _currentTime: number = 0; private _currentTickTime: number = 0;
// Current real time in millis. // Current fake system base time in millis.
private _currentRealTime: number = OriginalDate.now(); private _currentFakeBaseSystemTime: number = OriginalDate.now();
// track requeuePeriodicTimer // track requeuePeriodicTimer
private _currentTickRequeuePeriodicEntries: any[] = []; private _currentTickRequeuePeriodicEntries: any[] = [];
constructor() {} constructor() {}
getCurrentTime() { getCurrentTickTime() {
return this._currentTime; return this._currentTickTime;
} }
getCurrentRealTime() { getFakeSystemTime() {
return this._currentRealTime; return this._currentFakeBaseSystemTime + this._currentTickTime;
} }
setCurrentRealTime(realTime: number) { setFakeBaseSystemTime(fakeBaseSystemTime: number) {
this._currentRealTime = realTime; this._currentFakeBaseSystemTime = fakeBaseSystemTime;
} }
getRealSystemTime() { getRealSystemTime() {
@ -114,7 +113,7 @@ class Scheduler {
...options ...options
}; };
let currentId = options.id! < 0 ? Scheduler.nextId++ : options.id!; let currentId = options.id! < 0 ? Scheduler.nextId++ : options.id!;
let endTime = this._currentTime + delay; let endTime = this._currentTickTime + delay;
// Insert so that scheduler queue remains sorted by end time. // Insert so that scheduler queue remains sorted by end time.
let newEntry: ScheduledFunction = { let newEntry: ScheduledFunction = {
@ -165,7 +164,7 @@ class Scheduler {
} }
// Find the last task currently queued in the scheduler queue and tick // Find the last task currently queued in the scheduler queue and tick
// till that time. // till that time.
const startTime = this._currentTime; const startTime = this._currentTickTime;
const targetTask = this._schedulerQueue[step - 1]; const targetTask = this._schedulerQueue[step - 1];
this.tick(targetTask.endTime - startTime, doTick, tickOptions); this.tick(targetTask.endTime - startTime, doTick, tickOptions);
} }
@ -173,7 +172,7 @@ class Scheduler {
tick(millis: number = 0, doTick?: (elapsed: number) => void, tickOptions?: { tick(millis: number = 0, doTick?: (elapsed: number) => void, tickOptions?: {
processNewMacroTasksSynchronously: boolean processNewMacroTasksSynchronously: boolean
}): void { }): void {
let finalTime = this._currentTime + millis; let finalTime = this._currentTickTime + millis;
let lastCurrentTime = 0; let lastCurrentTime = 0;
tickOptions = Object.assign({processNewMacroTasksSynchronously: true}, tickOptions); tickOptions = Object.assign({processNewMacroTasksSynchronously: true}, tickOptions);
// we need to copy the schedulerQueue so nested timeout // we need to copy the schedulerQueue so nested timeout
@ -202,13 +201,13 @@ class Scheduler {
this._schedulerQueue.splice(idx, 1); this._schedulerQueue.splice(idx, 1);
} }
} }
lastCurrentTime = this._currentTime; lastCurrentTime = this._currentTickTime;
this._currentTime = current.endTime; this._currentTickTime = current.endTime;
if (doTick) { if (doTick) {
doTick(this._currentTime - lastCurrentTime); doTick(this._currentTickTime - lastCurrentTime);
} }
let retval = current.func.apply( let retval = current.func.apply(
global, current.isRequestAnimationFrame ? [this._currentTime] : current.args); global, current.isRequestAnimationFrame ? [this._currentTickTime] : current.args);
if (!retval) { if (!retval) {
// Uncaught exception in the current scheduled function. Stop processing the queue. // Uncaught exception in the current scheduled function. Stop processing the queue.
break; break;
@ -230,10 +229,10 @@ class Scheduler {
} }
} }
} }
lastCurrentTime = this._currentTime; lastCurrentTime = this._currentTickTime;
this._currentTime = finalTime; this._currentTickTime = finalTime;
if (doTick) { if (doTick) {
doTick(this._currentTime - lastCurrentTime); doTick(this._currentTickTime - lastCurrentTime);
} }
} }
@ -243,10 +242,10 @@ class Scheduler {
} }
// Find the last task currently queued in the scheduler queue and tick // Find the last task currently queued in the scheduler queue and tick
// till that time. // till that time.
const startTime = this._currentTime; const startTime = this._currentTickTime;
const lastTask = this._schedulerQueue[this._schedulerQueue.length - 1]; const lastTask = this._schedulerQueue[this._schedulerQueue.length - 1];
this.tick(lastTask.endTime - startTime, doTick, {processNewMacroTasksSynchronously: false}); this.tick(lastTask.endTime - startTime, doTick, {processNewMacroTasksSynchronously: false});
return this._currentTime - startTime; return this._currentTickTime - startTime;
} }
flush(limit = 20, flushPeriodic = false, doTick?: (elapsed: number) => void): number { flush(limit = 20, flushPeriodic = false, doTick?: (elapsed: number) => void): number {
@ -263,14 +262,14 @@ class Scheduler {
} }
// Find the last task currently queued in the scheduler queue and tick // Find the last task currently queued in the scheduler queue and tick
// till that time. // till that time.
const startTime = this._currentTime; const startTime = this._currentTickTime;
const lastTask = this._schedulerQueue[this._schedulerQueue.length - 1]; const lastTask = this._schedulerQueue[this._schedulerQueue.length - 1];
this.tick(lastTask.endTime - startTime, doTick); this.tick(lastTask.endTime - startTime, doTick);
return this._currentTime - startTime; return this._currentTickTime - startTime;
} }
private flushNonPeriodic(limit: number, doTick?: (elapsed: number) => void): number { private flushNonPeriodic(limit: number, doTick?: (elapsed: number) => void): number {
const startTime = this._currentTime; const startTime = this._currentTickTime;
let lastCurrentTime = 0; let lastCurrentTime = 0;
let count = 0; let count = 0;
while (this._schedulerQueue.length > 0) { while (this._schedulerQueue.length > 0) {
@ -289,11 +288,11 @@ class Scheduler {
} }
const current = this._schedulerQueue.shift()!; const current = this._schedulerQueue.shift()!;
lastCurrentTime = this._currentTime; lastCurrentTime = this._currentTickTime;
this._currentTime = current.endTime; this._currentTickTime = current.endTime;
if (doTick) { if (doTick) {
// Update any secondary schedulers like Jasmine mock Date. // Update any secondary schedulers like Jasmine mock Date.
doTick(this._currentTime - lastCurrentTime); doTick(this._currentTickTime - lastCurrentTime);
} }
const retval = current.func.apply(global, current.args); const retval = current.func.apply(global, current.args);
if (!retval) { if (!retval) {
@ -301,7 +300,7 @@ class Scheduler {
break; break;
} }
} }
return this._currentTime - startTime; return this._currentTickTime - startTime;
} }
} }
@ -426,16 +425,16 @@ class FakeAsyncTestZoneSpec implements ZoneSpec {
throw error; throw error;
} }
getCurrentTime() { getCurrentTickTime() {
return this._scheduler.getCurrentTime(); return this._scheduler.getCurrentTickTime();
} }
getCurrentRealTime() { getFakeSystemTime() {
return this._scheduler.getCurrentRealTime(); return this._scheduler.getFakeSystemTime();
} }
setCurrentRealTime(realTime: number) { setFakeBaseSystemTime(realTime: number) {
this._scheduler.setCurrentRealTime(realTime); this._scheduler.setFakeBaseSystemTime(realTime);
} }
getRealSystemTime() { getRealSystemTime() {

View File

@ -125,14 +125,23 @@ describe('jest modern fakeTimers with zone.js fakeAsync', () => {
expect(typeof fakeAsyncZoneSpec.tick).toEqual('function'); expect(typeof fakeAsyncZoneSpec.tick).toEqual('function');
}); });
test('setSystemTime should set FakeDate.currentRealTime', () => { test('setSystemTime should set FakeDate.currentFakeTime', () => {
const fakeAsyncZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); const fakeAsyncZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec');
const d = Date.now(); let d = fakeAsyncZoneSpec.getRealSystemTime();
jest.setSystemTime(d); jest.setSystemTime(d);
expect(Date.now()).toEqual(d); expect(Date.now()).toEqual(d);
for (let i = 0; i < 100000; i++) { for (let i = 0; i < 100000; i++) {
} }
expect(fakeAsyncZoneSpec.getRealSystemTime()).not.toEqual(d); expect(fakeAsyncZoneSpec.getRealSystemTime()).not.toEqual(d);
d = fakeAsyncZoneSpec.getRealSystemTime();
let timeoutTriggered = false;
setTimeout(() => {
timeoutTriggered = true;
}, 100);
jest.setSystemTime(d);
tick(100);
expect(timeoutTriggered).toBe(true);
expect(Date.now()).toEqual(d + 100);
}); });
test('runAllTicks should run all microTasks', () => { test('runAllTicks should run all microTasks', () => {