Skip to content
Snippets Groups Projects
Commit e2b85d46 authored by Géry Debongnie's avatar Géry Debongnie
Browse files

[REF] web: move error handling code to other file

parent bdc27b74
No related branches found
No related tags found
No related merge requests found
/** @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');
}
......@@ -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
......
......@@ -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>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment