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

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?

Answers:

Answer

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.

Answer

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 [[email protected]://me.com/helper.js:362:9]

See https://stackoverflow.com/a/27074218/ and also A proper wrapper for console.log with correct line number?

Answer

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.

Answer

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.

Answer

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 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

Answer

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);
}
Answer

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

Answer

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.

Answer

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);
}
Answer

My contribution to custom errors in JavaScript:

  1. First, I agree with this @B T guy at Inheriting from the Error object - where is the message property?, 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/

Answer

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);
    }
}
Answer
console.log(new Error);

It will show you the whole track.

Answer

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

Answer

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.

Answer

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);

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us Javascript

©2020 All rights reserved.