This repository has been archived by the owner on Feb 26, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 407
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(error): add a helper method to get non zone aware stack trace
- Loading branch information
1 parent
f3547cc
commit ab32b37
Showing
10 changed files
with
420 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
/** | ||
* @license | ||
* Copyright Google Inc. All Rights Reserved. | ||
* | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://angular.io/license | ||
*/ | ||
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory() : | ||
typeof define === 'function' && define.amd ? define(factory) : | ||
(factory()); | ||
}(this, (function () { 'use strict'; | ||
|
||
/** | ||
* @license | ||
* Copyright Google Inc. All Rights Reserved. | ||
* | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://angular.io/license | ||
*/ | ||
((function (_global) { | ||
var ErrorType = _global['Error']; | ||
var blackListedStackFrames = {}; | ||
var zoneAwareFunctionNames = ['Zone', 'drainMicrotask', 'getStacktraceWithUncaughtError', 'new LongStackTrace', 'Object.onScheduleTask']; | ||
var detectZone = Zone.root.fork(Zone['longStackTraceZoneSpec']).fork({ | ||
name: 'detectZone', | ||
onHandleError: function (parentDelegate, currentZone, targetZone, error) { | ||
parentDelegate.handleError(targetZone, error); | ||
var frames = error.stack.split(/\n/); | ||
var runFrame = false, runGuardedFrame = false, runTaskFrame = false; | ||
var _loop_1 = function () { | ||
var 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)) { | ||
var f_1 = frame.split(' [')[0]; | ||
if (zoneAwareFunctionNames.filter(function (zf) { return f_1.toLowerCase().indexOf(f_1.toLowerCase()) !== -1; }).length > 0) { | ||
blackListedStackFrames[f_1] = f_1; | ||
} | ||
} | ||
}; | ||
while (frames.length) { | ||
_loop_1(); | ||
} | ||
return false; | ||
} | ||
}); | ||
var detectZoneWithCallbacks = Zone.root.fork(Zone['longStackTraceZoneSpec']).fork({ | ||
name: 'detectZone', | ||
onFork: function (parentDelegate, currentZone, targetZone, zoneSpec) { | ||
return parentDelegate.fork(targetZone, zoneSpec); | ||
}, | ||
onIntercept: function (parentDelegate, currentZone, targetZone, delegate, source) { | ||
return parentDelegate.intercept(targetZone, delegate, source); | ||
}, | ||
onInvoke: function (parentZoneDelegate, currentZone, targetZone, delegate, applyThis, applyArgs, source) { | ||
return parentZoneDelegate.invoke(targetZone, delegate, applyThis, applyArgs, source); | ||
}, | ||
onScheduleTask: function (parentZoneDelegate, currentZone, targetZone, task) { | ||
return parentZoneDelegate.scheduleTask(targetZone, task); | ||
}, | ||
onInvokeTask: function (parentZoneDelegate, currentZone, targetZone, task, applyThis, applyArgs) { | ||
return parentZoneDelegate.invokeTask(targetZone, task, applyThis, applyArgs); | ||
}, | ||
onCancelTask: function (parentZoneDelegate, currentZone, targetZone, task) { | ||
return parentZoneDelegate.cancelTask(targetZone, task); | ||
}, | ||
onHasTask: function (delegate, current, target, hasTaskState) { | ||
return delegate.hasTask(target, hasTaskState); | ||
}, | ||
onHandleError: function (parentDelegate, currentZone, targetZone, error) { | ||
parentDelegate.handleError(targetZone, error); | ||
var frames = error.stack.split(/\n/); | ||
var runFrame = false, runGuardedFrame = false, runTaskFrame = false; | ||
while (frames.length) { | ||
var 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)) { | ||
var f = frame.split(' [')[0]; | ||
if (f.indexOf('Zone') !== -1 || f.toLowerCase().indexOf('zoneaware') !== -1 || f.indexOf('drainMicroTaskQueue') !== -1) { | ||
blackListedStackFrames[f] = f; | ||
} | ||
} | ||
} | ||
return false; | ||
} | ||
}); | ||
var detectFn = function () { | ||
throw new Error('zoneAwareFrames'); | ||
}; | ||
var detectPromiseFn = function () { | ||
var p = new Promise(function (resolve, reject) { | ||
reject(new Error('zoneAwareFrames')); | ||
}); | ||
}; | ||
var detectPromiseCaughtFn = function () { | ||
var p = new Promise(function (resolve, reject) { | ||
reject(new Error('zoneAwareFrames')); | ||
}); | ||
p.catch(function (err) { | ||
throw err; | ||
}); | ||
}; | ||
// Cause the error to extract the stack frames. | ||
detectZone.runTask(detectZone.scheduleEventTask('detect', detectFn, null, function () { return null; }, null)); | ||
detectZoneWithCallbacks.runTask(detectZoneWithCallbacks.scheduleEventTask('detect', detectFn, null, function () { return null; }, null)); | ||
detectZone.runTask(detectZone.scheduleMacroTask('detect', detectFn, null, function () { return null; }, null)); | ||
detectZoneWithCallbacks.runTask(detectZoneWithCallbacks.scheduleMacroTask('detect', detectFn, null, function () { return null; }, null)); | ||
detectZone.runTask(detectZone.scheduleMicroTask('detect', detectFn, null, function () { return null; })); | ||
detectZoneWithCallbacks.runTask(detectZoneWithCallbacks.scheduleMicroTask('detect', detectFn, null, function () { return null; })); | ||
detectZone.runGuarded(function () { | ||
detectZone.run(detectFn); | ||
}); | ||
detectZoneWithCallbacks.runGuarded(function () { | ||
detectZone.run(detectFn); | ||
}); | ||
detectZone.runGuarded(detectPromiseFn); | ||
detectZoneWithCallbacks.runGuarded(detectPromiseFn); | ||
detectZone.runGuarded(detectPromiseCaughtFn); | ||
detectZoneWithCallbacks.runGuarded(detectPromiseCaughtFn); | ||
var otherZoneAwareFunctionNames = ['ZoneTask.invoke', 'ZoneAware']; | ||
Object.defineProperty(ErrorType, 'getNonZoneAwareStack', { | ||
value: function (err) { | ||
if (err.stack) { | ||
var frames_1 = err.stack.split('\n'); | ||
var simplifiedFrames = []; | ||
var _loop_2 = function (i) { | ||
var frame = frames_1[i].split(' [')[0]; | ||
var frameWithoutZone = frame.split(' [')[0]; | ||
if (blackListedStackFrames.hasOwnProperty(frameWithoutZone) && | ||
blackListedStackFrames[frameWithoutZone]) { | ||
frames_1.splice(i, 1); | ||
i--; | ||
} | ||
else if (otherZoneAwareFunctionNames.filter(function (f) { return frame.toLowerCase().indexOf(f.toLowerCase()) !== -1; }).length > 0) { | ||
frames_1.splice(i, 1); | ||
i--; | ||
} | ||
else { | ||
simplifiedFrames.push(frame); | ||
} | ||
out_i_1 = i; | ||
}; | ||
var out_i_1; | ||
for (var i = 0; i < frames_1.length; i++) { | ||
_loop_2(i); | ||
i = out_i_1; | ||
} | ||
return simplifiedFrames.join('\n'); | ||
} | ||
return err.stack; | ||
} | ||
}); | ||
})(typeof window === 'object' && window || typeof self === 'object' && self || global)); | ||
|
||
}))); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
/** | ||
* @license | ||
* Copyright Google Inc. All Rights Reserved. | ||
* | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://angular.io/license | ||
*/ | ||
((function(_global: any) { | ||
const ErrorType = _global['Error']; | ||
const blackListedStackFrames = {}; | ||
const zoneAwareFunctionNames = [ | ||
'Zone', 'drainMicrotask', 'getStacktraceWithUncaughtError', 'new LongStackTrace', | ||
'Object.onScheduleTask' | ||
]; | ||
|
||
function handleError(error: Error) { | ||
let frames = error.stack ? error.stack.split(/\n/) : []; | ||
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)) { | ||
const f = frame.split(' [')[0]; | ||
if (zoneAwareFunctionNames.filter(zf => f.toLowerCase().indexOf(f.toLowerCase()) !== -1) | ||
.length > 0) { | ||
blackListedStackFrames[f] = f; | ||
} | ||
} | ||
} | ||
} | ||
|
||
const detectZone = Zone.root.fork(Zone['longStackTraceZoneSpec']).fork({ | ||
name: 'detectZone', | ||
onHandleError(parentDelegate, currentZone, targetZone, error) { | ||
parentDelegate.handleError(targetZone, error); | ||
handleError(error); | ||
return false; | ||
} | ||
}); | ||
|
||
const detectZoneWithCallbacks = Zone.root.fork(Zone['longStackTraceZoneSpec']).fork({ | ||
name: 'detectZone', | ||
onFork: (parentDelegate, currentZone, targetZone, zoneSpec) => { | ||
return parentDelegate.fork(targetZone, zoneSpec); | ||
}, | ||
onIntercept: (parentDelegate, currentZone, targetZone, delegate, source) => { | ||
return parentDelegate.intercept(targetZone, delegate, source); | ||
}, | ||
onInvoke: | ||
(parentZoneDelegate, currentZone, targetZone, delegate, applyThis, applyArgs, source) => { | ||
return parentZoneDelegate.invoke(targetZone, delegate, applyThis, applyArgs, source); | ||
}, | ||
onScheduleTask: (parentZoneDelegate, currentZone, targetZone, task) => { | ||
return parentZoneDelegate.scheduleTask(targetZone, task); | ||
}, | ||
onInvokeTask: (parentZoneDelegate, currentZone, targetZone, task, applyThis, applyArgs) => { | ||
return parentZoneDelegate.invokeTask(targetZone, task, applyThis, applyArgs); | ||
}, | ||
onCancelTask: (parentZoneDelegate, currentZone, targetZone, task) => { | ||
return parentZoneDelegate.cancelTask(targetZone, task); | ||
}, | ||
|
||
onHasTask: (delegate, current, target, hasTaskState) => { | ||
return delegate.hasTask(target, hasTaskState); | ||
}, | ||
|
||
onHandleError(parentDelegate, currentZone, targetZone, error) { | ||
parentDelegate.handleError(targetZone, error); | ||
handleError(error); | ||
return false; | ||
} | ||
}); | ||
|
||
let detectFn = () => { | ||
throw new Error('zoneAwareFrames'); | ||
}; | ||
|
||
let detectPromiseFn = () => { | ||
const p = new Promise((resolve, reject) => { | ||
reject(new Error('zoneAwareFrames')); | ||
}); | ||
}; | ||
|
||
let detectPromiseCaughtFn = () => { | ||
const p = new Promise((resolve, reject) => { | ||
reject(new Error('zoneAwareFrames')); | ||
}); | ||
p.catch(err => { | ||
throw err; | ||
}); | ||
}; | ||
|
||
// Cause the error to extract the stack frames. | ||
detectZone.runTask(detectZone.scheduleEventTask('detect', detectFn, null, () => null, null)); | ||
detectZoneWithCallbacks.runTask( | ||
detectZoneWithCallbacks.scheduleEventTask('detect', detectFn, null, () => null, null)); | ||
detectZone.runTask(detectZone.scheduleMacroTask('detect', detectFn, null, () => null, null)); | ||
detectZoneWithCallbacks.runTask( | ||
detectZoneWithCallbacks.scheduleMacroTask('detect', detectFn, null, () => null, null)); | ||
detectZone.runTask(detectZone.scheduleMicroTask('detect', detectFn, null, () => null)); | ||
detectZoneWithCallbacks.runTask( | ||
detectZoneWithCallbacks.scheduleMicroTask('detect', detectFn, null, () => null)); | ||
|
||
detectZone.runGuarded(() => { | ||
detectZone.run(detectFn); | ||
}); | ||
detectZoneWithCallbacks.runGuarded(() => { | ||
detectZone.run(detectFn); | ||
}); | ||
|
||
detectZone.runGuarded(detectPromiseFn); | ||
detectZoneWithCallbacks.runGuarded(detectPromiseFn); | ||
|
||
detectZone.runGuarded(detectPromiseCaughtFn); | ||
detectZoneWithCallbacks.runGuarded(detectPromiseCaughtFn); | ||
|
||
const otherZoneAwareFunctionNames = ['ZoneTask.invoke', 'ZoneAware']; | ||
|
||
Object.defineProperty(ErrorType, 'getNonZoneAwareStack', { | ||
value: function(err: Error) { | ||
if (err.stack) { | ||
let frames = err.stack.split('\n'); | ||
const simplifiedFrames: string[] = []; | ||
for (let i = 0; i < frames.length; i++) { | ||
const frame = frames[i].split(' [')[0]; | ||
const frameWithoutZone = frame.split(' [')[0]; | ||
if (blackListedStackFrames.hasOwnProperty(frameWithoutZone) && | ||
blackListedStackFrames[frameWithoutZone]) { | ||
frames.splice(i, 1); | ||
i--; | ||
} else if ( | ||
otherZoneAwareFunctionNames | ||
.filter(f => frame.toLowerCase().indexOf(f.toLowerCase()) !== -1) | ||
.length > 0) { | ||
frames.splice(i, 1); | ||
i--; | ||
} else { | ||
simplifiedFrames.push(frame); | ||
} | ||
} | ||
return simplifiedFrames.join('\n'); | ||
} | ||
return err.stack; | ||
} | ||
}); | ||
})(typeof window === 'object' && window || typeof self === 'object' && self || global)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.