diff --git a/js/js-resources.gresource.xml b/js/js-resources.gresource.xml index 5351390a8..f6b8b7e78 100644 --- a/js/js-resources.gresource.xml +++ b/js/js-resources.gresource.xml @@ -19,6 +19,7 @@ misc/dateUtils.js misc/dbusUtils.js misc/dependencies.js + misc/errorUtils.js misc/extensionUtils.js misc/fileUtils.js misc/gnomeSession.js diff --git a/js/misc/errorUtils.js b/js/misc/errorUtils.js new file mode 100644 index 000000000..c2bc1c794 --- /dev/null +++ b/js/misc/errorUtils.js @@ -0,0 +1,62 @@ +// Common code for displaying errors to the user in various dialogs + +function formatSyntaxErrorLocation(error) { + const {fileName = '', lineNumber = 0, columnNumber = 0} = error; + return ` @ ${fileName}:${lineNumber}:${columnNumber}`; +} + +function formatExceptionStack(error) { + const {stack} = error; + if (!stack) + return '\n\n(No stack trace)'; + + const indentedStack = stack.split('\n').map(line => ` ${line}`).join('\n'); + return `\n\nStack trace:\n${indentedStack}`; +} + +function formatExceptionWithCause(error, seenCauses) { + let fmt = formatExceptionStack(error); + + const {cause} = error; + if (!cause) + return fmt; + + fmt += `\nCaused by: ${cause}`; + + if (cause !== null && typeof cause === 'object') { + if (seenCauses.has(cause)) + return fmt; // avoid recursion + seenCauses.add(cause); + + fmt += formatExceptionWithCause(cause, seenCauses); + } + + return fmt; +} + +/** + * Formats a thrown exception into a string, including the stack, taking the + * location where a SyntaxError was thrown into account. + * + * @param {Error} error The error to format + * @returns {string} The formatted string + */ +export function formatError(error) { + try { + let fmt = `${error}`; + if (error === null || typeof error !== 'object') + return fmt; + + if (error instanceof SyntaxError) { + fmt += formatSyntaxErrorLocation(error); + fmt += formatExceptionStack(error); + return fmt; + } + + const seenCauses = new Set([error]); + fmt += formatExceptionWithCause(error, seenCauses); + return fmt; + } catch (e) { + return `(could not display error: ${e})`; + } +}