Repository navigation
displayErrors option of the vm module seems not to work well #4835
Description
Activity
I had a look and I can confirm what you're describing. What happens is this:
- The SyntaxError that V8 creates doesn't point to the source location of the invalid syntax.
- What node.js does is attach a hidden property to the exception object that contains the necessary information.
Example:
var vm = require('vm');
var util = require('internal/util'); // requires --expose_internals
try {
new vm.Script('?', {filename: 'x.js', displayErrors: true});
} catch (e) {
console.error('arrowMessage:', util.getHiddenValue(e, 'node:arrowMessage'));
}Which prints:
$ node --expose_internals t.js
arrowMessage: x.js:1
?
^
If you let the exception bubble up to node's top-level exception handler, it will include the arrowMessage string in the output. With that in mind:
Is this behavior of displayErrors: true is correct?
It's as correct as it can be given the circumstances but it's at odds with the documentation. We could either restore the old behavior where node prints the message immediately on syntax error or we could update the documentation.
If we update the documentation, there probably needs to be an official way to get the hidden property, which is awkward.
Are there some ways to know where the error occurred in the script for the last case?
Nothing official at the moment, no, except for letting the exception bubble up. (EDIT: Which doesn't work for promises, of course.)
/cc @nodejs/documentation @cjihrig
EDIT: Which doesn't work for promises, of course.
Why?
The exception won't bubble up all the way, at least not by default.
You could add a process.on('unhandledRejection', err => { throw err }) and drop any .catch(...) handlers from your promises but that's not very elegant and not always workable.
Well, if you have .catch handlers that's the same as not letting exceptions bubble (by not having a synchronous catch(e) {). Adding on('unahndledRejection', err => { throw err; }) is something you probably want to do when using vm.
I get your point though - thanks.
My guess is that this behavior goes back to f1de13b, which fixes nodejs/node-v0.x-archive#6920.
@bnoordhuis I'm happy to work on this if we decide how we want to fix it.
@bnoordhuis Thank you for your answer. I see the point.
I will try to use process.on('unhandledRejection', ...) for this case for now.
@cjihrig The best I can come up with is to intercept the SyntaxError and add the extra information to the .message property instead of a hidden property. That's pretty yuck, though.
I'm stuck for the behavior of the
displayErrorsoption of the vm module.First I wrote the code like below and this works well.
When
displayErrorsare set totrue, however, the behavior seems to be not consistent with the document "print any errors to stderr before throwing an exception" since this code does not output anything to stderr.Next, I tried to catch the error and get the information where the error has occurred but I couldn't.
I also re-threw the error and found that the information about the script is discarded when the error is re-thrown if
displayErrors: false, while thedisplayErrors: trueversion retains it.The problem is more serious when combined with
Promise.This code actually does not print anything since the error is swallowed by the Promise, and I have no idea to know where the error occurred in the script.
Note that all the codes throw syntax errors, but the results are almost same for throwing runtime errors.
Taken together, it seems that
displayErrors: truedoes only make the error retain the information where it occurred and does not letnew vm.Script(andrunInContextor something) print anything.In addition, there seems to be no way to know where the error occurred if it is in Promise.
Here I have two questions.
displayErrors: trueis correct?The version of Node.js is v5.5.0.
Thanks.