Skip to content

Commit fbc6cfb

Browse files
author
homyakov
committed
Opera stacktrace rewritten, tests updated (needs more testing)
1 parent d597292 commit fbc6cfb

2 files changed

Lines changed: 259 additions & 62 deletions

File tree

stacktrace.js

Lines changed: 71 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,21 @@ printStackTrace.implementation.prototype = {
5858
if (e['arguments'] && e.stack) {
5959
return 'chrome';
6060
} else if (e.message && typeof window !== 'undefined' && window.opera) {
61-
return e.stacktrace ? 'opera10' : 'opera';
61+
// e.message.indexOf("Backtrace:") > -1 -> opera
62+
// !e.stacktrace -> opera
63+
if (!e.stacktrace) {
64+
return 'opera9'; // use e.message
65+
}
66+
// e.stacktrace && !e.stack -> opera10a
67+
if (!e.stack) {
68+
return 'opera10a'; // use e.stacktrace
69+
}
70+
// e.stacktrace && e.stack -> opera10b
71+
if (e.stacktrace.indexOf("called from line") < 0) {
72+
return 'opera10b'; // use e.stacktrace, format differs from 'opera10a'
73+
}
74+
// e.stacktrace && e.stack -> opera11
75+
return 'opera11'; // use e.stacktrace, format differs from 'opera10a', 'opera10b'
6276
} else if (e.stack) {
6377
return 'firefox';
6478
}
@@ -124,37 +138,78 @@ printStackTrace.implementation.prototype = {
124138
return e.stack.replace(/(?:\n@:0)?\s+$/m, '').replace(/^\(/gm, '{anonymous}(').split('\n');
125139
},
126140

141+
opera11: function(e) {
142+
// "Error thrown at line 42, column 12 in <anonymous function: createException>() in file://localhost/G:/js/stacktrace.js:\n"
143+
// "called from line 7, column 4 in bar(n) in file://localhost/G:/js/test/functional/testcase1.html:\n"
144+
// "called from line 15, column 3 in file://localhost/G:/js/test/functional/testcase1.html:\n"
145+
var ANON = '{anonymous}', lineRE = /^.*line (\d+), column (\d+)(?: in (.+))? in (\S+):$/;
146+
var lines = e.stacktrace.split('\n'), result = [];
147+
148+
for (var i = 0, len = lines.length; i < len; i += 2) {
149+
var match = lineRE.exec(lines[i]);
150+
if (match) {
151+
var location = match[4] + ':' + match[1] + ':' + match[2];
152+
var fnName = match[3] || "global code";
153+
fnName = fnName.replace(/<anonymous function: (\S+)>/g, "$1");
154+
result.push(fnName + '@' + location + ' -- ' + lines[i + 1].replace(/^\s+/, ''));
155+
}
156+
}
157+
158+
return result;
159+
},
160+
161+
opera10b: function(e) {
162+
// "<anonymous function: run>([arguments not available])@file://localhost/G:/js/stacktrace.js:27\n" +
163+
// "printStackTrace([arguments not available])@file://localhost/G:/js/stacktrace.js:18\n" +
164+
// "@file://localhost/G:/js/test/functional/testcase1.html:15"
165+
var ANON = '{anonymous}', lineRE = /^(.*)@(.+):(\d+)$/;
166+
var lines = e.stacktrace.split('\n'), result = [];
167+
168+
for (var i = 0, len = lines.length; i < len; i++) {
169+
var match = lineRE.exec(lines[i]);
170+
if (match) {
171+
var fnName = match[1]? (match[1] + '()') : "global code";
172+
result.push(fnName + '@' + match[2] + ':' + match[3]);
173+
}
174+
}
175+
176+
return result;
177+
},
178+
127179
/**
128180
* Given an Error object, return a formatted Array based on Opera 10's stacktrace string.
129181
*
130182
* @param e - Error object to inspect
131183
* @return Array<String> of function calls, files and line numbers
132184
*/
133-
opera10: function(e) {
134-
var ANON = '{anonymous}', lineRE = /.*line (\d+), column (\d+) in ((<anonymous function\:?\s*(\S+))|([^\(]+)\([^\)]*\))(?: in )?(.*)\s*$/i, i, j, len;
185+
opera10a: function(e) {
186+
// " Line 27 of linked script file://localhost/G:/js/stacktrace.js\n"
187+
// " Line 11 of inline#1 script in file://localhost/G:/js/test/functional/testcase1.html: In function foo\n"
188+
var ANON = '{anonymous}', lineRE = /Line (\d+).*script (?:in )?(\S+)(?:: In function (\S+))?$/i;
135189
var lines = e.stacktrace.split('\n'), result = [];
136190

137-
for (i = 2, j = 0, len = lines.length; i < len - 2; i++) {
138-
if (lineRE.test(lines[i])) {
139-
var location = RegExp.$6 + ':' + RegExp.$1 + ':' + RegExp.$2;
140-
var fnName = RegExp.$3;
141-
fnName = fnName.replace(/<anonymous function\:?\s?(\S+)?>/g, ANON);
142-
result.push(fnName + '@' + location);
191+
for (var i = 0, len = lines.length; i < len; i += 2) {
192+
var match = lineRE.exec(lines[i]);
193+
if (match) {
194+
var fnName = match[3] || ANON;
195+
result.push(fnName + '()@' + match[2] + ':' + match[1] + ' -- ' + lines[i + 1].replace(/^\s+/, ''));
143196
}
144197
}
145198

146199
return result;
147200
},
148201

149-
// Opera 7.x-9.x only!
150-
opera: function(e) {
151-
var ANON = '{anonymous}', lineRE = /Line\s+(\d+).*script\s+(http\S+)(?:.*in\s+function\s+(\S+))?/i;
202+
// Opera 7.x-9.2x only!
203+
opera9: function(e) {
204+
// " Line 43 of linked script file://localhost/G:/js/stacktrace.js\n"
205+
// " Line 7 of inline#1 script in file://localhost/G:/js/test/functional/testcase1.html\n"
206+
var ANON = '{anonymous}', lineRE = /Line (\d+).*script (?:in )?(\S+)/i;
152207
var lines = e.message.split('\n'), result = [];
153208

154-
for (var i = 4, len = lines.length; i < len; i += 2) {
155-
//TODO: RegExp.exec() would probably be cleaner here
156-
if (lineRE.test(lines[i])) {
157-
result.push((RegExp.$3 ? RegExp.$3 + '()@' + RegExp.$2 + RegExp.$1 : ANON + '()@' + RegExp.$2 + ':' + RegExp.$1) + ' -- ' + lines[i + 1].replace(/^\s+/, ''));
209+
for (var i = 2, len = lines.length; i < len; i += 2) {
210+
var match = lineRE.exec(lines[i]);
211+
if (match) {
212+
result.push(ANON + '()@' + match[2] + ':' + match[1] + ' -- ' + lines[i + 1].replace(/^\s+/, ''));
158213
}
159214
}
160215

0 commit comments

Comments
 (0)