Matthew Murdoch
Matthew Murdoch

Reputation: 31493

How can I determine the current line number in JavaScript?

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

Upvotes: 134

Views: 96292

Answers (11)

Mark Bolusmjak
Mark Bolusmjak

Reputation: 24419

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.


UPDATE:

If you are debugging on browser you can see current line of running console.log() on right side of window under console section.

Current line of code running in browser

Upvotes: 87

DEV Tiago França
DEV Tiago França

Reputation: 1726

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'))
*/

Upvotes: 0

bmacnaughton
bmacnaughton

Reputation: 5318

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.

Upvotes: 2

Pawel
Pawel

Reputation: 18272

const line = new Error().stack.match(/(:[\d]+)/)[0].replace(':','')
console.log(line)

Upvotes: 2

Dave Burton
Dave Burton

Reputation: 3050

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.

Upvotes: -3

baligena
baligena

Reputation: 1302

You can use:

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

test();

Upvotes: 63

crishushu
crishushu

Reputation: 565

Inject the following snippet to your code:

console.debug("line:", /\(file:[\w\d/.-]+:([\d]+)/.exec(new Error().stack)[1]);

Upvotes: 3

scunliffe
scunliffe

Reputation: 63676

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)

Upvotes: 1

Viree
Viree

Reputation: 327

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

Upvotes: -1

jwatt
jwatt

Reputation: 870

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];
}

Upvotes: 36

Mikhail Nasyrov
Mikhail Nasyrov

Reputation: 898

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

Upvotes: 5

Related Questions