Which @angular/* package(s) are the source of the bug?
zone.js
Is this a regression?
No
Description
I've hit the same issue as described in #31680 and both this and that ticket have same root cause detailed bellow. Since I cannot reopened old issue I've created a new one. That older ticket was closed with a fix that was for a separate issue and the fix was not relevant or helped in anyway.
Repro
Following simplified code will emit unhandled promise rejection even tho there is a catch handler. This happens only when zone.js is loaded. Without zone.js, all majors browsers (Chrome, Safari, Firefox) don't report anything in this case.
onunhandledrejection = (e) => { console.log("Unhandled promise rejection", e) }
(async function() {
return Promise.reject(1);
})().catch(e => {});
// OR
(async function() {
await Promise.reject(2);
})().catch(e => {});
Using native Promise.reject will not emit unhandled rejection.
Root cause:
zone.js schedules the reporting of unhandled rejections on the microtask queue as soon as the promise is rejected. In the case of Promise.reject it schedules as part of the reject call.
JS async function calls .then on the returned inner promise (Promise.reject) on the next microtask tick. This is defined in the Ecmascript spec.
zone.js will end up running the code to report unhandled rejections before JS async function has a chance to call then and as such zone.js ends emiting unhandled rejection.
All major browsers check if unhandled rejections exists at the end of the microtask checkpoint (i.e. after draining the queue) and if needed will schedule on normal queue a task (or what you call a macro task) to process&report unhandled rejections. This allows sufficient time for the async infrastructure to hook to the returned promise. In Chrome and Safari it even allows sufficient time to add catch handler in a callback run by setTimeout of delay 0.
Chrome:
https://github.com/chromium/chromium/blob/89e00b6b959f5efb4bd7eec468973badb3093a3b/third_party/blink/renderer/platform/scheduler/common/event_loop.cc#L108
https://github.com/chromium/chromium/blob/89e00b6b959f5efb4bd7eec468973badb3093a3b/third_party/blink/renderer/bindings/core/v8/rejected_promises.cc#L248-L252
Firefox:
https://github.com/mozilla/gecko-dev/blob/77dd6aa3810610949a5ff925e24de2f8c11377fd/xpcom/base/CycleCollectedJSContext.cpp#L473-L480
Safari:
https://github.com/WebKit/WebKit/blob/75a3eb3a5fe3dce1867d880faf785137963b234a/Source/WebCore/dom/Microtasks.cpp#L107
https://github.com/WebKit/WebKit/blob/75a3eb3a5fe3dce1867d880faf785137963b234a/Source/WebCore/dom/RejectedPromiseTracker.cpp#L142-L144
Please provide a link to a minimal reproduction of the bug
No response
Please provide the exception or error you saw
Unhandled Promise rejection: 1 ; Zone: <root> ; Task: null ; Value: 1 undefined
Unhandled Promise rejection: 2 ; Zone: <root> ; Task: null ; Value: 2 undefined
Unhandled promise rejection PromiseRejectionEvent {isTrusted: true, reason: 1, type: 'unhandledrejection' ...}
Uncaught (in promise) 1
Unhandled promise rejection PromiseRejectionEvent {isTrusted: true, reason: 2, type: 'unhandledrejection' ...}
Uncaught (in promise) 2
Please provide the environment you discovered this bug in (run ng version)
No response
Anything else?
No response
Which @angular/* package(s) are the source of the bug?
zone.js
Is this a regression?
No
Description
I've hit the same issue as described in #31680 and both this and that ticket have same root cause detailed bellow. Since I cannot reopened old issue I've created a new one. That older ticket was closed with a fix that was for a separate issue and the fix was not relevant or helped in anyway.
Repro
Following simplified code will emit unhandled promise rejection even tho there is a catch handler. This happens only when zone.js is loaded. Without zone.js, all majors browsers (Chrome, Safari, Firefox) don't report anything in this case.
Using native Promise.reject will not emit unhandled rejection.
Root cause:
zone.js schedules the reporting of unhandled rejections on the microtask queue as soon as the promise is rejected. In the case of
Promise.rejectit schedules as part of the reject call.JS async function calls
.thenon the returned inner promise (Promise.reject) on the next microtask tick. This is defined in the Ecmascript spec.zone.js will end up running the code to report unhandled rejections before JS async function has a chance to call
thenand as such zone.js ends emiting unhandled rejection.All major browsers check if unhandled rejections exists at the end of the microtask checkpoint (i.e. after draining the queue) and if needed will schedule on normal queue a task (or what you call a macro task) to process&report unhandled rejections. This allows sufficient time for the async infrastructure to hook to the returned promise. In Chrome and Safari it even allows sufficient time to add catch handler in a callback run by setTimeout of delay 0.
Chrome:
https://github.com/chromium/chromium/blob/89e00b6b959f5efb4bd7eec468973badb3093a3b/third_party/blink/renderer/platform/scheduler/common/event_loop.cc#L108
https://github.com/chromium/chromium/blob/89e00b6b959f5efb4bd7eec468973badb3093a3b/third_party/blink/renderer/bindings/core/v8/rejected_promises.cc#L248-L252
Firefox:
https://github.com/mozilla/gecko-dev/blob/77dd6aa3810610949a5ff925e24de2f8c11377fd/xpcom/base/CycleCollectedJSContext.cpp#L473-L480
Safari:
https://github.com/WebKit/WebKit/blob/75a3eb3a5fe3dce1867d880faf785137963b234a/Source/WebCore/dom/Microtasks.cpp#L107
https://github.com/WebKit/WebKit/blob/75a3eb3a5fe3dce1867d880faf785137963b234a/Source/WebCore/dom/RejectedPromiseTracker.cpp#L142-L144
Please provide a link to a minimal reproduction of the bug
No response
Please provide the exception or error you saw
Please provide the environment you discovered this bug in (run
ng version)No response
Anything else?
No response