@@ -55,7 +55,7 @@ function printStackTrace(options) {
5555 options = options || { guess : true } ;
5656 var ex = options . e || null , guess = ! ! options . guess ;
5757 var p = new printStackTrace . implementation ( ) , result = p . run ( ex ) ;
58- return ( guess ) ? p . guessFunctions ( result ) : result ;
58+ return ( guess ) ? p . guessAnonymousFunctions ( result ) : result ;
5959}
6060
6161printStackTrace . implementation = function ( ) {
@@ -91,7 +91,7 @@ printStackTrace.implementation.prototype = {
9191 mode : function ( e ) {
9292 if ( e [ 'arguments' ] && e . stack ) {
9393 return ( this . _mode = 'chrome' ) ;
94- } else if ( typeof window !== 'undefined' && window . opera ) {
94+ } else if ( e . message && typeof window !== 'undefined' && window . opera ) {
9595 return ( this . _mode = e . stacktrace ? 'opera10' : 'opera' ) ;
9696 } else if ( e . stack ) {
9797 return ( this . _mode = 'firefox' ) ;
@@ -213,6 +213,7 @@ printStackTrace.implementation.prototype = {
213213 * @return {Array } of Strings with stringified arguments
214214 */
215215 stringifyArguments : function ( args ) {
216+ var slice = Array . prototype . slice ;
216217 for ( var i = 0 ; i < args . length ; ++ i ) {
217218 var arg = args [ i ] ;
218219 if ( arg === undefined ) {
@@ -224,7 +225,7 @@ printStackTrace.implementation.prototype = {
224225 if ( arg . length < 3 ) {
225226 args [ i ] = '[' + this . stringifyArguments ( arg ) + ']' ;
226227 } else {
227- args [ i ] = '[' + this . stringifyArguments ( Array . prototype . slice . call ( arg , 0 , 1 ) ) + '...' + this . stringifyArguments ( Array . prototype . slice . call ( arg , - 1 ) ) + ']' ;
228+ args [ i ] = '[' + this . stringifyArguments ( slice . call ( arg , 0 , 1 ) ) + '...' + this . stringifyArguments ( slice . call ( arg , - 1 ) ) + ']' ;
228229 }
229230 } else if ( arg . constructor === Object ) {
230231 args [ i ] = '#object' ;
@@ -306,48 +307,58 @@ printStackTrace.implementation.prototype = {
306307 return this . sourceCache [ url ] ;
307308 } ,
308309
309- guessFunctions : function ( stack ) {
310+ guessAnonymousFunctions : function ( stack ) {
310311 for ( var i = 0 ; i < stack . length ; ++ i ) {
311312 var reStack = / \{ a n o n y m o u s \} \( .* \) @ ( \w + : \/ \/ ( [ \- \w \. ] + ) + ( : \d + ) ? [ ^ : ] + ) : ( \d + ) : ? ( \d + ) ? / ;
312313 var frame = stack [ i ] , m = reStack . exec ( frame ) ;
313314 if ( m ) {
314- var file = m [ 1 ] , lineno = m [ 4 ] ; //m[7] is character position in Chrome
315+ var file = m [ 1 ] , lineno = m [ 4 ] , charno = m [ 7 ] || 0 ; //m[7] is character position in Chrome
315316 if ( file && this . isSameDomain ( file ) && lineno ) {
316- var functionName = this . guessFunctionName ( file , lineno ) ;
317+ var functionName = this . guessAnonymousFunction ( file , lineno , charno ) ;
317318 stack [ i ] = frame . replace ( '{anonymous}' , functionName ) ;
318319 }
319320 }
320321 }
321322 return stack ;
322323 } ,
323324
324- guessFunctionName : function ( url , lineNo ) {
325+ guessAnonymousFunction : function ( url , lineNo , charNo ) {
325326 var ret ;
326327 try {
327- ret = this . guessFunctionNameFromLines ( lineNo , this . getSource ( url ) ) ;
328+ ret = this . findFunctionName ( this . getSource ( url ) , lineNo ) ;
328329 } catch ( e ) {
329330 ret = 'getSource failed with url: ' + url + ', exception: ' + e . toString ( ) ;
330331 }
331332 return ret ;
332333 } ,
333334
334- guessFunctionNameFromLines : function ( lineNo , source ) {
335- var reFunctionArgNames = / f u n c t i o n ( [ ^ ( ] * ) \( ( [ ^ ) ] * ) \) / ;
336- var reGuessFunction = / [ ' " ] ? ( [ 0 - 9 A - Z a - z _ ] + ) [ ' " ] ? \s * [: = ] \s * ( f u n c t i o n | e v a l | n e w F u n c t i o n ) / ;
337- // Walk backwards from the first line in the function until we find the line which
338- // matches the pattern above, which is the function definition
339- var line = "" , maxLines = 10 ;
335+ findFunctionName : function ( source , lineNo ) {
336+ // TODO use captured args
337+ // function {name}({args}) m[1]=name m[2]=args
338+ var reFunctionDeclaration = / f u n c t i o n \s + ( [ ^ ( ] * ?) \s * \( ( [ ^ ) ] * ) \) / ;
339+ // {name} = function ({args}) TODO args capture
340+ var reFunctionExpression = / [ ' " ] ? ( [ 0 - 9 A - Z a - z _ ] + ) [ ' " ] ? \s * [: = ] \s * f u n c t i o n (?: [ ^ ( ] * ) / ;
341+ // {name} = eval()
342+ var reFunctionEvaluation = / [ ' " ] ? ( [ 0 - 9 A - Z a - z _ ] + ) [ ' " ] ? \s * [: = ] \s * (?: e v a l | n e w F u n c t i o n ) / ;
343+ // Walk backwards in the source lines until we find
344+ // the line which matches one of the patterns above
345+ var code = "" , line , maxLines = 10 , m ;
340346 for ( var i = 0 ; i < maxLines ; ++ i ) {
341- line = source [ lineNo - i ] + line ;
342- if ( line !== undefined ) {
343- var m = reGuessFunction . exec ( line ) ;
347+ line = source [ lineNo - i ] ;
348+ if ( line ) {
349+ code = line + code ;
350+ m = reFunctionExpression . exec ( code ) ;
351+ if ( m && m [ 1 ] ) {
352+ return m [ 1 ] ;
353+ }
354+ m = reFunctionDeclaration . exec ( code ) ;
355+ if ( m && m [ 1 ] ) {
356+ //return m[1] + "(" + (m[2] || "") + ")";
357+ return m [ 1 ] ;
358+ }
359+ m = reFunctionEvaluation . exec ( code ) ;
344360 if ( m && m [ 1 ] ) {
345361 return m [ 1 ] ;
346- } else {
347- m = reFunctionArgNames . exec ( line ) ;
348- if ( m && m [ 1 ] ) {
349- return m [ 1 ] ;
350- }
351362 }
352363 }
353364 }
0 commit comments