-
Notifications
You must be signed in to change notification settings - Fork 464
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
Documentation for error handling #259
Changes from 4 commits
825440a
d11cd21
178dd33
794ee4d
844b651
83fc181
ea2f927
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,101 @@ | ||
# Error | ||
|
||
You are reading a draft of the next documentation and it's in continuos update so | ||
if you don't find what you need please refer to: | ||
[C++ wrapper classes for the ABI-stable C APIs for Node.js](https://nodejs.github.io/node-addon-api/) | ||
The **Error** class is a representation of the JavaScript Error object that is thrown | ||
when runtime errors occur. The Error object can also be used as a base object for | ||
user defined exceptions. | ||
|
||
The **Error** class is a persistent reference to a JavaScript error object and | ||
inherits its behaviour from ObjectReference class (for more info see: [ObjectReference](object_reference.md) | ||
section). | ||
|
||
If C++ exceptions are enabled (for more info see: [Setup](setup.md) section), | ||
then the **Error** class extends ```std::exception``` and enables integrated | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For single line code I think you can just use a single backtick. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will provide to remove where necessary. |
||
error-handling for C++ exceptions and JavaScript exceptions. | ||
|
||
For more details about error handling refer to the section titled [Error handling](error_handling.md). | ||
|
||
## Methods | ||
|
||
### New | ||
|
||
Creates a new instance empty of ```Error``` object for the specified environment. | ||
|
||
```cpp | ||
Error::New(Napi:Env env); | ||
``` | ||
|
||
- ```[in] Env```: The environment in which to construct the Error object. | ||
|
||
Returns an instance of ```Error``` object. | ||
|
||
### New | ||
|
||
Creates a new instance of ```Error``` object | ||
|
||
```cpp | ||
Error::New(Napi:Env env, const char* message); | ||
``` | ||
|
||
- ```[in] Env```: The environment in which to construct the Error object. | ||
- ```[in] message```: Null-terminated strings to be used as the message for the Error. | ||
|
||
Returns an instance of ```Error``` object. | ||
|
||
### New | ||
|
||
Creates a new instance of ```Error``` object | ||
|
||
```cpp | ||
Error::New(Napi:Env env, const std::string& message); | ||
``` | ||
|
||
- `[in] Env`: The environment in which to construct the Error object. | ||
- `[in] message`: Reference string to be used as the message for the Error. | ||
|
||
Returns an instance of ```Error``` object. | ||
|
||
### Constructor | ||
|
||
Creates a new empty instance of ```Error``` | ||
|
||
```cpp | ||
Error(); | ||
``` | ||
|
||
### Constructor | ||
|
||
Initializes a ```Error``` instance from an existing ```Error``` object. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've been wresting with how to describe this, maybe "from an existing JavaScript |
||
|
||
```cpp | ||
TypeError(napi_env env, napi_value value); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is a typo, should be Error instead of TypeError. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Believe this should Error not TypeError |
||
``` | ||
|
||
- ```[in] Env```: The environment in which to construct the Error object. | ||
- ```[in] value```: The ```Error``` reference to wrap. | ||
|
||
Returns an instance of ```Error``` object. | ||
|
||
### Message | ||
|
||
```cpp | ||
std::string& Message() const NAPI_NOEXCEPT; | ||
``` | ||
|
||
Returns the reference to string that represent the message of the error. | ||
|
||
### ThrowAsJavaScriptException | ||
|
||
```cpp | ||
void ThrowAsJavaScriptException() const; | ||
``` | ||
|
||
Throw the error as JavaScript exception. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: I would move this above where the description normally goes and then update it to say "Throws" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 |
||
|
||
### what | ||
|
||
```cpp | ||
const char* what() const NAPI_NOEXCEPT override; | ||
``` | ||
|
||
Returns a pointer to a null-terminated string that is used to identify the | ||
exception. This method can be used only if the eceptions mechanis is enabled. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: "exception mechanism" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this file is also missing
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,138 @@ | ||
# Error handling | ||
|
||
You are reading a draft of the next documentation and it's in continuos update so | ||
if you don't find what you need please refer to: | ||
[C++ wrapper classes for the ABI-stable C APIs for Node.js](https://nodejs.github.io/node-addon-api/) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is our feeling about this? I've seen some of the documentation updates leave it, but maybe it's the right time to start removing these designations. /cc @mhdawson There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That was my thought, once we fill in the section lets remove the comment. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replied above at this point I'd say take it out. |
||
The error handling represents one of the most important thing on implementing a | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: "Error handling represents one of the most important considerations when implementing a Node.js native add-on." There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 |
||
Node.js native add-on. When an error occurs in your C++ code you have to handle | ||
and dispatch it correctly. **N-API** uses return values and JavaScript exceptions | ||
for error handling. You can choice one method or other based on your preferences | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: "You can choose return values or exception handling based on the mechanism that works best for your add-on." |
||
or on the C/C++, library that you are integrating. | ||
|
||
The **Error** is a persistent reference (for more info see: [Object reference](object_reference.md) | ||
section) to a JavaScript error object. Use of this class depends somewhat on | ||
whether C++ exceptions are enabled at compile time. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: avoid "somewhat", we want to be as descriptive as possible. If there are more nuances we should try to enumerate them. |
||
|
||
The following sections explain the approach for each case: | ||
|
||
- [Handling Errors With C++ Exceptions](#exceptions) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: I don't think this extra newline is necessary here |
||
- [Handling Errors Without C++ Exceptions](#noexceptions) | ||
|
||
<a name="exceptions"></a> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ? wondering why there is html here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is to create an anchor with a friendly name that's not affected by changes to the name of the header. The same approach is used in the official CHANGELOG There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok, just have not see it in other docs. |
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: extra newline There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm using markdownlint and it reports
but if you want I can remove the extra space. Maybe in general we need to have a standard to follow. |
||
## Handling Errors With C++ Exceptions | ||
|
||
If C++ exceptions are enabled (for more info see: [Setup](setup.md) section), | ||
then the **Error** class extends ```std::exception``` and enables integrated | ||
error-handling for C++ exceptions and JavaScript exceptions. | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If C++ exceptions are enabled then exceptions are converted and handled as C++ exceptions while in native code and as JavaScript exceptions in JavaScript code. What this means is that: and then make the following bullet points: |
||
If a N-API call fails without executing any JavaScript code (for example due to | ||
an invalid argument), then the N-API wrapper automatically converts and throws | ||
the error as a C++ exception of type **Error**. | ||
|
||
If a JavaScript function called by C++ code via N-API throws a JavaScript | ||
exception, then the N-API wrapper automatically converts and throws it as a C++ | ||
exception of type **Error**. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. on return from the JavaScript code to the native method. |
||
|
||
If a C++ exception of type **Error** escapes from a N-API C++ callback, then | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On return from a native method, N-API will automatically convert a pending C++ exception to a JavaScript exception. |
||
the N-API wrapper automatically converts and throws it as a JavaScript exception. | ||
|
||
Therefore, catching a C++ exception of type **Error** prevents a JavaScript | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When C++ exceptions are enabled try/catch can be used to catch exceptions thrown from calls to JavaScript and then they can either be handled or rethrown before returning from a native method. |
||
exception from being thrown. | ||
|
||
## Examples with C++ exceptions enabled | ||
|
||
### Throwing a C++ exception | ||
|
||
```cpp | ||
Napi::Env env = ... | ||
throw Napi::Error::New(env, "Example exception"); | ||
// other C++ statements | ||
// ... | ||
``` | ||
|
||
Following C++ statements will not be executed. The exception will bubble up as a | ||
C++ exception of type **Error**, until it is either caught while still in C++, or | ||
else automatically propataged as a JavaScript exception when returns to | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: "propagated" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: "C++ statements following the throwing statement will not be executed. The exception throw is of type Error and can be handled in C++ as usual. If the exception is not handled in C++ it will automatically propagate to the JavaScript caller. |
||
JavaScript. | ||
|
||
### Propagating a N-API C++ exception | ||
|
||
```cpp | ||
Napi::Function jsFunctionThatThrows = someObj.As<Napi::Function>(); | ||
Napi::Value result = jsFunctionThatThrows({ arg1, arg2 }); | ||
// other C++ statements | ||
// ... | ||
``` | ||
|
||
Following C++ statements will not be executed. The exception will bubble up as a | ||
C++ exception of type **Error**, until it is either caught while still in C++, or | ||
else automatically propagated as a JavaScript exception when returns to | ||
JavaScript. | ||
|
||
### Handling a N-API C++ exception | ||
|
||
```cpp | ||
Napi::Function jsFunctionThatThrows = someObj.As<Napi::Function>(); | ||
Napi::Value result; | ||
try { | ||
result = jsFunctionThatThrows({ arg1, arg2 }); | ||
} catch (const Napi::Error& e) { | ||
cerr << "Caught JavaScript exception: " + e.what(); | ||
} | ||
``` | ||
|
||
Since the exception was caught here, it will not be propagated as a JavaScript | ||
exception. | ||
|
||
<a name="noexceptions"></a> | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: extra newline There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe an example that shows rethrowing ? |
||
## Handling Errors Without C++ Exceptions | ||
|
||
If C++ exceptions are disabled (for more info see: [Setup](setup.md) section), | ||
then the **Error** class does not extend ```std::exception```. This means that | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: extra space after "Error" |
||
any call to node-addon-api functions does not throw C++ exception. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: "any calls to node-addon-api function do not throw C++ exceptions." |
||
Instead, it raises _pending_ JavaScript exceptions and return _empty_ **Value**. | ||
The calling code should check ```Value::IsEmpty()``` (for more info see: [Value](value.md)) | ||
before attempting or use a returned value, and may use methods on the **Env** class | ||
to check for, get, and clear a pending JavaScript exception (for more info see: [Env](env.md)). | ||
If the pending exception is not cleared, it will be thrown when the native code | ||
returns to JavaScript. | ||
|
||
## Examples with C++ exceptions disabled | ||
|
||
### Throwing a JS exception | ||
|
||
```cpp | ||
Napi::Env env = ... | ||
Napi::Error::New(env, "Example exception").ThrowAsJavaScriptException(); | ||
return; | ||
``` | ||
|
||
After throwing a JS exception, the code should generally return immediately from | ||
the native callback, after performing any necessary cleanup. | ||
|
||
### Propagating a N-API JS exception | ||
|
||
```cpp | ||
Napi::Function jsFunctionThatThrows = someObj.As<Napi::Function>(); | ||
Napi::Value result = jsFunctionThatThrows({ arg1, arg2 }); | ||
if (result.IsEmpty()) return; | ||
``` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would be better to suggest that they should check using IsExceptionPending as that will work for methods that don't return a value as well. |
||
|
||
An empty value result from a N-API call indicates that an error occurred, and a | ||
JavaScript exception is pending. To let the exception propagate, the code should | ||
generally return immediately from the native callback, after performing any | ||
necessary cleanup. | ||
|
||
### Handling a N-API JS exception | ||
|
||
```cpp | ||
Napi::Function jsFunctionThatThrows = someObj.As<Napi::Function>(); | ||
Napi::Value result = jsFunctionThatThrows({ arg1, arg2 }); | ||
if (result.IsEmpty()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same goes here to check with IsExceptionPending |
||
Napi::Error e = env.GetAndClearPendingException(); | ||
cerr << "Caught JavaScript exception: " + e.Message(); | ||
} | ||
``` | ||
|
||
Since the exception was cleared here, it will not be propagated as a JavaScript | ||
exception after the native callback returns. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
# RangeError | ||
|
||
The **RangeError** class is a representation of the JavaScript RangeError that is | ||
thrown when trying to pass a value as an argument to a function that does not allow | ||
a range that includes the value. | ||
|
||
The **RangeError** class inherits its behaviours from **Error** class (for more info | ||
see: [Error](error.md) section). | ||
|
||
For more details about error handling refer to the section titled [Error handling](error_handling.md). | ||
|
||
## Methods | ||
|
||
### New | ||
|
||
Creates a new instance of ```RangeError``` object | ||
|
||
```cpp | ||
RangeError::New(Napi:Env env, const char* message); | ||
``` | ||
|
||
- ```[in] Env```: The environment in which to construct the RangeError object. | ||
- ```[in] message```: Null-terminated strings to be used as the message for the RangeError. | ||
|
||
Returns an instance of ```RangeError``` object. | ||
|
||
### New | ||
|
||
Creates a new instance of ```RangeError``` object | ||
|
||
```cpp | ||
RangeError::New(Napi:Env env, const std::string& message); | ||
``` | ||
|
||
- `[in] Env`: The environment in which to construct the RangeError object. | ||
- `[in] message`: Reference string to be used as the message for the RangeError. | ||
|
||
Returns an instance of ```RangeError``` object. | ||
|
||
### Constructor | ||
|
||
Creates a new empty instance of ```RangeError``` | ||
|
||
```cpp | ||
RangeError(); | ||
``` | ||
|
||
### Constructor | ||
|
||
Initializes a ```RangeError``` instance from an existing ```Error``` object. | ||
|
||
```cpp | ||
RangeError(napi_env env, napi_value value); | ||
``` | ||
|
||
- ```[in] Env```: The environment in which to construct the RangeError object. | ||
- ```[in] value```: The ```Error``` reference to wrap. | ||
|
||
Returns an instance of ```RangeError``` object. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
# TypeError | ||
|
||
The **TypeError** class is a representation of the JavaScript TypeError that is | ||
thrown when an operand or argument passed to a function is incompatible with the | ||
type expected by the operator or function. | ||
|
||
The **TypeError** class inherits its behaviours from **Error** class (for more info | ||
see: [Error](error.md) section). | ||
|
||
For more details about error handling refer to the section titled [Error handling](error_handling.md). | ||
|
||
## Methods | ||
|
||
### New | ||
|
||
Creates a new instance of ```TypeError``` object | ||
|
||
```cpp | ||
TypeError::New(Napi:Env env, const char* message); | ||
``` | ||
|
||
- ```[in] Env```: The environment in which to construct the TypeError object. | ||
- ```[in] message```: Null-terminated strings to be used as the message for the TypeError. | ||
|
||
Returns an instance of ```TypeError``` object. | ||
|
||
### New | ||
|
||
Creates a new instance of ```TypeError``` object | ||
|
||
```cpp | ||
TypeError::New(Napi:Env env, const std::string& message); | ||
``` | ||
|
||
- `[in] Env`: The environment in which to construct the TypeError object. | ||
- `[in] message`: Reference string to be used as the message for the TypeError. | ||
|
||
Returns an instance of ```TypeError``` object. | ||
|
||
### Constructor | ||
|
||
Creates a new empty instance of ```TypeError``` | ||
|
||
```cpp | ||
TypeError(); | ||
``` | ||
|
||
### Constructor | ||
|
||
Initializes a ```TypeError``` instance from an existing ```Error``` object. | ||
|
||
```cpp | ||
TypeError(napi_env env, napi_value value); | ||
``` | ||
|
||
- ```[in] Env```: The environment in which to construct the TypeError object. | ||
- ```[in] value```: The ```Error``` reference to wrap. | ||
|
||
Returns an instance of ```TypeError``` object. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have a guideline for these sorts of stylistic flairs? It seems like
Error
and Error are used in different scenarios throughout this file, what is the guideline we're following?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No at moment we haven't a stylistic standard to follow. My opinion is that we need one.