From 1815d819272244f7794b7e9d53870789a61f836a Mon Sep 17 00:00:00 2001 From: "JiaLi.Passion" Date: Wed, 21 Dec 2016 04:16:55 +0900 Subject: [PATCH 01/20] Fix #546, #554, #555, the error should keep prototype chain and can be called without new --- lib/zone.ts | 30 ++++++++++++++++++++------- test/common/Error.spec.ts | 43 +++++++++++++++++++++++++++++++++++++++ test/test-util.ts | 27 ++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 7 deletions(-) diff --git a/lib/zone.ts b/lib/zone.ts index 992410575..6806cfd1c 100644 --- a/lib/zone.ts +++ b/lib/zone.ts @@ -1318,13 +1318,24 @@ const Zone: ZoneType = (function(global: any) { function ZoneAwareError() { // Create an Error. let error: Error = NativeError.apply(this, arguments); - + if (this && this !== global) { + // copy all properties except constructor from native error + let keys = Object.getOwnPropertyNames(NativeError.prototype); + keys.forEach(key => { + if (key !== 'constructor') { + this[key] = error[key]; + } + }); + } // Save original stack trace - error.originalStack = error.stack; + let originalStack = error.stack; + if (this && this !== global) { + this.originalStack = error.stack; + } // Process the stack trace and rewrite the frames. - if (ZoneAwareError[stackRewrite] && error.originalStack) { - let frames: string[] = error.originalStack.split('\n'); + if (ZoneAwareError[stackRewrite] && originalStack) { + let frames: string[] = originalStack.split('\n'); let zoneFrame = _currentZoneFrame; let i = 0; // Find the first frame @@ -1352,10 +1363,15 @@ const Zone: ZoneType = (function(global: any) { } } } - error.stack = error.zoneAwareStack = frames.join('\n'); + if (this && this !== global) { + this.stack = this.zoneAwareStack = frames.join('\n'); + } else { + error.stack = error.zoneAwareStack = frames.join('\n'); + error.originalStack = originalStack; + } } - return error; - } + return (this && this !== global) ? this : error; + }; // Copy the prototype so that instanceof operator works as expected ZoneAwareError.prototype = NativeError.prototype; diff --git a/test/common/Error.spec.ts b/test/common/Error.spec.ts index 053265331..68128a002 100644 --- a/test/common/Error.spec.ts +++ b/test/common/Error.spec.ts @@ -6,11 +6,54 @@ * found in the LICENSE file at https://angular.io/license */ +import {isFirefox, isIE} from '../test-util'; + describe('ZoneAwareError', () => { // If the environment does not supports stack rewrites, then these tests will fail // and there is no point in running them. if (!Error['stackRewrite']) return; + it('should keep error prototype chain correctly', () => { + class MyError extends Error {} + const myError = new MyError(); + expect(myError instanceof Error).toBe(true); + expect(myError instanceof MyError).toBe(true); + expect(myError.stack).not.toBe(undefined); + }); + + it('should return error itself from constructor', () => { + class MyError1 extends Error { + constructor() { + const err: any = super('MyError1'); + } + } + let myError1 = new MyError1(); + expect(myError1.message).toEqual('MyError1'); + expect(myError1.name).toEqual('Error'); + }); + + it('should return error by calling error directly', () => { + let myError = Error('myError'); + expect(myError.message).toEqual('myError'); + let myError1 = Error.call(undefined, 'myError'); + expect(myError1.message).toEqual('myError'); + let myError2 = Error.call(global, 'myError'); + expect(myError2.message).toEqual('myError'); + }); + + it('should have browser specified property', () => { + let myError = new Error('myError'); + if (isIE) { + expect((myError).description).toEqual('myError'); + expect((myError).number).not.toBe(undefined); + } + if (isFirefox) { + expect((myError).fileName).not.toBe(undefined); + expect((myError).lineNumber).not.toBe(undefined); + expect((myError).columnNumber).not.toBe(undefined); + } + }); + it('should show zone names in stack frames and remove extra frames', () => { const rootZone = getRootZone(); const innerZone = rootZone.fork({name: 'InnerZone'}); diff --git a/test/test-util.ts b/test/test-util.ts index 6897543ae..0189b1214 100644 --- a/test/test-util.ts +++ b/test/test-util.ts @@ -33,3 +33,30 @@ export function ifEnvSupports(test, block) { } }; }; + +function detectBrowser() { + const navigator = global['navigator']; + if (!navigator) { + return 'node'; + } + let ua = navigator.userAgent, tem, + M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || []; + if (/trident/i.test(M[1])) { + tem = /\brv[ :]+(\d+)/g.exec(ua) || []; + return 'IE ' + (tem[1] || ''); + } + if (M[1] === 'Chrome') { + tem = ua.match(/\b(OPR|Edge)\/(\d+)/); + if (tem != null) return tem.slice(1).join(' ').replace('OPR', 'Opera'); + } + M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?']; + if ((tem = ua.match(/version\/(\d+)/i)) != null) M.splice(1, 1, tem[1]); + return M.join(' ').toLowerCase(); +} + +export const isChrome = detectBrowser().indexOf('chrome') !== -1; +export const isFirefox = detectBrowser().indexOf('firefox') !== -1; +export const isSafari = detectBrowser().indexOf('safari') !== -1; +export const isIE = + detectBrowser().indexOf('msie') !== -1 || detectBrowser().indexOf('trident') !== -1; +export const isOpera = detectBrowser().indexOf('opera') !== -1; \ No newline at end of file From b961f5092c61ecc8890f6e31df20d5fe00a98a5b Mon Sep 17 00:00:00 2001 From: "JiaLi.Passion" Date: Wed, 21 Dec 2016 04:28:00 +0900 Subject: [PATCH 02/20] modify test cases --- test/common/Error.spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/test/common/Error.spec.ts b/test/common/Error.spec.ts index 68128a002..72d55421d 100644 --- a/test/common/Error.spec.ts +++ b/test/common/Error.spec.ts @@ -25,6 +25,7 @@ describe('ZoneAwareError', () => { class MyError1 extends Error { constructor() { const err: any = super('MyError1'); + this.message = err.message; } } let myError1 = new MyError1(); From 4d212c8a1fcebc3ae95afbc943cabce5ef126a7f Mon Sep 17 00:00:00 2001 From: "JiaLi.Passion" Date: Wed, 21 Dec 2016 19:34:18 +0900 Subject: [PATCH 03/20] remove test-util detect browser function, modify error test case --- test/common/Error.spec.ts | 10 ++++------ test/test-util.ts | 27 --------------------------- 2 files changed, 4 insertions(+), 33 deletions(-) diff --git a/test/common/Error.spec.ts b/test/common/Error.spec.ts index 72d55421d..a3463da03 100644 --- a/test/common/Error.spec.ts +++ b/test/common/Error.spec.ts @@ -6,8 +6,6 @@ * found in the LICENSE file at https://angular.io/license */ -import {isFirefox, isIE} from '../test-util'; - describe('ZoneAwareError', () => { // If the environment does not supports stack rewrites, then these tests will fail // and there is no point in running them. @@ -44,13 +42,13 @@ describe('ZoneAwareError', () => { it('should have browser specified property', () => { let myError = new Error('myError'); - if (isIE) { + if (Object.prototype.hasOwnProperty.call(Error.prototype, 'description')) { expect((myError).description).toEqual('myError'); expect((myError).number).not.toBe(undefined); } - if (isFirefox) { - expect((myError).fileName).not.toBe(undefined); - expect((myError).lineNumber).not.toBe(undefined); + if (Object.prototype.hasOwnProperty.call(Error.prototype, 'fileName')) { + expect((myError).fileName).toContain('zone'); + expect((myError).lineNumber).toBeGreaterThan(0); expect((myError).columnNumber).not.toBe(undefined); } }); diff --git a/test/test-util.ts b/test/test-util.ts index 0189b1214..6897543ae 100644 --- a/test/test-util.ts +++ b/test/test-util.ts @@ -33,30 +33,3 @@ export function ifEnvSupports(test, block) { } }; }; - -function detectBrowser() { - const navigator = global['navigator']; - if (!navigator) { - return 'node'; - } - let ua = navigator.userAgent, tem, - M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || []; - if (/trident/i.test(M[1])) { - tem = /\brv[ :]+(\d+)/g.exec(ua) || []; - return 'IE ' + (tem[1] || ''); - } - if (M[1] === 'Chrome') { - tem = ua.match(/\b(OPR|Edge)\/(\d+)/); - if (tem != null) return tem.slice(1).join(' ').replace('OPR', 'Opera'); - } - M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?']; - if ((tem = ua.match(/version\/(\d+)/i)) != null) M.splice(1, 1, tem[1]); - return M.join(' ').toLowerCase(); -} - -export const isChrome = detectBrowser().indexOf('chrome') !== -1; -export const isFirefox = detectBrowser().indexOf('firefox') !== -1; -export const isSafari = detectBrowser().indexOf('safari') !== -1; -export const isIE = - detectBrowser().indexOf('msie') !== -1 || detectBrowser().indexOf('trident') !== -1; -export const isOpera = detectBrowser().indexOf('opera') !== -1; \ No newline at end of file From 7c85fe6d546022aeb6fd666f0f40a2ed8a619732 Mon Sep 17 00:00:00 2001 From: "JiaLi.Passion" Date: Wed, 21 Dec 2016 19:51:01 +0900 Subject: [PATCH 04/20] remove test-util detect browser function, modify error test case --- test/common/Error.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/common/Error.spec.ts b/test/common/Error.spec.ts index a3463da03..899aa4ccd 100644 --- a/test/common/Error.spec.ts +++ b/test/common/Error.spec.ts @@ -49,7 +49,7 @@ describe('ZoneAwareError', () => { if (Object.prototype.hasOwnProperty.call(Error.prototype, 'fileName')) { expect((myError).fileName).toContain('zone'); expect((myError).lineNumber).toBeGreaterThan(0); - expect((myError).columnNumber).not.toBe(undefined); + expect((myError).columnNumber).toBeGreaterThan(0); } }); From c5866da9de4d543f0ac89be1aa42fba273848c8d Mon Sep 17 00:00:00 2001 From: "JiaLi.Passion" Date: Wed, 21 Dec 2016 20:51:42 +0900 Subject: [PATCH 05/20] modify error test case --- test/common/Error.spec.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/common/Error.spec.ts b/test/common/Error.spec.ts index 899aa4ccd..2e4e062b8 100644 --- a/test/common/Error.spec.ts +++ b/test/common/Error.spec.ts @@ -43,13 +43,12 @@ describe('ZoneAwareError', () => { it('should have browser specified property', () => { let myError = new Error('myError'); if (Object.prototype.hasOwnProperty.call(Error.prototype, 'description')) { + // in IE, error has description property expect((myError).description).toEqual('myError'); - expect((myError).number).not.toBe(undefined); } if (Object.prototype.hasOwnProperty.call(Error.prototype, 'fileName')) { + // in firefox, error has fileName property expect((myError).fileName).toContain('zone'); - expect((myError).lineNumber).toBeGreaterThan(0); - expect((myError).columnNumber).toBeGreaterThan(0); } }); From e71c487c6097b081ad2a6e7e0cf2f244aa0efeed Mon Sep 17 00:00:00 2001 From: "JiaLi.Passion" Date: Wed, 21 Dec 2016 21:01:43 +0900 Subject: [PATCH 06/20] use Object.create to create prototype --- lib/zone.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/zone.ts b/lib/zone.ts index 6806cfd1c..c4df8166e 100644 --- a/lib/zone.ts +++ b/lib/zone.ts @@ -1374,7 +1374,7 @@ const Zone: ZoneType = (function(global: any) { }; // Copy the prototype so that instanceof operator works as expected - ZoneAwareError.prototype = NativeError.prototype; + ZoneAwareError.prototype = Object.create(NativeError.prototype); ZoneAwareError[Zone.__symbol__('blacklistedStackFrames')] = blackListedStackFrames; ZoneAwareError[stackRewrite] = false; From 4fee5d3363878d9aaffd683a7260319c4694d97a Mon Sep 17 00:00:00 2001 From: "JiaLi.Passion" Date: Fri, 23 Dec 2016 22:39:55 +0800 Subject: [PATCH 07/20] use setPrototypeOf to fix #546, modify package.json to update typescript to 2.1.4 --- lib/zone.ts | 114 ++++++++++++++++++++++++--------------------------- package.json | 2 +- 2 files changed, 55 insertions(+), 61 deletions(-) diff --git a/lib/zone.ts b/lib/zone.ts index c4df8166e..e05cfe307 100644 --- a/lib/zone.ts +++ b/lib/zone.ts @@ -1310,71 +1310,65 @@ const Zone: ZoneType = (function(global: any) { let frameParserStrategy = null; const stackRewrite = 'stackRewrite'; - - /** - * This is ZoneAwareError which processes the stack frame and cleans up extra frames as well as - * adds zone information to it. - */ - function ZoneAwareError() { - // Create an Error. - let error: Error = NativeError.apply(this, arguments); - if (this && this !== global) { - // copy all properties except constructor from native error - let keys = Object.getOwnPropertyNames(NativeError.prototype); - keys.forEach(key => { - if (key !== 'constructor') { - this[key] = error[key]; - } - }); - } - // Save original stack trace - let originalStack = error.stack; - if (this && this !== global) { - this.originalStack = error.stack; - } - - // Process the stack trace and rewrite the frames. - if (ZoneAwareError[stackRewrite] && originalStack) { - let frames: string[] = originalStack.split('\n'); - let zoneFrame = _currentZoneFrame; - let i = 0; - // Find the first frame - while (frames[i] !== zoneAwareFrame && i < frames.length) { - i++; - } - for (; i < frames.length && zoneFrame; i++) { - let frame = frames[i]; - if (frame.trim()) { - let frameType = - blackListedStackFrames.hasOwnProperty(frame) && blackListedStackFrames[frame]; - if (frameType === FrameType.blackList) { - frames.splice(i, 1); - i--; - } else if (frameType === FrameType.transition) { - if (zoneFrame.parent) { - // This is the special frame where zone changed. Print and process it accordingly - frames[i] += ` [${zoneFrame.parent.zone.name} => ${zoneFrame.zone.name}]`; - zoneFrame = zoneFrame.parent; - } else { - zoneFrame = null; + const setPrototypeOf = Object.prototype['setPrototypeOf'] ? Object.prototype['setPrototypeOf'] : + function(obj, proto) { + obj.__proto__ = proto; + return obj; + } + + + /** + * This is ZoneAwareError which processes the stack frame and cleans up extra frames as well + * as + * adds zone information to it. + */ + function + ZoneAwareError() { + // Create an Error. + let error: Error = NativeError.apply(this, arguments); + // Save original stack trace + error.originalStack = error.stack; + + // Process the stack trace and rewrite the frames. + if (ZoneAwareError[stackRewrite] && error.originalStack) { + let frames: string[] = error.originalStack.split('\n'); + let zoneFrame = _currentZoneFrame; + let i = 0; + // Find the first frame + while (frames[i] !== zoneAwareFrame && i < frames.length) { + i++; + } + for (; i < frames.length && zoneFrame; i++) { + let frame = frames[i]; + if (frame.trim()) { + let frameType = + blackListedStackFrames.hasOwnProperty(frame) && blackListedStackFrames[frame]; + if (frameType === FrameType.blackList) { + frames.splice(i, 1); + i--; + } else if (frameType === FrameType.transition) { + if (zoneFrame.parent) { + // This is the special frame where zone changed. Print and process it accordingly + frames[i] += ` [${zoneFrame.parent.zone.name} => ${zoneFrame.zone.name}]`; + zoneFrame = zoneFrame.parent; + } else { + zoneFrame = null; + } + } else { + frames[i] += ` [${zoneFrame.zone.name}]`; + } } - } else { - frames[i] += ` [${zoneFrame.zone.name}]`; } + error.stack = error.zoneAwareStack = frames.join('\n'); } - } - if (this && this !== global) { - this.stack = this.zoneAwareStack = frames.join('\n'); - } else { - error.stack = error.zoneAwareStack = frames.join('\n'); - error.originalStack = originalStack; - } - } - return (this && this !== global) ? this : error; - }; + if (this && this !== global) { + error = setPrototypeOf(error, this.constructor.prototype); + } + return error; + }; // Copy the prototype so that instanceof operator works as expected - ZoneAwareError.prototype = Object.create(NativeError.prototype); + ZoneAwareError.prototype = NativeError.prototype; ZoneAwareError[Zone.__symbol__('blacklistedStackFrames')] = blackListedStackFrames; ZoneAwareError[stackRewrite] = false; diff --git a/package.json b/package.json index 293cd23e0..555433248 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "ts-loader": "^0.6.0", "tslint": "^3.15.1", "tslint-eslint-rules": "^3.1.0", - "typescript": "^2.0.2", + "typescript": "^2.1.4", "whatwg-fetch": "^2.0.1" } } From 5ddb051e2ed7490f63de245f6ae8e84d2c847412 Mon Sep 17 00:00:00 2001 From: "JiaLi.Passion" Date: Fri, 23 Dec 2016 22:56:59 +0800 Subject: [PATCH 08/20] reformat code and add comment --- lib/zone.ts | 417 ++++++++++++++++++++++++++-------------------------- 1 file changed, 209 insertions(+), 208 deletions(-) diff --git a/lib/zone.ts b/lib/zone.ts index e05cfe307..dd0404963 100644 --- a/lib/zone.ts +++ b/lib/zone.ts @@ -221,14 +221,14 @@ interface Zone { */ runTask(task: Task, applyThis?: any, applyArgs?: any): any; scheduleMicroTask( - source: string, callback: Function, data?: TaskData, - customSchedule?: (task: Task) => void): MicroTask; + source: string, callback: Function, data?: TaskData, + customSchedule?: (task: Task) => void): MicroTask; scheduleMacroTask( - source: string, callback: Function, data: TaskData, customSchedule: (task: Task) => void, - customCancel: (task: Task) => void): MacroTask; + source: string, callback: Function, data: TaskData, customSchedule: (task: Task) => void, + customCancel: (task: Task) => void): MacroTask; scheduleEventTask( - source: string, callback: Function, data: TaskData, customSchedule: (task: Task) => void, - customCancel: (task: Task) => void): EventTask; + source: string, callback: Function, data: TaskData, customSchedule: (task: Task) => void, + customCancel: (task: Task) => void): EventTask; /** * Allows the zone to intercept canceling of scheduled Task. * @@ -286,8 +286,8 @@ interface ZoneSpec { * @param zoneSpec The argument passed into the `fork` method. */ onFork?: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, - zoneSpec: ZoneSpec) => Zone; + (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, + zoneSpec: ZoneSpec) => Zone; /** * Allows interception of the wrapping of the callback. @@ -299,8 +299,8 @@ interface ZoneSpec { * @param source The argument passed into the `warp` method. */ onIntercept?: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function, - source: string) => Function; + (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function, + source: string) => Function; /** * Allows interception of the callback invocation. @@ -314,8 +314,8 @@ interface ZoneSpec { * @param source The argument passed into the `run` method. */ onInvoke?: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function, - applyThis: any, applyArgs: any[], source: string) => any; + (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function, + applyThis: any, applyArgs: any[], source: string) => any; /** * Allows interception of the error handling. @@ -326,8 +326,8 @@ interface ZoneSpec { * @param error The argument passed into the `handleError` method. */ onHandleError?: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, - error: any) => boolean; + (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, + error: any) => boolean; /** * Allows interception of task scheduling. @@ -338,11 +338,11 @@ interface ZoneSpec { * @param task The argument passed into the `scheduleTask` method. */ onScheduleTask?: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task) => Task; + (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task) => Task; onInvokeTask?: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task, - applyThis: any, applyArgs: any) => any; + (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task, + applyThis: any, applyArgs: any) => any; /** * Allows interception of task cancelation. @@ -353,7 +353,7 @@ interface ZoneSpec { * @param task The argument passed into the `cancelTask` method. */ onCancelTask?: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task) => any; + (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task) => any; /** * Notifies of changes to the task queue empty status. @@ -364,7 +364,7 @@ interface ZoneSpec { * @param isEmpty */ onHasTask?: - (delegate: ZoneDelegate, current: Zone, target: Zone, hasTaskState: HasTaskState) => void; + (delegate: ZoneDelegate, current: Zone, target: Zone, hasTaskState: HasTaskState) => void; } ; @@ -404,7 +404,7 @@ interface ZoneDelegate { fork(targetZone: Zone, zoneSpec: ZoneSpec): Zone; intercept(targetZone: Zone, callback: Function, source: string): Function; invoke(targetZone: Zone, callback: Function, applyThis: any, applyArgs: any[], source: string): - any; + any; handleError(targetZone: Zone, error: any): boolean; scheduleTask(targetZone: Zone, task: Task): Task; invokeTask(targetZone: Zone, task: Task, applyThis: any, applyArgs: any): any; @@ -462,7 +462,7 @@ interface Task { /** * Task type: `microTask`, `macroTask`, `eventTask`. */ - type: TaskType; + type: TaskType; /** * Debug string representing the API which requested the scheduling of the task. @@ -556,11 +556,11 @@ const Zone: ZoneType = (function(global: any) { static assertZonePatched() { if (global.Promise !== ZoneAwarePromise) { throw new Error( - 'Zone.js has detected that ZoneAwarePromise `(window|global).Promise` ' + - 'has been overwritten.\n' + - 'Most likely cause is that a Promise polyfill has been loaded ' + - 'after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. ' + - 'If you must load one, do so before loading zone.js.)'); + 'Zone.js has detected that ZoneAwarePromise `(window|global).Promise` ' + + 'has been overwritten.\n' + + 'Most likely cause is that a Promise polyfill has been loaded ' + + 'after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. ' + + 'If you must load one, do so before loading zone.js.)'); } } @@ -590,7 +590,7 @@ const Zone: ZoneType = (function(global: any) { this._name = zoneSpec ? zoneSpec.name || 'unnamed' : ''; this._properties = zoneSpec && zoneSpec.properties || {}; this._zoneDelegate = - new ZoneDelegate(this, this._parent && this._parent._zoneDelegate, zoneSpec); + new ZoneDelegate(this, this._parent && this._parent._zoneDelegate, zoneSpec); } public get(key: string): any { @@ -627,8 +627,8 @@ const Zone: ZoneType = (function(global: any) { public run(callback: Function, applyThis?: any, applyArgs?: any[], source?: string): any; public run( - callback: (...args: any[]) => T, applyThis: any = null, applyArgs: any[] = null, - source: string = null): T { + callback: (...args: any[]) => T, applyThis: any = null, applyArgs: any[] = null, + source: string = null): T { _currentZoneFrame = new ZoneFrame(_currentZoneFrame, this); try { return this._zoneDelegate.invoke(this, callback, applyThis, applyArgs, source); @@ -639,8 +639,8 @@ const Zone: ZoneType = (function(global: any) { public runGuarded(callback: Function, applyThis?: any, applyArgs?: any[], source?: string): any; public runGuarded( - callback: (...args: any[]) => T, applyThis: any = null, applyArgs: any[] = null, - source: string = null) { + callback: (...args: any[]) => T, applyThis: any = null, applyArgs: any[] = null, + source: string = null) { _currentZoneFrame = new ZoneFrame(_currentZoneFrame, this); try { try { @@ -660,8 +660,8 @@ const Zone: ZoneType = (function(global: any) { task.runCount++; if (task.zone != this) throw new Error( - 'A task can only be run in the zone which created it! (Creation: ' + task.zone.name + - '; Execution: ' + this.name + ')'); + 'A task can only be run in the zone which created it! (Creation: ' + task.zone.name + + '; Execution: ' + this.name + ')'); const previousTask = _currentTask; _currentTask = task; _currentZoneFrame = new ZoneFrame(_currentZoneFrame, this); @@ -684,26 +684,26 @@ const Zone: ZoneType = (function(global: any) { scheduleMicroTask( - source: string, callback: Function, data?: TaskData, - customSchedule?: (task: Task) => void): MicroTask { + source: string, callback: Function, data?: TaskData, + customSchedule?: (task: Task) => void): MicroTask { return this._zoneDelegate.scheduleTask( - this, new ZoneTask('microTask', this, source, callback, data, customSchedule, null)); + this, new ZoneTask('microTask', this, source, callback, data, customSchedule, null)); } scheduleMacroTask( - source: string, callback: Function, data: TaskData, customSchedule: (task: Task) => void, - customCancel: (task: Task) => void): MacroTask { + source: string, callback: Function, data: TaskData, customSchedule: (task: Task) => void, + customCancel: (task: Task) => void): MacroTask { return this._zoneDelegate.scheduleTask( - this, - new ZoneTask('macroTask', this, source, callback, data, customSchedule, customCancel)); + this, + new ZoneTask('macroTask', this, source, callback, data, customSchedule, customCancel)); } scheduleEventTask( - source: string, callback: Function, data: TaskData, customSchedule: (task: Task) => void, - customCancel: (task: Task) => void): EventTask { + source: string, callback: Function, data: TaskData, customSchedule: (task: Task) => void, + customCancel: (task: Task) => void): EventTask { return this._zoneDelegate.scheduleTask( - this, - new ZoneTask('eventTask', this, source, callback, data, customSchedule, customCancel)); + this, + new ZoneTask('eventTask', this, source, callback, data, customSchedule, customCancel)); } cancelTask(task: Task): any { @@ -718,8 +718,8 @@ const Zone: ZoneType = (function(global: any) { public zone: Zone; private _taskCounts: {microTask: number, - macroTask: number, - eventTask: number} = {microTask: 0, macroTask: 0, eventTask: 0}; + macroTask: number, + eventTask: number} = {microTask: 0, macroTask: 0, eventTask: 0}; private _parentDelegate: ZoneDelegate; @@ -764,84 +764,84 @@ const Zone: ZoneType = (function(global: any) { this._forkCurrZone = zoneSpec && (zoneSpec.onFork ? this.zone : parentDelegate.zone); this._interceptZS = - zoneSpec && (zoneSpec.onIntercept ? zoneSpec : parentDelegate._interceptZS); + zoneSpec && (zoneSpec.onIntercept ? zoneSpec : parentDelegate._interceptZS); this._interceptDlgt = - zoneSpec && (zoneSpec.onIntercept ? parentDelegate : parentDelegate._interceptDlgt); + zoneSpec && (zoneSpec.onIntercept ? parentDelegate : parentDelegate._interceptDlgt); this._interceptCurrZone = - zoneSpec && (zoneSpec.onIntercept ? this.zone : parentDelegate.zone); + zoneSpec && (zoneSpec.onIntercept ? this.zone : parentDelegate.zone); this._invokeZS = zoneSpec && (zoneSpec.onInvoke ? zoneSpec : parentDelegate._invokeZS); this._invokeDlgt = - zoneSpec && (zoneSpec.onInvoke ? parentDelegate : parentDelegate._invokeDlgt); + zoneSpec && (zoneSpec.onInvoke ? parentDelegate : parentDelegate._invokeDlgt); this._invokeCurrZone = zoneSpec && (zoneSpec.onInvoke ? this.zone : parentDelegate.zone); this._handleErrorZS = - zoneSpec && (zoneSpec.onHandleError ? zoneSpec : parentDelegate._handleErrorZS); + zoneSpec && (zoneSpec.onHandleError ? zoneSpec : parentDelegate._handleErrorZS); this._handleErrorDlgt = - zoneSpec && (zoneSpec.onHandleError ? parentDelegate : parentDelegate._handleErrorDlgt); + zoneSpec && (zoneSpec.onHandleError ? parentDelegate : parentDelegate._handleErrorDlgt); this._handleErrorCurrZone = - zoneSpec && (zoneSpec.onHandleError ? this.zone : parentDelegate.zone); + zoneSpec && (zoneSpec.onHandleError ? this.zone : parentDelegate.zone); this._scheduleTaskZS = - zoneSpec && (zoneSpec.onScheduleTask ? zoneSpec : parentDelegate._scheduleTaskZS); + zoneSpec && (zoneSpec.onScheduleTask ? zoneSpec : parentDelegate._scheduleTaskZS); this._scheduleTaskDlgt = - zoneSpec && (zoneSpec.onScheduleTask ? parentDelegate : parentDelegate._scheduleTaskDlgt); + zoneSpec && (zoneSpec.onScheduleTask ? parentDelegate : parentDelegate._scheduleTaskDlgt); this._scheduleTaskCurrZone = - zoneSpec && (zoneSpec.onScheduleTask ? this.zone : parentDelegate.zone); + zoneSpec && (zoneSpec.onScheduleTask ? this.zone : parentDelegate.zone); this._invokeTaskZS = - zoneSpec && (zoneSpec.onInvokeTask ? zoneSpec : parentDelegate._invokeTaskZS); + zoneSpec && (zoneSpec.onInvokeTask ? zoneSpec : parentDelegate._invokeTaskZS); this._invokeTaskDlgt = - zoneSpec && (zoneSpec.onInvokeTask ? parentDelegate : parentDelegate._invokeTaskDlgt); + zoneSpec && (zoneSpec.onInvokeTask ? parentDelegate : parentDelegate._invokeTaskDlgt); this._invokeTaskCurrZone = - zoneSpec && (zoneSpec.onInvokeTask ? this.zone : parentDelegate.zone); + zoneSpec && (zoneSpec.onInvokeTask ? this.zone : parentDelegate.zone); this._cancelTaskZS = - zoneSpec && (zoneSpec.onCancelTask ? zoneSpec : parentDelegate._cancelTaskZS); + zoneSpec && (zoneSpec.onCancelTask ? zoneSpec : parentDelegate._cancelTaskZS); this._cancelTaskDlgt = - zoneSpec && (zoneSpec.onCancelTask ? parentDelegate : parentDelegate._cancelTaskDlgt); + zoneSpec && (zoneSpec.onCancelTask ? parentDelegate : parentDelegate._cancelTaskDlgt); this._cancelTaskCurrZone = - zoneSpec && (zoneSpec.onCancelTask ? this.zone : parentDelegate.zone); + zoneSpec && (zoneSpec.onCancelTask ? this.zone : parentDelegate.zone); this._hasTaskZS = zoneSpec && (zoneSpec.onHasTask ? zoneSpec : parentDelegate._hasTaskZS); this._hasTaskDlgt = - zoneSpec && (zoneSpec.onHasTask ? parentDelegate : parentDelegate._hasTaskDlgt); + zoneSpec && (zoneSpec.onHasTask ? parentDelegate : parentDelegate._hasTaskDlgt); this._hasTaskCurrZone = zoneSpec && (zoneSpec.onHasTask ? this.zone : parentDelegate.zone); } fork(targetZone: Zone, zoneSpec: ZoneSpec): AmbientZone { return this._forkZS ? this._forkZS.onFork(this._forkDlgt, this.zone, targetZone, zoneSpec) : - new Zone(targetZone, zoneSpec); + new Zone(targetZone, zoneSpec); } intercept(targetZone: Zone, callback: Function, source: string): Function { return this._interceptZS ? - this._interceptZS.onIntercept( - this._interceptDlgt, this._interceptCurrZone, targetZone, callback, source) : - callback; + this._interceptZS.onIntercept( + this._interceptDlgt, this._interceptCurrZone, targetZone, callback, source) : + callback; } invoke(targetZone: Zone, callback: Function, applyThis: any, applyArgs: any[], source: string): - any { + any { return this._invokeZS ? - this._invokeZS.onInvoke( - this._invokeDlgt, this._invokeCurrZone, targetZone, callback, applyThis, applyArgs, - source) : - callback.apply(applyThis, applyArgs); + this._invokeZS.onInvoke( + this._invokeDlgt, this._invokeCurrZone, targetZone, callback, applyThis, applyArgs, + source) : + callback.apply(applyThis, applyArgs); } handleError(targetZone: Zone, error: any): boolean { return this._handleErrorZS ? - this._handleErrorZS.onHandleError( - this._handleErrorDlgt, this._handleErrorCurrZone, targetZone, error) : - true; + this._handleErrorZS.onHandleError( + this._handleErrorDlgt, this._handleErrorCurrZone, targetZone, error) : + true; } scheduleTask(targetZone: Zone, task: Task): Task { try { if (this._scheduleTaskZS) { return this._scheduleTaskZS.onScheduleTask( - this._scheduleTaskDlgt, this._scheduleTaskCurrZone, targetZone, task); + this._scheduleTaskDlgt, this._scheduleTaskCurrZone, targetZone, task); } else if (task.scheduleFn) { task.scheduleFn(task); } else if (task.type == 'microTask') { @@ -860,13 +860,13 @@ const Zone: ZoneType = (function(global: any) { invokeTask(targetZone: Zone, task: Task, applyThis: any, applyArgs: any): any { try { return this._invokeTaskZS ? - this._invokeTaskZS.onInvokeTask( - this._invokeTaskDlgt, this._invokeTaskCurrZone, targetZone, task, applyThis, - applyArgs) : - task.callback.apply(applyThis, applyArgs); + this._invokeTaskZS.onInvokeTask( + this._invokeTaskDlgt, this._invokeTaskCurrZone, targetZone, task, applyThis, + applyArgs) : + task.callback.apply(applyThis, applyArgs); } finally { if (targetZone == this.zone && (task.type != 'eventTask') && - !(task.data && task.data.isPeriodic)) { + !(task.data && task.data.isPeriodic)) { this._updateTaskCount(task.type, -1); } } @@ -876,7 +876,7 @@ const Zone: ZoneType = (function(global: any) { let value; if (this._cancelTaskZS) { value = this._cancelTaskZS.onCancelTask( - this._cancelTaskDlgt, this._cancelTaskCurrZone, targetZone, task); + this._cancelTaskDlgt, this._cancelTaskCurrZone, targetZone, task); } else if (!task.cancelFn) { throw new Error('Task does not support cancellation, or is already canceled.'); } else { @@ -891,7 +891,7 @@ const Zone: ZoneType = (function(global: any) { hasTask(targetZone: Zone, isEmpty: HasTaskState) { return this._hasTaskZS && - this._hasTaskZS.onHasTask(this._hasTaskDlgt, this._hasTaskCurrZone, targetZone, isEmpty); + this._hasTaskZS.onHasTask(this._hasTaskDlgt, this._hasTaskCurrZone, targetZone, isEmpty); } private _updateTaskCount(type: TaskType, count: number) { @@ -932,8 +932,8 @@ const Zone: ZoneType = (function(global: any) { public runCount: number = 0; constructor( - type: TaskType, zone: Zone, source: string, callback: Function, options: TaskData, - scheduleFn: (task: Task) => void, cancelFn: (task: Task) => void) { + type: TaskType, zone: Zone, source: string, callback: Function, options: TaskData, + scheduleFn: (task: Task) => void, cancelFn: (task: Task) => void) { this.type = type; this.zone = zone; this.source = source; @@ -1016,10 +1016,10 @@ const Zone: ZoneType = (function(global: any) { const rejection = e && e.rejection; if (rejection) { console.error( - 'Unhandled Promise rejection:', - rejection instanceof Error ? rejection.message : rejection, '; Zone:', - (e.zone).name, '; Task:', e.task && (e.task).source, '; Value:', rejection, - rejection instanceof Error ? rejection.stack : undefined); + 'Unhandled Promise rejection:', + rejection instanceof Error ? rejection.message : rejection, '; Zone:', + (e.zone).name, '; Task:', e.task && (e.task).source, '; Value:', rejection, + rejection instanceof Error ? rejection.stack : undefined); } console.error(e); } @@ -1084,10 +1084,10 @@ const Zone: ZoneType = (function(global: any) { } function resolvePromise( - promise: ZoneAwarePromise, state: boolean, value: any): ZoneAwarePromise { + promise: ZoneAwarePromise, state: boolean, value: any): ZoneAwarePromise { if (promise[symbolState] === UNRESOLVED) { if (value instanceof ZoneAwarePromise && value.hasOwnProperty(symbolState) && - value.hasOwnProperty(symbolValue) && value[symbolState] !== UNRESOLVED) { + value.hasOwnProperty(symbolValue) && value[symbolState] !== UNRESOLVED) { clearRejectedNoCatch(>value); resolvePromise(promise, value[symbolState], value[symbolValue]); } else if (isThenable(value)) { @@ -1104,8 +1104,8 @@ const Zone: ZoneType = (function(global: any) { promise[symbolState] = REJECTED_NO_CATCH; try { throw new Error( - 'Uncaught (in promise): ' + value + - (value && value.stack ? '\n' + value.stack : '')); + 'Uncaught (in promise): ' + value + + (value && value.stack ? '\n' + value.stack : '')); } catch (e) { const error: UncaughtPromiseError = e; error.rejection = value; @@ -1136,11 +1136,11 @@ const Zone: ZoneType = (function(global: any) { function scheduleResolveOrReject( - promise: ZoneAwarePromise, zone: AmbientZone, chainPromise: ZoneAwarePromise, - onFulfilled?: (value: R) => U, onRejected?: (error: any) => U): void { + promise: ZoneAwarePromise, zone: AmbientZone, chainPromise: ZoneAwarePromise, + onFulfilled?: (value: R) => U, onRejected?: (error: any) => U): void { clearRejectedNoCatch(promise); const delegate = - promise[symbolState] ? onFulfilled || forwardResolution : onRejected || forwardRejection; + promise[symbolState] ? onFulfilled || forwardResolution : onRejected || forwardRejection; zone.scheduleMicroTask(source, () => { try { resolvePromise(chainPromise, true, zone.run(delegate, null, [promise[symbolValue]])); @@ -1195,14 +1195,14 @@ const Zone: ZoneType = (function(global: any) { value = this.resolve(value); } value.then( - ((index) => (value) => { - resolvedValues[index] = value; - count--; - if (!count) { - resolve(resolvedValues); - } - })(count), - reject); + ((index) => (value) => { + resolvedValues[index] = value; + count--; + if (!count) { + resolve(resolvedValues); + } + })(count), + reject); count++; } if (!count) resolve(resolvedValues); @@ -1210,8 +1210,8 @@ const Zone: ZoneType = (function(global: any) { } constructor( - executor: - (resolve: (value?: R|PromiseLike) => void, reject: (error?: any) => void) => void) { + executor: + (resolve: (value?: R|PromiseLike) => void, reject: (error?: any) => void) => void) { const promise: ZoneAwarePromise = this; if (!(promise instanceof ZoneAwarePromise)) { throw new Error('Must be an instanceof Promise.'); @@ -1226,8 +1226,8 @@ const Zone: ZoneType = (function(global: any) { } then( - onFulfilled?: (value: R) => U | PromiseLike, - onRejected?: (error: any) => U | PromiseLike): Promise { + onFulfilled?: (value: R) => U | PromiseLike, + onRejected?: (error: any) => U | PromiseLike): Promise { const chainPromise: Promise = new (this.constructor as typeof ZoneAwarePromise)(null); const zone = Zone.current; if (this[symbolState] == UNRESOLVED) { @@ -1254,13 +1254,13 @@ const Zone: ZoneType = (function(global: any) { function patchThen(NativePromise) { const NativePromiseProtototype = NativePromise.prototype; const NativePromiseThen = NativePromiseProtototype[__symbol__('then')] = - NativePromiseProtototype.then; + NativePromiseProtototype.then; NativePromiseProtototype.then = function(onResolve, onReject) { const nativePromise = this; return new ZoneAwarePromise((resolve, reject) => { - NativePromiseThen.call(nativePromise, resolve, reject); - }) - .then(onResolve, onReject); + NativePromiseThen.call(nativePromise, resolve, reject); + }) + .then(onResolve, onReject); }; } @@ -1278,7 +1278,7 @@ const Zone: ZoneType = (function(global: any) { // ignore output to prevent error; fetchPromise.then(() => null, () => null); if (fetchPromise.constructor != NativePromise && - fetchPromise.constructor != ZoneAwarePromise) { + fetchPromise.constructor != ZoneAwarePromise) { patchThen(fetchPromise.constructor); } } @@ -1296,7 +1296,7 @@ const Zone: ZoneType = (function(global: any) { enum FrameType { /// Skip this frame when printing out stack blackList, - /// This frame marks zone transition + /// This frame marks zone transition transition } @@ -1310,62 +1310,63 @@ const Zone: ZoneType = (function(global: any) { let frameParserStrategy = null; const stackRewrite = 'stackRewrite'; - const setPrototypeOf = Object.prototype['setPrototypeOf'] ? Object.prototype['setPrototypeOf'] : - function(obj, proto) { - obj.__proto__ = proto; - return obj; - } - - - /** - * This is ZoneAwareError which processes the stack frame and cleans up extra frames as well - * as - * adds zone information to it. - */ - function - ZoneAwareError() { - // Create an Error. - let error: Error = NativeError.apply(this, arguments); - // Save original stack trace - error.originalStack = error.stack; - - // Process the stack trace and rewrite the frames. - if (ZoneAwareError[stackRewrite] && error.originalStack) { - let frames: string[] = error.originalStack.split('\n'); - let zoneFrame = _currentZoneFrame; - let i = 0; - // Find the first frame - while (frames[i] !== zoneAwareFrame && i < frames.length) { - i++; - } - for (; i < frames.length && zoneFrame; i++) { - let frame = frames[i]; - if (frame.trim()) { - let frameType = - blackListedStackFrames.hasOwnProperty(frame) && blackListedStackFrames[frame]; - if (frameType === FrameType.blackList) { - frames.splice(i, 1); - i--; - } else if (frameType === FrameType.transition) { - if (zoneFrame.parent) { - // This is the special frame where zone changed. Print and process it accordingly - frames[i] += ` [${zoneFrame.parent.zone.name} => ${zoneFrame.zone.name}]`; - zoneFrame = zoneFrame.parent; - } else { - zoneFrame = null; - } - } else { - frames[i] += ` [${zoneFrame.zone.name}]`; - } + const setPrototypeOf = Object.prototype['setPrototypeOf'] ? + Object.prototype['setPrototypeOf'] : + function(obj, proto) { + obj.__proto__ = proto; + return obj; + }; + + /** + * This is ZoneAwareError which processes the stack frame and cleans up extra frames as well as + * adds zone information to it. + */ + function ZoneAwareError() { + // Create an Error. + let error: Error = NativeError.apply(this, arguments); + + // Save original stack trace + error.originalStack = error.stack; + + // Process the stack trace and rewrite the frames. + if (ZoneAwareError[stackRewrite] && error.originalStack) { + let frames: string[] = error.originalStack.split('\n'); + let zoneFrame = _currentZoneFrame; + let i = 0; + // Find the first frame + while (frames[i] !== zoneAwareFrame && i < frames.length) { + i++; + } + for (; i < frames.length && zoneFrame; i++) { + let frame = frames[i]; + if (frame.trim()) { + let frameType = + blackListedStackFrames.hasOwnProperty(frame) && blackListedStackFrames[frame]; + if (frameType === FrameType.blackList) { + frames.splice(i, 1); + i--; + } else if (frameType === FrameType.transition) { + if (zoneFrame.parent) { + // This is the special frame where zone changed. Print and process it accordingly + frames[i] += ` [${zoneFrame.parent.zone.name} => ${zoneFrame.zone.name}]`; + zoneFrame = zoneFrame.parent; + } else { + zoneFrame = null; } + } else { + frames[i] += ` [${zoneFrame.zone.name}]`; } - error.stack = error.zoneAwareStack = frames.join('\n'); - } - if (this && this !== global) { - error = setPrototypeOf(error, this.constructor.prototype); } - return error; - }; + } + error.stack = error.zoneAwareStack = frames.join('\n'); + } + // if this is valid, means not undefined + // and not global (non-strict mode call Error()) + if (this && this !== global) { + error = setPrototypeOf(error, this.constructor.prototype); + } + return error; + } // Copy the prototype so that instanceof operator works as expected ZoneAwareError.prototype = NativeError.prototype; @@ -1413,53 +1414,53 @@ const Zone: ZoneType = (function(global: any) { let detectZone: Zone = Zone.current.fork({ name: 'detect', onInvoke: function( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function, - applyThis: any, applyArgs: any[], source: string): any { + parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function, + applyThis: any, applyArgs: any[], source: string): any { // Here only so that it will show up in the stack frame so that it can be black listed. return parentZoneDelegate.invoke(targetZone, delegate, applyThis, applyArgs, source); }, onHandleError: function(parentZD: ZoneDelegate, current: Zone, target: Zone, error: any): - boolean { - if (error.originalStack && Error === ZoneAwareError) { - let frames = error.originalStack.split(/\n/); - let runFrame = false, runGuardedFrame = false, runTaskFrame = false; - while (frames.length) { - let frame = frames.shift(); - // On safari it is possible to have stack frame with no line number. - // This check makes sure that we don't filter frames on name only (must have - // linenumber) - if (/:\d+:\d+/.test(frame)) { - // Get rid of the path so that we don't accidintely find function name in path. - // In chrome the seperator is `(` and `@` in FF and safari - // Chrome: at Zone.run (zone.js:100) - // Chrome: at Zone.run (http://localhost:9876/base/build/lib/zone.js:100:24) - // FireFox: Zone.prototype.run@http://localhost:9876/base/build/lib/zone.js:101:24 - // Safari: run@http://localhost:9876/base/build/lib/zone.js:101:24 - let fnName: string = frame.split('(')[0].split('@')[0]; - let frameType = FrameType.transition; - if (fnName.indexOf('ZoneAwareError') !== -1) { - zoneAwareFrame = frame; - } - if (fnName.indexOf('runGuarded') !== -1) { - runGuardedFrame = true; - } else if (fnName.indexOf('runTask') !== -1) { - runTaskFrame = true; - } else if (fnName.indexOf('run') !== -1) { - runFrame = true; - } else { - frameType = FrameType.blackList; - } - blackListedStackFrames[frame] = frameType; - // Once we find all of the frames we can stop looking. - if (runFrame && runGuardedFrame && runTaskFrame) { - ZoneAwareError[stackRewrite] = true; - break; - } - } + boolean { + if (error.originalStack && Error === ZoneAwareError) { + let frames = error.originalStack.split(/\n/); + let runFrame = false, runGuardedFrame = false, runTaskFrame = false; + while (frames.length) { + let frame = frames.shift(); + // On safari it is possible to have stack frame with no line number. + // This check makes sure that we don't filter frames on name only (must have + // linenumber) + if (/:\d+:\d+/.test(frame)) { + // Get rid of the path so that we don't accidintely find function name in path. + // In chrome the seperator is `(` and `@` in FF and safari + // Chrome: at Zone.run (zone.js:100) + // Chrome: at Zone.run (http://localhost:9876/base/build/lib/zone.js:100:24) + // FireFox: Zone.prototype.run@http://localhost:9876/base/build/lib/zone.js:101:24 + // Safari: run@http://localhost:9876/base/build/lib/zone.js:101:24 + let fnName: string = frame.split('(')[0].split('@')[0]; + let frameType = FrameType.transition; + if (fnName.indexOf('ZoneAwareError') !== -1) { + zoneAwareFrame = frame; + } + if (fnName.indexOf('runGuarded') !== -1) { + runGuardedFrame = true; + } else if (fnName.indexOf('runTask') !== -1) { + runTaskFrame = true; + } else if (fnName.indexOf('run') !== -1) { + runFrame = true; + } else { + frameType = FrameType.blackList; + } + blackListedStackFrames[frame] = frameType; + // Once we find all of the frames we can stop looking. + if (runFrame && runGuardedFrame && runTaskFrame) { + ZoneAwareError[stackRewrite] = true; + break; } } - return false; } + } + return false; + } }) as Zone; // carefully constructor a stack frame which contains all of the frames of interest which // need to be detected and blacklisted. @@ -1474,4 +1475,4 @@ const Zone: ZoneType = (function(global: any) { detectZone.runTask(detectZone.scheduleMacroTask('detect', detectRunFn, null, () => null, null)); return global['Zone'] = Zone; -})(typeof window === 'object' && window || typeof self === 'object' && self || global); +})(typeof window === 'object' && window || typeof self === 'object' && self || global); \ No newline at end of file From b1955187968044bc924ca5934bdc59259f2771d9 Mon Sep 17 00:00:00 2001 From: "JiaLi.Passion" Date: Fri, 23 Dec 2016 23:10:47 +0800 Subject: [PATCH 09/20] reformat with gulp format --- lib/zone.ts | 322 ++++++++++++++++++++++++++-------------------------- 1 file changed, 161 insertions(+), 161 deletions(-) diff --git a/lib/zone.ts b/lib/zone.ts index dd0404963..3d53f91f6 100644 --- a/lib/zone.ts +++ b/lib/zone.ts @@ -221,14 +221,14 @@ interface Zone { */ runTask(task: Task, applyThis?: any, applyArgs?: any): any; scheduleMicroTask( - source: string, callback: Function, data?: TaskData, - customSchedule?: (task: Task) => void): MicroTask; + source: string, callback: Function, data?: TaskData, + customSchedule?: (task: Task) => void): MicroTask; scheduleMacroTask( - source: string, callback: Function, data: TaskData, customSchedule: (task: Task) => void, - customCancel: (task: Task) => void): MacroTask; + source: string, callback: Function, data: TaskData, customSchedule: (task: Task) => void, + customCancel: (task: Task) => void): MacroTask; scheduleEventTask( - source: string, callback: Function, data: TaskData, customSchedule: (task: Task) => void, - customCancel: (task: Task) => void): EventTask; + source: string, callback: Function, data: TaskData, customSchedule: (task: Task) => void, + customCancel: (task: Task) => void): EventTask; /** * Allows the zone to intercept canceling of scheduled Task. * @@ -286,8 +286,8 @@ interface ZoneSpec { * @param zoneSpec The argument passed into the `fork` method. */ onFork?: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, - zoneSpec: ZoneSpec) => Zone; + (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, + zoneSpec: ZoneSpec) => Zone; /** * Allows interception of the wrapping of the callback. @@ -299,8 +299,8 @@ interface ZoneSpec { * @param source The argument passed into the `warp` method. */ onIntercept?: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function, - source: string) => Function; + (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function, + source: string) => Function; /** * Allows interception of the callback invocation. @@ -314,8 +314,8 @@ interface ZoneSpec { * @param source The argument passed into the `run` method. */ onInvoke?: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function, - applyThis: any, applyArgs: any[], source: string) => any; + (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function, + applyThis: any, applyArgs: any[], source: string) => any; /** * Allows interception of the error handling. @@ -326,8 +326,8 @@ interface ZoneSpec { * @param error The argument passed into the `handleError` method. */ onHandleError?: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, - error: any) => boolean; + (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, + error: any) => boolean; /** * Allows interception of task scheduling. @@ -338,11 +338,11 @@ interface ZoneSpec { * @param task The argument passed into the `scheduleTask` method. */ onScheduleTask?: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task) => Task; + (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task) => Task; onInvokeTask?: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task, - applyThis: any, applyArgs: any) => any; + (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task, + applyThis: any, applyArgs: any) => any; /** * Allows interception of task cancelation. @@ -353,7 +353,7 @@ interface ZoneSpec { * @param task The argument passed into the `cancelTask` method. */ onCancelTask?: - (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task) => any; + (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task) => any; /** * Notifies of changes to the task queue empty status. @@ -364,7 +364,7 @@ interface ZoneSpec { * @param isEmpty */ onHasTask?: - (delegate: ZoneDelegate, current: Zone, target: Zone, hasTaskState: HasTaskState) => void; + (delegate: ZoneDelegate, current: Zone, target: Zone, hasTaskState: HasTaskState) => void; } ; @@ -404,7 +404,7 @@ interface ZoneDelegate { fork(targetZone: Zone, zoneSpec: ZoneSpec): Zone; intercept(targetZone: Zone, callback: Function, source: string): Function; invoke(targetZone: Zone, callback: Function, applyThis: any, applyArgs: any[], source: string): - any; + any; handleError(targetZone: Zone, error: any): boolean; scheduleTask(targetZone: Zone, task: Task): Task; invokeTask(targetZone: Zone, task: Task, applyThis: any, applyArgs: any): any; @@ -462,7 +462,7 @@ interface Task { /** * Task type: `microTask`, `macroTask`, `eventTask`. */ - type: TaskType; + type: TaskType; /** * Debug string representing the API which requested the scheduling of the task. @@ -556,11 +556,11 @@ const Zone: ZoneType = (function(global: any) { static assertZonePatched() { if (global.Promise !== ZoneAwarePromise) { throw new Error( - 'Zone.js has detected that ZoneAwarePromise `(window|global).Promise` ' + - 'has been overwritten.\n' + - 'Most likely cause is that a Promise polyfill has been loaded ' + - 'after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. ' + - 'If you must load one, do so before loading zone.js.)'); + 'Zone.js has detected that ZoneAwarePromise `(window|global).Promise` ' + + 'has been overwritten.\n' + + 'Most likely cause is that a Promise polyfill has been loaded ' + + 'after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. ' + + 'If you must load one, do so before loading zone.js.)'); } } @@ -590,7 +590,7 @@ const Zone: ZoneType = (function(global: any) { this._name = zoneSpec ? zoneSpec.name || 'unnamed' : ''; this._properties = zoneSpec && zoneSpec.properties || {}; this._zoneDelegate = - new ZoneDelegate(this, this._parent && this._parent._zoneDelegate, zoneSpec); + new ZoneDelegate(this, this._parent && this._parent._zoneDelegate, zoneSpec); } public get(key: string): any { @@ -627,8 +627,8 @@ const Zone: ZoneType = (function(global: any) { public run(callback: Function, applyThis?: any, applyArgs?: any[], source?: string): any; public run( - callback: (...args: any[]) => T, applyThis: any = null, applyArgs: any[] = null, - source: string = null): T { + callback: (...args: any[]) => T, applyThis: any = null, applyArgs: any[] = null, + source: string = null): T { _currentZoneFrame = new ZoneFrame(_currentZoneFrame, this); try { return this._zoneDelegate.invoke(this, callback, applyThis, applyArgs, source); @@ -639,8 +639,8 @@ const Zone: ZoneType = (function(global: any) { public runGuarded(callback: Function, applyThis?: any, applyArgs?: any[], source?: string): any; public runGuarded( - callback: (...args: any[]) => T, applyThis: any = null, applyArgs: any[] = null, - source: string = null) { + callback: (...args: any[]) => T, applyThis: any = null, applyArgs: any[] = null, + source: string = null) { _currentZoneFrame = new ZoneFrame(_currentZoneFrame, this); try { try { @@ -660,8 +660,8 @@ const Zone: ZoneType = (function(global: any) { task.runCount++; if (task.zone != this) throw new Error( - 'A task can only be run in the zone which created it! (Creation: ' + task.zone.name + - '; Execution: ' + this.name + ')'); + 'A task can only be run in the zone which created it! (Creation: ' + task.zone.name + + '; Execution: ' + this.name + ')'); const previousTask = _currentTask; _currentTask = task; _currentZoneFrame = new ZoneFrame(_currentZoneFrame, this); @@ -684,26 +684,26 @@ const Zone: ZoneType = (function(global: any) { scheduleMicroTask( - source: string, callback: Function, data?: TaskData, - customSchedule?: (task: Task) => void): MicroTask { + source: string, callback: Function, data?: TaskData, + customSchedule?: (task: Task) => void): MicroTask { return this._zoneDelegate.scheduleTask( - this, new ZoneTask('microTask', this, source, callback, data, customSchedule, null)); + this, new ZoneTask('microTask', this, source, callback, data, customSchedule, null)); } scheduleMacroTask( - source: string, callback: Function, data: TaskData, customSchedule: (task: Task) => void, - customCancel: (task: Task) => void): MacroTask { + source: string, callback: Function, data: TaskData, customSchedule: (task: Task) => void, + customCancel: (task: Task) => void): MacroTask { return this._zoneDelegate.scheduleTask( - this, - new ZoneTask('macroTask', this, source, callback, data, customSchedule, customCancel)); + this, + new ZoneTask('macroTask', this, source, callback, data, customSchedule, customCancel)); } scheduleEventTask( - source: string, callback: Function, data: TaskData, customSchedule: (task: Task) => void, - customCancel: (task: Task) => void): EventTask { + source: string, callback: Function, data: TaskData, customSchedule: (task: Task) => void, + customCancel: (task: Task) => void): EventTask { return this._zoneDelegate.scheduleTask( - this, - new ZoneTask('eventTask', this, source, callback, data, customSchedule, customCancel)); + this, + new ZoneTask('eventTask', this, source, callback, data, customSchedule, customCancel)); } cancelTask(task: Task): any { @@ -718,8 +718,8 @@ const Zone: ZoneType = (function(global: any) { public zone: Zone; private _taskCounts: {microTask: number, - macroTask: number, - eventTask: number} = {microTask: 0, macroTask: 0, eventTask: 0}; + macroTask: number, + eventTask: number} = {microTask: 0, macroTask: 0, eventTask: 0}; private _parentDelegate: ZoneDelegate; @@ -764,84 +764,84 @@ const Zone: ZoneType = (function(global: any) { this._forkCurrZone = zoneSpec && (zoneSpec.onFork ? this.zone : parentDelegate.zone); this._interceptZS = - zoneSpec && (zoneSpec.onIntercept ? zoneSpec : parentDelegate._interceptZS); + zoneSpec && (zoneSpec.onIntercept ? zoneSpec : parentDelegate._interceptZS); this._interceptDlgt = - zoneSpec && (zoneSpec.onIntercept ? parentDelegate : parentDelegate._interceptDlgt); + zoneSpec && (zoneSpec.onIntercept ? parentDelegate : parentDelegate._interceptDlgt); this._interceptCurrZone = - zoneSpec && (zoneSpec.onIntercept ? this.zone : parentDelegate.zone); + zoneSpec && (zoneSpec.onIntercept ? this.zone : parentDelegate.zone); this._invokeZS = zoneSpec && (zoneSpec.onInvoke ? zoneSpec : parentDelegate._invokeZS); this._invokeDlgt = - zoneSpec && (zoneSpec.onInvoke ? parentDelegate : parentDelegate._invokeDlgt); + zoneSpec && (zoneSpec.onInvoke ? parentDelegate : parentDelegate._invokeDlgt); this._invokeCurrZone = zoneSpec && (zoneSpec.onInvoke ? this.zone : parentDelegate.zone); this._handleErrorZS = - zoneSpec && (zoneSpec.onHandleError ? zoneSpec : parentDelegate._handleErrorZS); + zoneSpec && (zoneSpec.onHandleError ? zoneSpec : parentDelegate._handleErrorZS); this._handleErrorDlgt = - zoneSpec && (zoneSpec.onHandleError ? parentDelegate : parentDelegate._handleErrorDlgt); + zoneSpec && (zoneSpec.onHandleError ? parentDelegate : parentDelegate._handleErrorDlgt); this._handleErrorCurrZone = - zoneSpec && (zoneSpec.onHandleError ? this.zone : parentDelegate.zone); + zoneSpec && (zoneSpec.onHandleError ? this.zone : parentDelegate.zone); this._scheduleTaskZS = - zoneSpec && (zoneSpec.onScheduleTask ? zoneSpec : parentDelegate._scheduleTaskZS); + zoneSpec && (zoneSpec.onScheduleTask ? zoneSpec : parentDelegate._scheduleTaskZS); this._scheduleTaskDlgt = - zoneSpec && (zoneSpec.onScheduleTask ? parentDelegate : parentDelegate._scheduleTaskDlgt); + zoneSpec && (zoneSpec.onScheduleTask ? parentDelegate : parentDelegate._scheduleTaskDlgt); this._scheduleTaskCurrZone = - zoneSpec && (zoneSpec.onScheduleTask ? this.zone : parentDelegate.zone); + zoneSpec && (zoneSpec.onScheduleTask ? this.zone : parentDelegate.zone); this._invokeTaskZS = - zoneSpec && (zoneSpec.onInvokeTask ? zoneSpec : parentDelegate._invokeTaskZS); + zoneSpec && (zoneSpec.onInvokeTask ? zoneSpec : parentDelegate._invokeTaskZS); this._invokeTaskDlgt = - zoneSpec && (zoneSpec.onInvokeTask ? parentDelegate : parentDelegate._invokeTaskDlgt); + zoneSpec && (zoneSpec.onInvokeTask ? parentDelegate : parentDelegate._invokeTaskDlgt); this._invokeTaskCurrZone = - zoneSpec && (zoneSpec.onInvokeTask ? this.zone : parentDelegate.zone); + zoneSpec && (zoneSpec.onInvokeTask ? this.zone : parentDelegate.zone); this._cancelTaskZS = - zoneSpec && (zoneSpec.onCancelTask ? zoneSpec : parentDelegate._cancelTaskZS); + zoneSpec && (zoneSpec.onCancelTask ? zoneSpec : parentDelegate._cancelTaskZS); this._cancelTaskDlgt = - zoneSpec && (zoneSpec.onCancelTask ? parentDelegate : parentDelegate._cancelTaskDlgt); + zoneSpec && (zoneSpec.onCancelTask ? parentDelegate : parentDelegate._cancelTaskDlgt); this._cancelTaskCurrZone = - zoneSpec && (zoneSpec.onCancelTask ? this.zone : parentDelegate.zone); + zoneSpec && (zoneSpec.onCancelTask ? this.zone : parentDelegate.zone); this._hasTaskZS = zoneSpec && (zoneSpec.onHasTask ? zoneSpec : parentDelegate._hasTaskZS); this._hasTaskDlgt = - zoneSpec && (zoneSpec.onHasTask ? parentDelegate : parentDelegate._hasTaskDlgt); + zoneSpec && (zoneSpec.onHasTask ? parentDelegate : parentDelegate._hasTaskDlgt); this._hasTaskCurrZone = zoneSpec && (zoneSpec.onHasTask ? this.zone : parentDelegate.zone); } fork(targetZone: Zone, zoneSpec: ZoneSpec): AmbientZone { return this._forkZS ? this._forkZS.onFork(this._forkDlgt, this.zone, targetZone, zoneSpec) : - new Zone(targetZone, zoneSpec); + new Zone(targetZone, zoneSpec); } intercept(targetZone: Zone, callback: Function, source: string): Function { return this._interceptZS ? - this._interceptZS.onIntercept( - this._interceptDlgt, this._interceptCurrZone, targetZone, callback, source) : - callback; + this._interceptZS.onIntercept( + this._interceptDlgt, this._interceptCurrZone, targetZone, callback, source) : + callback; } invoke(targetZone: Zone, callback: Function, applyThis: any, applyArgs: any[], source: string): - any { + any { return this._invokeZS ? - this._invokeZS.onInvoke( - this._invokeDlgt, this._invokeCurrZone, targetZone, callback, applyThis, applyArgs, - source) : - callback.apply(applyThis, applyArgs); + this._invokeZS.onInvoke( + this._invokeDlgt, this._invokeCurrZone, targetZone, callback, applyThis, applyArgs, + source) : + callback.apply(applyThis, applyArgs); } handleError(targetZone: Zone, error: any): boolean { return this._handleErrorZS ? - this._handleErrorZS.onHandleError( - this._handleErrorDlgt, this._handleErrorCurrZone, targetZone, error) : - true; + this._handleErrorZS.onHandleError( + this._handleErrorDlgt, this._handleErrorCurrZone, targetZone, error) : + true; } scheduleTask(targetZone: Zone, task: Task): Task { try { if (this._scheduleTaskZS) { return this._scheduleTaskZS.onScheduleTask( - this._scheduleTaskDlgt, this._scheduleTaskCurrZone, targetZone, task); + this._scheduleTaskDlgt, this._scheduleTaskCurrZone, targetZone, task); } else if (task.scheduleFn) { task.scheduleFn(task); } else if (task.type == 'microTask') { @@ -860,13 +860,13 @@ const Zone: ZoneType = (function(global: any) { invokeTask(targetZone: Zone, task: Task, applyThis: any, applyArgs: any): any { try { return this._invokeTaskZS ? - this._invokeTaskZS.onInvokeTask( - this._invokeTaskDlgt, this._invokeTaskCurrZone, targetZone, task, applyThis, - applyArgs) : - task.callback.apply(applyThis, applyArgs); + this._invokeTaskZS.onInvokeTask( + this._invokeTaskDlgt, this._invokeTaskCurrZone, targetZone, task, applyThis, + applyArgs) : + task.callback.apply(applyThis, applyArgs); } finally { if (targetZone == this.zone && (task.type != 'eventTask') && - !(task.data && task.data.isPeriodic)) { + !(task.data && task.data.isPeriodic)) { this._updateTaskCount(task.type, -1); } } @@ -876,7 +876,7 @@ const Zone: ZoneType = (function(global: any) { let value; if (this._cancelTaskZS) { value = this._cancelTaskZS.onCancelTask( - this._cancelTaskDlgt, this._cancelTaskCurrZone, targetZone, task); + this._cancelTaskDlgt, this._cancelTaskCurrZone, targetZone, task); } else if (!task.cancelFn) { throw new Error('Task does not support cancellation, or is already canceled.'); } else { @@ -891,7 +891,7 @@ const Zone: ZoneType = (function(global: any) { hasTask(targetZone: Zone, isEmpty: HasTaskState) { return this._hasTaskZS && - this._hasTaskZS.onHasTask(this._hasTaskDlgt, this._hasTaskCurrZone, targetZone, isEmpty); + this._hasTaskZS.onHasTask(this._hasTaskDlgt, this._hasTaskCurrZone, targetZone, isEmpty); } private _updateTaskCount(type: TaskType, count: number) { @@ -932,8 +932,8 @@ const Zone: ZoneType = (function(global: any) { public runCount: number = 0; constructor( - type: TaskType, zone: Zone, source: string, callback: Function, options: TaskData, - scheduleFn: (task: Task) => void, cancelFn: (task: Task) => void) { + type: TaskType, zone: Zone, source: string, callback: Function, options: TaskData, + scheduleFn: (task: Task) => void, cancelFn: (task: Task) => void) { this.type = type; this.zone = zone; this.source = source; @@ -1016,10 +1016,10 @@ const Zone: ZoneType = (function(global: any) { const rejection = e && e.rejection; if (rejection) { console.error( - 'Unhandled Promise rejection:', - rejection instanceof Error ? rejection.message : rejection, '; Zone:', - (e.zone).name, '; Task:', e.task && (e.task).source, '; Value:', rejection, - rejection instanceof Error ? rejection.stack : undefined); + 'Unhandled Promise rejection:', + rejection instanceof Error ? rejection.message : rejection, '; Zone:', + (e.zone).name, '; Task:', e.task && (e.task).source, '; Value:', rejection, + rejection instanceof Error ? rejection.stack : undefined); } console.error(e); } @@ -1084,10 +1084,10 @@ const Zone: ZoneType = (function(global: any) { } function resolvePromise( - promise: ZoneAwarePromise, state: boolean, value: any): ZoneAwarePromise { + promise: ZoneAwarePromise, state: boolean, value: any): ZoneAwarePromise { if (promise[symbolState] === UNRESOLVED) { if (value instanceof ZoneAwarePromise && value.hasOwnProperty(symbolState) && - value.hasOwnProperty(symbolValue) && value[symbolState] !== UNRESOLVED) { + value.hasOwnProperty(symbolValue) && value[symbolState] !== UNRESOLVED) { clearRejectedNoCatch(>value); resolvePromise(promise, value[symbolState], value[symbolValue]); } else if (isThenable(value)) { @@ -1104,8 +1104,8 @@ const Zone: ZoneType = (function(global: any) { promise[symbolState] = REJECTED_NO_CATCH; try { throw new Error( - 'Uncaught (in promise): ' + value + - (value && value.stack ? '\n' + value.stack : '')); + 'Uncaught (in promise): ' + value + + (value && value.stack ? '\n' + value.stack : '')); } catch (e) { const error: UncaughtPromiseError = e; error.rejection = value; @@ -1136,11 +1136,11 @@ const Zone: ZoneType = (function(global: any) { function scheduleResolveOrReject( - promise: ZoneAwarePromise, zone: AmbientZone, chainPromise: ZoneAwarePromise, - onFulfilled?: (value: R) => U, onRejected?: (error: any) => U): void { + promise: ZoneAwarePromise, zone: AmbientZone, chainPromise: ZoneAwarePromise, + onFulfilled?: (value: R) => U, onRejected?: (error: any) => U): void { clearRejectedNoCatch(promise); const delegate = - promise[symbolState] ? onFulfilled || forwardResolution : onRejected || forwardRejection; + promise[symbolState] ? onFulfilled || forwardResolution : onRejected || forwardRejection; zone.scheduleMicroTask(source, () => { try { resolvePromise(chainPromise, true, zone.run(delegate, null, [promise[symbolValue]])); @@ -1195,14 +1195,14 @@ const Zone: ZoneType = (function(global: any) { value = this.resolve(value); } value.then( - ((index) => (value) => { - resolvedValues[index] = value; - count--; - if (!count) { - resolve(resolvedValues); - } - })(count), - reject); + ((index) => (value) => { + resolvedValues[index] = value; + count--; + if (!count) { + resolve(resolvedValues); + } + })(count), + reject); count++; } if (!count) resolve(resolvedValues); @@ -1210,8 +1210,8 @@ const Zone: ZoneType = (function(global: any) { } constructor( - executor: - (resolve: (value?: R|PromiseLike) => void, reject: (error?: any) => void) => void) { + executor: + (resolve: (value?: R|PromiseLike) => void, reject: (error?: any) => void) => void) { const promise: ZoneAwarePromise = this; if (!(promise instanceof ZoneAwarePromise)) { throw new Error('Must be an instanceof Promise.'); @@ -1226,8 +1226,8 @@ const Zone: ZoneType = (function(global: any) { } then( - onFulfilled?: (value: R) => U | PromiseLike, - onRejected?: (error: any) => U | PromiseLike): Promise { + onFulfilled?: (value: R) => U | PromiseLike, + onRejected?: (error: any) => U | PromiseLike): Promise { const chainPromise: Promise = new (this.constructor as typeof ZoneAwarePromise)(null); const zone = Zone.current; if (this[symbolState] == UNRESOLVED) { @@ -1254,13 +1254,13 @@ const Zone: ZoneType = (function(global: any) { function patchThen(NativePromise) { const NativePromiseProtototype = NativePromise.prototype; const NativePromiseThen = NativePromiseProtototype[__symbol__('then')] = - NativePromiseProtototype.then; + NativePromiseProtototype.then; NativePromiseProtototype.then = function(onResolve, onReject) { const nativePromise = this; return new ZoneAwarePromise((resolve, reject) => { - NativePromiseThen.call(nativePromise, resolve, reject); - }) - .then(onResolve, onReject); + NativePromiseThen.call(nativePromise, resolve, reject); + }) + .then(onResolve, onReject); }; } @@ -1278,7 +1278,7 @@ const Zone: ZoneType = (function(global: any) { // ignore output to prevent error; fetchPromise.then(() => null, () => null); if (fetchPromise.constructor != NativePromise && - fetchPromise.constructor != ZoneAwarePromise) { + fetchPromise.constructor != ZoneAwarePromise) { patchThen(fetchPromise.constructor); } } @@ -1296,7 +1296,7 @@ const Zone: ZoneType = (function(global: any) { enum FrameType { /// Skip this frame when printing out stack blackList, - /// This frame marks zone transition + /// This frame marks zone transition transition } @@ -1310,12 +1310,12 @@ const Zone: ZoneType = (function(global: any) { let frameParserStrategy = null; const stackRewrite = 'stackRewrite'; - const setPrototypeOf = Object.prototype['setPrototypeOf'] ? - Object.prototype['setPrototypeOf'] : - function(obj, proto) { - obj.__proto__ = proto; - return obj; - }; + const setPrototypeOf = + Object.prototype['setPrototypeOf'] ? Object.prototype['setPrototypeOf'] : function( + obj, proto) { + obj.__proto__ = proto; + return obj; + }; /** * This is ZoneAwareError which processes the stack frame and cleans up extra frames as well as @@ -1341,7 +1341,7 @@ const Zone: ZoneType = (function(global: any) { let frame = frames[i]; if (frame.trim()) { let frameType = - blackListedStackFrames.hasOwnProperty(frame) && blackListedStackFrames[frame]; + blackListedStackFrames.hasOwnProperty(frame) && blackListedStackFrames[frame]; if (frameType === FrameType.blackList) { frames.splice(i, 1); i--; @@ -1414,53 +1414,53 @@ const Zone: ZoneType = (function(global: any) { let detectZone: Zone = Zone.current.fork({ name: 'detect', onInvoke: function( - parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function, - applyThis: any, applyArgs: any[], source: string): any { + parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function, + applyThis: any, applyArgs: any[], source: string): any { // Here only so that it will show up in the stack frame so that it can be black listed. return parentZoneDelegate.invoke(targetZone, delegate, applyThis, applyArgs, source); }, onHandleError: function(parentZD: ZoneDelegate, current: Zone, target: Zone, error: any): - boolean { - if (error.originalStack && Error === ZoneAwareError) { - let frames = error.originalStack.split(/\n/); - let runFrame = false, runGuardedFrame = false, runTaskFrame = false; - while (frames.length) { - let frame = frames.shift(); - // On safari it is possible to have stack frame with no line number. - // This check makes sure that we don't filter frames on name only (must have - // linenumber) - if (/:\d+:\d+/.test(frame)) { - // Get rid of the path so that we don't accidintely find function name in path. - // In chrome the seperator is `(` and `@` in FF and safari - // Chrome: at Zone.run (zone.js:100) - // Chrome: at Zone.run (http://localhost:9876/base/build/lib/zone.js:100:24) - // FireFox: Zone.prototype.run@http://localhost:9876/base/build/lib/zone.js:101:24 - // Safari: run@http://localhost:9876/base/build/lib/zone.js:101:24 - let fnName: string = frame.split('(')[0].split('@')[0]; - let frameType = FrameType.transition; - if (fnName.indexOf('ZoneAwareError') !== -1) { - zoneAwareFrame = frame; - } - if (fnName.indexOf('runGuarded') !== -1) { - runGuardedFrame = true; - } else if (fnName.indexOf('runTask') !== -1) { - runTaskFrame = true; - } else if (fnName.indexOf('run') !== -1) { - runFrame = true; - } else { - frameType = FrameType.blackList; - } - blackListedStackFrames[frame] = frameType; - // Once we find all of the frames we can stop looking. - if (runFrame && runGuardedFrame && runTaskFrame) { - ZoneAwareError[stackRewrite] = true; - break; + boolean { + if (error.originalStack && Error === ZoneAwareError) { + let frames = error.originalStack.split(/\n/); + let runFrame = false, runGuardedFrame = false, runTaskFrame = false; + while (frames.length) { + let frame = frames.shift(); + // On safari it is possible to have stack frame with no line number. + // This check makes sure that we don't filter frames on name only (must have + // linenumber) + if (/:\d+:\d+/.test(frame)) { + // Get rid of the path so that we don't accidintely find function name in path. + // In chrome the seperator is `(` and `@` in FF and safari + // Chrome: at Zone.run (zone.js:100) + // Chrome: at Zone.run (http://localhost:9876/base/build/lib/zone.js:100:24) + // FireFox: Zone.prototype.run@http://localhost:9876/base/build/lib/zone.js:101:24 + // Safari: run@http://localhost:9876/base/build/lib/zone.js:101:24 + let fnName: string = frame.split('(')[0].split('@')[0]; + let frameType = FrameType.transition; + if (fnName.indexOf('ZoneAwareError') !== -1) { + zoneAwareFrame = frame; + } + if (fnName.indexOf('runGuarded') !== -1) { + runGuardedFrame = true; + } else if (fnName.indexOf('runTask') !== -1) { + runTaskFrame = true; + } else if (fnName.indexOf('run') !== -1) { + runFrame = true; + } else { + frameType = FrameType.blackList; + } + blackListedStackFrames[frame] = frameType; + // Once we find all of the frames we can stop looking. + if (runFrame && runGuardedFrame && runTaskFrame) { + ZoneAwareError[stackRewrite] = true; + break; + } + } } } + return false; } - } - return false; - } }) as Zone; // carefully constructor a stack frame which contains all of the frames of interest which // need to be detected and blacklisted. From 15f39628850d5f2f11beecdd89795c1bce5fbb25 Mon Sep 17 00:00:00 2001 From: "JiaLi.Passion" Date: Fri, 23 Dec 2016 23:13:29 +0800 Subject: [PATCH 10/20] add blank line --- lib/zone.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/zone.ts b/lib/zone.ts index 3d53f91f6..7abfa84ff 100644 --- a/lib/zone.ts +++ b/lib/zone.ts @@ -1475,4 +1475,4 @@ const Zone: ZoneType = (function(global: any) { detectZone.runTask(detectZone.scheduleMacroTask('detect', detectRunFn, null, () => null, null)); return global['Zone'] = Zone; -})(typeof window === 'object' && window || typeof self === 'object' && self || global); \ No newline at end of file +})(typeof window === 'object' && window || typeof self === 'object' && self || global); From 0429f9e20f4d74aeebd788c9823bc40a8b59ebc5 Mon Sep 17 00:00:00 2001 From: "JiaLi.Passion" Date: Sat, 24 Dec 2016 00:07:52 +0800 Subject: [PATCH 11/20] use Object.getPrototypeOf insteadof this.constructor.prototype --- lib/zone.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/zone.ts b/lib/zone.ts index 7abfa84ff..6355c1cf7 100644 --- a/lib/zone.ts +++ b/lib/zone.ts @@ -1316,6 +1316,9 @@ const Zone: ZoneType = (function(global: any) { obj.__proto__ = proto; return obj; }; + const getPrototypeOf = Object.getPrototypeOf ? Object.getPrototypeOf : function(obj) { + return obj.__proto__ || obj.constructor.prototype; + }; /** * This is ZoneAwareError which processes the stack frame and cleans up extra frames as well as @@ -1363,7 +1366,7 @@ const Zone: ZoneType = (function(global: any) { // if this is valid, means not undefined // and not global (non-strict mode call Error()) if (this && this !== global) { - error = setPrototypeOf(error, this.constructor.prototype); + error = setPrototypeOf(error, getPrototypeOf(this)); } return error; } From 8989d830a486af7a01d88193500f55320a8a44fe Mon Sep 17 00:00:00 2001 From: "JiaLi.Passion" Date: Sat, 24 Dec 2016 11:18:57 +0800 Subject: [PATCH 12/20] use Obejct.setPrototypeOf and add testcase --- lib/zone.ts | 4 ++-- test/common/Error.spec.ts | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/zone.ts b/lib/zone.ts index 6355c1cf7..e8ee36e72 100644 --- a/lib/zone.ts +++ b/lib/zone.ts @@ -1311,8 +1311,8 @@ const Zone: ZoneType = (function(global: any) { const stackRewrite = 'stackRewrite'; const setPrototypeOf = - Object.prototype['setPrototypeOf'] ? Object.prototype['setPrototypeOf'] : function( - obj, proto) { + Object['setPrototypeOf'] ? Object['setPrototypeOf'] : function( + obj, proto) { obj.__proto__ = proto; return obj; }; diff --git a/test/common/Error.spec.ts b/test/common/Error.spec.ts index 2e4e062b8..e94f02b53 100644 --- a/test/common/Error.spec.ts +++ b/test/common/Error.spec.ts @@ -38,6 +38,8 @@ describe('ZoneAwareError', () => { expect(myError1.message).toEqual('myError'); let myError2 = Error.call(global, 'myError'); expect(myError2.message).toEqual('myError'); + let myError3 = Error.call({}, 'myError'); + expect(myError3.message).toEqual('myError'); }); it('should have browser specified property', () => { From bf13636f87456a822d0b67ea290327ea8008dfb7 Mon Sep 17 00:00:00 2001 From: "JiaLi.Passion" Date: Sat, 24 Dec 2016 20:58:12 +0800 Subject: [PATCH 13/20] reformat --- lib/zone.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/zone.ts b/lib/zone.ts index e8ee36e72..d9adf3b64 100644 --- a/lib/zone.ts +++ b/lib/zone.ts @@ -1311,8 +1311,7 @@ const Zone: ZoneType = (function(global: any) { const stackRewrite = 'stackRewrite'; const setPrototypeOf = - Object['setPrototypeOf'] ? Object['setPrototypeOf'] : function( - obj, proto) { + Object['setPrototypeOf'] ? Object['setPrototypeOf'] : function(obj, proto) { obj.__proto__ = proto; return obj; }; From f65dfffb9533315eff90e4f37d5e0d530ecc27a6 Mon Sep 17 00:00:00 2001 From: "JiaLi.Passion" Date: Sun, 25 Dec 2016 20:57:28 +0800 Subject: [PATCH 14/20] should always be error --- lib/zone.ts | 3 ++- test/common/Error.spec.ts | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/zone.ts b/lib/zone.ts index d9adf3b64..b78bdd991 100644 --- a/lib/zone.ts +++ b/lib/zone.ts @@ -1364,7 +1364,8 @@ const Zone: ZoneType = (function(global: any) { } // if this is valid, means not undefined // and not global (non-strict mode call Error()) - if (this && this !== global) { + // and it is an error not an unrelated object + if (this && this !== global && this instanceof Error) { error = setPrototypeOf(error, getPrototypeOf(this)); } return error; diff --git a/test/common/Error.spec.ts b/test/common/Error.spec.ts index e94f02b53..949aee17a 100644 --- a/test/common/Error.spec.ts +++ b/test/common/Error.spec.ts @@ -19,6 +19,19 @@ describe('ZoneAwareError', () => { expect(myError.stack).not.toBe(undefined); }); + it('should instanceof error correctly', () => { + let myError = Error('myError'); + expect(myError instanceof Error).toBe(true); + let myError1 = Error.call(undefined, 'myError'); + expect(myError1 instanceof Error).toBe(true); + let myError2 = Error.call(global, 'myError'); + expect(myError2 instanceof Error).toBe(true); + let myError3 = Error.call({}, 'myError'); + expect(myError3 instanceof Error).toBe(true); + let myError4 = Error.call({test:'test'}, 'myError'); + expect(myError4 instanceof Error).toBe(true); + }); + it('should return error itself from constructor', () => { class MyError1 extends Error { constructor() { From 0dbbf4dead6cccf7f5c82fa18e117c8dd32f6777 Mon Sep 17 00:00:00 2001 From: "JiaLi.Passion" Date: Sun, 25 Dec 2016 21:01:39 +0800 Subject: [PATCH 15/20] reformat --- test/common/Error.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/common/Error.spec.ts b/test/common/Error.spec.ts index 949aee17a..6cfd00a95 100644 --- a/test/common/Error.spec.ts +++ b/test/common/Error.spec.ts @@ -28,7 +28,7 @@ describe('ZoneAwareError', () => { expect(myError2 instanceof Error).toBe(true); let myError3 = Error.call({}, 'myError'); expect(myError3 instanceof Error).toBe(true); - let myError4 = Error.call({test:'test'}, 'myError'); + let myError4 = Error.call({test: 'test'}, 'myError'); expect(myError4 instanceof Error).toBe(true); }); From 4a6a17112b6d34931e718be4e87618b3f53708b0 Mon Sep 17 00:00:00 2001 From: "JiaLi.Passion" Date: Thu, 5 Jan 2017 01:35:07 +0900 Subject: [PATCH 16/20] don't use setPrototypeOf --- lib/zone.ts | 43 +++++++++++++++++++++++++++++++++---------- package.json | 2 +- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/lib/zone.ts b/lib/zone.ts index b78bdd991..6205b6f45 100644 --- a/lib/zone.ts +++ b/lib/zone.ts @@ -1310,14 +1310,36 @@ const Zone: ZoneType = (function(global: any) { let frameParserStrategy = null; const stackRewrite = 'stackRewrite'; - const setPrototypeOf = - Object['setPrototypeOf'] ? Object['setPrototypeOf'] : function(obj, proto) { - obj.__proto__ = proto; - return obj; - }; - const getPrototypeOf = Object.getPrototypeOf ? Object.getPrototypeOf : function(obj) { - return obj.__proto__ || obj.constructor.prototype; - }; + const assignAll = function (to, from) { + if (to == null) { + return to; + } + + if (from != null) { // Skip over if undefined or null + let keys = Object.getOwnPropertyNames(from); + for (let i = 0; i < keys.length; i ++) { + const key = keys[i]; + // Avoid bugs when hasOwnProperty is shadowed + if (Object.prototype.hasOwnProperty.call(from, key)) { + to[key] = from[key]; + } + } + + // copy all properties from prototype + // in Error, such as name/message is in Error's prototype + // but not enumerable, so we copy those properties through + // Error's prototype + let pkeys = Object.getOwnPropertyNames(Object.getPrototypeOf(from)); + for (let i = 0; i < pkeys.length; i ++) { + const key = pkeys[i]; + // skip constructor + if (key !== 'constructor') { + to[key] = from[key]; + } + } + } + return to; + }; /** * This is ZoneAwareError which processes the stack frame and cleans up extra frames as well as @@ -1365,8 +1387,9 @@ const Zone: ZoneType = (function(global: any) { // if this is valid, means not undefined // and not global (non-strict mode call Error()) // and it is an error not an unrelated object - if (this && this !== global && this instanceof Error) { - error = setPrototypeOf(error, getPrototypeOf(this)); + if (this && this !== global && this instanceof Error + && Object.getPrototypeOf(this) !== NativeError.prototype && assignAll(this, error)) { + return this; } return error; } diff --git a/package.json b/package.json index 555433248..293cd23e0 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "ts-loader": "^0.6.0", "tslint": "^3.15.1", "tslint-eslint-rules": "^3.1.0", - "typescript": "^2.1.4", + "typescript": "^2.0.2", "whatwg-fetch": "^2.0.1" } } From 3d7c6efd7f579f3f43e795fdb6481a2764d735da Mon Sep 17 00:00:00 2001 From: "JiaLi.Passion" Date: Thu, 5 Jan 2017 02:15:40 +0900 Subject: [PATCH 17/20] reformat --- lib/zone.ts | 54 ++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/lib/zone.ts b/lib/zone.ts index 6205b6f45..29eb6c7fd 100644 --- a/lib/zone.ts +++ b/lib/zone.ts @@ -1310,36 +1310,36 @@ const Zone: ZoneType = (function(global: any) { let frameParserStrategy = null; const stackRewrite = 'stackRewrite'; - const assignAll = function (to, from) { - if (to == null) { - return to; - } + const assignAll = function(to, from) { + if (to == null) { + return to; + } - if (from != null) { // Skip over if undefined or null - let keys = Object.getOwnPropertyNames(from); - for (let i = 0; i < keys.length; i ++) { - const key = keys[i]; - // Avoid bugs when hasOwnProperty is shadowed - if (Object.prototype.hasOwnProperty.call(from, key)) { - to[key] = from[key]; - } + if (from != null) { // Skip over if undefined or null + let keys = Object.getOwnPropertyNames(from); + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + // Avoid bugs when hasOwnProperty is shadowed + if (Object.prototype.hasOwnProperty.call(from, key)) { + to[key] = from[key]; } + } - // copy all properties from prototype - // in Error, such as name/message is in Error's prototype - // but not enumerable, so we copy those properties through - // Error's prototype - let pkeys = Object.getOwnPropertyNames(Object.getPrototypeOf(from)); - for (let i = 0; i < pkeys.length; i ++) { - const key = pkeys[i]; - // skip constructor - if (key !== 'constructor') { - to[key] = from[key]; - } + // copy all properties from prototype + // in Error, such as name/message is in Error's prototype + // but not enumerable, so we copy those properties through + // Error's prototype + let pkeys = Object.getOwnPropertyNames(Object.getPrototypeOf(from)); + for (let i = 0; i < pkeys.length; i++) { + const key = pkeys[i]; + // skip constructor + if (key !== 'constructor') { + to[key] = from[key]; } } - return to; - }; + } + return to; + }; /** * This is ZoneAwareError which processes the stack frame and cleans up extra frames as well as @@ -1387,8 +1387,8 @@ const Zone: ZoneType = (function(global: any) { // if this is valid, means not undefined // and not global (non-strict mode call Error()) // and it is an error not an unrelated object - if (this && this !== global && this instanceof Error - && Object.getPrototypeOf(this) !== NativeError.prototype && assignAll(this, error)) { + if (this && this !== global && this instanceof Error && + Object.getPrototypeOf(this) !== NativeError.prototype && assignAll(this, error)) { return this; } return error; From d48acae02942419e53755b069dc512d457b52168 Mon Sep 17 00:00:00 2001 From: "JiaLi.Passion" Date: Thu, 5 Jan 2017 09:33:13 +0900 Subject: [PATCH 18/20] add check code to prevent invalid this when create ZoneAwareError --- lib/zone.ts | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/lib/zone.ts b/lib/zone.ts index 29eb6c7fd..4fbc6f105 100644 --- a/lib/zone.ts +++ b/lib/zone.ts @@ -1329,9 +1329,9 @@ const Zone: ZoneType = (function(global: any) { // in Error, such as name/message is in Error's prototype // but not enumerable, so we copy those properties through // Error's prototype - let pkeys = Object.getOwnPropertyNames(Object.getPrototypeOf(from)); - for (let i = 0; i < pkeys.length; i++) { - const key = pkeys[i]; + let pKeys = Object.getOwnPropertyNames(Object.getPrototypeOf(from)); + for (let i = 0; i < pKeys.length; i++) { + const key = pKeys[i]; // skip constructor if (key !== 'constructor') { to[key] = from[key]; @@ -1346,6 +1346,13 @@ const Zone: ZoneType = (function(global: any) { * adds zone information to it. */ function ZoneAwareError() { + // make sure we have a valid this + // if this is undefined(call Error without new) or this is global + // or this is some other objects, we should force to create a + // valid ZoneAwareError by call Object.create() + if (!(this instanceof ZoneAwareError)) { + return ZoneAwareError.apply(Object.create(ZoneAwareError.prototype), arguments); + } // Create an Error. let error: Error = NativeError.apply(this, arguments); @@ -1384,14 +1391,8 @@ const Zone: ZoneType = (function(global: any) { } error.stack = error.zoneAwareStack = frames.join('\n'); } - // if this is valid, means not undefined - // and not global (non-strict mode call Error()) - // and it is an error not an unrelated object - if (this && this !== global && this instanceof Error && - Object.getPrototypeOf(this) !== NativeError.prototype && assignAll(this, error)) { - return this; - } - return error; + assignAll(this, error); + return this; } // Copy the prototype so that instanceof operator works as expected From 9ee3ba5161bc69f7139aa7e3748870e58af04d04 Mon Sep 17 00:00:00 2001 From: "JiaLi.Passion" Date: Thu, 5 Jan 2017 10:29:47 +0900 Subject: [PATCH 19/20] refactor --- lib/zone.ts | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/lib/zone.ts b/lib/zone.ts index 4fbc6f105..a8da40caa 100644 --- a/lib/zone.ts +++ b/lib/zone.ts @@ -1311,11 +1311,11 @@ const Zone: ZoneType = (function(global: any) { const stackRewrite = 'stackRewrite'; const assignAll = function(to, from) { - if (to == null) { + if (!to) { return to; } - if (from != null) { // Skip over if undefined or null + if (from) { let keys = Object.getOwnPropertyNames(from); for (let i = 0; i < keys.length; i++) { const key = keys[i]; @@ -1326,15 +1326,18 @@ const Zone: ZoneType = (function(global: any) { } // copy all properties from prototype - // in Error, such as name/message is in Error's prototype + // in Error, property such as name/message is in Error's prototype // but not enumerable, so we copy those properties through // Error's prototype - let pKeys = Object.getOwnPropertyNames(Object.getPrototypeOf(from)); - for (let i = 0; i < pKeys.length; i++) { - const key = pKeys[i]; - // skip constructor - if (key !== 'constructor') { - to[key] = from[key]; + const proto = Object.getPrototypeOf(from); + if (proto) { + let pKeys = Object.getOwnPropertyNames(proto); + for (let i = 0; i < pKeys.length; i++) { + const key = pKeys[i]; + // skip constructor + if (key !== 'constructor') { + to[key] = from[key]; + } } } } @@ -1391,8 +1394,7 @@ const Zone: ZoneType = (function(global: any) { } error.stack = error.zoneAwareStack = frames.join('\n'); } - assignAll(this, error); - return this; + return assignAll(this, error); } // Copy the prototype so that instanceof operator works as expected From ae9301a26591809b28050411d9ef4fab04ac4470 Mon Sep 17 00:00:00 2001 From: "JiaLi.Passion" Date: Thu, 5 Jan 2017 10:38:33 +0900 Subject: [PATCH 20/20] remove duplicate commemt --- lib/zone.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/zone.ts b/lib/zone.ts index a8da40caa..b83871187 100644 --- a/lib/zone.ts +++ b/lib/zone.ts @@ -1434,8 +1434,6 @@ const Zone: ZoneType = (function(global: any) { } }); - // Now we need to populet the `blacklistedStackFrames` as well as find the - // Now we need to populet the `blacklistedStackFrames` as well as find the // run/runGuraded/runTask frames. This is done by creating a detect zone and then threading // the execution through all of the above methods so that we can look at the stack trace and