@@ -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 = / ^ .* l i n e ( \d + ) , c o l u m n ( \d + ) (?: i n ( .+ ) ) ? i n ( \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 ( / < a n o n y m o u s f u n c t i o n : ( \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 = / .* l i n e ( \d + ) , c o l u m n ( \d + ) i n ( ( < a n o n y m o u s f u n c t i o n \: ? \s * ( \S + ) ) | ( [ ^ \( ] + ) \( [ ^ \) ] * \) ) (?: i n ) ? ( .* ) \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 = / L i n e ( \d + ) .* s c r i p t (?: i n ) ? ( \S + ) (?: : I n f u n c t i o n ( \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 ( / < a n o n y m o u s f u n c t i o n \: ? \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 = / L i n e \s + ( \d + ) .* s c r i p t \s + ( h t t p \S + ) (?: .* i n \s + f u n c t i o n \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 = / L i n e ( \d + ) .* s c r i p t (?: i n ) ? ( \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