|  | 
|  | 1 | +/** | 
|  | 2 | + * @license | 
|  | 3 | + * Copyright Google LLC All Rights Reserved. | 
|  | 4 | + * | 
|  | 5 | + * Use of this source code is governed by an MIT-style license that can be | 
|  | 6 | + * found in the LICENSE file at https://angular.io/license | 
|  | 7 | + */ | 
|  | 8 | + | 
|  | 9 | +interface Console { | 
|  | 10 | +  scheduleAsyncTask(name: string, recurring?: boolean): number; | 
|  | 11 | +  startAsyncTask(task: number): void; | 
|  | 12 | +  finishAsyncTask(task: number): void; | 
|  | 13 | +  cancelAsyncTask(task: number): void; | 
|  | 14 | +} | 
|  | 15 | + | 
|  | 16 | +interface Task { | 
|  | 17 | +  asyncId?: number; | 
|  | 18 | +} | 
|  | 19 | + | 
|  | 20 | +class AsyncStackTaggingZoneSpec implements ZoneSpec { | 
|  | 21 | +  scheduleAsyncTask: Console['scheduleAsyncTask']; | 
|  | 22 | +  startAsyncTask: Console['startAsyncTask']; | 
|  | 23 | +  finishAsyncTask: Console['finishAsyncTask']; | 
|  | 24 | +  cancelAsyncTask: Console['finishAsyncTask']; | 
|  | 25 | + | 
|  | 26 | +  constructor(namePrefix: string, consoleAsyncStackTaggingImpl: Console = console) { | 
|  | 27 | +    this.name = 'asyncStackTagging for ' + namePrefix; | 
|  | 28 | +    this.scheduleAsyncTask = consoleAsyncStackTaggingImpl?.scheduleAsyncTask ?? (() => {}); | 
|  | 29 | +    this.startAsyncTask = consoleAsyncStackTaggingImpl?.startAsyncTask ?? (() => {}); | 
|  | 30 | +    this.finishAsyncTask = consoleAsyncStackTaggingImpl?.finishAsyncTask ?? (() => {}); | 
|  | 31 | +    this.cancelAsyncTask = consoleAsyncStackTaggingImpl?.cancelAsyncTask ?? (() => {}); | 
|  | 32 | +  } | 
|  | 33 | + | 
|  | 34 | +  // ZoneSpec implementation below. | 
|  | 35 | + | 
|  | 36 | +  name: string; | 
|  | 37 | + | 
|  | 38 | +  onScheduleTask(delegate: ZoneDelegate, current: Zone, target: Zone, task: Task): Task { | 
|  | 39 | +    task.asyncId = this.scheduleAsyncTask( | 
|  | 40 | +        task.source || task.type, task.data?.isPeriodic || task.type === 'eventTask'); | 
|  | 41 | +    return delegate.scheduleTask(target, task); | 
|  | 42 | +  } | 
|  | 43 | + | 
|  | 44 | +  onInvokeTask( | 
|  | 45 | +      delegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task, applyThis: any, | 
|  | 46 | +      applyArgs?: any[]) { | 
|  | 47 | +    task.asyncId && this.startAsyncTask(task.asyncId); | 
|  | 48 | +    try { | 
|  | 49 | +      return delegate.invokeTask(targetZone, task, applyThis, applyArgs); | 
|  | 50 | +    } finally { | 
|  | 51 | +      task.asyncId && this.finishAsyncTask(task.asyncId); | 
|  | 52 | +      if (task.type !== 'eventTask' && !task.data?.isPeriodic) { | 
|  | 53 | +        task.asyncId = undefined; | 
|  | 54 | +      } | 
|  | 55 | +    } | 
|  | 56 | +  } | 
|  | 57 | + | 
|  | 58 | +  onCancelTask(delegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task) { | 
|  | 59 | +    task.asyncId && this.cancelAsyncTask(task.asyncId); | 
|  | 60 | +    task.asyncId = undefined; | 
|  | 61 | +    return delegate.cancelTask(targetZone, task); | 
|  | 62 | +  } | 
|  | 63 | +} | 
|  | 64 | + | 
|  | 65 | +// Export the class so that new instances can be created with proper | 
|  | 66 | +// constructor params. | 
|  | 67 | +(Zone as any)['AsyncStackTaggingZoneSpec'] = AsyncStackTaggingZoneSpec; | 
0 commit comments