Search code examples
javascriptangularjsevalline-numbers

Keep track of current line number in eval


I'm running some code using eval that will change a $scope object called variables.

Here's my watcher:

$scope.$watch(function () {
  return $scope.variables;
}, function (variables) {
  console.log('changed!');
}, true);

Here's the code I'm running (this is just example code; it could be any arbitrary code I can't anticipate):

eval('$scope.variables.foo = "bar";\n$scope.variables.bar = "foo";');

In this example, the watcher is triggered twice, and gives me the new values. So far so good. What's missing is the information that the first trigger was caused by the first line in the eval call, and the second one on the second line (note the \n in the eval call denoting a new line number).

Is there a way to achieve this using Angular or just plain JavaScript? I have looked into tools like https://github.com/stacktracejs/stacktrace.js but they don't seem to do the trick.

Just to be clear, I'm not looking for line numbers for when errors are thrown. I need to keep track of which line the eval statement is currently on when the watcher's callback is triggered, so that I can associate that line number with the change that has been made to the object I'm watching.


Solution

  • You could split your input string by \n and insert new statements keeping track of the line numbers

    var s = '$scope.variables.foo = "bar";\n$scope.variables.bar = "foo";\n'
    var arr = s.split(/\n/);
    var out = [];
    for (var i = 0; i < arr.length; i++) {
      out.push("console.log('current line: " + i + "');");
      out.push(arr[i]);
    }
    out = out.join('\n');
    console.log(out);
    document.write('<pre>' + out + '</pre>');

    You can replace the console.log() by what you want, a call to another function, a debug call...