130

Does JavaScript have a mechanism for determining the line number of the currently executing statement (and if so, what is it)?

Jon Seigel
  • 12,251
  • 8
  • 58
  • 92
Matthew Murdoch
  • 30,874
  • 30
  • 96
  • 127
  • 1
    Possible duplicate of [How to get JavaScript caller function line number? How to get JavaScript caller source URL?](http://stackoverflow.com/questions/1340872/how-to-get-javascript-caller-function-line-number-how-to-get-javascript-caller) – Michael Freidgeim Apr 18 '16 at 23:58

11 Answers11

85

var thisline = new Error().lineNumber

If that doesn't work in whatever environment you're using, you can try:

var stack = new Error().stack

Then hunt through the stack for the line number.

Matthew Murdoch
  • 30,874
  • 30
  • 96
  • 127
Mark Bolusmjak
  • 23,606
  • 10
  • 74
  • 129
  • 3
    Will not work in IE, the `lineNumber` property doesn't exist on error objects. Neither does `stack` :-) – Andy E Feb 26 '10 at 17:11
  • 1
    there is a line number somewhere on IE. I know this because when my javascript throws an error is says it's on a line with a number greater than 100 million. – Malfist Feb 26 '10 at 17:17
  • i dont quite get the correct number, its 1350 when it should be 1250. – john-jones Jan 07 '14 at 09:45
  • 1
    Problem: if you're using PHP, the "source code" seen by javascript is not the original source code, so it has the wrong line numbers. (That's probably what's happening to Hermann.) Does anyone know how to make javascript see the original PHP source code line numbers? The solution probably involves some kind of "source map" generation, but I can't find how to do it. Surely this is a solved problem, right?? – Dave Burton Dec 21 '16 at 06:53
  • Note: sometimes the stack/line number is not available when the Error object is constructed, only when it's thrown, for example in Google Apps Script - in that case see [this answer](https://stackoverflow.com/a/27074218/5267751) for the solution. – user202729 Nov 02 '19 at 06:02
  • 1
    I think [.lineNumber](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/lineNumber) only works in Firefox – kurdtpage Feb 21 '20 at 01:06
58

You can use:

function test(){
    console.trace();
}

test();
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
baligena
  • 1,222
  • 12
  • 10
  • 2
    By far the simplest solution and it even works on MS Edge. – Danger Nov 10 '16 at 16:55
  • It provides the same number that the console from firefox as example. Which is not the line in your code but the execution line. – Mbotet Aug 03 '22 at 11:45
35

A bit more portable between different browsers and browser versions (should work in Firefox, Chrome and IE10+):

function ln() {
  var e = new Error();
  if (!e.stack) try {
    // IE requires the Error to actually be throw 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/);
  // We want our caller's frame. It's index into |stack| depends on the
  // browser and browser version, so we need to search for the second frame:
  var frameRE = /:(\d+):(?:\d+)[^\d]*$/;
  do {
    var frame = stack.shift();
  } while (!frameRE.exec(frame) && stack.length);
  return frameRE.exec(stack.shift())[1];
}
jwatt
  • 860
  • 10
  • 8
  • Thanks. I adapted your suggestion to this: http://stackoverflow.com/a/37081135/470749 – Ryan May 06 '16 at 20:46
  • 3
    If you adjust the regex, you can return both line and column numbers: `var frameRE = /:(\d+:\d+)[^\d]*$/;` which is much more useful, particularly when the JS is minified into one long line. – Quinn Comendant Mar 18 '17 at 07:36
  • Warning, doesn't work in ViolentMonkey scripts for Chrome - you'll get a bogus number, don't know why. – hanshenrik Feb 14 '19 at 11:50
  • maybe interesting hint. this works within a 0ad mod (version 0.0.26) – SL5net Aug 14 '23 at 16:32
5

You can try to parse a source of a function to seek some marks.
Here is a quick example (yes, it's messed a little).

function foo()  
{       
    alert(line(1));
    var a;
    var b;      
    alert(line(2));
}   
foo();

function line(mark)
{
    var token = 'line\\(' + mark + '\\)';       
    var m = line.caller.toString().match(
        new RegExp('(^(?!.*' + token + '))|(' + token + ')', 'gm')) || [];
    var i = 0;
    for (; i < m.length; i++) if (m[i]) break;
    return i + 1;
}
Matthew Murdoch
  • 30,874
  • 30
  • 96
  • 127
Mikhail Nasyrov
  • 900
  • 1
  • 8
  • 14
2

Inject the following snippet to your code:

console.debug("line:", /\(file:[\w\d/.-]+:([\d]+)/.exec(new Error().stack)[1]);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
crishushu
  • 435
  • 2
  • 4
  • 14
1

You can try:

window.onerror = handleError;
function handleError(err, url, line){
    alert(err + '\n on page: ' + url + '\n on line: ' + line);
}

Then throw an error where you want to know (not overly desired, but it might help you if you are debugging.

Note: window.onerror isn't defined/handled in WebKit or Opera (the last time I checked)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
scunliffe
  • 62,582
  • 25
  • 126
  • 161
  • 1
    Note that window.onerror doesn't work in webkit: https://bugs.webkit.org/show_bug.cgi?id=8519 – Annie Feb 26 '10 at 18:35
  • 1
    Interesting. You could even create a special function `throwAndResume(resumeFunction);` that would store resumeFunction, throw the error, and in your error handler log the details then call resumeFunction to continue your program. – Mark Bolusmjak Feb 26 '10 at 18:37
1
const line = new Error().stack.match(/(:[\d]+)/)[0].replace(':','')
console.log(line)
Pawel
  • 16,093
  • 5
  • 70
  • 73
1

If you're using node.js and you care about the cost of getting the line number (not likely the most important thing), then using v8's callsites is the best way I know of to get the line number.

The following code avoids the cost of converting the stack to text and extracts the callers (stack[1]) line number directly from the callsites object.

  'use strict';

  function thisLine() {
    let line;
    const _prepareStackTrace = Error.prepareStackTrace;
    Error.prepareStackTrace = (_, stack) => {
      line = stack[1].getLineNumber();
    };
    const e = new Error();
    e.stack;
    Error.prepareStackTrace = _prepareStackTrace;

    return line;
  }

  if (require.main === module) {
    console.log('this line is', thisLine());
  }

see https://v8.dev/docs/stack-trace-api for documentation.

bmacnaughton
  • 4,950
  • 3
  • 27
  • 36
0

Source: git @tiagofrancafernandes


var getPos = (toGet = null) => {
    let stack = String(new Error().stack);
    let calledFrom = String((stack.split(`\n`)).filter(item => item).at(-1));
    calledFrom = calledFrom.startsWith('@') ? calledFrom.slice(1) : calledFrom;

    let items = {
        stack: stack,
        calledFrom: calledFrom,
    }

    let lineCol = String(calledFrom).match(/(\:)([0-9]){1,}(:([0-9]).?)$/g)[0];
    lineCol = String(lineCol).split(':').filter(item => item)
    items['lineCol'] = lineCol.join(':');
    items['line'] = lineCol.length == 2 ? lineCol[0] : null;
    items['col'] = lineCol.length == 2 ? lineCol[1] : null;

    toGet = toGet ? String(toGet) : null;

    if (toGet && !Object.keys(items).includes(toGet)) {
        return null;
    }

    return items[`${toGet}`] ?? items;
}

var __LINE__ = () => getPos('line');

// Usage
/*
    console.log(getPos())
    console.log(__LINE__())
    console.log(getPos('lineCol'))
    console.log(getPos('line'))
    console.log(getPos('col'))
    console.log(getPos('calledFrom'))
    console.log(getPos('stack'))
*/
DEV Tiago França
  • 1,271
  • 9
  • 9
-1

Purely one can't get the line number out of Error.stack, because in Angular the line number is the line number of the compiled code. But one can get the info in which method the error was created. The class Logger in this code snippet add this piece of information to a new logbook entry.

https://stackblitz.com/edit/angular-logger?file=src/app/Logger/logger.ts

Viree
  • 317
  • 3
  • 3
-3

If your code is JavaScript + PHP, then the current PHP line number is available in JavaScript as a literal constant, because it's available in PHP as   <?= __LINE__ ?>

(That's assuming you have PHP short tags enabled, obviously.)

So, for example, in JavaScript you can say:

this_php_line_number = <?= __LINE__ ?>;

However, if you are not careful, the PHP line number might be different from the JavaScript line number, because PHP "eats" source lines before the browser ever sees them. So the problem becomes ensuring that your PHP and JavaScript line numbers are the same. If they're different it makes using the browser's JavaScript debugger a lot less pleasant.

You can ensure the line numbers are the same by including a PHP statement that writes the correct number of newlines needed to synchronize server-side (PHP) and browser-side (JavaScript) line numbers.

Here's what my code looks like:

<!DOCTYPE html>
<html lang="en">
<!-- Copyright 2016, 2017, me and my web site -->
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1, user-scalable=yes">

<?php

...lots of PHP stuff here, including all PHP function definitions ...

echo str_repeat("\n",__LINE__-6); # Synchronize PHP and JavaScript line numbers
?>
<!-- *** this is line <?php echo __LINE__ . ' of ' . basename(__FILE__); ?> *** -->

  <title>My web page title</title>

...lots of HTML and JavaScript stuff here...

</body>
</html>
<!-- *** this is line <?php echo __LINE__ . ' of ' . basename(__FILE__); ?> *** -->

The key is this PHP statement:

echo str_repeat("\n",__LINE__-6);

That spits out enough newlines to make the line number seen by JavaScript be the same as the PHP line number. All the PHP function definitions, etc. are at the top, ahead of that line.

After that line, I restrict my use of PHP to code that doesn't change the line numbers.

The "-6" accounts for the fact that my PHP code starts on line 8. If you start your PHP code earlier, you'll reduce that number. Some people put their PHP right at the very top, even ahead of the DOCTYPE.

(The meta viewport line disables Android Chrome "font boosting" per this Stack Overflow Q&A: Chrome on Android resizes font. Consider it boilerplate, which every web page needs.)

The following line is just for verifying that I haven't made a mistake. Viewed in the browser's debugger, or by right-click / save-web-page, it becomes an HTML comment which shows the correct source file name and line number:

<!-- *** this is line <?php echo __LINE__ . ' of ' . basename(__FILE__); ?> *** -->

becomes:

<!-- *** this is line 1234 of my_file.php *** -->

Now, wherever I see a line number, whether it's in an error message or in the JavaScript debugger, it's correct. PHP line numbers and JavaScript line numbers are always consistent and identical.

Dave Burton
  • 2,960
  • 29
  • 19
  • 1
    This wasn't a bad answer. And its valid considering what was asked. The question doesn't specify any details about the environment. – JΛYDΞV Feb 12 '22 at 07:01