Conditional support for C++ exceptions#52
Conversation
Enable using the N-API C++ wrapper classes with or without C++ exceptions. See the updated `Napi::Error` class documentation for an overview of the developer experience. - Add a `NAPI_CPP_EXCEPTIONS` preprocessor symbol that is defined when C++ exceptions are enabled. - Add `Env::GetAndClearPendingException()` method. - Add `Value::IsEmpty()` method. - Update documentation on Error class to provide parallel explanation and examples for error-handling without C++ exceptions. - Update README to mention optional C++ exception support. - Define a `NAPI_THROW_IF_FAILED()` macro that throws either a C++ or JS exception depending on whether `NAPI_CPP_EXCEPTIONS` is defined. - Define a `details::WrapCallback()` helper function that catches C++ exceptions thrown from callbacks, only if `NAPI_CPP_EXCEPTIONS` is defined. - Update implementation of all methods to use `NAPI_THROW_IF_FAILED()` and `details::WrapCallback()` as appropriate. - Fix a bug in `Error::New()` when there was a pending exception but some different error status was reported by the last error info. - Update `test/binding.gyp` to build two separate modules, with and without C++ exceptions enabled. - Update test JS code to run the same tests against both modules. - Update test C++ code to throw JS exceptions (to be compatible with both modes). - Add some additional test cases to verify expected exceptions are observed from JS regardless of whether C++ exceptions are enabled or not. - Change CI config to ignore failures on nightly builds.
|
There are two motivations for this change:
|
addaleax
left a comment
There was a problem hiding this comment.
Just skimmed over the test changes, but this basically LGTM.
| return Message().c_str(); | ||
| } | ||
|
|
||
| #endif // NAPI_CPP_EXCEPTIONS |
There was a problem hiding this comment.
Why doesn’t this work if NAPI_CPP_EXCEPTIONS is not set?
There was a problem hiding this comment.
It would work. But when NAPI_CPP_EXCEPTIONS is not set, the Error class does not inherit from std::exception. In that case, it didn't seem to make sense to have a what() method that is otherwise inconsistent with the method naming style, and just a duplicate of Message().
napi.h
Outdated
| #endif | ||
| #endif | ||
|
|
||
| #ifdef NAPI_CPP_EXCEPTIONS |
There was a problem hiding this comment.
Are you sure this code isn’t kept best as it is? It’s not like noexcept will be incorrect if NAPI_CPP_EXCEPTIONS isn’t set, right?
There was a problem hiding this comment.
I wasn't sure whether the noexcept keyword would be allowed when exceptions are disabled. But it probably would be fine. I can test that in the CI.
There was a problem hiding this comment.
I pushed a commit that reverted this change.
| "test": "node test" | ||
| }, | ||
| "version": "0.3.1" | ||
| "version": "0.3.2" |
There was a problem hiding this comment.
Are we counting minors at this point? Because this certainly is one :)
There was a problem hiding this comment.
My understanding is that the usual practice for 0.x.y versions is the x indicates breaking changes and the y non-breaking changes. That is what node-semver assumes.
mhdawson
left a comment
There was a problem hiding this comment.
LGTM. I definitely agree that being able to not use exceptions is a good thing to support. From what I've seen its relatively common to avoid using C++ exceptions.
Enable using the N-API C++ wrapper classes with or without C++ exceptions. See the updated
Napi::Errorclass documentation for an overview of the developer experience.NAPI_CPP_EXCEPTIONSpreprocessor symbol that is defined when C++ exceptions are enabled.Env::GetAndClearPendingException()method.Value::IsEmpty()method.Errorclass to provide parallel explanation and examples for error-handling without C++ exceptions.NAPI_THROW_IF_FAILED()macro that throws either a C++ or JS exception depending on whetherNAPI_CPP_EXCEPTIONSis defined.details::WrapCallback()helper function that catches C++ exceptions thrown from callbacks, only ifNAPI_CPP_EXCEPTIONSis defined.NAPI_THROW_IF_FAILED()anddetails::WrapCallback()as appropriate.Error::New()when there was a pending exception but some different error status was reported by the last error info.test/binding.gypto build two separate modules, with and without C++ exceptions enabled.