From e2b85d4613d56d40c5361470fb03d946bf7dc823 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= <ged@odoo.com> Date: Thu, 25 Feb 2021 14:28:59 +0000 Subject: [PATCH] [REF] web: move error handling code to other file --- addons/web/static/src/js/core/error_utils.js | 67 +++++++++++++++++++ .../static/src/js/services/crash_manager.js | 65 +----------------- addons/web/views/webclient_templates.xml | 1 + 3 files changed, 69 insertions(+), 64 deletions(-) create mode 100644 addons/web/static/src/js/core/error_utils.js diff --git a/addons/web/static/src/js/core/error_utils.js b/addons/web/static/src/js/core/error_utils.js new file mode 100644 index 000000000000..9bdc0a1009fd --- /dev/null +++ b/addons/web/static/src/js/core/error_utils.js @@ -0,0 +1,67 @@ +/** @odoo-module **/ + +import { loadJS } from "web.ajax"; + +/** + * Format the traceback of an error. Basically, we just add the error message + * in the traceback if necessary (Chrome already does it by default, but not + * other browser. yay for non standard APIs) + * + * @param {Error} error + * @returns {string} + */ +export function formatTraceback(error) { + const traceback = error.stack; + // Error.prototype.stack is non-standard. + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error + // However, most engines provide an implementation. + // In particular, Chrome formats the contents of Error.stack + // https://v8.dev/docs/stack-trace-api#compatibility + const browserDetection = new BrowserDetection(); + if (browserDetection.isBrowserChrome()) { + return error.stack; + } else { + return `${_t("Error:")} ${error.message}\n${error.stack}`; + } +} + +/** +* Returns an annotated traceback from an error. This is asynchronous because +* it needs to fetch the sourcemaps for each script involved in the error, +* then compute the correct file/line numbers and add the information to the +* correct line. +* +* @param {Error} error +* @returns {Promise<string>} +*/ +export async function annotateTraceback(error) { + const traceback = formatTraceback(error); + await loadJS('/web/static/lib/stacktracejs/stacktrace.js'); + const frames = await StackTrace.fromError(error); + const lines = traceback.split('\n'); + if (lines[lines.length-1].trim() === "") { + // firefox traceback have an empty line at the end + lines.splice(-1); + } + + // Chrome stacks contains some lines with (index 0) which apparently + // corresponds to some native functions (at least Promise.all). We need to + // ignore them because they will not correspond to a stackframe. + const skips = lines.filter(l => l.includes("(index 0")).length; + const offset = lines.length - frames.length - skips; + let lineIndex = offset; + let frameIndex = 0; + while (frameIndex < frames.length) { + const line = lines[lineIndex]; + if (line.includes("(index 0)")) { + lineIndex++; + continue; + } + const frame = frames[frameIndex]; + const info = ` (${frame.fileName}:${frame.lineNumber})`; + lines[lineIndex] = line + info; + lineIndex++; + frameIndex++; + } + return lines.join('\n'); +} diff --git a/addons/web/static/src/js/services/crash_manager.js b/addons/web/static/src/js/services/crash_manager.js index 7bd3e58e8544..eb31131d7dc7 100644 --- a/addons/web/static/src/js/services/crash_manager.js +++ b/addons/web/static/src/js/services/crash_manager.js @@ -17,6 +17,7 @@ var Dialog = require('web.Dialog'); var ErrorDialogRegistry = require('web.ErrorDialogRegistry'); var Widget = require('web.Widget'); var config = require('web.config'); +var { formatTraceback, annotateTraceback} = require("@web/js/core/error_utils"); var _t = core._t; var _lt = core._lt; @@ -29,70 +30,6 @@ window.addEventListener('unhandledrejection', ev => let active = true; -/** - * Format the traceback of an error. Basically, we just add the error message - * in the traceback if necessary (Chrome already does it by default, but not - * other browser. yay for non standard APIs) - * - * @param {Error} error - * @returns {string} - */ -function formatTraceback(error) { - const traceback = error.stack; - // Error.prototype.stack is non-standard. - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error - // However, most engines provide an implementation. - // In particular, Chrome formats the contents of Error.stack - // https://v8.dev/docs/stack-trace-api#compatibility - const browserDetection = new BrowserDetection(); - if (browserDetection.isBrowserChrome()) { - return error.stack; - } else { - return `${_t("Error:")} ${error.message}\n${error.stack}`; - } -} - -/** - * Returns an annotated traceback from an error. This is asynchronous because - * it needs to fetch the sourcemaps for each script involved in the error, - * then compute the correct file/line numbers and add the information to the - * correct line. - * - * @param {Error} error - * @returns {Promise<string>} - */ -async function annotateTraceback(error) { - const traceback = formatTraceback(error); - await ajax.loadJS('/web/static/lib/stacktracejs/stacktrace.js'); - const frames = await StackTrace.fromError(error); - const lines = traceback.split('\n'); - if (lines[lines.length-1].trim() === "") { - // firefox traceback have an empty line at the end - lines.splice(-1); - } - - // Chrome stacks contains some lines with (index 0) which apparently - // corresponds to some native functions (at least Promise.all). We need to - // ignore them because they will not correspond to a stackframe. - const skips = lines.filter(l => l.includes("(index 0")).length; - const offset = lines.length - frames.length - skips; - let lineIndex = offset; - let frameIndex = 0; - while (frameIndex < frames.length) { - const line = lines[lineIndex]; - if (line.includes("(index 0)")) { - lineIndex++; - continue; - } - const frame = frames[frameIndex]; - const info = ` (${frame.fileName}:${frame.lineNumber})`; - lines[lineIndex] = line + info; - lineIndex++; - frameIndex++; - } - return lines.join('\n'); -} - /** * An extension of Dialog Widget to render the warnings and errors on the website. * Extend it with your template of choice like ErrorDialog/WarningDialog diff --git a/addons/web/views/webclient_templates.xml b/addons/web/views/webclient_templates.xml index 7effc9952da2..60982a48392d 100644 --- a/addons/web/views/webclient_templates.xml +++ b/addons/web/views/webclient_templates.xml @@ -166,6 +166,7 @@ <script type="text/javascript" src="/web/static/src/js/services/local_storage_service.js"></script> <script type="text/javascript" src="/web/static/src/js/services/notification_service.js"></script> <script type="text/javascript" src="/web/static/src/js/services/crash_manager.js"></script> + <script type="text/javascript" src="/web/static/src/js/core/error_utils.js"></script> <script type="text/javascript" src="/web/static/src/js/services/session_storage_service.js"></script> <script type="text/javascript" src="/web/static/src/js/tools/debug_manager.js"></script> -- GitLab