[IMP] web: don't swallow errors in async handlers
This commit adds a 'guardedCatch' function to the Promise API. This function has to be used when we don't want to swallow real errors (crashes), like 'catch' does (i.e. basically all the time in Odoo). When the promise has been rejected because of a real error, the rejected Promises chain bubbles up to the top and triggers the 'unhandledrejection' event (triggered on all browsers thanks to the unhandled-rejection-polyfill lib). We then add a listener on that event to display real errors with the CrashManager. Part of task 1896658 Co-authored-by: Aaron Bohy <aab@odoo.com> Co-authored-by: Christophe Matthieu <chm@odoo.com> Co-authored-by: Mathieu Duckerts-Antoine <dam@odoo.com> Co-authored-by: David Monjoie <dmo@odoo.com> Co-authored-by: Martin Geubelle <mge@odoo.com> Co-authored-by: svs-odoo <svs@odoo.com> Co-authored-by: Vincent Schippefilt <vsc@odoo.com>
This commit is contained in:
co-authored by
Christophe Matthieu
Mathieu Duckerts-Antoine
David Monjoie
Martin Geubelle
svs-odoo
Vincent Schippefilt
parent
96b0319239
commit
380550f62f
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* This file adds a 'guardedCatch' function to the Promise API. This function
|
||||
* has to be used when we don't want to swallow real errors (crashes), like
|
||||
* 'catch' does (i.e. basically all the time in Odoo). We only execute the
|
||||
* 'onRejected' handler if the rejection's reason is not an Error, and we always
|
||||
* return a rejected Promise to let the rejection bubble up (and trigger the
|
||||
* 'unhandledrejection' event).
|
||||
*/
|
||||
|
||||
(function () {
|
||||
var _catch = Promise.prototype.catch;
|
||||
Promise.prototype.guardedCatch = function (onRejected) {
|
||||
return _catch.call(this, function (reason) {
|
||||
if (!reason || !(reason instanceof Error)) {
|
||||
if (onRejected) {
|
||||
onRejected.call(this, reason);
|
||||
}
|
||||
}
|
||||
return Promise.reject(reason);
|
||||
});
|
||||
};
|
||||
})();
|
||||
@@ -20,9 +20,29 @@ var map_title ={
|
||||
};
|
||||
|
||||
var CrashManager = core.Class.extend({
|
||||
init: function() {
|
||||
init: function () {
|
||||
var self = this;
|
||||
this.active = true;
|
||||
this.isConnected = true;
|
||||
|
||||
// listen to unhandled rejected promises, and throw an error when the
|
||||
// promise has been rejected due to a crash
|
||||
window.addEventListener('unhandledrejection', function (ev) {
|
||||
if (ev.reason && ev.reason instanceof Error) {
|
||||
var traceback = ev.reason.stack;
|
||||
self.show_error({
|
||||
type: _t("Odoo Client Error"),
|
||||
message: '',
|
||||
data: {debug: _t('Traceback:') + "\n" + traceback},
|
||||
});
|
||||
} else {
|
||||
// the rejection is not due to an Error, so prevent the browser
|
||||
// from displaying an 'unhandledrejection' error in the console
|
||||
ev.stopPropagation();
|
||||
ev.stopImmediatePropagation();
|
||||
ev.preventDefault();
|
||||
}
|
||||
});
|
||||
},
|
||||
enable: function () {
|
||||
this.active = true;
|
||||
|
||||
@@ -104,6 +104,7 @@
|
||||
<script type="text/javascript" src="/web/static/lib/clipboard/clipboard.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/web/static/lib/qweb/qweb2.js"></script>
|
||||
<script type="text/javascript" src="/web/static/src/js/promise_extension.js"></script>
|
||||
<script type="text/javascript" src="/web/static/src/js/boot.js"></script>
|
||||
<script type="text/javascript" src="/web/static/src/js/libs/autocomplete.js"></script>
|
||||
<script type="text/javascript" src="/web/static/src/js/libs/bootstrap.js"></script>
|
||||
|
||||
Reference in New Issue
Block a user