Reputation: 3352
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:
SyntaxError
or something else. instaceof
doesn't work (update - I can use e.name === "SyntaxError"
).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
).
Upvotes: 14
Views: 11674
Reputation: 163
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)
Upvotes: 0
Reputation: 2043
use 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
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)
Upvotes: 4
Reputation: 17048
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.
Upvotes: 0
Reputation: 56547
1) Use if (e.name === "SyntaxError")
.
2) All data associated with the error is kept in e.stack
.
Upvotes: 3