diff --git a/src/004-base/domPassage.js b/src/004-base/domPassage.js index e051f45dd2766e3eea75262f6bf112a4f8117782..c5bc9037593c7ba8fc742b79c4f96208f4c952f9 100644 --- a/src/004-base/domPassage.js +++ b/src/004-base/domPassage.js @@ -25,21 +25,7 @@ App.DomPassage = class extends Passage { try { return this.callback(); } catch (ex) { - const fragment = document.createDocumentFragment(); - - App.UI.DOM.appendNewElement("p", fragment, `${ex.name}: ${ex.message}`, ["bold", "error"]); - - const p = document.createElement("p"); - const lines = ex.stack.split("\n"); - for (const ll of lines) { - const div = document.createElement("div"); - // remove file path from error message - div.append(ll.replace(/file:.*\//, "<path>/")); - p.append(div); - } - fragment.append(p); - - return fragment; + return App.UI.DOM.formatException(ex); } } }; diff --git a/src/js/main.js b/src/js/main.js index 750d32686277c38d6865c7cac47a8c4311cb13cf..a78c5e95b414dee619049a9d55072d5e989517bd 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -349,17 +349,7 @@ App.MainView.full = function() { fragment.append(assemble()); } catch (ex) { - App.UI.DOM.appendNewElement("p", fragment, `${ex.name}: ${ex.message}`, ["bold", "error"]); - - const p = document.createElement("p"); - const lines = ex.stack.split("\n"); - for (const ll of lines) { - const div = document.createElement("div"); - // remove file path from error message - div.append(ll.replace(/file:.*\//, "<path>/")); - p.append(div); - } - fragment.append(p); + fragment.append(App.UI.DOM.formatException(ex)); } return fragment; diff --git a/src/js/utilsDOM.js b/src/js/utilsDOM.js index a904b1117d55ad28749c8419ac08551872fc53e8..926132a916b73f0c9d95ee497a8225994a06e769 100644 --- a/src/js/utilsDOM.js +++ b/src/js/utilsDOM.js @@ -438,3 +438,65 @@ App.UI.DOM.cashFormat = function(s) { span.textContent = cashFormat(Math.trunc(s)); return span; }; + +/** + * Renders an exception to DOM. + * Tries it's best to not fail itself. + * + * @param {Error } ex Exception + * @param {boolean} recursion set if formatException() called itself, never set from outside + * @returns {DocumentFragment|HTMLParagraphElement} + */ +App.UI.DOM.formatException = function formatException(ex, recursion = false) { + /** + * In case the normal rendering failed attempts to provide some information on it. + * In the worst case gives back a default error message. + * + * @param exception + * @returns {DocumentFragment|HTMLParagraphElement} + */ + function failSafe(exception) { + if (!recursion) { + return formatException(exception, true); + } else { + // Not using custom functions here, as they may be the cause of the error + const p = document.createElement("p"); + p.classList.add("bold", "error"); + p.append("Unrecoverable error in App.UI.DOM.formatException()! Please report this."); + return p; + } + } + + /** + * Renders the exception to DOM + * + * @returns {DocumentFragment} + */ + function render() { + const fragment = document.createDocumentFragment(); + + App.UI.DOM.appendNewElement("p", fragment, `${ex.name}: ${ex.message}; ${Config.saves.version}`, ["bold", "error"]); + + const p = document.createElement("p"); + const lines = ex.stack.split("\n"); + for (const ll of lines) { + const div = document.createElement("div"); + // remove file path from error message + div.append(ll.replace(/file:.*\//, "<path>/")); + p.append(div); + } + fragment.append(p); + + return fragment; + } + + try { + if (!ex) { + // Create a new Error so we have access to a stacktrace. + return failSafe(new Error("No exception provided!")); + } + return render(); + } catch (ex) { + return failSafe(ex); + } +};