Open In App

How to get JavaScript stack trace when throw an exception ?

Improve
Improve
Like Article
Like
Save
Share
Report

The stack trace is a stable method to identify the error that comes into the program when the function of that program is called. It helps programmers to check where the particular error/exception comes and what is the reason behind it. Depending upon the time trace data is collected, the file size for these traces can be huge. We have to find a way to get a JavaScript stack trace when throwing an error/exception.

The stack trace is a report of the active stack frames at a particular point in time during the execution of a program. When the program is running, memory is often dynamically allocated in the stack as well as the heap. The stack is more active as compared to heap because it usually a continuous region of memory allocating local context for each executing function. Stack also refers to programming construct so this stack is referred to as a program’s runtime stack. Once a block of memory has been allocated on the stack. It cannot be easily removed as there can be other blocks of memory that were allocated before it. Every time when the function is called in the program a block of memory is allocated on the top of the runtime stack called the activation record. Programmers commonly use stack tracing during interactive and debugging. End-users may see stack trace displayed as part of an error message, which the users can report to the programmers.

Stack is a type of data structure where data can be store in the form of last in first out (LIFO). It means the stack is a type of storage and when a group of data comes inside the stack, it stores one by one in such manner where last data does remove first and the first data does remove in last. The way any group of datastore and remove from the stack can be understood by stack trace.
There are the following methods by which we can get a stack trace for JavaScript when throwing an exception.

  • console.trace
  • Error Object
  • caller Object
  • Using console.trace: The console object also has a method called console.trace() method, which gives you the trace on the console. Every time when it is called stack trace generate for the function. We can understand this with the help of this example.

    • Program:




      // Sum function
      function sum(a, b) {
          console.trace('sum called with ', a, 'and', b);
          return a+b;
      }
        
      // Calculation function 
      function calc() {
          return sum(8, 11) + sum(9, 14);
      }
        
      // Start function
      function start() {
          var a = sum(2, 3);
          var b = calc();
      }
         
      // Calling start function 
      start();

      
      

    • Output:
      /usr/bin/node stacktrace.js
      Trace: add called with  2 and 3
          at sum (/home/dev/Documents/stacktrace.js:2:13)
          at start (/home/dev/Documents/stacktrace.js:11:13)
          at Object. (/home/dev/Documents/stacktrace.js:16:1)
          at Module._compile (internal/modules/cjs/loader.js:959:30)
          at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10)
          at Module.load (internal/modules/cjs/loader.js:815:32)
          at Function.Module._load (internal/modules/cjs/loader.js:727:14)
          at Function.Module.runMain (internal/modules/cjs/loader.js:1047:10)
          at internal/main/run_main_module.js:17:11
      Trace: add called with  8 and 11
          at sum (/home/dev/Documents/stacktrace.js:2:13)
          at calc (/home/dev/Documents/stacktrace.js:7:12)
          at start (/home/dev/Documents/stacktrace.js:12:13)
          at Object. (/home/dev/Documents/stacktrace.js:16:1)
          at Module._compile (internal/modules/cjs/loader.js:959:30)
          at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10)
          at Module.load (internal/modules/cjs/loader.js:815:32)
          at Function.Module._load (internal/modules/cjs/loader.js:727:14)
          at Function.Module.runMain (internal/modules/cjs/loader.js:1047:10)
          at internal/main/run_main_module.js:17:11
      Trace: add called with  9 and 14
          at sum (/home/dev/Documents/stacktrace.js:2:13)
          at calc (/home/dev/Documents/stacktrace.js:7:25)
          at start (/home/dev/Documents/stacktrace.js:12:13)
          at Object. (/home/dev/Documents/stacktrace.js:16:1)
          at Module._compile (internal/modules/cjs/loader.js:959:30)
          at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10)
          at Module.load (internal/modules/cjs/loader.js:815:32)
          at Function.Module._load (internal/modules/cjs/loader.js:727:14)
          at Function.Module.runMain (internal/modules/cjs/loader.js:1047:10)
          at internal/main/run_main_module.js:17:11
      

    Using Error Object: We can create an Error object and return stack attribute. A non-standard stack property of Error object gives you the stack trace when that particular function was called from which line and file, and with what arguments. The stack string proceeds from the most recent calls to earlier ones.

  • Program:




    // Sum function
    function sum(a, b) {
        console.log(new Error().stack);
        return a+b;
    }
      
    // Calculation function 
    function calc() {
        return sum(8, 11) + sum(9, 14);
    }
      
    // Start function 
    function start() {
        var a = sum(2, 3);
        var b = calc();
    }
       
    // Calling start function 
    start();

    
    

  • Output:
    /usr/bin/node trace.js
    Error
        at sum (/home/dev/Documents/trace.js:2:17)
        at start (/home/dev/Documents/trace.js:11:13)
        at Object. (/home/dev/Documents/trace.js:16:1)
        at Module._compile (internal/modules/cjs/loader.js:959:30)
        at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10)
        at Module.load (internal/modules/cjs/loader.js:815:32)
        at Function.Module._load (internal/modules/cjs/loader.js:727:14)
        at Function.Module.runMain (internal/modules/cjs/loader.js:1047:10)
        at internal/main/run_main_module.js:17:11
    Error
        at sum (/home/dev/Documents/trace.js:2:17)
        at calc (/home/dev/Documents/trace.js:7:12)
        at start (/home/dev/Documents/trace.js:12:13)
        at Object. (/home/dev/Documents/trace.js:16:1)
        at Module._compile (internal/modules/cjs/loader.js:959:30)
        at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10)
        at Module.load (internal/modules/cjs/loader.js:815:32)
        at Function.Module._load (internal/modules/cjs/loader.js:727:14)
        at Function.Module.runMain (internal/modules/cjs/loader.js:1047:10)
        at internal/main/run_main_module.js:17:11
    Error
        at sum (/home/dev/Documents/trace.js:2:17)
        at calc (/home/dev/Documents/trace.js:7:25)
        at start (/home/dev/Documents/trace.js:12:13)
        at Object. (/home/dev/Documents/trace.js:16:1)
        at Module._compile (internal/modules/cjs/loader.js:959:30)
        at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10)
        at Module.load (internal/modules/cjs/loader.js:815:32)
        at Function.Module._load (internal/modules/cjs/loader.js:727:14)
        at Function.Module.runMain (internal/modules/cjs/loader.js:1047:10)
        at internal/main/run_main_module.js:17:11
    
  • Using caller object: We have implemented a function called stacktrace that will return a string representing the call history to the point where stacktrace() was called. Internally it uses another function called st2 that will be called recursively traversing the call-tree up till the point where we reach the main body of our JavaScript script. At the end of the declaration of stacktrace we call st2 with the arguments.callee.caller. arguments is a special object that belongs to the current function call and that contains a lot of information about the current call. The st2 function is then called recursively and it returns the stacktrace string so far.

    • Program:




      // Sum function
      function sum(a,b) {
         
          // Calling stacktrace function
          console.log(stacktrace()); 
          return a+b;
      }
         
      // Calculation function 
      function calc() {
          return sum(8, 11) + sum(9, 14);
      }
         
      // Start function 
      function start() {
          var a = sum(2, 3);
          var b = calc();
      }
          
      // Calling start function 
      start();
         
      // Stacktrace function 
      function stacktrace() {
        function st2(f) {
          var args = [];
          if (f) {
              for (var i = 0; i < f.arguments.length; i++) {
                  args.push(f.arguments[i]);
              }
              var function_name = f.toString().
              split('(')[0].substring(9);
              return st2(f.caller) + function_name + 
              '(' + args.join(', ') + ')' + "\n";
          } else {
              return "";
          }
        }
        return st2(arguments.callee.caller);
      }

      
      

    • Output:
      /usr/bin/node stackt.js
      ([object Object], function require(path) {
            return mod.require(path);
          }, [object Object], /home/dev/Documents/stackt.js, /home/dev/Documents)
      start()
      sum(2, 3)
      ([object Object], function require(path) {
            return mod.require(path);
          }, [object Object], /home/dev/Documents/stackt.js, /home/dev/Documents)
      start()
      calc()
      sum(8, 11)
      ([object Object], function require(path) {
            return mod.require(path);
          }, [object Object], /home/dev/Documents/stackt.js, /home/dev/Documents)
      start()
      calc()
      sum(9, 14)
      


    Last Updated : 02 Mar, 2020
    Like Article
    Save Article
    Previous
    Next
    Share your thoughts in the comments
    Similar Reads