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

feat(longStackTraceSpec): handled promise rejection can also render longstacktrace #631

Merged
merged 1 commit into from
Mar 10, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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__;