How to get JavaScript caller function line number and caller source URL

Javascript

Javascript Problem Overview


I am using the following for getting the JavaScript caller function name:

var callerFunc = arguments.callee.caller.toString();
callerFuncName = (callerFunc.substring(callerFunc.indexOf("function") + 8, callerFunc.indexOf("(")) || "anoynmous")

Is there a way to discover the line number from which the method was called?

Also, is there a way to get the name of the JavaScript file the method was called from? Or the source URL?

Javascript Solutions


Solution 1 - Javascript

This works for me in chrome/QtWebView

function getErrorObject(){
    try { throw Error('') } catch(err) { return err; }
}

var err = getErrorObject();
var caller_line = err.stack.split("\n")[4];
var index = caller_line.indexOf("at ");
var clean = caller_line.slice(index+2, caller_line.length);

Solution 2 - Javascript

kangax's solution introduces unnecessary try..catch scope. If you need to access the line number of something in JavaScript (as long as you are using Firefox or Opera), just access (new Error).lineNumber.

Solution 3 - Javascript

I was surprised that most of these answers assumed that you wanted to handle an error rather than just output helpful debug traces for normal cases as well.

For example, I like using a console.log wrapper like this:

consoleLog = function(msg) {//See https://stackoverflow.com/a/27074218/470749
    var e = new Error();
    if (!e.stack) {
        try {
            // IE requires the Error to actually be thrown or else the 
            // Error's 'stack' property is undefined.
            throw e;
        } catch (e) {
            if (!e.stack) {
                //return 0; // IE < 10, likely
            }
        }
    }
    var stack = e.stack.toString().split(/\r\n|\n/);
    if (msg === '') {
        msg = '""';
    }
    console.log(msg, '          [' + stack[1] + ']');        
}

This ends up printing an output such as the following to my console:

1462567104174 [getAllPosts@http://me.com/helper.js:362:9]

See https://stackoverflow.com/a/27074218/ and also https://stackoverflow.com/questions/13815640/

Solution 4 - Javascript

I realize this is an old question but there is now a method called console.trace("Message") that will show you the line number and the chain of method calls that led to the log along with the message you pass it. More info on javascript logging tricks are available here at freecodecamp and this medium blog post

Solution 5 - Javascript

This is often achieved by throwing an error from the current context; then analyzing error object for properties like lineNumber and fileName (which some browsers have)

function getErrorObject(){
  try { throw Error('') } catch(err) { return err; }
}

var err = getErrorObject();

err.fileName;
err.lineNumber; // or `err.line` in WebKit

Don't forget that callee.caller property is deprecated (and was never really in ECMA 3rd ed. in the first place).

Also remember that function decompilation is specified to be implementation dependent and so might yield quite unexpected results. I wrote about it here and here.

Solution 6 - Javascript

It seems I'm kind of late :), but the discussion is pretty interesting so.. here it goes... Assuming you want to build a error handler, and you're using your own exception handler class like:

function  errorHandler(error){
    this.errorMessage = error;
}
errorHandler.prototype. displayErrors = function(){
    throw new Error(this.errorMessage);
}

And you're wrapping your code like this:

try{
if(condition){
    //whatever...
}else{
    throw new errorHandler('Some Error Message');
}
}catch(e){
    e.displayErrors();
}

Most probably you'll have the error handler in a separate .js file.

You'll notice that in firefox or chrome's error console the code line number(and file name) showed is the line(file) that throws the 'Error' exception and not the 'errorHandler' exception wich you really want in order to make debugging easy. Throwing your own exceptions is great but on large projects locating them can be quite an issue, especially if they have similar messages. So, what you can do is to pass a reference to an actual empty Error object to your error handler, and that reference will hold all the information you want( for example in firefox you can get the file name, and line number etc.. ; in chrome you get something similar if you read the 'stack' property of the Error instance). Long story short , you can do something like this:

function  errorHandler(error, errorInstance){
    this.errorMessage = error;
    this. errorInstance = errorInstance;
}
errorHandler.prototype. displayErrors = function(){
    //add the empty error trace to your message
    this.errorMessage += '  stack trace: '+ this. errorInstance.stack;
    throw new Error(this.errorMessage);
}

try{
if(condition){
    //whatever...
}else{
    throw new errorHandler('Some Error Message', new Error());
}
}catch(e){
    e.displayErrors();
}

Now you can get the actual file and line number that throwed you custom exception.

Solution 7 - Javascript

Line number is actually something static, so if you just want it for logging then it could be preprocessed with something like gulp. I've written a small gulp [plugin][1] that does exactly that:

var gulp = require('gulp');
var logLine = require('gulp-log-line');
gulp.task('log-line', function() {
    return gulp.src("file.js", {buffer : true})
    //Write here the loggers you use.
        .pipe(logLine(['console.log']))
        .pipe(gulp.dest('./build'))
 
})
 
gulp.task('default', ['log-line'])

This will attach the file name and line to all logs from console.log, so console.log(something) will become console.log('filePath:fileNumber', something). The advantage is that now you can concat your files, transpile them... and you will still get the line [1]: https://www.npmjs.com/package/gulp-log-line

Solution 8 - Javascript

If you would like to know the line number for debugging purposes, or only during development (For a reason or another), you could use Firebug (a Firefox extension) and throw an exception.

Edit:

If you really need to do that in production for some reason, you can pre-process your javascript files in order for each function to keep track of the line it is on. I know some frameworks that find the coverage of code use this (such as JSCoverage).

For example, let's say your original call is:

function x() {
  1 + 1;
  2 + 2;
  y();
}

You could write a preprocessor to make it into:

function x() {
  var me = arguments.callee;
  me.line = 1;
  1 + 1;
  me.line = 2;
  2 + 2;
  me.line = 3;
  y();
}

Then in y(), you could use arguments.callee.caller.line to know the line from which it was called, such as:

function y() {
  alert(arguments.callee.caller.line);
}

Solution 9 - Javascript

This is how I have done it, I have tested it in both Firefox and Chrome. This makes it possible to check the filename and line number of the place where the function is called from.

logFileAndLineNumber(new Error());

function logFileAndLineNumber(newErr)
{
   if(navigator.userAgent.indexOf("Firefox") != -1)
   {
      var originPath = newErr.stack.split('\n')[0].split("/");
      var fileNameAndLineNumber = originPath[originPath.length - 1].split(">")[0];
      console.log(fileNameAndLineNumber);
   }else if(navigator.userAgent.indexOf("Chrome") != -1)
   {
      var originFile = newErr.stack.split('\n')[1].split('/');
      var fileName = originFile[originFile.length - 1].split(':')[0];
      var lineNumber = originFile[originFile.length - 1].split(':')[1];
      console.log(fileName+" line "+lineNumber);
    }
}

Solution 10 - Javascript

Here is what I wrote based on info found on this forum:

This is part of a MyDebugNamespace, Debug is apparently reserved and won't do as namespace name.

    var DEBUG = true;

...

    if (true == DEBUG && !test)
    {
        var sAlert = "Assertion failed! ";
        if (null != message)
            sAlert += "\n" + message;
        if (null != err)
            sAlert += "\n" + "File: " + err.fileName + "\n" + "Line: " + err.lineNumber;
        alert(sAlert);
    }

...

How to call:

    MyDebugNamespace.Assert(new Error(""), (null != someVar), "Something is wrong!")

I included two functions with variable number of arguments calling this base code in my namespace so as to optionally omit message or error in calls.

This works fine with Firefox, IE6 and Chrome report the fileName and lineNumber as undefined.

Solution 11 - Javascript

the following code works for me in Mozilla and Chrome.

Its log function that shows the file's name and the line of the caller.

log: function (arg) {
    var toPrint = [];
    for (var i = 0; i < arguments.length; ++i) {
        toPrint.push(arguments[i]);
    }

    function getErrorObject(){
        try { throw Error('') } catch(err) { return err; }
    }

    var err = getErrorObject(),
        caller;

    if ($.browser.mozilla) {
        caller = err.stack.split("\n")[2];
    } else {
        caller = err.stack.split("\n")[4];
    }
        
    var index = caller.indexOf('.js');

    var str = caller.substr(0, index + 3);
    index = str.lastIndexOf('/');
    str = str.substr(index + 1, str.length);
        
    var info = "\t\tFile: " + str;

    if ($.browser.mozilla) {
        str = caller;
    } else {
        index = caller.lastIndexOf(':');
        str = caller.substr(0, index);
    }
    index = str.lastIndexOf(':');
    str = str.substr(index + 1, str.length);
    info += " Line: " + str;
    toPrint.push(info);

    console.log.apply(console, toPrint);
}

Solution 12 - Javascript

My contribution to custom errors in JavaScript:

  1. First, I agree with this @B T guy at https://stackoverflow.com/questions/8802845/inheriting-from-the-error-object-where-is-the-message-property?lq=1, we have to built it properly (actually you have to use a js object library, my favorite: https://github.com/jiem/my-class):

     window.g3 = window.g3 || {};
     g3.Error = function (message, name, original) {
          this.original = original;
          this.name = name || 'Error.g3';
          this.message = message || 'A g3.Error was thrown!';
          (original)? this.stack = this.original.stack: this.stack = null;
          this.message += '<br>---STACK---<br>' + this.stack;
      };
    
      var ClassEmpty = function() {};
      ClassEmpty.prototype = Error.prototype;
      g3.Error.prototype = new ClassEmpty();
      g3.Error.prototype.constructor = g3.Error;
    
  2. then, we should define a global error handling function (optional) or, they'll end up to the engine:

     window.onerror = printError; 
     function printError(msg, url, line){
         document.getElementById('test').innerHTML = msg+'<br>at: '+url+'<br>line: '+line;
         return true;
     }
    
  3. finally, we should throw our custom errors carefully:

     //hit it!
     //throw new g3.Error('Hey, this is an error message!', 'Error.Factory.g3');
     throw new g3.Error('Hey, this is an error message!', 'Error.Factory.g3', new Error());
    

Only, when passing the third parameter as new Error() we are able to see the stack with function and line numbers!

At 2, the function can also handle error thrown by the engine as well.

Of course, the real question is if we really need it and when; there are cases (99% in my opinion) where a graceful return of false is enough and leave only some critical points to be shown with the thrown of an error.

Example: http://jsfiddle.net/centurianii/m2sQ3/1/

Solution 13 - Javascript

console.log(new Error);

It will show you the whole track.

Solution 14 - Javascript

To determine which line something is on you have to search all the code for the code that occupies the particular line of interest and count the "\n" characters from the top to this of interest and add 1.

I am actually doing this very thing in an application I am writing. It is a best practices validator for HTML and is still heavily under development, but the error output process that you would be interested in is complete.

http://mailmarkup.org/htmlint/htmlint.html

Solution 15 - Javascript

It was easier in the past, but at this time with browser updates:

This is the safe Multi Browser Solution

<!DOCTYPE html>
<html lang="en">
<head>
    <script>
        var lastErr;
        function errHand(e) {
            lastErr = e;
            switch (e.target.nodeName) {
                case 'SCRIPT':
                    alert('script not found: ' + e.srcElement.src);
                    break;
                case 'LINK':
                    alert('css not found: ' + e.srcElement.href);
            }
            return false;
        }
        window.onerror = function (msg, url, lineNo, columnNo, error) {
            alert(msg + ' - ' + url + ' - ' + lineNo + ' - ' + columnNo);
            return false;
        }
    </script>
    <script src="http://22.com/k.js" onerror="errHand(event)"></script>
    <link rel="stylesheet" href="http://22.com/k.css" onerror="errHand(event)" type="text/css" />
</head>
<body>
    <script>
        not_exist_function();
    </script>
</body>
</html>
  1. Dont try to override or read console auto generated error logs by browser, Not work at this time but in the past it was happened
  2. For control loading each external linked css/js/etc use onerror event property innertag
  3. For control inline/loaded scripts use window.onerror
  4. Place error handle functions in the top of your html code
  5. To develop this code for other special tags like "include" set onerror inline event like step 2 and after fire error use console.log(lastErr) to see error object fields
  6. If you have an error in source of attached js file, then window.onerror fetch the complete log just when the js have same origin host with the main html file, if you test this situation on local with no host then the logs not be complete because of the local-no-host environment not known as same origin
  7. For send Request error handling like Ajax/Websocket its better use their built-in error handle functions

For NodeJS - Global Error Handling Solution

process.on('uncaughtException', function (err) {
	console.error('uncaughtException:\n' + err.stack + '\n');
})

This is very useful, Because it will show up you errors that exist but dont break your main program process.

Solution 16 - Javascript

If you need something that is very complete and accurate, for v8 (meaning NodeJS and Chrome) there is the stack-trace package, which worked for me:

https://www.npmjs.com/package/stack-trace

This has several advantages: being able to produce deep stack-traces, being able to traverse async calls, and providing the full URL of scripts at every stack-frame.

You can find more information about the v8 stack-track API here.

If you need something that works in more browsers, there is this package:

https://www.npmjs.com/package/stacktrace-js

This library parses the formatted stack-trace strings you normally see in the devtools console, which means it only has access to information that actually appears in a formatted stack-track - unlike the v8 API, you can't get (among other things) the full URL of the script in a stack-frame.

Note that parsing a formatted stack-trace is a somewhat fragile approach, as this formatting could change in the browsers, which would break your app.

As far as I know, there is no safer bet for something cross-browser - if you need something fast, accurate and complete that works in all browsers, you're pretty much out of luck.

Solution 17 - Javascript

Answers are simple. No and No (No).

By the time javascript is running the concept of source files/urls from which the come is gone.

There is also no way to determine a line number because again by the time of execution the notion of code "lines" is no longer meaningful in Javascript.

Specific implementations may provide API hooks to allow priviledged code access to such details for the purpose of debugging but these APIs are not exposed to ordinary standard Javascript code.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTalView Question on Stackoverflow
Solution 1 - JavascriptNathan LandisView Answer on Stackoverflow
Solution 2 - JavascriptEli GreyView Answer on Stackoverflow
Solution 3 - JavascriptRyanView Answer on Stackoverflow
Solution 4 - JavascriptJapheth Ongeri - inkalimevaView Answer on Stackoverflow
Solution 5 - JavascriptkangaxView Answer on Stackoverflow
Solution 6 - Javascriptrusu bogdanView Answer on Stackoverflow
Solution 7 - JavascriptGabriel FurstenheimView Answer on Stackoverflow
Solution 8 - JavascriptSinan TaifourView Answer on Stackoverflow
Solution 9 - JavascriptDilshan LiyanageView Answer on Stackoverflow
Solution 10 - JavascriptpasxView Answer on Stackoverflow
Solution 11 - JavascriptNoampzView Answer on Stackoverflow
Solution 12 - JavascriptcenturianView Answer on Stackoverflow
Solution 13 - JavascriptRatajSView Answer on Stackoverflow
Solution 14 - Javascriptaustin cheneyView Answer on Stackoverflow
Solution 15 - JavascriptEyni KaveView Answer on Stackoverflow
Solution 16 - Javascriptmindplay.dkView Answer on Stackoverflow
Solution 17 - JavascriptAnthonyWJonesView Answer on Stackoverflow