views:

2166

answers:

7

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?

A: 

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.

AnthonyWJones
In firefox the exceptions include such information... would it be possible in firefox at least?
Zoidberg
When you launch MS Script debugger and put some breakpoint, you see in call stack where exactly you came from.This is because of specialized hooks?
Tal
A: 

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

the particular line of interest can be many...If I have same method called several times from another method, how can I know (in that other method) where did the call arrive from?
Tal
You are not going to be able to analyze JavaScript interpretation at execution time from outside the interpreter. You could write a program to trace the execution path in your program, but it would be that program that is executing and not the code that you wish to analyze. This is typically a complicated task that is performed manually with the help of tools. If you really want to see what is happening in your code as it executes then have it write meta-data to the screen that tells you want decisions are executing which other parts.
+2  A: 

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);
}
Sinan Taifour
Thanks,I would like to this in production for support reasons.I have found some code that enables you to see the call stack of all flow until the method, but it doesnt have the line numbers where methods were called.I guess to easy solution for that?
Tal
+1  A: 

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.

kangax
Thanks,it seems a bit problematic to add this code in the application I need. (some js tracing framework)Do you know any other method which is not deprecated that I can use?
Tal
You should be able to inspect error object without relying on deprecated `callee.caller`.
kangax
You don't need to throw the Error. You just use (new Error).lineNumber to access the current line number in a script.
Eli Grey
@Elijah That's what I see in FF3. WebKit, on the other hand, populates `line` only when error is thrown.
kangax
What is the substitue for callee.caller ? If I need to get the function name?
Tal
You can use `callee.caller`, as long as you account for it being non-existent in some clients (due to its non-standard nature). Using function decompilation for debugging purposes is OK, but building actual application on top of it (and without fallback for clients that lack it) is not.
kangax
Is it supported for IE/Firefox/Safari ? do you know any other standard method for fetching the caller function name?
Tal
+3  A: 

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.

Eli Grey
Hi, Thanks for that addon.do you know if its possible to get line number from previous call ?Lets say method A calls B , and now in B I would like to know in what line under A the call was made?
Tal
+1  A: 

Yes. Here's a cross-browser function that makes use of each browsers' proprietary methods:

http://github.com/emwendelin/javascript-stacktrace

scotts
A: 

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