From 825440adcba1e47e79e2e37dc9e17199603ce899 Mon Sep 17 00:00:00 2001 From: Nicola Del Gobbo Date: Thu, 4 Jan 2018 02:07:14 +0100 Subject: [PATCH 01/17] 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 02/17] 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 03/17] 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 3eae5e1da9cc8e2e1eadb1f57626521b452e1410 Mon Sep 17 00:00:00 2001 From: NickNaso Date: Thu, 17 May 2018 01:41:53 +0200 Subject: [PATCH 04/17] Async operations documentation --- doc/async_operations.md | 26 +++++++++++++-- doc/async_worker.md | 74 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 93 insertions(+), 7 deletions(-) diff --git a/doc/async_operations.md b/doc/async_operations.md index 438312a9b..4806fecbf 100644 --- a/doc/async_operations.md +++ b/doc/async_operations.md @@ -1,5 +1,25 @@ # Asynchronous operations -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 +Node.js native add-ons often need to execute long running tasks and to avoid of +blocking the **event loop** they have to accomplish to them in the asynchronous way. +Lets do a quick overview of how asynchronous code work in Node.js. In our model +of execution we have **two threads**, the first is the **event loop** thread, that +represents the thread where or JavaScript code is executing in. We want avoid to +stall the event loop thread doing heavy computation so we need to create a sencond +thread called **worker thread** managed by **libuv**, the libary that supports the +asynchronous I/O in Node.js. + +All this means that native add-ons need to leverage async helpers from libuv as +part of their implementation. This allows them to schedule work to be executed +asynchronously so that their methods can return in advance of the work being +completed. + +Node Addon API provides an ABI-stable interface to support functions which covers +the most common asynchronous use cases. You have two abstract class to implement +asynchronous operation: + +- [AsyncWorker](async_worker.md) +- [Async Context](async_context.md) + +These two classes help you to manage asynchronous operations through an abstraction +of the concept of moving data between the **event loop** and **worker threads**. \ No newline at end of file diff --git a/doc/async_worker.md b/doc/async_worker.md index a50f6f777..5e0ec1157 100644 --- a/doc/async_worker.md +++ b/doc/async_worker.md @@ -1,5 +1,71 @@ -# Async worker +# AsyncWorker -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 +`AsyncWorker` is an abstract class that you can subclass to remove much of the +tedious tasks on moving data between the event loop and worker threads. This +class internally handles all the details of creating and executing asynchronous +operation. + +## Methods + +### Env + +Requests the environment in which the async worker has been initially created. + +```cpp +Env Env() const; +``` + +Returns the environment in which the async worker has been created. + +### Queue + +Requests that the created work or task will be placed on the queue of the execution. + +```cpp +void Queue(); +``` + +### Cancel + +Cancels queued work if it has not yet been started. If it has already started +executing, it cannot be cancelled. + +```cpp +void Cancel(); +``` + +### Receiver + +```cpp +ObjectReference& Receiver(); +``` + +### Callback + +```cpp +FunctionReference& Callback(); +``` + +### SetError + +```cpp +void SetError(const std::string& error); +``` + +### Execute + +```cpp +virtual void Execute() = 0; +``` + +### OnOK + +```cpp +virtual void OnOK(); +``` + +### OnError + +```cpp +virtual void OnError(const Error& e); +``` \ No newline at end of file From 8cc39bea0c1e3272177a5fc92c348a6f8f5293c0 Mon Sep 17 00:00:00 2001 From: NickNaso Date: Thu, 17 May 2018 02:32:37 +0200 Subject: [PATCH 05/17] Added example of async woirker --- doc/async_operations.md | 4 +-- doc/async_worker.md | 74 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/doc/async_operations.md b/doc/async_operations.md index 4806fecbf..082d69841 100644 --- a/doc/async_operations.md +++ b/doc/async_operations.md @@ -18,8 +18,8 @@ Node Addon API provides an ABI-stable interface to support functions which cover the most common asynchronous use cases. You have two abstract class to implement asynchronous operation: -- [AsyncWorker](async_worker.md) -- [Async Context](async_context.md) +- **[AsyncWorker](async_worker.md)** +- **[Async Context](async_context.md)** These two classes help you to manage asynchronous operations through an abstraction of the concept of moving data between the **event loop** and **worker threads**. \ No newline at end of file diff --git a/doc/async_worker.md b/doc/async_worker.md index 5e0ec1157..06a1058aa 100644 --- a/doc/async_worker.md +++ b/doc/async_worker.md @@ -1,7 +1,7 @@ # AsyncWorker `AsyncWorker` is an abstract class that you can subclass to remove much of the -tedious tasks on moving data between the event loop and worker threads. This +tedious tasks on moving data between the event loop and worker threads. This class internally handles all the details of creating and executing asynchronous operation. @@ -68,4 +68,74 @@ virtual void OnOK(); ```cpp virtual void OnError(const Error& e); -``` \ No newline at end of file +``` + +## Example + +The first step to use `AsyncWorker` class is to create a new class that inherit +from it and implement the `Execute` abstract method. Typically input to your +worker will be saved within your fields' class generally passed in through its +constructor. + +When the `Execute` method complete without errors the `OnOK` function callback +will be invoked. In this function the results of the computation will be +reassembled and returned back to initial JavaScript context. + +`AsyncWorker` ensure that all the code inside in the `Execute` function runs in +background out of the **event loop** thread and at the end `OnOK` or `OnError` +function will be called and are executed as part of the event loop. + +The code below show a basic example of `AsyncWorker` implementation: + +```cpp +#include + +#include +#include + +use namespace Napi; + +class EchoWorker : public AsyncWorker { + public: + EchoWorker(Function& callback, std::string& echo) + : AsyncWorker(callback), echo(echo) {} + + ~EchoWorker() {} + // This code will be executed on the worker thread + void Execute() { + // Need to simulate cpu heavy task + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + + void OnOK() { + HandleScope scope(Env()); + Callback().Call({Env().Null(), String::New(Env(), echo)}); + } + + private: + std::string echo; +}; +``` + +The `EchoWorker`'s contructor call the base class's constructor to pass in the +callback that the `AsyncWorker` base class will store persistently. When the work +on the `Execute` method is done the `OnOk` method is called and the results return +back to JavaScript invoking the stored callback with its associated environment. + +The following code show an example on how to create and and use an `AsyncWorker` + +```cpp +Value Echo(const CallbackInfo& info) { + // You need to check the input data here + Function cb = info[1].As(); + std::string in = info[0].As(); + EchoWorker* wk = new EchoWorker(cb, in); + wk->Queue(); + return info.Env().Undefined(); +``` + +Use the implementation of an `AsyncWorker` is very simple you need only to +create a new instance and pass to its constructor the callback you want exectute +when your asynchronous task end and other data you need for your computation. The +only action you have to do is to call the `Queue` method that will place the +crearted worker on the queue of the execution. \ No newline at end of file From b79abf055021244957c9d9095c16078cb810cf87 Mon Sep 17 00:00:00 2001 From: NickNaso Date: Thu, 17 May 2018 11:27:57 +0200 Subject: [PATCH 06/17] Add description for some async worker method --- doc/async_worker.md | 51 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/doc/async_worker.md b/doc/async_worker.md index 06a1058aa..e8731983d 100644 --- a/doc/async_worker.md +++ b/doc/async_worker.md @@ -40,26 +40,44 @@ void Cancel(); ObjectReference& Receiver(); ``` +Returns the persistent object reference of the receiver objet set when the async +worker is created. + ### Callback ```cpp FunctionReference& Callback(); ``` +Returns the persistent function reference of the callback set when the async +worker is created. The returned function reference will be called passing it the +results of the computation happened on the `Execute` method. + ### SetError +Sets the error message for the error happened during the execution. + ```cpp void SetError(const std::string& error); ``` +- `[in] error`: The reference to string that represent the message of the error. + + ### Execute +This method is used to execute some tasks out of the **event loop** on a libuv +worker thread. + ```cpp virtual void Execute() = 0; ``` ### OnOK +This method represents a callback that is invoked when the computation on the +`Excecute` method end. + ```cpp virtual void OnOK(); ``` @@ -70,6 +88,39 @@ virtual void OnOK(); virtual void OnError(const Error& e); ``` +### Constructor + +Creates new async worker + +```cpp +explicit AsyncWorker(const Function& callback); +``` + +### Constructor + +Creates new async worker + +```cpp +explicit AsyncWorker(const Object& receiver, const Function& callback); +``` + +### Destructor + +Deletes the created work object that is used to execute logic asynchronously + +```cpp +virtual ~AsyncWorker(); +``` + +## Operator + +```cpp +operator napi_async_work() const; +``` + +Returns the N-API napi_async_work wrapped by the AsyncWorker object. This can be +used to mix usage of the C N-API and node-addon-api. + ## Example The first step to use `AsyncWorker` class is to create a new class that inherit From bfdd76f1170f45c1697da1388d73cf7e0d34046e Mon Sep 17 00:00:00 2001 From: NickNaso Date: Tue, 22 May 2018 22:14:50 +0200 Subject: [PATCH 07/17] Ececuted changes oafter forst review --- doc/async_operations.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/doc/async_operations.md b/doc/async_operations.md index 082d69841..fb66c9297 100644 --- a/doc/async_operations.md +++ b/doc/async_operations.md @@ -1,13 +1,12 @@ # Asynchronous operations -Node.js native add-ons often need to execute long running tasks and to avoid of -blocking the **event loop** they have to accomplish to them in the asynchronous way. -Lets do a quick overview of how asynchronous code work in Node.js. In our model -of execution we have **two threads**, the first is the **event loop** thread, that -represents the thread where or JavaScript code is executing in. We want avoid to -stall the event loop thread doing heavy computation so we need to create a sencond -thread called **worker thread** managed by **libuv**, the libary that supports the -asynchronous I/O in Node.js. +Node.js native add-ons often need to execute long running tasks and to avoid +blocking the **event loop** they have to run them asynchronously from the +**event loop**. +In the Node.js model of execution there are **two threads**, the first is the +**event loop** thread, that represents the thread where JavaScript code is +executing. The node.js guidance is to avoid you blocking other work queued on the +event loop by. Therefore, we need to do this work on another thread. All this means that native add-ons need to leverage async helpers from libuv as part of their implementation. This allows them to schedule work to be executed From 83103ebfcc1248ec0f09a8c72e0ce8c6e20b4504 Mon Sep 17 00:00:00 2001 From: NickNaso Date: Mon, 11 Jun 2018 23:50:15 +0200 Subject: [PATCH 08/17] Fixed errors reported in the first review and added some missing parts about constructor --- doc/async_operations.md | 12 ++-- doc/async_worker.md | 132 ++++++++++++++++++++++++++++++---------- 2 files changed, 106 insertions(+), 38 deletions(-) diff --git a/doc/async_operations.md b/doc/async_operations.md index fb66c9297..b08a36ace 100644 --- a/doc/async_operations.md +++ b/doc/async_operations.md @@ -5,20 +5,20 @@ blocking the **event loop** they have to run them asynchronously from the **event loop**. In the Node.js model of execution there are **two threads**, the first is the **event loop** thread, that represents the thread where JavaScript code is -executing. The node.js guidance is to avoid you blocking other work queued on the -event loop by. Therefore, we need to do this work on another thread. +executing. The node.js guidance is to avoid blocking other work queued on the +event loop thread. Therefore, we need to do this work on another thread. All this means that native add-ons need to leverage async helpers from libuv as part of their implementation. This allows them to schedule work to be executed asynchronously so that their methods can return in advance of the work being completed. -Node Addon API provides an ABI-stable interface to support functions which covers -the most common asynchronous use cases. You have two abstract class to implement -asynchronous operation: +Node Addon API provides an ABI-stable interface to support functions that cover +the most common asynchronous use cases. There are abstract classes to implement +asynchronous operations: - **[AsyncWorker](async_worker.md)** - **[Async Context](async_context.md)** -These two classes help you to manage asynchronous operations through an abstraction +These two classes help manage asynchronous operations through an abstraction of the concept of moving data between the **event loop** and **worker threads**. \ No newline at end of file diff --git a/doc/async_worker.md b/doc/async_worker.md index e8731983d..04a5dc866 100644 --- a/doc/async_worker.md +++ b/doc/async_worker.md @@ -1,8 +1,8 @@ # AsyncWorker -`AsyncWorker` is an abstract class that you can subclass to remove much of the -tedious tasks on moving data between the event loop and worker threads. This -class internally handles all the details of creating and executing asynchronous +`AsyncWorker` is an abstract class that you can subclass to remove many of the +tedious tasks of moving data between the event loop and worker threads. This +class internally handles all the details of creating and executing an asynchronous operation. ## Methods @@ -19,7 +19,7 @@ Returns the environment in which the async worker has been created. ### Queue -Requests that the created work or task will be placed on the queue of the execution. +Requests that the created work or task will be queued for execution. ```cpp void Queue(); @@ -40,8 +40,8 @@ void Cancel(); ObjectReference& Receiver(); ``` -Returns the persistent object reference of the receiver objet set when the async -worker is created. +Returns the persistent object reference of the receiver object set when the async +worker was created. ### Callback @@ -50,24 +50,23 @@ FunctionReference& Callback(); ``` Returns the persistent function reference of the callback set when the async -worker is created. The returned function reference will be called passing it the -results of the computation happened on the `Execute` method. +worker was created. The returned function reference will receive the results of +the computation that happened in the `Execute` method. ### SetError -Sets the error message for the error happened during the execution. +Sets the error message for the error that happened during the execution. ```cpp void SetError(const std::string& error); ``` -- `[in] error`: The reference to string that represent the message of the error. - +- `[in] error`: The reference to the string that represent the message of the error. ### Execute -This method is used to execute some tasks out of the **event loop** on a libuv -worker thread. +This method is used to execute some tasks out of the **event loop** on a libuv +worker thread. ```cpp virtual void Execute() = 0; @@ -75,8 +74,8 @@ virtual void Execute() = 0; ### OnOK -This method represents a callback that is invoked when the computation on the -`Excecute` method end. +This method represents a callback that is invoked when the computation in the +`Excecute` method ends. ```cpp virtual void OnOK(); @@ -90,23 +89,92 @@ virtual void OnError(const Error& e); ### Constructor -Creates new async worker +Creates new async worker. ```cpp explicit AsyncWorker(const Function& callback); ``` +- ```[in] callback```: The function which will be called when an asynchronous +operations ends. The given function is called from the main event loop thread. + +### Constructor + +Creates new async worker. + +```cpp +explicit AsyncWorker(const Function& callback, const char* resource_name); +``` + +- ```[in] callback```: The function which will be called when an asynchronous +operations ends. The given function is called from the main event loop thread. +- ```[in] resource_name```: Null-terminated strings that represents the +identifier for the kind of resource that is being provided for diagnostic +information exposed by the async_hooks API. + +### Constructor + +Creates new async worker. + +```cpp +explicit AsyncWorker(const Function& callback, const char* resource_name, const Object& resource); +``` + +- ```[in] callback```: The function which will be called when an asynchronous +operations ends. The given function is called from the main event loop thread. +- ```[in] resource_name```: Null-terminated strings that represents the +identifier for the kind of resource that is being provided for diagnostic +information exposed by the async_hooks API. +- ```[in] resource```: Object associated with the asynchronous operation that +will be passed to possible async_hooks. + ### Constructor -Creates new async worker +Creates new async worker. ```cpp explicit AsyncWorker(const Object& receiver, const Function& callback); ``` +- ```[in] receiver```: The `this` object passed to the called function. +- ```[in] callback```: The function which will be called when an asynchronous +operations ends. The given function is called from the main event loop thread. + +### Constructor + +Creates new async worker. + +```cpp +explicit AsyncWorker(const Object& receiver, const Function& callback,const char* resource_name); +``` + +- ```[in] receiver```: The `this` object passed to the called function. +- ```[in] callback```: The function which will be called when an asynchronous +operations ends. The given function is called from the main event loop thread. +- ```[in] resource_name```: Null-terminated strings that represents the +identifier for the kind of resource that is being provided for diagnostic +information exposed by the async_hooks API. + +### Constructor + +Creates new async worker. + +```cpp +explicit AsyncWorker(const Object& receiver, const Function& callback, const char* resource_name, const Object& resource); +``` + +- ```[in] receiver```: The `this` object passed to the called function. +- ```[in] callback```: The function which will be called when an asynchronous +operations ends. The given function is called from the main event loop thread. +- ```[in] resource_name```: Null-terminated strings that represents the +identifier for the kind of resource that is being provided for diagnostic +information exposed by the async_hooks API. +- ```[in] resource```: Object associated with the asynchronous operation that +will be passed to possible async_hooks. + ### Destructor -Deletes the created work object that is used to execute logic asynchronously +Deletes the created work object that is used to execute logic asynchronously. ```cpp virtual ~AsyncWorker(); @@ -123,20 +191,20 @@ used to mix usage of the C N-API and node-addon-api. ## Example -The first step to use `AsyncWorker` class is to create a new class that inherit +The first step to use the `AsyncWorker` class is to create a new class that inherit from it and implement the `Execute` abstract method. Typically input to your -worker will be saved within your fields' class generally passed in through its +worker will be saved within class' fields generally passed in through its constructor. -When the `Execute` method complete without errors the `OnOK` function callback +When the `Execute` method completes without errors the `OnOK` function callback will be invoked. In this function the results of the computation will be -reassembled and returned back to initial JavaScript context. +reassembled and returned back to the initial JavaScript context. -`AsyncWorker` ensure that all the code inside in the `Execute` function runs in -background out of the **event loop** thread and at the end `OnOK` or `OnError` +`AsyncWorker` ensure that all the code in the `Execute` function runs in the +background out of the **event loop** thread and at the end the `OnOK` or `OnError` function will be called and are executed as part of the event loop. -The code below show a basic example of `AsyncWorker` implementation: +The code below show a basic example of `AsyncWorker` the implementation: ```cpp #include @@ -168,12 +236,12 @@ class EchoWorker : public AsyncWorker { }; ``` -The `EchoWorker`'s contructor call the base class's constructor to pass in the +The `EchoWorker`'s contructor call the base class' constructor to pass in the callback that the `AsyncWorker` base class will store persistently. When the work on the `Execute` method is done the `OnOk` method is called and the results return back to JavaScript invoking the stored callback with its associated environment. -The following code show an example on how to create and and use an `AsyncWorker` +The following code shows an example on how to create and and use an `AsyncWorker` ```cpp Value Echo(const CallbackInfo& info) { @@ -185,8 +253,8 @@ Value Echo(const CallbackInfo& info) { return info.Env().Undefined(); ``` -Use the implementation of an `AsyncWorker` is very simple you need only to -create a new instance and pass to its constructor the callback you want exectute -when your asynchronous task end and other data you need for your computation. The -only action you have to do is to call the `Queue` method that will place the -crearted worker on the queue of the execution. \ No newline at end of file +Using the implementation of an `AsyncWorker` is very simple. You need only create +a new instance and pass to its constructor the callback you want to execute when +your asynchronous task ends and other data you need for your computation. The +only action you have to do is to call the `Queue` method that will that will +queue the created worker for execution. \ No newline at end of file From b46fd8dff717f8dfbc5fc5cb128850a405309f6d Mon Sep 17 00:00:00 2001 From: NickNaso Date: Tue, 12 Jun 2018 02:07:56 +0200 Subject: [PATCH 09/17] Fixed error handling documentation ofeter review --- doc/error.md | 60 +++++++++++++---------- doc/error_handling.md | 109 +++++++++++++++++++++++------------------- doc/range_error.md | 30 ++++++------ doc/type_error.md | 32 ++++++------- 4 files changed, 128 insertions(+), 103 deletions(-) diff --git a/doc/error.md b/doc/error.md index ae03cdfa2..9d289c3c3 100644 --- a/doc/error.md +++ b/doc/error.md @@ -2,14 +2,13 @@ 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. +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). +The **Error** class is a persistent reference to a JavaScript error object thus +inherits its behavior from the `ObjectReference` class (for more info see: [ObjectReference](object_reference.md)). -If C++ exceptions are enabled (for more info see: [Setup](setup.md) section), -then the **Error** class extends ```std::exception``` and enables integrated +If C++ exceptions are enabled (for more info see: [Setup](setup.md)), 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 +17,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 empty instance of an `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 instance of an `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 string to be used as the message for the Error. -Returns an instance of ```Error``` object. +Returns instance of an `Error` object. ### New -Creates a new instance of ```Error``` object +Creates instance of an `Error` object ```cpp Error::New(Napi:Env env, const std::string& message); @@ -52,11 +51,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 instance of an `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 empty instance of an `Error`. ```cpp Error(); @@ -64,16 +74,16 @@ Error(); ### Constructor -Initializes a ```Error``` instance from an existing ```Error``` object. +Initializes an `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. -- ```[in] value```: The ```Error``` reference to wrap. +- `[in] Env`: The environment in which to construct the Error object. +- `[in] value`: The `Error` reference to wrap. -Returns an instance of ```Error``` object. +Returns instance of an `Error` object. ### Message @@ -81,15 +91,17 @@ Returns an instance of ```Error``` object. std::string& Message() const NAPI_NOEXCEPT; ``` -Returns the reference to string that represent the message of the error. +Returns the reference to the 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 a JavaScript exception. ### what @@ -98,4 +110,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..1bff430ec 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. - -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. +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)) +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)), 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 -JavaScript. +The statements following the throw statement 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 returning 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 -JavaScript. +The C++ statements following the call to the JavaScript function 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 returning 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(); } ``` @@ -87,12 +95,12 @@ 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)) -before attempting or use a returned value, and may use methods on the **Env** class +If C++ exceptions are disabled (for more info see: [Setup](setup.md)), then the +**Error** class does not extend `std::exception`. This means that any calls to +node-addon-api function do not throw a C++ exceptions. Instead, it raises +_pending_ JavaScript exceptions and returns an _empty_ **Value**. +The calling code should check `Value::IsEmpty()` (for more info see: [Value](value.md)) +before attempting to 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. @@ -102,20 +110,24 @@ 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; ``` -After throwing a JS exception, the code should generally return immediately from -the native callback, after performing any necessary cleanup. +After throwing a JavaScript 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::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..e0bd14d30 100644 --- a/doc/range_error.md +++ b/doc/range_error.md @@ -4,8 +4,8 @@ The **RangeError** class is a representation of the JavaScript RangeError that i 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). +The **RangeError** class inherits its behaviors from the **Error** class (for +more info see: [Error](error.md)). For more details about error handling refer to the section titled [Error handling](error_handling.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 a `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 string to be used as the message for the `RangeError`. -Returns an instance of ```RangeError``` object. +Returns an instance of a `RangeError` object. ### New -Creates a new instance of ```RangeError``` object +Creates a new instance of a `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 a `RangeError` object. ### Constructor -Creates a new empty instance of ```RangeError``` +Creates a new empty instance of a `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 a `RangeError` object. \ No newline at end of file diff --git a/doc/type_error.md b/doc/type_error.md index b9d0e8430..7cfb9d1bf 100644 --- a/doc/type_error.md +++ b/doc/type_error.md @@ -1,11 +1,11 @@ # TypeError -The **TypeError** class is a representation of the JavaScript TypeError that is +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). +The **TypeError** class inherits its behaviors from the **Error** class (for more info +see: [Error](error.md)). For more details about error handling refer to the section titled [Error handling](error_handling.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 the `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 string to be used as the message for the `TypeError`. -Returns an instance of ```TypeError``` object. +Returns an instance of a `TypeError` object. ### New -Creates a new instance of ```TypeError``` object +Creates a new instance of a `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 a `TypeError` object. ### Constructor -Creates a new empty instance of ```TypeError``` +Creates a new empty instance of a `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 a `TypeError` object. \ No newline at end of file From be01a86e22de541ac38e043f890007e3240bb665 Mon Sep 17 00:00:00 2001 From: NickNaso Date: Tue, 12 Jun 2018 20:01:10 +0200 Subject: [PATCH 10/17] Fixed async worker contructor docs --- doc/async_worker.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/async_worker.md b/doc/async_worker.md index 04a5dc866..42115bf21 100644 --- a/doc/async_worker.md +++ b/doc/async_worker.md @@ -89,7 +89,7 @@ virtual void OnError(const Error& e); ### Constructor -Creates new async worker. +Creates a new `AsyncWorker`. ```cpp explicit AsyncWorker(const Function& callback); @@ -100,7 +100,7 @@ operations ends. The given function is called from the main event loop thread. ### Constructor -Creates new async worker. +Creates a new `AsyncWorker`. ```cpp explicit AsyncWorker(const Function& callback, const char* resource_name); @@ -114,7 +114,7 @@ information exposed by the async_hooks API. ### Constructor -Creates new async worker. +Creates a new `AsyncWorker`. ```cpp explicit AsyncWorker(const Function& callback, const char* resource_name, const Object& resource); @@ -130,7 +130,7 @@ will be passed to possible async_hooks. ### Constructor -Creates new async worker. +Creates a new `AsyncWorker`. ```cpp explicit AsyncWorker(const Object& receiver, const Function& callback); @@ -142,7 +142,7 @@ operations ends. The given function is called from the main event loop thread. ### Constructor -Creates new async worker. +Creates a new `AsyncWorker`. ```cpp explicit AsyncWorker(const Object& receiver, const Function& callback,const char* resource_name); @@ -157,7 +157,7 @@ information exposed by the async_hooks API. ### Constructor -Creates new async worker. +Creates a new `AsyncWorker`. ```cpp explicit AsyncWorker(const Object& receiver, const Function& callback, const char* resource_name, const Object& resource); From c7eb8cbadac7a9043a7e5dc66de2103333fa8554 Mon Sep 17 00:00:00 2001 From: NickNaso Date: Tue, 12 Jun 2018 20:20:40 +0200 Subject: [PATCH 11/17] Updated initial description on ansynchronous operation --- doc/async_operations.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/async_operations.md b/doc/async_operations.md index b08a36ace..3d35c47f0 100644 --- a/doc/async_operations.md +++ b/doc/async_operations.md @@ -3,10 +3,10 @@ Node.js native add-ons often need to execute long running tasks and to avoid blocking the **event loop** they have to run them asynchronously from the **event loop**. -In the Node.js model of execution there are **two threads**, the first is the -**event loop** thread, that represents the thread where JavaScript code is -executing. The node.js guidance is to avoid blocking other work queued on the -event loop thread. Therefore, we need to do this work on another thread. +In the Node.js model of execution the event loop thread represents the thread +where JavaScript code is executing. The node.js guidance is to avoid blocking +other work queued on the event loop thread. Therefore, we need to do this work on +another thread. All this means that native add-ons need to leverage async helpers from libuv as part of their implementation. This allows them to schedule work to be executed From 5793481483697a1cd01a8f300bac4d11e7a3fe5f Mon Sep 17 00:00:00 2001 From: NickNaso Date: Thu, 14 Jun 2018 08:49:59 +0200 Subject: [PATCH 12/17] Use one single backtick on constructor doc --- doc/async_worker.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/doc/async_worker.md b/doc/async_worker.md index 42115bf21..c3a72805e 100644 --- a/doc/async_worker.md +++ b/doc/async_worker.md @@ -95,7 +95,7 @@ Creates a new `AsyncWorker`. explicit AsyncWorker(const Function& callback); ``` -- ```[in] callback```: The function which will be called when an asynchronous +- `[in] callback`: The function which will be called when an asynchronous operations ends. The given function is called from the main event loop thread. ### Constructor @@ -106,9 +106,9 @@ Creates a new `AsyncWorker`. explicit AsyncWorker(const Function& callback, const char* resource_name); ``` -- ```[in] callback```: The function which will be called when an asynchronous +- `[in] callback`: The function which will be called when an asynchronous operations ends. The given function is called from the main event loop thread. -- ```[in] resource_name```: Null-terminated strings that represents the +- `[in] resource_name`: Null-terminated strings that represents the identifier for the kind of resource that is being provided for diagnostic information exposed by the async_hooks API. @@ -120,12 +120,12 @@ Creates a new `AsyncWorker`. explicit AsyncWorker(const Function& callback, const char* resource_name, const Object& resource); ``` -- ```[in] callback```: The function which will be called when an asynchronous +- `[in] callback`: The function which will be called when an asynchronous operations ends. The given function is called from the main event loop thread. -- ```[in] resource_name```: Null-terminated strings that represents the +- `[in] resource_name`: Null-terminated strings that represents the identifier for the kind of resource that is being provided for diagnostic information exposed by the async_hooks API. -- ```[in] resource```: Object associated with the asynchronous operation that +- `[in] resource`: Object associated with the asynchronous operation that will be passed to possible async_hooks. ### Constructor @@ -136,8 +136,8 @@ Creates a new `AsyncWorker`. explicit AsyncWorker(const Object& receiver, const Function& callback); ``` -- ```[in] receiver```: The `this` object passed to the called function. -- ```[in] callback```: The function which will be called when an asynchronous +- `[in] receiver`: The `this` object passed to the called function. +- `[in] callback`: The function which will be called when an asynchronous operations ends. The given function is called from the main event loop thread. ### Constructor @@ -148,10 +148,10 @@ Creates a new `AsyncWorker`. explicit AsyncWorker(const Object& receiver, const Function& callback,const char* resource_name); ``` -- ```[in] receiver```: The `this` object passed to the called function. -- ```[in] callback```: The function which will be called when an asynchronous +- `[in] receiver`: The `this` object passed to the called function. +- `[in] callback`: The function which will be called when an asynchronous operations ends. The given function is called from the main event loop thread. -- ```[in] resource_name```: Null-terminated strings that represents the +- `[in] resource_name`: Null-terminated strings that represents the identifier for the kind of resource that is being provided for diagnostic information exposed by the async_hooks API. @@ -163,13 +163,13 @@ Creates a new `AsyncWorker`. explicit AsyncWorker(const Object& receiver, const Function& callback, const char* resource_name, const Object& resource); ``` -- ```[in] receiver```: The `this` object passed to the called function. -- ```[in] callback```: The function which will be called when an asynchronous +- `[in] receiver`: The `this` object passed to the called function. +- `[in] callback`: The function which will be called when an asynchronous operations ends. The given function is called from the main event loop thread. -- ```[in] resource_name```: Null-terminated strings that represents the +- `[in] resource_name`: Null-terminated strings that represents the identifier for the kind of resource that is being provided for diagnostic information exposed by the async_hooks API. -- ```[in] resource```: Object associated with the asynchronous operation that +- `[in] resource`: Object associated with the asynchronous operation that will be passed to possible async_hooks. ### Destructor From 977cf1f07483463982d5a86c2260941bb28e4d4f Mon Sep 17 00:00:00 2001 From: Michael Dawson Date: Thu, 14 Jun 2018 11:20:58 -0400 Subject: [PATCH 13/17] squash: made some suggested changes --- doc/async_operations.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/doc/async_operations.md b/doc/async_operations.md index 3d35c47f0..b8dec37cf 100644 --- a/doc/async_operations.md +++ b/doc/async_operations.md @@ -13,12 +13,11 @@ part of their implementation. This allows them to schedule work to be executed asynchronously so that their methods can return in advance of the work being completed. -Node Addon API provides an ABI-stable interface to support functions that cover -the most common asynchronous use cases. There are abstract classes to implement +Node Addon API provides an interface to support functions that cover +the most common asynchronous use cases. There is an abstract classes to implement asynchronous operations: - **[AsyncWorker](async_worker.md)** -- **[Async Context](async_context.md)** -These two classes help manage asynchronous operations through an abstraction -of the concept of moving data between the **event loop** and **worker threads**. \ No newline at end of file +These class helps manage asynchronous operations through an abstraction +of the concept of moving data between the **event loop** and **worker threads**. From fce33d19bf675509a0deb6db184cbfcce3ce6005 Mon Sep 17 00:00:00 2001 From: Michael Dawson Date: Thu, 14 Jun 2018 11:52:27 -0400 Subject: [PATCH 14/17] squash: add additional details for AsyncWorker --- doc/async_worker.md | 72 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 13 deletions(-) diff --git a/doc/async_worker.md b/doc/async_worker.md index c3a72805e..33ebcae6e 100644 --- a/doc/async_worker.md +++ b/doc/async_worker.md @@ -5,6 +5,14 @@ tedious tasks of moving data between the event loop and worker threads. This class internally handles all the details of creating and executing an asynchronous operation. +Once created, execution is requested by calling `Queue`. When a thread is +available for execution the `Execute` method will be invoked. Once `Execute` +complets either `OnOK` or `OnError` will be invoked. Once the `OnOK` or +`OnError` methods are complete the AsyncWorker instance is destructed. + +For the most basic use, only the `Execute` method must be implemented in a +subclass. + ## Methods ### Env @@ -19,7 +27,7 @@ Returns the environment in which the async worker has been created. ### Queue -Requests that the created work or task will be queued for execution. +Requests that the work be queued for execution. ```cpp void Queue(); @@ -28,7 +36,8 @@ void Queue(); ### Cancel Cancels queued work if it has not yet been started. If it has already started -executing, it cannot be cancelled. +executing, it cannot be cancelled. If cancelled successfully neither +`OnOK` nor `OnError` will be called. ```cpp void Cancel(); @@ -51,11 +60,14 @@ FunctionReference& Callback(); Returns the persistent function reference of the callback set when the async worker was created. The returned function reference will receive the results of -the computation that happened in the `Execute` method. +the computation that happened in the `Execute` method, unless the default +implementation of `OnOK` or `OnError` is overridden. ### SetError -Sets the error message for the error that happened during the execution. +Sets the error message for the error that happened during the execution. Setting +an error message will cause the `OnError` method to be invoked instead of `OnOK` +once the `Execute` method completes. ```cpp void SetError(const std::string& error); @@ -66,7 +78,13 @@ void SetError(const std::string& error); ### Execute This method is used to execute some tasks out of the **event loop** on a libuv -worker thread. +worker thread. Subclasses must implement this method and the method is run on +a thread other than that running the main event loop. As the method is not +running on the main event loop, it must avoid calling any methods from node-addon-api +or running any code that might invoke JavaScript. Instead once this method is +complete any interactive through node-addon-api with JavaScript should be implemented +in the `OnOK` method which runs on the main thread and is invoked when the `Execute` +method completes. ```cpp virtual void Execute() = 0; @@ -74,8 +92,9 @@ virtual void Execute() = 0; ### OnOK -This method represents a callback that is invoked when the computation in the -`Excecute` method ends. +This method is invoked when the computation in the `Excecute` method ends. +The default implementation runs the Callback provided when the AsyncWorker class +was created. ```cpp virtual void OnOK(); @@ -83,6 +102,12 @@ virtual void OnOK(); ### OnError +This method is invoked afer Execute() completes if an error occurs +while `Execute` is running and C++ exceptions are enabled or if an +error was set through a call to `SetError`. The default implementation +calls the callback provided when the AsyncWorker class was created, passing +in the error as the first parameter. + ```cpp virtual void OnError(const Error& e); ``` @@ -98,6 +123,9 @@ explicit AsyncWorker(const Function& callback); - `[in] callback`: The function which will be called when an asynchronous operations ends. The given function is called from the main event loop thread. +Returns an AsyncWork instance which can later be queued for execution by calling +`Queue`. + ### Constructor Creates a new `AsyncWorker`. @@ -112,6 +140,10 @@ operations ends. The given function is called from the main event loop thread. identifier for the kind of resource that is being provided for diagnostic information exposed by the async_hooks API. +Returns an AsyncWork instance which can later be queued for execution by calling +`Queue`. + + ### Constructor Creates a new `AsyncWorker`. @@ -128,6 +160,9 @@ information exposed by the async_hooks API. - `[in] resource`: Object associated with the asynchronous operation that will be passed to possible async_hooks. +Returns an AsyncWork instance which can later be queued for execution by calling +`Queue`. + ### Constructor Creates a new `AsyncWorker`. @@ -140,6 +175,10 @@ explicit AsyncWorker(const Object& receiver, const Function& callback); - `[in] callback`: The function which will be called when an asynchronous operations ends. The given function is called from the main event loop thread. +Returns an AsyncWork instance which can later be queued for execution by calling +`Queue`. + + ### Constructor Creates a new `AsyncWorker`. @@ -155,6 +194,10 @@ operations ends. The given function is called from the main event loop thread. identifier for the kind of resource that is being provided for diagnostic information exposed by the async_hooks API. +Returns an AsyncWork instance which can later be queued for execution by calling +`Queue`. + + ### Constructor Creates a new `AsyncWorker`. @@ -172,6 +215,9 @@ information exposed by the async_hooks API. - `[in] resource`: Object associated with the asynchronous operation that will be passed to possible async_hooks. +Returns an AsyncWork instance which can later be queued for execution by calling +`Queue`. + ### Destructor Deletes the created work object that is used to execute logic asynchronously. @@ -200,7 +246,7 @@ When the `Execute` method completes without errors the `OnOK` function callback will be invoked. In this function the results of the computation will be reassembled and returned back to the initial JavaScript context. -`AsyncWorker` ensure that all the code in the `Execute` function runs in the +`AsyncWorker` ensures that all the code in the `Execute` function runs in the background out of the **event loop** thread and at the end the `OnOK` or `OnError` function will be called and are executed as part of the event loop. @@ -236,7 +282,7 @@ class EchoWorker : public AsyncWorker { }; ``` -The `EchoWorker`'s contructor call the base class' constructor to pass in the +The `EchoWorker`'s contructor calls the base class' constructor to pass in the callback that the `AsyncWorker` base class will store persistently. When the work on the `Execute` method is done the `OnOk` method is called and the results return back to JavaScript invoking the stored callback with its associated environment. @@ -253,8 +299,8 @@ Value Echo(const CallbackInfo& info) { return info.Env().Undefined(); ``` -Using the implementation of an `AsyncWorker` is very simple. You need only create +Using the implementation of an `AsyncWorker` is straight forward. You need only create a new instance and pass to its constructor the callback you want to execute when -your asynchronous task ends and other data you need for your computation. The -only action you have to do is to call the `Queue` method that will that will -queue the created worker for execution. \ No newline at end of file +your asynchronous task ends and other data you need for your computation. Once created the +only other action you have to do is to call the `Queue` method that will that will +queue the created worker for execution. From 1c87b82c3e98562b2be8b2be326e5a1ffea43b5d Mon Sep 17 00:00:00 2001 From: Michael Dawson Date: Thu, 14 Jun 2018 12:13:08 -0400 Subject: [PATCH 15/17] squash: Add some info/edits for error_handling.md --- doc/error_handling.md | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/doc/error_handling.md b/doc/error_handling.md index 1bff430ec..d56281575 100644 --- a/doc/error_handling.md +++ b/doc/error_handling.md @@ -2,7 +2,7 @@ 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 +have to handle and dispatch it correctly. **node-addon-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. @@ -21,25 +21,30 @@ The following sections explain the approach for each case: +In most cases when an error occurs, the addon should do whatever clean is possible +and then return to JavaScript so that they error can be propagated. In less frequent +cases the addon may be able to recover from the error, clear the error and then +continue. + ## 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 +If a node-addon-api call fails without executing any JavaScript code (for example due to +an invalid argument), then node-addon-api 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++ +If a JavaScript function called by C++ code via node-addon-api throws a JavaScript +exception, then node-addon-api 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++ +On return from a native method, node-addon-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 @@ -99,11 +104,11 @@ If C++ exceptions are disabled (for more info see: [Setup](setup.md)), then the **Error** class does not extend `std::exception`. This means that any calls to node-addon-api function do not throw a C++ exceptions. Instead, it raises _pending_ JavaScript exceptions and returns an _empty_ **Value**. -The calling code should check `Value::IsEmpty()` (for more info see: [Value](value.md)) -before attempting to use a returned value, and may use methods on the **Env** class +The calling code should check `env.IsExceptionPending()` before attempting to 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. +returns to JavaScript. ## Examples with C++ exceptions disabled @@ -130,7 +135,7 @@ if (env.IsExceptionPending()) { } ``` -An empty value result from a N-API call indicates that an error occurred, and a +If env.IsExceptionPending() is returns true 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. @@ -148,4 +153,4 @@ if (env.IsExceptionPending()) { ``` 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 +exception after the native callback returns. From 5a3cc8507535cadf996f7ce836c3b2648fe3eeea Mon Sep 17 00:00:00 2001 From: Michael Dawson Date: Thu, 14 Jun 2018 12:20:34 -0400 Subject: [PATCH 16/17] squash: address comments --- doc/error.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/error.md b/doc/error.md index 9d289c3c3..dc5e7ea07 100644 --- a/doc/error.md +++ b/doc/error.md @@ -48,8 +48,8 @@ Creates instance of an `Error` object 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. +- `[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 instance of an `Error` object. @@ -72,6 +72,8 @@ Creates empty instance of an `Error`. Error(); ``` +Returns an instance of `Error` object. + ### Constructor Initializes an `Error` instance from an existing JavaScript error object. @@ -110,4 +112,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 exception mechanism is enabled. \ No newline at end of file +exception. This method can be used only if the exception mechanism is enabled. From c5906f27e45b99e6cd624d37e7289acff42e9daf Mon Sep 17 00:00:00 2001 From: Michael Dawson Date: Thu, 14 Jun 2018 17:19:01 -0400 Subject: [PATCH 17/17] squash: fix typo --- doc/async_worker.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/async_worker.md b/doc/async_worker.md index 33ebcae6e..0d78c1b62 100644 --- a/doc/async_worker.md +++ b/doc/async_worker.md @@ -82,7 +82,7 @@ worker thread. Subclasses must implement this method and the method is run on a thread other than that running the main event loop. As the method is not running on the main event loop, it must avoid calling any methods from node-addon-api or running any code that might invoke JavaScript. Instead once this method is -complete any interactive through node-addon-api with JavaScript should be implemented +complete any interaction through node-addon-api with JavaScript should be implemented in the `OnOK` method which runs on the main thread and is invoked when the `Execute` method completes.