luci-base: luci.js: rework L.error()
authorJo-Philipp Wich <jo@mein.io>
Tue, 28 May 2019 16:57:43 +0000 (18:57 +0200)
committerJo-Philipp Wich <jo@mein.io>
Sun, 7 Jul 2019 13:36:25 +0000 (15:36 +0200)
Factor out an L.raise() function out of L.error() which constructs and
throws an exception object.

Rework the remaining L.error() function to internally use L.raise() to
construct exceptionts to render.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
modules/luci-base/htdocs/luci-static/resources/luci.js

index 24af80f692041019b93e4c52910ba82eadac0d85..6332790c77b726408f786b56f32a94b27570eef4 100644 (file)
                        window.cbi_init = function() {};
                },
 
-               error: function(type, fmt /*, ...*/) {
+               raise: function(type, fmt /*, ...*/) {
                        var e = null,
                            msg = fmt ? String.prototype.format.apply(fmt, this.varargs(arguments, 2)) : null,
                            stack = null;
                        else {
                                e = new (window[type || 'Error'] || Error)(msg || 'Unspecified error');
                                e.name = type || 'Error';
+                       }
 
-                               try { throw new Error('stacktrace') }
-                               catch (e2) { stack = (e2.stack || '').split(/\n/) }
+                       if (window.console && console.debug)
+                               console.debug(e);
 
-                               /* IE puts the exception message into the first line */
-                               if (stack[0] == 'Error: stacktrace')
-                                       stack.shift();
+                       throw e;
+               },
 
-                               /* Pop L.error() invocation from stack */
-                               stack.shift();
+               error: function(type, fmt /*, ...*/) {
+                       try {
+                               L.raise.apply(L, Array.prototype.slice.call(arguments));
                        }
+                       catch (e) {
+                               var stack = (e.stack || '').split(/\n/).map(function(frame) {
+                                       frame = frame.replace(/(.*?)@(.+):(\d+):(\d+)/g, 'at $1 ($2:$3:$4)').trim();
+                                       return frame ? '  ' + frame : '';
+                               });
 
-                       /* Append shortened & beautified stacktrace to message */
-                       var trace = stack.join('\n')
-                               .replace(/(.*?)@(.+):(\d+):(\d+)/g, '  at $1 ($2:$3:$4)');
+                               if (!/^  at /.test(stack[0]))
+                                       stack.shift();
 
-                       if (e.message.indexOf(trace) == -1)
-                               e.message += '\n' + trace;
+                               if (/\braise /.test(stack[0]))
+                                       stack.shift();
 
-                       if (window.console && console.debug)
-                               console.debug(e);
+                               if (/\berror /.test(stack[0]))
+                                       stack.shift();
 
-                       if (this.ui)
-                               this.ui.showModal(_('Runtime error'),
-                                       E('pre', { 'class': 'alert-message error' }, e));
-                       else
-                               L.dom.content(document.querySelector('#maincontent'),
-                                       E('pre', { 'class': 'alert-message error' }, e));
+                               stack = stack.length ? '\n' + stack.join('\n') : '';
 
-                       throw e;
+                               if (L.ui)
+                                       L.ui.showModal(e.name || _('Runtime error'),
+                                               E('pre', { 'class': 'alert-message error' }, e.message + stack));
+                               else
+                                       L.dom.content(document.querySelector('#maincontent'),
+                                               E('pre', { 'class': 'alert-message error' }, e + stack));
+
+                               throw e;
+                       }
                },
 
                bind: function(fn, self /*, ... */) {