From 825440adcba1e47e79e2e37dc9e17199603ce899 Mon Sep 17 00:00:00 2001 From: Nicola Del Gobbo Date: Thu, 4 Jan 2018 02:07:14 +0100 Subject: [PATCH 1/5] Update package.json example Changed version of node-addon-api on the package.json example see: [issue 206](https://github.com/nodejs/node-addon-api/issues/206#issuecomment-355165254) --- doc/setup.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/setup.md b/doc/setup.md index 84dafd3f7..be95e747e 100644 --- a/doc/setup.md +++ b/doc/setup.md @@ -19,7 +19,7 @@ To use **N-API** in a native module: ```json "dependencies": { - "node-addon-api": "1.0.0", + "node-addon-api": "1.1.0", } ``` @@ -65,4 +65,4 @@ To use **N-API** in a native module: ``` At build time, the N-API back-compat library code will be used only when the -targeted node version *does not* have N-API built-in. \ No newline at end of file +targeted node version *does not* have N-API built-in. From d11cd21bfed1d83a667ff2fb3094ffbdd8e7cb22 Mon Sep 17 00:00:00 2001 From: NickNaso Date: Thu, 8 Mar 2018 20:16:01 +0100 Subject: [PATCH 2/5] First step of error documentation --- doc/error_handling.md | 110 ++++++++++++++++++++++++++++++++++++++++-- doc/setup.md | 2 +- 2 files changed, 108 insertions(+), 4 deletions(-) diff --git a/doc/error_handling.md b/doc/error_handling.md index 14c0c4ac0..5517483eb 100644 --- a/doc/error_handling.md +++ b/doc/error_handling.md @@ -1,5 +1,109 @@ # 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/) \ No newline at end of file +A persistent reference to a JavaScript error object. Use of this class depends +somewhat on whether C++ exceptions are enabled at compile time. + +### Handling Errors With C++ Exceptions + +If C++ exceptions are enabled, then the `Error` class extends `std::exception` +and enables integrated error-handling for C++ exceptions and JavaScript +exceptions. + +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 `Napi::Error`. Or 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 +`Napi::Error`. + +If a C++ exception of type `Napi::Error` escapes from a N-API C++ callback, then +the N-API wrapper automatically converts and throws it as a JavaScript exception. +Therefore, catching a C++ exception of type `Napi::Error` prevents a JavaScript +exception from being thrown. + +#### Example 1A - Throwing a C++ exception: + +```cpp +Napi::Env env = ... +throw Napi::Error::New(env, "Example exception"); +``` + +Following C++ statements will not be executed. The exception will bubble up as a +C++ exception of type `Napi::Error`, until it is either caught while still in +C++, or else automatically propataged as a JavaScript exception when the callback +returns to JavaScript. + +#### Example 2A - Propagating a N-API C++ exception: + +```cpp +Napi::Function jsFunctionThatThrows = someObj.As(); +Napi::Value result = jsFunctionThatThrows({ arg1, arg2 }); +``` + +Following C++ statements will not be executed. The exception will bubble up as a +C++ exception of type `Napi::Error`, until it is either caught while still in +C++, or else automatically propagated as a JavaScript exception when the callback +returns to JavaScript. + +#### Example 3A - Handling a N-API C++ exception: + +```cpp +Napi::Function jsFunctionThatThrows = someObj.As(); +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. + +### Handling Errors Without C++ Exceptions + +If C++ exceptions are disabled (by defining `NAPI_DISABLE_CPP_EXCEPTIONS`) then +this class does not extend `std::exception`, and APIs in the `Napi` namespace do +not throw C++ exceptions when they fail. Instead, they raise _pending_ JavaScript +exceptions and return _empty_ `Value`s. Calling code should check +`Value::IsEmpty()` before attempting o use a returned value, and may use methods +on the `Env` class to check for, get, and clear a pending JavaScript exception. +If the pending exception is not cleared, it will be thrown when the native +callback returns to JavaScript. + +#### Example 1B - 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. + +#### Example 2B - Propagating a N-API JS exception: + +```cpp +Napi::Function jsFunctionThatThrows = someObj.As(); +Napi::Value result = jsFunctionThatThrows({ arg1, arg2 }); +if (result.IsEmpty()) return; +``` + +An empty value result from a N-API call indicates an error occurred, and a +JavaScript xception is pending. To let the exception propagate, the code should +generally return immediately from the native callback, after performing any +necessary cleanup. + +#### Example 3B - Handling a N-API JS exception: + +```cpp +Napi::Function jsFunctionThatThrows = someObj.As(); +Napi::Value result = jsFunctionThatThrows({ arg1, arg2 }); +if (result.IsEmpty()) { + 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. \ No newline at end of file diff --git a/doc/setup.md b/doc/setup.md index be95e747e..176815a96 100644 --- a/doc/setup.md +++ b/doc/setup.md @@ -19,7 +19,7 @@ To use **N-API** in a native module: ```json "dependencies": { - "node-addon-api": "1.1.0", + "node-addon-api": "1.2.0", } ``` From 794ee4db4b8b64a473caaf50c681c19a273cd928 Mon Sep 17 00:00:00 2001 From: NickNaso Date: Thu, 3 May 2018 04:03:02 +0200 Subject: [PATCH 3/5] Documentation for error handling --- README.md | 2 + doc/error.md | 102 ++++++++++++++++++++++++++++++++++-- doc/error_handling.md | 117 ++++++++++++++++++++++++++---------------- doc/range_error.md | 59 +++++++++++++++++++++ doc/type_error.md | 59 +++++++++++++++++++++ 5 files changed, 292 insertions(+), 47 deletions(-) create mode 100644 doc/range_error.md create mode 100644 doc/type_error.md diff --git a/README.md b/README.md index ebf6fec2d..409fd1d16 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,8 @@ values. Concepts and operations generally map to ideas specified in the - [PropertyDescriptor](doc/property_descriptor.md) - [Error Handling](doc/error_handling.md) - [Error](doc/error.md) + - [TypeError](doc/type_error.md) + - [RangeError](doc/range_error.md) - [Object Lifettime Management](doc/object_lifetime_management.md) - [HandleScope](doc/handle_scope.md) - [EscapableHandleScope](doc/escapable_handle_scope.md) diff --git a/doc/error.md b/doc/error.md index 5ad6befc8..ae03cdfa2 100644 --- a/doc/error.md +++ b/doc/error.md @@ -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/) \ No newline at end of file +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 +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. + +```cpp +TypeError(napi_env env, napi_value value); +``` + +- ```[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. + +### 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. \ No newline at end of file diff --git a/doc/error_handling.md b/doc/error_handling.md index 5517483eb..d8684de72 100644 --- a/doc/error_handling.md +++ b/doc/error_handling.md @@ -1,51 +1,74 @@ # Error handling -A persistent reference to a JavaScript error object. Use of this class depends -somewhat on whether C++ exceptions are enabled at compile time. +The error handling represents one of the most important thing on implementing a +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 +or on the C/C++, library that you are integrating. -### Handling Errors With C++ Exceptions +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. -If C++ exceptions are enabled, then the `Error` class extends `std::exception` -and enables integrated error-handling for C++ exceptions and JavaScript -exceptions. +The following sections explain the approach for each case: -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 `Napi::Error`. Or 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 -`Napi::Error`. +- [Handling Errors With C++ Exceptions](#exceptions) -If a C++ exception of type `Napi::Error` escapes from a N-API C++ callback, then -the N-API wrapper automatically converts and throws it as a JavaScript exception. -Therefore, catching a C++ exception of type `Napi::Error` prevents a JavaScript +- [Handling Errors Without C++ Exceptions](#noexceptions) + + + +## 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. + +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**. + +If a C++ exception of type **Error** escapes from a N-API C++ callback, then +the N-API wrapper automatically converts and throws it as a JavaScript exception. + +Therefore, catching a C++ exception of type **Error** prevents a JavaScript exception from being thrown. -#### Example 1A - Throwing a C++ exception: +## 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 `Napi::Error`, until it is either caught while still in -C++, or else automatically propataged as a JavaScript exception when the callback -returns to JavaScript. +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 +JavaScript. -#### Example 2A - Propagating a N-API C++ exception: +### Propagating a N-API C++ exception ```cpp Napi::Function jsFunctionThatThrows = someObj.As(); 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 `Napi::Error`, until it is either caught while still in -C++, or else automatically propagated as a JavaScript exception when the callback -returns to JavaScript. +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. -#### Example 3A - Handling a N-API C++ exception: +### Handling a N-API C++ exception ```cpp Napi::Function jsFunctionThatThrows = someObj.As(); @@ -57,21 +80,26 @@ try { } ``` -Since the exception was caught here, it will not be propagated as a JavaScript +Since the exception was caught here, it will not be propagated as a JavaScript exception. -### Handling Errors Without C++ Exceptions + -If C++ exceptions are disabled (by defining `NAPI_DISABLE_CPP_EXCEPTIONS`) then -this class does not extend `std::exception`, and APIs in the `Napi` namespace do -not throw C++ exceptions when they fail. Instead, they raise _pending_ JavaScript -exceptions and return _empty_ `Value`s. Calling code should check -`Value::IsEmpty()` before attempting o use a returned value, and may use methods -on the `Env` class to check for, get, and clear a pending JavaScript exception. -If the pending exception is not cleared, it will be thrown when the native -callback returns to JavaScript. +## Handling Errors Without C++ Exceptions -#### Example 1B - Throwing a JS exception +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 +any call to node-addon-api functions does not throw C++ exception. +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 = ... @@ -79,10 +107,10 @@ Napi::Error::New(env, "Example exception").ThrowAsJavaScriptException(); return; ``` -After throwing a JS exception, the code should generally return immediately from +After throwing a JS exception, the code should generally return immediately from the native callback, after performing any necessary cleanup. -#### Example 2B - Propagating a N-API JS exception: +### Propagating a N-API JS exception ```cpp Napi::Function jsFunctionThatThrows = someObj.As(); @@ -90,12 +118,12 @@ Napi::Value result = jsFunctionThatThrows({ arg1, arg2 }); if (result.IsEmpty()) return; ``` -An empty value result from a N-API call indicates an error occurred, and a -JavaScript xception is pending. To let the exception propagate, the code should -generally return immediately from the native callback, after performing any +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. -#### Example 3B - Handling a N-API JS exception: +### Handling a N-API JS exception ```cpp Napi::Function jsFunctionThatThrows = someObj.As(); @@ -105,5 +133,6 @@ if (result.IsEmpty()) { cerr << "Caught JavaScript exception: " + e.Message(); } ``` -Since the exception was cleared here, it will not be propagated as a JavaScript + +Since the exception was cleared here, it will not be propagated as a JavaScript exception after the native callback returns. \ No newline at end of file diff --git a/doc/range_error.md b/doc/range_error.md new file mode 100644 index 000000000..6a27053f3 --- /dev/null +++ b/doc/range_error.md @@ -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. \ No newline at end of file diff --git a/doc/type_error.md b/doc/type_error.md new file mode 100644 index 000000000..b9d0e8430 --- /dev/null +++ b/doc/type_error.md @@ -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. \ No newline at end of file From 844b651e2106dd81a59268bd9c233f13b3c4180c Mon Sep 17 00:00:00 2001 From: NickNaso Date: Thu, 10 May 2018 14:47:26 +0200 Subject: [PATCH 4/5] Complete fix proposed on first review --- doc/error.md | 43 ++++++++++++++-------- doc/error_handling.md | 85 +++++++++++++++++++++++++------------------ doc/range_error.md | 26 ++++++------- doc/type_error.md | 26 ++++++------- 4 files changed, 103 insertions(+), 77 deletions(-) diff --git a/doc/error.md b/doc/error.md index ae03cdfa2..c0c71d637 100644 --- a/doc/error.md +++ b/doc/error.md @@ -9,7 +9,7 @@ inherits its behaviour from ObjectReference class (for more info see: [ObjectRef section). If C++ exceptions are enabled (for more info see: [Setup](setup.md) section), -then the **Error** class extends ```std::exception``` and enables integrated +then the **Error** class extends `std::exception` and enables integrated error-handling for C++ exceptions and JavaScript exceptions. For more details about error handling refer to the section titled [Error handling](error_handling.md). @@ -18,32 +18,32 @@ For more details about error handling refer to the section titled [Error handlin ### New -Creates a new instance empty of ```Error``` object for the specified environment. +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. +- `[in] Env`: The environment in which to construct the Error object. -Returns an instance of ```Error``` object. +Returns an instance of `Error` object. ### New -Creates a new instance of ```Error``` object +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. +- `[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. +Returns an instance of `Error` object. ### New -Creates a new instance of ```Error``` object +Creates a new instance of `Error` object ```cpp Error::New(Napi:Env env, const std::string& message); @@ -52,11 +52,22 @@ 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. +Returns an instance of `Error` object. + +### Fatal + +In case of an unrecoverable error in a native module, a fatal error can be thrown +to immediately terminate the process. + +```cpp +static NAPI_NO_RETURN void Fatal(const char* location, const char* message); +``` + +The function call does not return, the process will be terminated. ### Constructor -Creates a new empty instance of ```Error``` +Creates a new empty instance of `Error` ```cpp Error(); @@ -64,10 +75,10 @@ Error(); ### Constructor -Initializes a ```Error``` instance from an existing ```Error``` object. +Initializes a `Error` instance from an existing JavaScript error object. ```cpp -TypeError(napi_env env, napi_value value); +Error(napi_env env, napi_value value); ``` - ```[in] Env```: The environment in which to construct the Error object. @@ -85,11 +96,13 @@ Returns the reference to string that represent the message of the error. ### ThrowAsJavaScriptException +Throw the error as JavaScript exception. + ```cpp void ThrowAsJavaScriptException() const; ``` -Throw the error as JavaScript exception. +Throws the error as JavaScript exception. ### what @@ -98,4 +111,4 @@ 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. \ No newline at end of file +exception. This method can be used only if the exception mechanism is enabled. \ No newline at end of file diff --git a/doc/error_handling.md b/doc/error_handling.md index d8684de72..093ba6736 100644 --- a/doc/error_handling.md +++ b/doc/error_handling.md @@ -1,28 +1,31 @@ # Error handling -The error handling represents one of the most important thing on implementing a -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 -or on the C/C++, library that you are integrating. +Error handling represents one of the most important considerations when +implementing a 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 choose return values or +exception handling based on the mechanism that works best for your add-on. 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. +section) to a JavaScript error object. Use of this class depends on whether C++ +exceptions are enabled at compile time. + +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. The following sections explain the approach for each case: - [Handling Errors With C++ Exceptions](#exceptions) - - [Handling Errors Without C++ Exceptions](#noexceptions) ## 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. +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. 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 @@ -30,52 +33,57 @@ 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**. +exception of type **Error** 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 the N-API wrapper automatically converts and throws it as a JavaScript exception. -Therefore, catching a C++ exception of type **Error** prevents a JavaScript -exception from being thrown. +On return from a native method, N-API will automatically convert a pending C++ +exception to a JavaScript exception. + +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. ## Examples with C++ exceptions enabled ### Throwing a C++ exception ```cpp -Napi::Env env = ... -throw Napi::Error::New(env, "Example exception"); +Env env = ... +throw 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 +else automatically propagated as a JavaScript exception when returns to JavaScript. ### Propagating a N-API C++ exception ```cpp -Napi::Function jsFunctionThatThrows = someObj.As(); -Napi::Value result = jsFunctionThatThrows({ arg1, arg2 }); +Function jsFunctionThatThrows = someObj.As(); +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 +else automatically propagated as a JavaScript exception when returns to JavaScript. ### Handling a N-API C++ exception ```cpp -Napi::Function jsFunctionThatThrows = someObj.As(); -Napi::Value result; +Function jsFunctionThatThrows = someObj.As(); +Value result; try { result = jsFunctionThatThrows({ arg1, arg2 }); -} catch (const Napi::Error& e) { +} catch (const Error& e) { cerr << "Caught JavaScript exception: " + e.what(); } ``` @@ -88,10 +96,10 @@ exception. ## 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 -any call to node-addon-api functions does not throw C++ exception. -Instead, it raises _pending_ JavaScript exceptions and return _empty_ **Value**. -The calling code should check ```Value::IsEmpty()``` (for more info see: [Value](value.md)) +then the **Error** class does not extend `std::exception`. This means that 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 @@ -102,8 +110,8 @@ returns to JavaScript. ### Throwing a JS exception ```cpp -Napi::Env env = ... -Napi::Error::New(env, "Example exception").ThrowAsJavaScriptException(); +Env env = ... +Error::New(env, "Example exception").ThrowAsJavaScriptException(); return; ``` @@ -113,9 +121,13 @@ the native callback, after performing any necessary cleanup. ### Propagating a N-API JS exception ```cpp -Napi::Function jsFunctionThatThrows = someObj.As(); -Napi::Value result = jsFunctionThatThrows({ arg1, arg2 }); -if (result.IsEmpty()) return; +Env env = ... +Function jsFunctionThatThrows = someObj.As(); +Value result = jsFunctionThatThrows({ arg1, arg2 }); +if (env.IsExceptionPending()) { + Error e = env.GetAndClearPendingException(); + return e.Value(); +} ``` An empty value result from a N-API call indicates that an error occurred, and a @@ -126,10 +138,11 @@ necessary cleanup. ### Handling a N-API JS exception ```cpp -Napi::Function jsFunctionThatThrows = someObj.As(); -Napi::Value result = jsFunctionThatThrows({ arg1, arg2 }); -if (result.IsEmpty()) { - Napi::Error e = env.GetAndClearPendingException(); +Env env = ... +Function jsFunctionThatThrows = someObj.As(); +Value result = jsFunctionThatThrows({ arg1, arg2 }); +if (env.IsExceptionPending()) { + Error e = env.GetAndClearPendingException(); cerr << "Caught JavaScript exception: " + e.Message(); } ``` diff --git a/doc/range_error.md b/doc/range_error.md index 6a27053f3..776401399 100644 --- a/doc/range_error.md +++ b/doc/range_error.md @@ -13,33 +13,33 @@ For more details about error handling refer to the section titled [Error handlin ### New -Creates a new instance of ```RangeError``` object +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. +- `[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. +Returns an instance of `RangeError` object. ### New -Creates a new instance of ```RangeError``` object +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. +- `[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. +Returns an instance of `RangeError` object. ### Constructor -Creates a new empty instance of ```RangeError``` +Creates a new empty instance of `RangeError` ```cpp RangeError(); @@ -47,13 +47,13 @@ RangeError(); ### Constructor -Initializes a ```RangeError``` instance from an existing ```Error``` object. +Initializes a `RangeError` instance from an existing Javascript 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. +- `[in] Env`: The environment in which to construct the `RangeError` object. +- `[in] value`: The `Error` reference to wrap. -Returns an instance of ```RangeError``` object. \ No newline at end of file +Returns an instance of `RangeError` object. \ No newline at end of file diff --git a/doc/type_error.md b/doc/type_error.md index b9d0e8430..1fd2532ba 100644 --- a/doc/type_error.md +++ b/doc/type_error.md @@ -13,33 +13,33 @@ For more details about error handling refer to the section titled [Error handlin ### New -Creates a new instance of ```TypeError``` object +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. +- `[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. +Returns an instance of `TypeError` object. ### New -Creates a new instance of ```TypeError``` object +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. +- `[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. +Returns an instance of `TypeError` object. ### Constructor -Creates a new empty instance of ```TypeError``` +Creates a new empty instance of `TypeError` ```cpp TypeError(); @@ -47,13 +47,13 @@ TypeError(); ### Constructor -Initializes a ```TypeError``` instance from an existing ```Error``` object. +Initializes a ```TypeError``` instance from an existing JavaScript 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. +- `[in] Env`: The environment in which to construct the `TypeError` object. +- `[in] value`: The `Error` reference to wrap. -Returns an instance of ```TypeError``` object. \ No newline at end of file +Returns an instance of `TypeError` object. \ No newline at end of file From 83fc1813811ada812d89cbaf7015d93022953222 Mon Sep 17 00:00:00 2001 From: NickNaso Date: Thu, 8 Mar 2018 20:16:01 +0100 Subject: [PATCH 5/5] Sqash the commits for error hadnling documentation First step of error documentation Documentation for error handling Complete fix proposed on first review --- README.md | 2 + doc/error.md | 115 +++++++++++++++++++++++++++++++- doc/error_handling.md | 152 +++++++++++++++++++++++++++++++++++++++++- doc/range_error.md | 59 ++++++++++++++++ doc/setup.md | 2 +- doc/type_error.md | 59 ++++++++++++++++ 6 files changed, 382 insertions(+), 7 deletions(-) create mode 100644 doc/range_error.md create mode 100644 doc/type_error.md diff --git a/README.md b/README.md index ebf6fec2d..409fd1d16 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,8 @@ values. Concepts and operations generally map to ideas specified in the - [PropertyDescriptor](doc/property_descriptor.md) - [Error Handling](doc/error_handling.md) - [Error](doc/error.md) + - [TypeError](doc/type_error.md) + - [RangeError](doc/range_error.md) - [Object Lifettime Management](doc/object_lifetime_management.md) - [HandleScope](doc/handle_scope.md) - [EscapableHandleScope](doc/escapable_handle_scope.md) diff --git a/doc/error.md b/doc/error.md index 5ad6befc8..c0c71d637 100644 --- a/doc/error.md +++ b/doc/error.md @@ -1,5 +1,114 @@ # 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/) \ No newline at end of file +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 +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. + +### Fatal + +In case of an unrecoverable error in a native module, a fatal error can be thrown +to immediately terminate the process. + +```cpp +static NAPI_NO_RETURN void Fatal(const char* location, const char* message); +``` + +The function call does not return, the process will be terminated. + +### Constructor + +Creates a new empty instance of `Error` + +```cpp +Error(); +``` + +### Constructor + +Initializes a `Error` instance from an existing JavaScript error object. + +```cpp +Error(napi_env env, napi_value value); +``` + +- ```[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 + +Throw the error as JavaScript exception. + +```cpp +void ThrowAsJavaScriptException() const; +``` + +Throws the error as JavaScript exception. + +### 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 exception mechanism is enabled. \ No newline at end of file diff --git a/doc/error_handling.md b/doc/error_handling.md index 14c0c4ac0..093ba6736 100644 --- a/doc/error_handling.md +++ b/doc/error_handling.md @@ -1,5 +1,151 @@ # 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/) \ No newline at end of file +Error handling represents one of the most important considerations when +implementing a 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 choose return values or +exception handling based on the mechanism that works best for your add-on. + +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 on whether C++ +exceptions are enabled at compile time. + +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. + +The following sections explain the approach for each case: + +- [Handling Errors With C++ Exceptions](#exceptions) +- [Handling Errors Without C++ Exceptions](#noexceptions) + + + +## Handling Errors With C++ Exceptions + +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. + +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** 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 +the N-API wrapper automatically converts and throws it as a JavaScript exception. + +On return from a native method, N-API will automatically convert a pending C++ +exception to a JavaScript exception. + +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. + +## Examples with C++ exceptions enabled + +### Throwing a C++ exception + +```cpp +Env env = ... +throw 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 propagated as a JavaScript exception when returns to +JavaScript. + +### Propagating a N-API C++ exception + +```cpp +Function jsFunctionThatThrows = someObj.As(); +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 +Function jsFunctionThatThrows = someObj.As(); +Value result; +try { + result = jsFunctionThatThrows({ arg1, arg2 }); +} catch (const Error& e) { + cerr << "Caught JavaScript exception: " + e.what(); +} +``` + +Since the exception was caught here, it will not be propagated as a JavaScript +exception. + + + +## 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 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 +Env env = ... +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 +Env env = ... +Function jsFunctionThatThrows = someObj.As(); +Value result = jsFunctionThatThrows({ arg1, arg2 }); +if (env.IsExceptionPending()) { + Error e = env.GetAndClearPendingException(); + return e.Value(); +} +``` + +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 +Env env = ... +Function jsFunctionThatThrows = someObj.As(); +Value result = jsFunctionThatThrows({ arg1, arg2 }); +if (env.IsExceptionPending()) { + 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. \ No newline at end of file diff --git a/doc/range_error.md b/doc/range_error.md new file mode 100644 index 000000000..776401399 --- /dev/null +++ b/doc/range_error.md @@ -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 Javascript 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. \ No newline at end of file diff --git a/doc/setup.md b/doc/setup.md index be95e747e..176815a96 100644 --- a/doc/setup.md +++ b/doc/setup.md @@ -19,7 +19,7 @@ To use **N-API** in a native module: ```json "dependencies": { - "node-addon-api": "1.1.0", + "node-addon-api": "1.2.0", } ``` diff --git a/doc/type_error.md b/doc/type_error.md new file mode 100644 index 000000000..1fd2532ba --- /dev/null +++ b/doc/type_error.md @@ -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 JavaScript 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. \ No newline at end of file