| 
									
										
										
										
											2019-06-01 00:56:07 +09:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							|  |  |  |  * Copyright Google Inc. All Rights Reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Use of this source code is governed by an MIT-style license that can be | 
					
						
							|  |  |  |  * found in the LICENSE file at https://angular.io/license
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | class ProxyZoneSpec implements ZoneSpec { | 
					
						
							|  |  |  |   name: string = 'ProxyZone'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   private _delegateSpec: ZoneSpec|null = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   properties: {[k: string]: any} = {'ProxyZoneSpec': this}; | 
					
						
							|  |  |  |   propertyKeys: string[]|null = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   lastTaskState: HasTaskState|null = null; | 
					
						
							|  |  |  |   isNeedToTriggerHasTask = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   private tasks: Task[] = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static get(): ProxyZoneSpec { return Zone.current.get('ProxyZoneSpec'); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static isLoaded(): boolean { return ProxyZoneSpec.get() instanceof ProxyZoneSpec; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static assertPresent(): ProxyZoneSpec { | 
					
						
							|  |  |  |     if (!ProxyZoneSpec.isLoaded()) { | 
					
						
							|  |  |  |       throw new Error(`Expected to be running in 'ProxyZone', but it was not found.`); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return ProxyZoneSpec.get(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   constructor(private defaultSpecDelegate: ZoneSpec|null = null) { | 
					
						
							|  |  |  |     this.setDelegate(defaultSpecDelegate); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   setDelegate(delegateSpec: ZoneSpec|null) { | 
					
						
							|  |  |  |     const isNewDelegate = this._delegateSpec !== delegateSpec; | 
					
						
							|  |  |  |     this._delegateSpec = delegateSpec; | 
					
						
							|  |  |  |     this.propertyKeys && this.propertyKeys.forEach((key) => delete this.properties[key]); | 
					
						
							|  |  |  |     this.propertyKeys = null; | 
					
						
							|  |  |  |     if (delegateSpec && delegateSpec.properties) { | 
					
						
							|  |  |  |       this.propertyKeys = Object.keys(delegateSpec.properties); | 
					
						
							|  |  |  |       this.propertyKeys.forEach((k) => this.properties[k] = delegateSpec.properties ![k]); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-06-30 05:02:52 -04:00
										 |  |  |     // if a new delegateSpec was set, check if we need to trigger hasTask
 | 
					
						
							| 
									
										
										
										
											2019-06-01 00:56:07 +09:00
										 |  |  |     if (isNewDelegate && this.lastTaskState && | 
					
						
							|  |  |  |         (this.lastTaskState.macroTask || this.lastTaskState.microTask)) { | 
					
						
							|  |  |  |       this.isNeedToTriggerHasTask = true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   getDelegate() { return this._delegateSpec; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   resetDelegate() { | 
					
						
							|  |  |  |     const delegateSpec = this.getDelegate(); | 
					
						
							|  |  |  |     this.setDelegate(this.defaultSpecDelegate); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   tryTriggerHasTask(parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone) { | 
					
						
							|  |  |  |     if (this.isNeedToTriggerHasTask && this.lastTaskState) { | 
					
						
							|  |  |  |       // last delegateSpec has microTask or macroTask
 | 
					
						
							|  |  |  |       // should call onHasTask in current delegateSpec
 | 
					
						
							|  |  |  |       this.isNeedToTriggerHasTask = false; | 
					
						
							|  |  |  |       this.onHasTask(parentZoneDelegate, currentZone, targetZone, this.lastTaskState); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   removeFromTasks(task: Task) { | 
					
						
							|  |  |  |     if (!this.tasks) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     for (let i = 0; i < this.tasks.length; i++) { | 
					
						
							|  |  |  |       if (this.tasks[i] === task) { | 
					
						
							|  |  |  |         this.tasks.splice(i, 1); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   getAndClearPendingTasksInfo() { | 
					
						
							|  |  |  |     if (this.tasks.length === 0) { | 
					
						
							|  |  |  |       return ''; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     const taskInfo = this.tasks.map((task: Task) => { | 
					
						
							|  |  |  |       const dataInfo = task.data && | 
					
						
							|  |  |  |           Object.keys(task.data) | 
					
						
							|  |  |  |               .map((key: string) => { return key + ':' + (task.data as any)[key]; }) | 
					
						
							|  |  |  |               .join(','); | 
					
						
							|  |  |  |       return `type: ${task.type}, source: ${task.source}, args: {${dataInfo}}`; | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2019-06-30 05:02:52 -04:00
										 |  |  |     const pendingTasksInfo = '--Pending async tasks are: [' + taskInfo + ']'; | 
					
						
							| 
									
										
										
										
											2019-06-01 00:56:07 +09:00
										 |  |  |     // clear tasks
 | 
					
						
							|  |  |  |     this.tasks = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return pendingTasksInfo; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onFork(parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, zoneSpec: ZoneSpec): | 
					
						
							|  |  |  |       Zone { | 
					
						
							|  |  |  |     if (this._delegateSpec && this._delegateSpec.onFork) { | 
					
						
							|  |  |  |       return this._delegateSpec.onFork(parentZoneDelegate, currentZone, targetZone, zoneSpec); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       return parentZoneDelegate.fork(targetZone, zoneSpec); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onIntercept( | 
					
						
							|  |  |  |       parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function, | 
					
						
							|  |  |  |       source: string): Function { | 
					
						
							|  |  |  |     if (this._delegateSpec && this._delegateSpec.onIntercept) { | 
					
						
							|  |  |  |       return this._delegateSpec.onIntercept( | 
					
						
							|  |  |  |           parentZoneDelegate, currentZone, targetZone, delegate, source); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       return parentZoneDelegate.intercept(targetZone, delegate, source); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onInvoke( | 
					
						
							|  |  |  |       parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function, | 
					
						
							|  |  |  |       applyThis: any, applyArgs?: any[], source?: string): any { | 
					
						
							|  |  |  |     this.tryTriggerHasTask(parentZoneDelegate, currentZone, targetZone); | 
					
						
							|  |  |  |     if (this._delegateSpec && this._delegateSpec.onInvoke) { | 
					
						
							|  |  |  |       return this._delegateSpec.onInvoke( | 
					
						
							|  |  |  |           parentZoneDelegate, currentZone, targetZone, delegate, applyThis, applyArgs, source); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       return parentZoneDelegate.invoke(targetZone, delegate, applyThis, applyArgs, source); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onHandleError(parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, error: any): | 
					
						
							|  |  |  |       boolean { | 
					
						
							|  |  |  |     if (this._delegateSpec && this._delegateSpec.onHandleError) { | 
					
						
							|  |  |  |       return this._delegateSpec.onHandleError(parentZoneDelegate, currentZone, targetZone, error); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       return parentZoneDelegate.handleError(targetZone, error); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onScheduleTask(parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): | 
					
						
							|  |  |  |       Task { | 
					
						
							|  |  |  |     if (task.type !== 'eventTask') { | 
					
						
							|  |  |  |       this.tasks.push(task); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (this._delegateSpec && this._delegateSpec.onScheduleTask) { | 
					
						
							|  |  |  |       return this._delegateSpec.onScheduleTask(parentZoneDelegate, currentZone, targetZone, task); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       return parentZoneDelegate.scheduleTask(targetZone, task); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onInvokeTask( | 
					
						
							|  |  |  |       parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task, | 
					
						
							|  |  |  |       applyThis: any, applyArgs: any): any { | 
					
						
							|  |  |  |     if (task.type !== 'eventTask') { | 
					
						
							|  |  |  |       this.removeFromTasks(task); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     this.tryTriggerHasTask(parentZoneDelegate, currentZone, targetZone); | 
					
						
							|  |  |  |     if (this._delegateSpec && this._delegateSpec.onInvokeTask) { | 
					
						
							|  |  |  |       return this._delegateSpec.onInvokeTask( | 
					
						
							|  |  |  |           parentZoneDelegate, currentZone, targetZone, task, applyThis, applyArgs); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       return parentZoneDelegate.invokeTask(targetZone, task, applyThis, applyArgs); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onCancelTask(parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): | 
					
						
							|  |  |  |       any { | 
					
						
							|  |  |  |     if (task.type !== 'eventTask') { | 
					
						
							|  |  |  |       this.removeFromTasks(task); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     this.tryTriggerHasTask(parentZoneDelegate, currentZone, targetZone); | 
					
						
							|  |  |  |     if (this._delegateSpec && this._delegateSpec.onCancelTask) { | 
					
						
							|  |  |  |       return this._delegateSpec.onCancelTask(parentZoneDelegate, currentZone, targetZone, task); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       return parentZoneDelegate.cancelTask(targetZone, task); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onHasTask(delegate: ZoneDelegate, current: Zone, target: Zone, hasTaskState: HasTaskState): void { | 
					
						
							|  |  |  |     this.lastTaskState = hasTaskState; | 
					
						
							|  |  |  |     if (this._delegateSpec && this._delegateSpec.onHasTask) { | 
					
						
							|  |  |  |       this._delegateSpec.onHasTask(delegate, current, target, hasTaskState); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       delegate.hasTask(target, hasTaskState); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Export the class so that new instances can be created with proper
 | 
					
						
							|  |  |  | // constructor params.
 | 
					
						
							|  |  |  | (Zone as any)['ProxyZoneSpec'] = ProxyZoneSpec; |