Rethrow callback errors as fatal Node.js errors

Instead of rethrowing the JavaScript error emitted from a callback function, we should instead pass it to `node::FatalException`.

Callbacks are employed when there is no other JavaScript frame on the stack prior so rethrowing the JS error as a C++ exception is not going to propagate the error back to JavaScript. `node::FatalException` will raise the `uncaughtError` event on the `process` object , print the error and stacktrace, and alert the debugger is there is one attached. This would make our async callbacks behave consistently with Node’s own async callbacks such as `setTimeout` when encountering an error.
This commit is contained in:
Yavor Georgiev 2017-07-11 13:17:41 +02:00
parent e0facc77ff
commit fe756bdc86
No known key found for this signature in database
GPG Key ID: 83FC145DA0CCA9C3
2 changed files with 16 additions and 3 deletions

View File

@ -1,3 +1,16 @@
vNext Release notes (TBD)
=============================================================
### Breaking changes
* None
### Enhancements
* None
### Bug fixes
* Fix crash on Node.js when a listener callback throws an error.
The error will now be forwarded to Node's fatal error handling facilities. This means better error reporting,
the ability to debug such errors in a Node.js debugger, and proper invocation of the `uncaughtError` event on the `process` object.
1.9.0 Release notes (2017-7-10)
=============================================================
### Breaking changes

View File

@ -38,13 +38,13 @@ inline v8::Local<v8::Value> node::Function::call(v8::Isolate* isolate, const v8:
template<>
inline v8::Local<v8::Value> node::Function::callback(v8::Isolate* isolate, const v8::Local<v8::Function> &function, const v8::Local<v8::Object> &this_object, size_t argc, const v8::Local<v8::Value> arguments[]) {
Nan::TryCatch trycatch;
v8::TryCatch trycatch(isolate);
auto recv = this_object.IsEmpty() ? isolate->GetCurrentContext()->Global() : this_object;
auto result = Nan::MakeCallback(recv, function, (int)argc, const_cast<v8::Local<v8::Value>*>(arguments));
auto result = ::node::MakeCallback(isolate, recv, function, (int)argc, const_cast<v8::Local<v8::Value>*>(arguments));
if (trycatch.HasCaught()) {
throw node::Exception(isolate, trycatch.Exception());
::node::FatalException(isolate, trycatch);
}
return result;
}