text: var printStackTrace=function(options){options=options||{guess:!0};var ex=options.e||null,guess=!!options.guess,mode=options.mode||null;var p=new printStackTrace.implementation(),result=p.run(ex,mode);return(guess)?p.guessAnonymousFunctions(result):result}
  printStackTrace.implementation=function(){};printStackTrace.implementation.prototype={run:function(ex,mode){ex=ex||this.createException();mode=mode||this.mode(ex);if(mode==='other'){return this.other(arguments.callee)}else{return this[mode](ex)}},createException:function(){try{this.undef()}catch(e){return e}},mode:function(e){if(typeof window!=='undefined'&&window.navigator.userAgent.indexOf('PhantomJS')>-1){return'phantomjs'}
  if(e['arguments']&&e.stack){return'chrome'}
  if(e.stack&&e.sourceURL){return'safari'}
  if(e.stack&&e.number){return'ie'}
  if(e.stack&&e.fileName){return'firefox'}
  if(e.message&&e['opera#sourceloc']){if(!e.stacktrace){return'opera9'}
  if(e.message.indexOf('\n')>-1&&e.message.split('\n').length>e.stacktrace.split('\n').length){return'opera9'}
  return'opera10a'}
  if(e.message&&e.stack&&e.stacktrace){if(e.stacktrace.indexOf("called from line")<0){return'opera10b'}
  return'opera11'}
  if(e.stack&&!e.fileName){return'chrome'}
  return'other'},instrumentFunction:function(context,functionName,callback){context=context||window;var original=context[functionName];context[functionName]=function instrumented(){callback.call(this,printStackTrace().slice(4));return context[functionName]._instrumented.apply(this,arguments)};context[functionName]._instrumented=original},deinstrumentFunction:function(context,functionName){if(context[functionName].constructor===Function&&context[functionName]._instrumented&&context[functionName]._instrumented.constructor===Function){context[functionName]=context[functionName]._instrumented}},chrome:function(e){return(e.stack+'\n').replace(/^[\s\S]+?\s+at\s+/,' at ').replace(/^\s+(at eval )?at\s+/gm,'').replace(/^([^\(]+?)([\n$])/gm,'{anonymous}() ($1)$2').replace(/^Object.<anonymous>\s*\(([^\)]+)\)/gm,'{anonymous}() ($1)').replace(/^(.+) \((.+)\)$/gm,'$1@$2').split('\n').slice(0,-1)},safari:function(e){return e.stack.replace(/\[native code\]\n/m,'').replace(/^(?=\w+Error\:).*$\n/m,'').replace(/^@/gm,'{anonymous}()@').split('\n')},ie:function(e){return e.stack.replace(/^\s*at\s+(.*)$/gm,'$1').replace(/^Anonymous function\s+/gm,'{anonymous}() ').replace(/^(.+)\s+\((.+)\)$/gm,'$1@$2').split('\n').slice(1)},firefox:function(e){return e.stack.replace(/(?:\n@:0)?\s+$/m,'').replace(/^(?:\((\S*)\))?@/gm,'{anonymous}($1)@').split('\n')},opera11:function(e){var ANON='{anonymous}',lineRE=/^.*line (\d+), column (\d+)(?: in (.+))? in (\S+):$/;var lines=e.stacktrace.split('\n'),result=[];for(var i=0,len=lines.length;i<len;i+=2){var match=lineRE.exec(lines[i]);if(match){var location=match[4]+':'+match[1]+':'+match[2];var fnName=match[3]||"global code";fnName=fnName.replace(/<anonymous function: (\S+)>/,"$1").replace(/<anonymous function>/,ANON);result.push(fnName+'@'+location+' -- '+lines[i+1].replace(/^\s+/,''))}}
  return result},opera10b:function(e){var lineRE=/^(.*)@(.+):(\d+)$/;var lines=e.stacktrace.split('\n'),result=[];for(var i=0,len=lines.length;i<len;i++){var match=lineRE.exec(lines[i]);if(match){var fnName=match[1]?(match[1]+'()'):"global code";result.push(fnName+'@'+match[2]+':'+match[3])}}
  return result},opera10a:function(e){var ANON='{anonymous}',lineRE=/Line (\d+).*script (?:in )?(\S+)(?:: In function (\S+))?$/i;var lines=e.stacktrace.split('\n'),result=[];for(var i=0,len=lines.length;i<len;i+=2){var match=lineRE.exec(lines[i]);if(match){var fnName=match[3]||ANON;result.push(fnName+'()@'+match[2]+':'+match[1]+' -- '+lines[i+1].replace(/^\s+/,''))}}
  return result},opera9:function(e){var ANON='{anonymous}',lineRE=/Line (\d+).*script (?:in )?(\S+)/i;var lines=e.message.split('\n'),result=[];for(var i=2,len=lines.length;i<len;i+=2){var match=lineRE.exec(lines[i]);if(match){result.push(ANON+'()@'+match[2]+':'+match[1]+' -- '+lines[i+1].replace(/^\s+/,''))}}
  return result},phantomjs:function(e){var ANON='{anonymous}',lineRE=/(\S+) \((\S+)\)/i;var lines=e.stack.split('\n'),result=[];for(var i=1,len=lines.length;i<len;i++){lines[i]=lines[i].replace(/^\s+at\s+/gm,'');var match=lineRE.exec(lines[i]);if(match){result.push(match[1]+'()@'+match[2])}
  else{result.push(ANON+'()@'+lines[i])}}
  return result},other:function(curr){var ANON='{anonymous}',fnRE=/function(?:\s+([\w$]+))?\s*\(/,stack=[],fn,args,maxStackSize=10;var slice=Array.prototype.slice;while(curr&&stack.length<maxStackSize){fn=fnRE.test(curr.toString())?RegExp.$1||ANON:ANON;try{args=slice.call(curr['arguments']||[])}catch(e){args=['Cannot access arguments: '+e]}
  stack[stack.length]=fn+'('+this.stringifyArguments(args)+')';try{curr=curr.caller}catch(e){stack[stack.length]='Cannot access caller: '+e;break}}
  return stack},stringifyArguments:function(args){var result=[];var slice=Array.prototype.slice;for(var i=0;i<args.length;++i){var arg=args[i];if(arg===undefined){result[i]='undefined'}else if(arg===null){result[i]='null'}else if(arg.constructor){if(arg.constructor===Array){if(arg.length<3){result[i]='['+this.stringifyArguments(arg)+']'}else{result[i]='['+this.stringifyArguments(slice.call(arg,0,1))+'...'+this.stringifyArguments(slice.call(arg,-1))+']'}}else if(arg.constructor===Object){result[i]='#object'}else if(arg.constructor===Function){result[i]='#function'}else if(arg.constructor===String){result[i]='"'+arg+'"'}else if(arg.constructor===Number){result[i]=arg}else{result[i]='?'}}}
  return result.join(',')},sourceCache:{},ajax:function(url){var req=this.createXMLHTTPObject();if(req){try{req.open('GET',url,!1);req.send(null);return req.responseText}catch(e){}}
  return''},createXMLHTTPObject:function(){var xmlhttp,XMLHttpFactories=[function(){return new XMLHttpRequest()},function(){return new ActiveXObject('Msxml2.XMLHTTP')},function(){return new ActiveXObject('Msxml3.XMLHTTP')},function(){return new ActiveXObject('Microsoft.XMLHTTP')}];for(var i=0;i<XMLHttpFactories.length;i++){try{xmlhttp=XMLHttpFactories[i]();this.createXMLHTTPObject=XMLHttpFactories[i];return xmlhttp}catch(e){}}},isSameDomain:function(url){return typeof location!=="undefined"&&url.indexOf(location.hostname)!==-1},getSource:function(url){if(!(url in this.sourceCache)){this.sourceCache[url]=this.ajax(url).split('\n')}
  return this.sourceCache[url]},guessAnonymousFunctions:function(stack){for(var i=0;i<stack.length;++i){var reStack=/\{anonymous\}\(.*\)@(.*)/,reRef=/^(.*?)(?::(\d+))(?::(\d+))?(?: -- .+)?$/,frame=stack[i],ref=reStack.exec(frame);if(ref){var m=reRef.exec(ref[1]);if(m){var file=m[1],lineno=m[2],charno=m[3]||0;if(file&&this.isSameDomain(file)&&lineno){var functionName=this.guessAnonymousFunction(file,lineno,charno);stack[i]=frame.replace('{anonymous}',functionName)}}}}
  return stack},guessAnonymousFunction:function(url,lineNo,charNo){var ret;try{ret=this.findFunctionName(this.getSource(url),lineNo)}catch(e){ret='getSource failed with url: '+url+', exception: '+e.toString()}
  return ret},findFunctionName:function(source,lineNo){var reFunctionDeclaration=/function\s+([^(]*?)\s*\(([^)]*)\)/;var reFunctionExpression=/['"]?([$_A-Za-z][$_A-Za-z0-9]*)['"]?\s*[:=]\s*function\b/;var reFunctionEvaluation=/['"]?([$_A-Za-z][$_A-Za-z0-9]*)['"]?\s*[:=]\s*(?:eval|new Function)\b/;var code="",line,maxLines=Math.min(lineNo,20),m,commentPos;for(var i=0;i<maxLines;++i){line=source[lineNo-i-1];commentPos=line.indexOf('//');if(commentPos>=0){line=line.substr(0,commentPos)}
  if(line){code=line+code;m=reFunctionExpression.exec(code);if(m&&m[1]){return m[1]}
  m=reFunctionDeclaration.exec(code);if(m&&m[1]){return m[1]}
  m=reFunctionEvaluation.exec(code);if(m&&m[1]){return m[1]}}}
  return'(?)'}}