-
-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
errors thrown from a vm aren't recognized as errors #1770
Comments
I think this is fixed in master, from #1758: https://github.com/mochajs/mocha/blob/master/lib/runner.js#L205-L207 try {
vm.runInNewContext('throw new TypeError()');
} catch (err) {
console.log(err instanceof Error || err && typeof err.message == 'string');
}
// => true |
@danielstjules OK. That "works", but checking the log, the intent was to solve cross-frame issues, not open it up to throwing plain-jane objects. I like var errorTag = '[object Error]';
var objectProto = Object.prototype;
var objToString = objectProto.toString;
function isError(value) {
return isObjectLike(value) && typeof value.message == 'string' && objToString.call(value) == errorTag;
} No |
But that wouldn't work with custom error objects cross-frame (or in the same context, depending on how it's used) var errorTag = '[object Error]';
var objectProto = Object.prototype;
var objToString = objectProto.toString;
function isError(value) {
return typeof value.message == 'string' && objToString.call(value) == errorTag;
}
function FooBarError(message) { this.message = message; }
FooBarError.prototype = new TypeError();
isError(new FooBarError('test'));
// => false |
@danielstjules No, it wouldn't; not like that, anyway. That isn't an |
there are comments in #1770 but let's keep the discussion here. |
How is it not an error instance any way you look at it? It's an error-like object? var utils = require('util');
var errorTag = '[object Error]';
var objectProto = Object.prototype;
var objToString = objectProto.toString;
function isError(value) {
return typeof value.message == 'string' && objToString.call(value) == errorTag;
}
function FooBarError(message) {
this.message = message;
}
util.inherits(FooBarError, TypeError);
isError(new FooBarError('test'));
// => false var utils = require('util');
var errorTag = '[object Error]';
var objectProto = Object.prototype;
var objToString = objectProto.toString;
function isError(value) {
return typeof value.message == 'string' && objToString.call(value) == errorTag;
}
function FooBarError(message) {
this.message = message;
}
util.inherits(FooBarError, Error);
isError(new FooBarError('test'));
// => false |
I think we're stuck just checking for the presence of |
@danielstjules I think maybe I haven't made my intent clear. Above, I wrote:
The code you wrote does not result in an At any rate, there's no good way to "subclass" If you're using ES6, you can of course |
(I'm unsure where the idea that throwing |
So, that's why I targeted the #1771 to v3.0.0--because currently, you can throw a function with a |
because new FooBarError('test') instanceof Error // false thus not an |
That's not true. It is an instance of Error, and it's a common practice for defining custom error objects. See below: var utils = require('util');
var errorTag = '[object Error]';
var objectProto = Object.prototype;
var objToString = objectProto.toString;
function isError(value) {
return typeof value.message == 'string' && objToString.call(value) == errorTag;
}
function FooBarError(message) {
this.message = message;
}
util.inherits(FooBarError, Error);
(new FooBarError('test') instanceof Error);
// true Tested with iojs v1.6.2 and node 0.12. |
@danielstjules my bad. I got like 3 hours of sleep, sorry. |
I would vehemently argue it's a poor one |
Even node src has example of this: I'm not sure how we can ignore custom errors defined in this way. |
No worries haha I know the feeling. |
I don't think inheriting the prototype from Error is odd at all. That's exactly how you should be able to define custom errors in JS. I agree that defining plain old objects with a message property alone is a terrible approach though. But for a catch-all solution, I think we're stuck with only checking for a message property. Which I understand def sucks lol |
I guess we're getting philosophical. You can do it, but look at the // THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
It's not "odd"--it's commonplace, as you said--it's just completely unnecessary. Find the usages of var assertionError = new Error();
assertionError.type = 'AssertionError';
throw assertionError; Then, look at those usages again and tell me where they couldn't simply compare |
(even in ES6, the value |
Fair enough. :) I agree that "sub-classing" Error doesn't get you much given how weak try/catch is in JS. As for AssertionError - that constructor seems over-complicated. Just inheriting the proto works in v8 for capturing the stack trace. SpiderMonkey doesn't seem to care for it though. function FooBarError(message) { this.message = message; }
FooBarError.prototype = new Error();
function test() {
throw new FooBarError('oh no!');
}
test(); |
As a result of the behavior shown in #1770 (comment) and #1770 (comment), do you agree that we'll have to resort to solely checking for a message property on the object? |
Yeah I guess. It depends how opinionated we want to get. As a testing framework we probably shouldn't be dictating how people write their code. My point stands that subclassing |
On the flip side though, I'm 99.9999% sure throwing a string has no use case and shouldn't be supported. 😄 |
Agreed! |
As you can read in the comments on commit 02d421b, it seems that if code under test uses
vm.runInNewContext()
and throws anError
:I think we can safeguard against this by duck-typing instead of an
instanceof
check.The text was updated successfully, but these errors were encountered: