@ -6,144 +6,144 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
(function(_global: any) {
|
||||
class AsyncTestZoneSpec implements ZoneSpec {
|
||||
static symbolParentUnresolved = Zone.__symbol__('parentUnresolved');
|
||||
class AsyncTestZoneSpec implements ZoneSpec {
|
||||
static symbolParentUnresolved = Zone.__symbol__('parentUnresolved');
|
||||
|
||||
_pendingMicroTasks: boolean = false;
|
||||
_pendingMacroTasks: boolean = false;
|
||||
_alreadyErrored: boolean = false;
|
||||
_isSync: boolean = false;
|
||||
runZone = Zone.current;
|
||||
unresolvedChainedPromiseCount = 0;
|
||||
_pendingMicroTasks: boolean = false;
|
||||
_pendingMacroTasks: boolean = false;
|
||||
_alreadyErrored: boolean = false;
|
||||
_isSync: boolean = false;
|
||||
runZone = Zone.current;
|
||||
unresolvedChainedPromiseCount = 0;
|
||||
|
||||
supportWaitUnresolvedChainedPromise = false;
|
||||
supportWaitUnresolvedChainedPromise = false;
|
||||
|
||||
constructor(
|
||||
private finishCallback: Function, private failCallback: Function, namePrefix: string) {
|
||||
this.name = 'asyncTestZone for ' + namePrefix;
|
||||
this.properties = {'AsyncTestZoneSpec': this};
|
||||
this.supportWaitUnresolvedChainedPromise =
|
||||
_global[Zone.__symbol__('supportWaitUnResolvedChainedPromise')] === true;
|
||||
constructor(
|
||||
private finishCallback: Function, private failCallback: Function, namePrefix: string) {
|
||||
this.name = 'asyncTestZone for ' + namePrefix;
|
||||
this.properties = {'AsyncTestZoneSpec': this};
|
||||
this.supportWaitUnresolvedChainedPromise =
|
||||
_global[Zone.__symbol__('supportWaitUnResolvedChainedPromise')] === true;
|
||||
}
|
||||
|
||||
isUnresolvedChainedPromisePending() {
|
||||
return this.unresolvedChainedPromiseCount > 0;
|
||||
}
|
||||
|
||||
_finishCallbackIfDone() {
|
||||
if (!(this._pendingMicroTasks || this._pendingMacroTasks ||
|
||||
(this.supportWaitUnresolvedChainedPromise && this.isUnresolvedChainedPromisePending()))) {
|
||||
// We do this because we would like to catch unhandled rejected promises.
|
||||
this.runZone.run(() => {
|
||||
setTimeout(() => {
|
||||
if (!this._alreadyErrored && !(this._pendingMicroTasks || this._pendingMacroTasks)) {
|
||||
this.finishCallback();
|
||||
}
|
||||
}, 0);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
isUnresolvedChainedPromisePending() { return this.unresolvedChainedPromiseCount > 0; }
|
||||
patchPromiseForTest() {
|
||||
if (!this.supportWaitUnresolvedChainedPromise) {
|
||||
return;
|
||||
}
|
||||
const patchPromiseForTest = (Promise as any)[Zone.__symbol__('patchPromiseForTest')];
|
||||
if (patchPromiseForTest) {
|
||||
patchPromiseForTest();
|
||||
}
|
||||
}
|
||||
|
||||
_finishCallbackIfDone() {
|
||||
if (!(this._pendingMicroTasks || this._pendingMacroTasks ||
|
||||
(this.supportWaitUnresolvedChainedPromise &&
|
||||
this.isUnresolvedChainedPromisePending()))) {
|
||||
// We do this because we would like to catch unhandled rejected promises.
|
||||
this.runZone.run(() => {
|
||||
setTimeout(() => {
|
||||
if (!this._alreadyErrored && !(this._pendingMicroTasks || this._pendingMacroTasks)) {
|
||||
this.finishCallback();
|
||||
}
|
||||
}, 0);
|
||||
});
|
||||
unPatchPromiseForTest() {
|
||||
if (!this.supportWaitUnresolvedChainedPromise) {
|
||||
return;
|
||||
}
|
||||
const unPatchPromiseForTest = (Promise as any)[Zone.__symbol__('unPatchPromiseForTest')];
|
||||
if (unPatchPromiseForTest) {
|
||||
unPatchPromiseForTest();
|
||||
}
|
||||
}
|
||||
|
||||
// ZoneSpec implementation below.
|
||||
|
||||
name: string;
|
||||
|
||||
properties: {[key: string]: any};
|
||||
|
||||
onScheduleTask(delegate: ZoneDelegate, current: Zone, target: Zone, task: Task): Task {
|
||||
if (task.type !== 'eventTask') {
|
||||
this._isSync = false;
|
||||
}
|
||||
if (task.type === 'microTask' && task.data && task.data instanceof Promise) {
|
||||
// check whether the promise is a chained promise
|
||||
if ((task.data as any)[AsyncTestZoneSpec.symbolParentUnresolved] === true) {
|
||||
// chained promise is being scheduled
|
||||
this.unresolvedChainedPromiseCount--;
|
||||
}
|
||||
}
|
||||
return delegate.scheduleTask(target, task);
|
||||
}
|
||||
|
||||
patchPromiseForTest() {
|
||||
if (!this.supportWaitUnresolvedChainedPromise) {
|
||||
return;
|
||||
}
|
||||
const patchPromiseForTest = (Promise as any)[Zone.__symbol__('patchPromiseForTest')];
|
||||
if (patchPromiseForTest) {
|
||||
patchPromiseForTest();
|
||||
}
|
||||
onInvokeTask(
|
||||
delegate: ZoneDelegate, current: Zone, target: Zone, task: Task, applyThis: any,
|
||||
applyArgs: any) {
|
||||
if (task.type !== 'eventTask') {
|
||||
this._isSync = false;
|
||||
}
|
||||
return delegate.invokeTask(target, task, applyThis, applyArgs);
|
||||
}
|
||||
|
||||
unPatchPromiseForTest() {
|
||||
if (!this.supportWaitUnresolvedChainedPromise) {
|
||||
return;
|
||||
}
|
||||
const unPatchPromiseForTest = (Promise as any)[Zone.__symbol__('unPatchPromiseForTest')];
|
||||
if (unPatchPromiseForTest) {
|
||||
unPatchPromiseForTest();
|
||||
}
|
||||
onCancelTask(delegate: ZoneDelegate, current: Zone, target: Zone, task: Task) {
|
||||
if (task.type !== 'eventTask') {
|
||||
this._isSync = false;
|
||||
}
|
||||
return delegate.cancelTask(target, task);
|
||||
}
|
||||
|
||||
// ZoneSpec implementation below.
|
||||
|
||||
name: string;
|
||||
|
||||
properties: {[key: string]: any};
|
||||
|
||||
onScheduleTask(delegate: ZoneDelegate, current: Zone, target: Zone, task: Task): Task {
|
||||
if (task.type !== 'eventTask') {
|
||||
this._isSync = false;
|
||||
}
|
||||
if (task.type === 'microTask' && task.data && task.data instanceof Promise) {
|
||||
// check whether the promise is a chained promise
|
||||
if ((task.data as any)[AsyncTestZoneSpec.symbolParentUnresolved] === true) {
|
||||
// chained promise is being scheduled
|
||||
this.unresolvedChainedPromiseCount--;
|
||||
}
|
||||
}
|
||||
return delegate.scheduleTask(target, task);
|
||||
}
|
||||
|
||||
onInvokeTask(
|
||||
delegate: ZoneDelegate, current: Zone, target: Zone, task: Task, applyThis: any,
|
||||
applyArgs: any) {
|
||||
if (task.type !== 'eventTask') {
|
||||
this._isSync = false;
|
||||
}
|
||||
return delegate.invokeTask(target, task, applyThis, applyArgs);
|
||||
}
|
||||
|
||||
onCancelTask(delegate: ZoneDelegate, current: Zone, target: Zone, task: Task) {
|
||||
if (task.type !== 'eventTask') {
|
||||
this._isSync = false;
|
||||
}
|
||||
return delegate.cancelTask(target, task);
|
||||
}
|
||||
|
||||
// Note - we need to use onInvoke at the moment to call finish when a test is
|
||||
// fully synchronous. TODO(juliemr): remove this when the logic for
|
||||
// onHasTask changes and it calls whenever the task queues are dirty.
|
||||
// updated by(JiaLiPassion), only call finish callback when no task
|
||||
// was scheduled/invoked/canceled.
|
||||
onInvoke(
|
||||
parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function,
|
||||
applyThis: any, applyArgs?: any[], source?: string): any {
|
||||
let previousTaskCounts: any = null;
|
||||
try {
|
||||
this._isSync = true;
|
||||
return parentZoneDelegate.invoke(targetZone, delegate, applyThis, applyArgs, source);
|
||||
} finally {
|
||||
const afterTaskCounts: any = (parentZoneDelegate as any)._taskCounts;
|
||||
if (this._isSync) {
|
||||
this._finishCallbackIfDone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onHandleError(
|
||||
parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone,
|
||||
error: any): boolean {
|
||||
// Let the parent try to handle the error.
|
||||
const result = parentZoneDelegate.handleError(targetZone, error);
|
||||
if (result) {
|
||||
this.failCallback(error);
|
||||
this._alreadyErrored = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
onHasTask(delegate: ZoneDelegate, current: Zone, target: Zone, hasTaskState: HasTaskState) {
|
||||
delegate.hasTask(target, hasTaskState);
|
||||
if (hasTaskState.change == 'microTask') {
|
||||
this._pendingMicroTasks = hasTaskState.microTask;
|
||||
this._finishCallbackIfDone();
|
||||
} else if (hasTaskState.change == 'macroTask') {
|
||||
this._pendingMacroTasks = hasTaskState.macroTask;
|
||||
// Note - we need to use onInvoke at the moment to call finish when a test is
|
||||
// fully synchronous. TODO(juliemr): remove this when the logic for
|
||||
// onHasTask changes and it calls whenever the task queues are dirty.
|
||||
// updated by(JiaLiPassion), only call finish callback when no task
|
||||
// was scheduled/invoked/canceled.
|
||||
onInvoke(
|
||||
parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function,
|
||||
applyThis: any, applyArgs?: any[], source?: string): any {
|
||||
let previousTaskCounts: any = null;
|
||||
try {
|
||||
this._isSync = true;
|
||||
return parentZoneDelegate.invoke(targetZone, delegate, applyThis, applyArgs, source);
|
||||
} finally {
|
||||
const afterTaskCounts: any = (parentZoneDelegate as any)._taskCounts;
|
||||
if (this._isSync) {
|
||||
this._finishCallbackIfDone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Export the class so that new instances can be created with proper
|
||||
// constructor params.
|
||||
(Zone as any)['AsyncTestZoneSpec'] = AsyncTestZoneSpec;
|
||||
onHandleError(parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, error: any):
|
||||
boolean {
|
||||
// Let the parent try to handle the error.
|
||||
const result = parentZoneDelegate.handleError(targetZone, error);
|
||||
if (result) {
|
||||
this.failCallback(error);
|
||||
this._alreadyErrored = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
onHasTask(delegate: ZoneDelegate, current: Zone, target: Zone, hasTaskState: HasTaskState) {
|
||||
delegate.hasTask(target, hasTaskState);
|
||||
if (hasTaskState.change == 'microTask') {
|
||||
this._pendingMicroTasks = hasTaskState.microTask;
|
||||
this._finishCallbackIfDone();
|
||||
} else if (hasTaskState.change == 'macroTask') {
|
||||
this._pendingMacroTasks = hasTaskState.macroTask;
|
||||
this._finishCallbackIfDone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Export the class so that new instances can be created with proper
|
||||
// constructor params.
|
||||
(Zone as any)['AsyncTestZoneSpec'] = AsyncTestZoneSpec;
|
||||
})(typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -88,7 +88,7 @@ function stackTracesEnabled(): boolean {
|
||||
return (Error as any).stackTraceLimit > 0;
|
||||
}
|
||||
|
||||
type LongStackTraceZoneSpec = ZoneSpec & {longStackTraceLimit: number};
|
||||
type LongStackTraceZoneSpec = ZoneSpec&{longStackTraceLimit: number};
|
||||
|
||||
(Zone as any)['longStackTraceZoneSpec'] = <LongStackTraceZoneSpec>{
|
||||
name: 'long-stack-trace',
|
||||
|
@ -18,9 +18,13 @@ class ProxyZoneSpec implements ZoneSpec {
|
||||
|
||||
private tasks: Task[] = [];
|
||||
|
||||
static get(): ProxyZoneSpec { return Zone.current.get('ProxyZoneSpec'); }
|
||||
static get(): ProxyZoneSpec {
|
||||
return Zone.current.get('ProxyZoneSpec');
|
||||
}
|
||||
|
||||
static isLoaded(): boolean { return ProxyZoneSpec.get() instanceof ProxyZoneSpec; }
|
||||
static isLoaded(): boolean {
|
||||
return ProxyZoneSpec.get() instanceof ProxyZoneSpec;
|
||||
}
|
||||
|
||||
static assertPresent(): ProxyZoneSpec {
|
||||
if (!ProxyZoneSpec.isLoaded()) {
|
||||
@ -40,7 +44,7 @@ class ProxyZoneSpec implements ZoneSpec {
|
||||
this.propertyKeys = null;
|
||||
if (delegateSpec && delegateSpec.properties) {
|
||||
this.propertyKeys = Object.keys(delegateSpec.properties);
|
||||
this.propertyKeys.forEach((k) => this.properties[k] = delegateSpec.properties ![k]);
|
||||
this.propertyKeys.forEach((k) => this.properties[k] = delegateSpec.properties![k]);
|
||||
}
|
||||
// if a new delegateSpec was set, check if we need to trigger hasTask
|
||||
if (isNewDelegate && this.lastTaskState &&
|
||||
@ -49,7 +53,9 @@ class ProxyZoneSpec implements ZoneSpec {
|
||||
}
|
||||
}
|
||||
|
||||
getDelegate() { return this._delegateSpec; }
|
||||
getDelegate() {
|
||||
return this._delegateSpec;
|
||||
}
|
||||
|
||||
|
||||
resetDelegate() {
|
||||
@ -85,7 +91,9 @@ class ProxyZoneSpec implements ZoneSpec {
|
||||
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]; })
|
||||
.map((key: string) => {
|
||||
return key + ':' + (task.data as any)[key];
|
||||
})
|
||||
.join(',');
|
||||
return `type: ${task.type}, source: ${task.source}, args: {${dataInfo}}`;
|
||||
});
|
||||
|
@ -9,7 +9,9 @@
|
||||
class SyncTestZoneSpec implements ZoneSpec {
|
||||
runZone = Zone.current;
|
||||
|
||||
constructor(namePrefix: string) { this.name = 'syncTestZone for ' + namePrefix; }
|
||||
constructor(namePrefix: string) {
|
||||
this.name = 'syncTestZone for ' + namePrefix;
|
||||
}
|
||||
|
||||
// ZoneSpec implementation below.
|
||||
|
||||
|
@ -19,7 +19,9 @@ class TaskTrackingZoneSpec implements ZoneSpec {
|
||||
eventTasks: Task[] = [];
|
||||
properties: {[key: string]: any} = {'TaskTrackingZone': this};
|
||||
|
||||
static get() { return Zone.current.get('TaskTrackingZone'); }
|
||||
static get() {
|
||||
return Zone.current.get('TaskTrackingZone');
|
||||
}
|
||||
|
||||
private getTasksFor(type: string): Task[] {
|
||||
switch (type) {
|
||||
|
@ -11,152 +11,150 @@
|
||||
*/
|
||||
|
||||
(function(global: any) {
|
||||
interface Wtf {
|
||||
trace: WtfTrace;
|
||||
}
|
||||
interface WtfScope {}
|
||||
interface WtfRange {}
|
||||
interface WtfTrace {
|
||||
events: WtfEvents;
|
||||
leaveScope(scope: WtfScope, returnValue?: any): void;
|
||||
beginTimeRange(rangeType: string, action: string): WtfRange;
|
||||
endTimeRange(range: WtfRange): void;
|
||||
}
|
||||
interface WtfEvents {
|
||||
createScope(signature: string, flags?: any): WtfScopeFn;
|
||||
createInstance(signature: string, flags?: any): WtfEventFn;
|
||||
}
|
||||
interface Wtf {
|
||||
trace: WtfTrace;
|
||||
}
|
||||
interface WtfScope {}
|
||||
interface WtfRange {}
|
||||
interface WtfTrace {
|
||||
events: WtfEvents;
|
||||
leaveScope(scope: WtfScope, returnValue?: any): void;
|
||||
beginTimeRange(rangeType: string, action: string): WtfRange;
|
||||
endTimeRange(range: WtfRange): void;
|
||||
}
|
||||
interface WtfEvents {
|
||||
createScope(signature: string, flags?: any): WtfScopeFn;
|
||||
createInstance(signature: string, flags?: any): WtfEventFn;
|
||||
}
|
||||
|
||||
type WtfScopeFn = (...args: any[]) => WtfScope;
|
||||
type WtfEventFn = (...args: any[]) => any;
|
||||
type WtfScopeFn = (...args: any[]) => WtfScope;
|
||||
type WtfEventFn = (...args: any[]) => any;
|
||||
|
||||
// Detect and setup WTF.
|
||||
let wtfTrace: WtfTrace|null = null;
|
||||
let wtfEvents: WtfEvents|null = null;
|
||||
const wtfEnabled: boolean = (function(): boolean {
|
||||
const wtf: Wtf = global['wtf'];
|
||||
if (wtf) {
|
||||
wtfTrace = wtf.trace;
|
||||
if (wtfTrace) {
|
||||
wtfEvents = wtfTrace.events;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
})();
|
||||
|
||||
class WtfZoneSpec implements ZoneSpec {
|
||||
name: string = 'WTF';
|
||||
|
||||
static forkInstance =
|
||||
wtfEnabled? wtfEvents !.createInstance('Zone:fork(ascii zone, ascii newZone)'): null;
|
||||
static scheduleInstance: {[key: string]: WtfEventFn} = {};
|
||||
static cancelInstance: {[key: string]: WtfEventFn} = {};
|
||||
static invokeScope: {[key: string]: WtfEventFn} = {};
|
||||
static invokeTaskScope: {[key: string]: WtfEventFn} = {};
|
||||
|
||||
onFork(
|
||||
parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone,
|
||||
zoneSpec: ZoneSpec): Zone {
|
||||
const retValue = parentZoneDelegate.fork(targetZone, zoneSpec);
|
||||
WtfZoneSpec.forkInstance !(zonePathName(targetZone), retValue.name);
|
||||
return retValue;
|
||||
}
|
||||
|
||||
onInvoke(
|
||||
parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function,
|
||||
applyThis: any, applyArgs?: any[], source?: string): any {
|
||||
const src = source || 'unknown';
|
||||
let scope = WtfZoneSpec.invokeScope[src];
|
||||
if (!scope) {
|
||||
scope = WtfZoneSpec.invokeScope[src] =
|
||||
wtfEvents !.createScope(`Zone:invoke:${source}(ascii zone)`);
|
||||
}
|
||||
return wtfTrace !.leaveScope(
|
||||
scope(zonePathName(targetZone)),
|
||||
parentZoneDelegate.invoke(targetZone, delegate, applyThis, applyArgs, source));
|
||||
}
|
||||
|
||||
|
||||
onHandleError(
|
||||
parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone,
|
||||
error: any): boolean {
|
||||
return parentZoneDelegate.handleError(targetZone, error);
|
||||
}
|
||||
|
||||
onScheduleTask(
|
||||
parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): any {
|
||||
const key = task.type + ':' + task.source;
|
||||
let instance = WtfZoneSpec.scheduleInstance[key];
|
||||
if (!instance) {
|
||||
instance = WtfZoneSpec.scheduleInstance[key] =
|
||||
wtfEvents !.createInstance(`Zone:schedule:${key}(ascii zone, any data)`);
|
||||
}
|
||||
const retValue = parentZoneDelegate.scheduleTask(targetZone, task);
|
||||
instance(zonePathName(targetZone), shallowObj(task.data, 2));
|
||||
return retValue;
|
||||
}
|
||||
|
||||
|
||||
onInvokeTask(
|
||||
parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task,
|
||||
applyThis?: any, applyArgs?: any[]): any {
|
||||
const source = task.source;
|
||||
let scope = WtfZoneSpec.invokeTaskScope[source];
|
||||
if (!scope) {
|
||||
scope = WtfZoneSpec.invokeTaskScope[source] =
|
||||
wtfEvents !.createScope(`Zone:invokeTask:${source}(ascii zone)`);
|
||||
}
|
||||
return wtfTrace !.leaveScope(
|
||||
scope(zonePathName(targetZone)),
|
||||
parentZoneDelegate.invokeTask(targetZone, task, applyThis, applyArgs));
|
||||
}
|
||||
|
||||
onCancelTask(parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task):
|
||||
any {
|
||||
const key = task.source;
|
||||
let instance = WtfZoneSpec.cancelInstance[key];
|
||||
if (!instance) {
|
||||
instance = WtfZoneSpec.cancelInstance[key] =
|
||||
wtfEvents !.createInstance(`Zone:cancel:${key}(ascii zone, any options)`);
|
||||
}
|
||||
const retValue = parentZoneDelegate.cancelTask(targetZone, task);
|
||||
instance(zonePathName(targetZone), shallowObj(task.data, 2));
|
||||
return retValue;
|
||||
// Detect and setup WTF.
|
||||
let wtfTrace: WtfTrace|null = null;
|
||||
let wtfEvents: WtfEvents|null = null;
|
||||
const wtfEnabled: boolean = (function(): boolean {
|
||||
const wtf: Wtf = global['wtf'];
|
||||
if (wtf) {
|
||||
wtfTrace = wtf.trace;
|
||||
if (wtfTrace) {
|
||||
wtfEvents = wtfTrace.events;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
})();
|
||||
|
||||
function shallowObj(obj: {[k: string]: any} | undefined, depth: number): any {
|
||||
if (!obj || !depth) return null;
|
||||
const out: {[k: string]: any} = {};
|
||||
for (const key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
// explicit : any due to https://github.com/microsoft/TypeScript/issues/33191
|
||||
let value: any = obj[key];
|
||||
switch (typeof value) {
|
||||
case 'object':
|
||||
const name = value && value.constructor && (<any>value.constructor).name;
|
||||
value = name == (<any>Object).name ? shallowObj(value, depth - 1) : name;
|
||||
break;
|
||||
case 'function':
|
||||
value = value.name || undefined;
|
||||
break;
|
||||
}
|
||||
out[key] = value;
|
||||
class WtfZoneSpec implements ZoneSpec {
|
||||
name: string = 'WTF';
|
||||
|
||||
static forkInstance =
|
||||
wtfEnabled ? wtfEvents!.createInstance('Zone:fork(ascii zone, ascii newZone)') : null;
|
||||
static scheduleInstance: {[key: string]: WtfEventFn} = {};
|
||||
static cancelInstance: {[key: string]: WtfEventFn} = {};
|
||||
static invokeScope: {[key: string]: WtfEventFn} = {};
|
||||
static invokeTaskScope: {[key: string]: WtfEventFn} = {};
|
||||
|
||||
onFork(parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, zoneSpec: ZoneSpec):
|
||||
Zone {
|
||||
const retValue = parentZoneDelegate.fork(targetZone, zoneSpec);
|
||||
WtfZoneSpec.forkInstance!(zonePathName(targetZone), retValue.name);
|
||||
return retValue;
|
||||
}
|
||||
|
||||
onInvoke(
|
||||
parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function,
|
||||
applyThis: any, applyArgs?: any[], source?: string): any {
|
||||
const src = source || 'unknown';
|
||||
let scope = WtfZoneSpec.invokeScope[src];
|
||||
if (!scope) {
|
||||
scope = WtfZoneSpec.invokeScope[src] =
|
||||
wtfEvents!.createScope(`Zone:invoke:${source}(ascii zone)`);
|
||||
}
|
||||
return wtfTrace!.leaveScope(
|
||||
scope(zonePathName(targetZone)),
|
||||
parentZoneDelegate.invoke(targetZone, delegate, applyThis, applyArgs, source));
|
||||
}
|
||||
|
||||
|
||||
onHandleError(parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, error: any):
|
||||
boolean {
|
||||
return parentZoneDelegate.handleError(targetZone, error);
|
||||
}
|
||||
|
||||
onScheduleTask(parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task):
|
||||
any {
|
||||
const key = task.type + ':' + task.source;
|
||||
let instance = WtfZoneSpec.scheduleInstance[key];
|
||||
if (!instance) {
|
||||
instance = WtfZoneSpec.scheduleInstance[key] =
|
||||
wtfEvents!.createInstance(`Zone:schedule:${key}(ascii zone, any data)`);
|
||||
}
|
||||
const retValue = parentZoneDelegate.scheduleTask(targetZone, task);
|
||||
instance(zonePathName(targetZone), shallowObj(task.data, 2));
|
||||
return retValue;
|
||||
}
|
||||
|
||||
|
||||
onInvokeTask(
|
||||
parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task,
|
||||
applyThis?: any, applyArgs?: any[]): any {
|
||||
const source = task.source;
|
||||
let scope = WtfZoneSpec.invokeTaskScope[source];
|
||||
if (!scope) {
|
||||
scope = WtfZoneSpec.invokeTaskScope[source] =
|
||||
wtfEvents!.createScope(`Zone:invokeTask:${source}(ascii zone)`);
|
||||
}
|
||||
return wtfTrace!.leaveScope(
|
||||
scope(zonePathName(targetZone)),
|
||||
parentZoneDelegate.invokeTask(targetZone, task, applyThis, applyArgs));
|
||||
}
|
||||
|
||||
onCancelTask(parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task):
|
||||
any {
|
||||
const key = task.source;
|
||||
let instance = WtfZoneSpec.cancelInstance[key];
|
||||
if (!instance) {
|
||||
instance = WtfZoneSpec.cancelInstance[key] =
|
||||
wtfEvents!.createInstance(`Zone:cancel:${key}(ascii zone, any options)`);
|
||||
}
|
||||
const retValue = parentZoneDelegate.cancelTask(targetZone, task);
|
||||
instance(zonePathName(targetZone), shallowObj(task.data, 2));
|
||||
return retValue;
|
||||
}
|
||||
}
|
||||
|
||||
function shallowObj(obj: {[k: string]: any}|undefined, depth: number): any {
|
||||
if (!obj || !depth) return null;
|
||||
const out: {[k: string]: any} = {};
|
||||
for (const key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
// explicit : any due to https://github.com/microsoft/TypeScript/issues/33191
|
||||
let value: any = obj[key];
|
||||
switch (typeof value) {
|
||||
case 'object':
|
||||
const name = value && value.constructor && (<any>value.constructor).name;
|
||||
value = name == (<any>Object).name ? shallowObj(value, depth - 1) : name;
|
||||
break;
|
||||
case 'function':
|
||||
value = value.name || undefined;
|
||||
break;
|
||||
}
|
||||
out[key] = value;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function zonePathName(zone: Zone) {
|
||||
let name: string = zone.name;
|
||||
let localZone = zone.parent;
|
||||
while (localZone != null) {
|
||||
name = localZone.name + '::' + name;
|
||||
localZone = localZone.parent;
|
||||
}
|
||||
return name;
|
||||
function zonePathName(zone: Zone) {
|
||||
let name: string = zone.name;
|
||||
let localZone = zone.parent;
|
||||
while (localZone != null) {
|
||||
name = localZone.name + '::' + name;
|
||||
localZone = localZone.parent;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
(Zone as any)['wtfZoneSpec'] = !wtfEnabled ? null : new WtfZoneSpec();
|
||||
(Zone as any)['wtfZoneSpec'] = !wtfEnabled ? null : new WtfZoneSpec();
|
||||
})(typeof window === 'object' && window || typeof self === 'object' && self || global);
|
||||
|
Reference in New Issue
Block a user