fix(zone.js): don't wrap uncaught promise error. (#31443)

Close #27840

PR Close #31443
This commit is contained in:
JiaLiPassion 2019-07-07 11:07:32 +08:00 committed by Miško Hevery
parent 6b51ed29ef
commit 2bb9a65351
3 changed files with 54 additions and 21 deletions

View File

@ -176,20 +176,25 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr
}
if (queue.length == 0 && state == REJECTED) {
(promise as any)[symbolState] = REJECTED_NO_CATCH;
try {
// try to print more readable error log
throw new Error(
'Uncaught (in promise): ' + readableObjectToString(value) +
(value && value.stack ? '\n' + value.stack : ''));
} catch (err) {
const error: UncaughtPromiseError = err;
error.rejection = value;
error.promise = promise;
error.zone = Zone.current;
error.task = Zone.currentTask !;
_uncaughtPromiseErrors.push(error);
api.scheduleMicroTask(); // to make sure that it is running
let uncaughtPromiseError: any;
if (value instanceof Error || (value && value.message)) {
uncaughtPromiseError = value;
} else {
try {
// try to print more readable error log
throw new Error(
'Uncaught (in promise): ' + readableObjectToString(value) +
(value && value.stack ? '\n' + value.stack : ''));
} catch (err) {
uncaughtPromiseError = err;
}
}
uncaughtPromiseError.rejection = value;
uncaughtPromiseError.promise = promise;
uncaughtPromiseError.zone = Zone.current;
uncaughtPromiseError.task = Zone.currentTask !;
_uncaughtPromiseErrors.push(uncaughtPromiseError);
api.scheduleMicroTask(); // to make sure that it is running
}
}
}

View File

@ -345,11 +345,8 @@ describe(
});
setTimeout((): any => null);
setTimeout(() => {
expect(promiseError !.message)
.toBe(
'Uncaught (in promise): ' + error +
(error !.stack ? '\n' + error !.stack : ''));
expect((promiseError as any)['rejection']).toBe(error);
expect(promiseError).toBe(error);
expect((promiseError as any)['zone']).toBe(zone);
expect((promiseError as any)['task']).toBe(task);
done();
@ -389,6 +386,39 @@ describe(
});
});
it('should print original information when throw a not error object with a message property',
(done) => {
let promiseError: Error|null = null;
let zone: Zone|null = null;
let task: Task|null = null;
let rejectObj: TestRejection;
queueZone
.fork({
name: 'promise-error',
onHandleError: (delegate: ZoneDelegate, current: Zone, target: Zone, error: any):
boolean => {
promiseError = error;
delegate.handleError(target, error);
return false;
}
})
.run(() => {
zone = Zone.current;
task = Zone.currentTask;
rejectObj = new TestRejection();
rejectObj.prop1 = 'value1';
rejectObj.prop2 = 'value2';
(rejectObj as any).message = 'rejectMessage';
Promise.reject(rejectObj);
expect(promiseError).toBe(null);
});
setTimeout((): any => null);
setTimeout(() => {
expect(promiseError).toEqual(rejectObj as any);
done();
});
});
describe('Promise.race', () => {
it('should reject the value', () => {
queueZone.run(() => {

View File

@ -84,9 +84,7 @@ describe('FakeAsyncTestZoneSpec', () => {
() => {
fakeAsyncTestZone.run(() => {
Promise.resolve(null).then((_) => { throw new Error('async'); });
expect(() => {
testZoneSpec.flushMicrotasks();
}).toThrowError(/Uncaught \(in promise\): Error: async/);
expect(() => { testZoneSpec.flushMicrotasks(); }).toThrowError(/async/);
});
});
@ -1171,7 +1169,7 @@ const {fakeAsync, tick, discardPeriodicTasks, flush, flushMicrotasks} = fakeAsyn
resolvedPromise.then((_) => { throw new Error('async'); });
flushMicrotasks();
})();
}).toThrowError(/Uncaught \(in promise\): Error: async/);
}).toThrowError(/async/);
});
it('should complain if a test throws an exception', () => {