I have some code that uses vm
module and runInNewContext
function and executes dynamically generated JavaScript code. Basically a safer option of eval
.
The code (variable code
) can possibly contain syntax errors, so I would like to catch them and print some useful information.
try {
vm.runInNewContext(code, sandbox, filename);
}
catch (e) {
if (e instanceof SyntaxError) { // always false
console.log(e.toString()); // "SyntaxError: Unexpected token ||" for example
console.log(e.line); // how to get the line number?
}
}
I'd like to print the number of the line with the syntax error, but I have two problems:
- I don't know how to recognize whether the exception is
SyntaxError
or something else.instaceof
doesn't work (update - I can usee.name === "SyntaxError"
). - Even if I was able to recognize it, how could I get the line number? Is it possible?
Thanks in advance.
Update: I can get some information from e.stack
- however, the topmost call in the stack trace is runInNewContext
(with its line number), but I still can't find the line number inside code
, which caused the exception (SyntaxError
).
I have some code that uses vm
module and runInNewContext
function and executes dynamically generated JavaScript code. Basically a safer option of eval
.
The code (variable code
) can possibly contain syntax errors, so I would like to catch them and print some useful information.
try {
vm.runInNewContext(code, sandbox, filename);
}
catch (e) {
if (e instanceof SyntaxError) { // always false
console.log(e.toString()); // "SyntaxError: Unexpected token ||" for example
console.log(e.line); // how to get the line number?
}
}
I'd like to print the number of the line with the syntax error, but I have two problems:
- I don't know how to recognize whether the exception is
SyntaxError
or something else.instaceof
doesn't work (update - I can usee.name === "SyntaxError"
). - Even if I was able to recognize it, how could I get the line number? Is it possible?
Thanks in advance.
Update: I can get some information from e.stack
- however, the topmost call in the stack trace is runInNewContext
(with its line number), but I still can't find the line number inside code
, which caused the exception (SyntaxError
).
- Unfortunately, the information you are looking for cannot currently be obtained from the SyntaxError object: code.google.com/p/v8/issues/detail?id=2589 – Will Commented Aug 14, 2014 at 21:24
4 Answers
Reset to default 4 +50use a try/catch
store the stack in a global variable
log the sandbox
var util = require('util');
var vm = require('vm');
var sandbox = {e:null};
var src = 'try{count += 1;}catch(err) {e=err.stack}';
vm.runInNewContext(src , sandbox, 'myfile.vm');
console.log(util.inspect(sandbox));
this will log:
{ e: 'ReferenceError: count is not defined\n at myfile.vm:1:13\n ...
now you can see that the error occurs at line 1, character 13 of myfile.vm this will still require you to place some try/cathc blocks at various places but at least you can get feedback now
EDIT:
Adding a method to detect Syntax errors from within your running code
var acorn = require('acorn');
var src = "try{\n"+
" {" +
" count += 1;\n"+
" }catch(err) {\n" +
" e=err.stack\n" +
"}";
var result = acorn.parse(src);
doing this will result in a thrown Exception with "SyntaxError: Unexpected token (3:4)" eg. line 3, character 4 is the unexpected token, (the extra { that shouldnt be there)
1) Use if (e.name === "SyntaxError")
.
2) All data associated with the error is kept in e.stack
.
Although a bit (very) old, you can use the stackedy
module, which can help you manipulate stack traces. It isn't the perfect solution though, as the line number displayed is the line number inside the function call, and not the line number in the source file.
In particular, look at the simple example:
index.js
var stackedy = require('stackedy');
var fs = require('fs');
var src = fs.readFileSync(__dirname + '/src.js');
var stack = stackedy(src, { filename : 'stax.js' }).run();
stack.on('error', function (err, c) {
stack.stop();
console.log('Error: ' + err);
var cur = c.current;
console.log(' in ' + cur.filename + ' at line ' + cur.start.line);
c.stack.forEach(function (s) {
console.log(' in ' + s.filename + ', '
+ s.functionName + '() at line ' + s.start.line
);
});
});
src.js
function f () { g() }
function g () { h() }
function h () { throw new SyntaxError('woops') }
f();
Output:
~/tmp ❯❯❯ node index.js
Error: SyntaxError: woops
in stax.js at line 2
in stax.js, h() at line 1
in stax.js, g() at line 0
in stax.js, f() at line 4
As noted in the comments, you can use err.name === 'SyntaxError'
to check for the error type.
For *nix:
if (err) console.log(err.stack.split('\n')[1]);
It will log second line of stacktrace, the point where the error occured.
Windows or mac can require other split symbol (depends on system line endings)