Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Commit

Permalink
feat(longStackTraceSpec): handled promise rejection can also render l…
Browse files Browse the repository at this point in the history
…ongstacktrace (#631)
  • Loading branch information
JiaLiPassion authored and mhevery committed Mar 10, 2017
1 parent 2d30914 commit a4c6525
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 6 deletions.
21 changes: 17 additions & 4 deletions lib/zone-spec/long-stack-trace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,18 @@ function getStacktraceWithUncaughtError(): Error {
function getStacktraceWithCaughtError(): Error {
try {
throw getStacktraceWithUncaughtError();
} catch (error) {
return error;
} catch (err) {
return err;
}
}

// Some implementations of exception handling don't create a stack trace if the exception
// isn't thrown, however it's faster not to actually throw the exception.
const error = getStacktraceWithUncaughtError();
const coughtError = getStacktraceWithCaughtError();
const caughtError = getStacktraceWithCaughtError();
const getStacktrace = error.stack ?
getStacktraceWithUncaughtError :
(coughtError.stack ? getStacktraceWithCaughtError : getStacktraceWithUncaughtError);
(caughtError.stack ? getStacktraceWithCaughtError : getStacktraceWithUncaughtError);

function getFrames(error: Error): string[] {
return error.stack ? error.stack.split(NEWLINE) : [];
Expand Down Expand Up @@ -77,6 +77,19 @@ function renderLongStackTrace(frames: LongStackTrace[], stack: string): string {
Zone['longStackTraceZoneSpec'] = <ZoneSpec>{
name: 'long-stack-trace',
longStackTraceLimit: 10, // Max number of task to keep the stack trace for.
// add a getLongStackTrace method in spec to
// handle handled reject promise error.
getLongStackTrace: function(error: Error): string {
if (!error) {
return undefined;
}
const task = error[Zone['__symbol__']('currentTask')];
const trace = task && task.data && task.data[creationTrace];
if (!trace) {
return error.stack;
}
return renderLongStackTrace(trace, error.stack);
},

onScheduleTask: function(
parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task): any {
Expand Down
6 changes: 6 additions & 0 deletions lib/zone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1332,6 +1332,12 @@ const Zone: ZoneType = (function(global: any) {
const queue = promise[symbolValue];
promise[symbolValue] = value;

// record task information in value when error occurs, so we can
// do some additional work such as render longStackTrace
if (state === REJECTED && value instanceof Error) {
value[__symbol__('currentTask')] = Zone.currentTask;
}

for (let i = 0; i < queue.length;) {
scheduleResolveOrReject(promise, queue[i++], queue[i++], queue[i++], queue[i++]);
}
Expand Down
25 changes: 23 additions & 2 deletions test/zone-spec/long-stack-trace-zone.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ const defineProperty = Object[zoneSymbol('defineProperty')] || Object.defineProp
describe('longStackTraceZone', function() {
let log: Error[];
let lstz: Zone;
let longStackTraceZoneSpec = Zone['longStackTraceZoneSpec'];

beforeEach(function() {
lstz = Zone.current.fork(Zone['longStackTraceZoneSpec']).fork({
lstz = Zone.current.fork(longStackTraceZoneSpec).fork({
name: 'long-stack-trace-zone-test',
onHandleError: (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone,
error: any): boolean => {
Expand Down Expand Up @@ -67,7 +68,7 @@ describe('longStackTraceZone', function() {
});
});

it('should produce long stack traces when reject in promise', function(done) {
it('should produce long stack traces when has uncaught error in promise', function(done) {
lstz.runGuarded(function() {
setTimeout(function() {
setTimeout(function() {
Expand All @@ -91,6 +92,26 @@ describe('longStackTraceZone', function() {
}, 0);
});
});

it('should produce long stack traces when handling error in promise', function(done) {
lstz.runGuarded(function() {
setTimeout(function() {
setTimeout(function() {
let promise = new Promise(function(resolve, reject) {
setTimeout(function() {
reject(new Error('Hello Promise'));
}, 0);
});
promise.catch(function(error) {
// should be able to get long stack trace
const longStackFrames: string = longStackTraceZoneSpec.getLongStackTrace(error);
expect(longStackFrames.split('Elapsed: ').length).toBe(4);
done();
});
}, 0);
}, 0);
});
});
});

export let __something__;

0 comments on commit a4c6525

Please sign in to comment.