node-addon-api 1.6.1 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +112 -4
- package/CONTRIBUTING.md +66 -0
- package/README.md +33 -6
- package/doc/async_worker.md +91 -11
- package/doc/basic_types.md +11 -0
- package/doc/class_property_descriptor.md +85 -3
- package/doc/creating_a_release.md +37 -16
- package/doc/error_handling.md +31 -0
- package/doc/function_reference.md +2 -2
- package/doc/number.md +5 -5
- package/doc/object.md +5 -5
- package/doc/object_reference.md +2 -2
- package/doc/object_wrap.md +2 -2
- package/doc/prebuild_tools.md +1 -1
- package/doc/property_descriptor.md +1 -1
- package/doc/setup.md +13 -2
- package/doc/string.md +3 -0
- package/doc/threadsafe_function.md +303 -0
- package/index.js +1 -0
- package/napi-inl.deprecated.h +2 -2
- package/napi-inl.h +510 -83
- package/napi.h +280 -10
- package/package.json +19 -2
- package/tools/README.md +2 -2
|
@@ -1,30 +1,51 @@
|
|
|
1
1
|
# Creating a release
|
|
2
2
|
|
|
3
|
-
Only collaborators in npm for node-addon-api can create releases.
|
|
3
|
+
Only collaborators in npm for **node-addon-api** can create releases.
|
|
4
4
|
If you want to be able to do releases ask one of the existing
|
|
5
|
-
collaborators to add you.
|
|
5
|
+
collaborators to add you. If necessary you can ask the build
|
|
6
6
|
Working Group who manages the Node.js npm user to add you if
|
|
7
7
|
there are no other active collaborators.
|
|
8
8
|
|
|
9
|
+
## Prerequisites
|
|
10
|
+
|
|
11
|
+
Before to start creating a new release check if you have installed the following
|
|
12
|
+
tools:
|
|
13
|
+
|
|
14
|
+
* [Changelog maker](https://www.npmjs.com/package/changelog-maker)
|
|
15
|
+
|
|
16
|
+
If not please follow the instruction reported in the tool's documentation to
|
|
17
|
+
install it.
|
|
18
|
+
|
|
19
|
+
## Publish new release
|
|
20
|
+
|
|
9
21
|
These are the steps to follow to create a new release:
|
|
10
22
|
|
|
11
|
-
* Open an issue in the node-addon-api repo documenting
|
|
12
|
-
|
|
13
|
-
time to comment or suggest PRs that should land first.
|
|
23
|
+
* Open an issue in the **node-addon-api** repo documenting the intent to create a
|
|
24
|
+
new release. Give people some time to comment or suggest PRs that should land first.
|
|
14
25
|
|
|
15
26
|
* Validate all tests pass by running npm test on master.
|
|
16
27
|
|
|
17
|
-
*
|
|
18
|
-
to validate tests pass for latest 9, 8, 6, 4 releases
|
|
19
|
-
(note there are still some issues on SmartOS and
|
|
20
|
-
Windows in the testing).
|
|
28
|
+
* Update the version in **package.json** appropriately.
|
|
21
29
|
|
|
22
|
-
* Update the
|
|
30
|
+
* Update the [README.md](https://github.com/nodejs/node-addon-api/blob/master/README.md)
|
|
31
|
+
to show the new version as the latest.
|
|
23
32
|
|
|
24
|
-
*
|
|
33
|
+
* Generate the changelog for the new version using **changelog maker** tool. From
|
|
34
|
+
the route folder of the repo launch the following command:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
> changelog-maker
|
|
38
|
+
```
|
|
39
|
+
* Use the output generated by **changelog maker** to pdate the [CHANGELOG.md](https://github.com/nodejs/node-addon-api/blob/master/CHANGELOG.md)
|
|
40
|
+
following the style used in publishing the previous release.
|
|
41
|
+
|
|
42
|
+
* Add any new contributors to the "contributors" section in the package.json
|
|
43
|
+
|
|
44
|
+
* Validate all tests pass by running npm test on master.
|
|
25
45
|
|
|
26
|
-
*
|
|
27
|
-
|
|
46
|
+
* Use **[CI](https://ci.nodejs.org/view/x%20-%20Abi%20stable%20module%20API/job/node-test-node-addon-api/)**
|
|
47
|
+
to validate tests pass for latest 11, 10, 8, 6 releases (note there are still some issues on SmartOS and
|
|
48
|
+
Windows in the testing).
|
|
28
49
|
|
|
29
50
|
* Do a clean checkout of node-addon-api.
|
|
30
51
|
|
|
@@ -33,9 +54,9 @@ These are the steps to follow to create a new release:
|
|
|
33
54
|
* Create a release in Github (look at existing releases for an example).
|
|
34
55
|
|
|
35
56
|
* Validate that you can run `npm install node-addon-api` successfully
|
|
36
|
-
|
|
57
|
+
and that the correct version is installed.
|
|
37
58
|
|
|
38
|
-
* Comment on the issue opened in the first step that the
|
|
39
|
-
|
|
59
|
+
* Comment on the issue opened in the first step that the release has been created
|
|
60
|
+
and close the issue.
|
|
40
61
|
|
|
41
62
|
* Tweet that the release has been created.
|
package/doc/error_handling.md
CHANGED
|
@@ -153,3 +153,34 @@ if (env.IsExceptionPending()) {
|
|
|
153
153
|
|
|
154
154
|
Since the exception was cleared here, it will not be propagated as a JavaScript
|
|
155
155
|
exception after the native callback returns.
|
|
156
|
+
|
|
157
|
+
## Calling N-API directly from a **node-addon-api** addon
|
|
158
|
+
|
|
159
|
+
**node-addon-api** provides macros for throwing errors in response to non-OK
|
|
160
|
+
`napi_status` results when calling [N-API](https://nodejs.org/docs/latest/api/n-api.html)
|
|
161
|
+
functions from within a native addon. These macros are defined differently
|
|
162
|
+
depending on whether C++ exceptions are enabled or not, but are available for
|
|
163
|
+
use in either case.
|
|
164
|
+
|
|
165
|
+
### `NAPI_THROW(e, ...)`
|
|
166
|
+
|
|
167
|
+
This macro accepts a `Napi::Error`, throws it, and returns the value given as
|
|
168
|
+
the last parameter. If C++ exceptions are enabled (by defining
|
|
169
|
+
`NAPI_CPP_EXCEPTIONS` during the build), the return value will be ignored.
|
|
170
|
+
|
|
171
|
+
### `NAPI_THROW_IF_FAILED(env, status, ...)`
|
|
172
|
+
|
|
173
|
+
This macro accepts a `Napi::Env` and a `napi_status`. It constructs an error
|
|
174
|
+
from the `napi_status`, throws it, and returns the value given as the last
|
|
175
|
+
parameter. If C++ exceptions are enabled (by defining `NAPI_CPP_EXCEPTIONS`
|
|
176
|
+
during the build), the return value will be ignored.
|
|
177
|
+
|
|
178
|
+
### `NAPI_THROW_IF_FAILED_VOID(env, status)`
|
|
179
|
+
|
|
180
|
+
This macro accepts a `Napi::Env` and a `napi_status`. It constructs an error
|
|
181
|
+
from the `napi_status`, throws it, and returns.
|
|
182
|
+
|
|
183
|
+
### `NAPI_FATAL_IF_FAILED(status, location, message)`
|
|
184
|
+
|
|
185
|
+
This macro accepts a `napi_status`, a C string indicating the location where the
|
|
186
|
+
error occurred, and a second C string for the message to display.
|
|
@@ -23,7 +23,7 @@ Creates a "weak" reference to the value, in that the initial reference count is
|
|
|
23
23
|
set to 0.
|
|
24
24
|
|
|
25
25
|
```cpp
|
|
26
|
-
static Napi::FunctionReference Napi::
|
|
26
|
+
static Napi::FunctionReference Napi::Weak(const Napi::Function& value);
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
- `[in] value`: The value which is to be referenced.
|
|
@@ -36,7 +36,7 @@ Creates a "persistent" reference to the value, in that the initial reference
|
|
|
36
36
|
count is set to 1.
|
|
37
37
|
|
|
38
38
|
```cpp
|
|
39
|
-
static Napi::FunctionReference Napi::
|
|
39
|
+
static Napi::FunctionReference Napi::Persistent(const Napi::Function& value);
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
- `[in] value`: The value which is to be referenced.
|
package/doc/number.md
CHANGED
|
@@ -24,8 +24,8 @@ Creates a new instance of a `Napi::Number` object.
|
|
|
24
24
|
Napi::Number(napi_env env, napi_value value);
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
- `[in] env`: The `napi_env` environment in which to construct the `Napi::
|
|
28
|
-
- `[in] value`: The
|
|
27
|
+
- `[in] env`: The `napi_env` environment in which to construct the `Napi::Number` object.
|
|
28
|
+
- `[in] value`: The JavaScript value holding a number.
|
|
29
29
|
|
|
30
30
|
Returns a non-empty `Napi::Number` object.
|
|
31
31
|
|
|
@@ -36,14 +36,14 @@ Napi::Number(napi_env env, napi_value value);
|
|
|
36
36
|
```cpp
|
|
37
37
|
Napi::Number Napi::Number::New(napi_env env, double value);
|
|
38
38
|
```
|
|
39
|
-
- `[in] env`: The `napi_env` environment in which to construct the `Napi::
|
|
40
|
-
- `[in] value`: The
|
|
39
|
+
- `[in] env`: The `napi_env` environment in which to construct the `Napi::Number` object.
|
|
40
|
+
- `[in] value`: The C++ primitive from which to instantiate the `Napi::Number`.
|
|
41
41
|
|
|
42
42
|
Creates a new instance of a `Napi::Number` object.
|
|
43
43
|
|
|
44
44
|
### Int32Value
|
|
45
45
|
|
|
46
|
-
Converts a `Napi::Number` value to a `
|
|
46
|
+
Converts a `Napi::Number` value to a `int32_t` primitive type.
|
|
47
47
|
|
|
48
48
|
```cpp
|
|
49
49
|
Napi::Number::Int32Value() const;
|
package/doc/object.md
CHANGED
|
@@ -23,12 +23,12 @@ Void Init(Env env) {
|
|
|
23
23
|
|
|
24
24
|
// Assign values to properties
|
|
25
25
|
obj.Set("hello", "world");
|
|
26
|
-
obj.Set(42, "The Answer to Life, the Universe, and Everything");
|
|
26
|
+
obj.Set(uint32_t(42), "The Answer to Life, the Universe, and Everything");
|
|
27
27
|
obj.Set("Douglas Adams", true);
|
|
28
28
|
|
|
29
29
|
// Get properties
|
|
30
30
|
Value val1 = obj.Get("hello");
|
|
31
|
-
Value val2 = obj.Get(42);
|
|
31
|
+
Value val2 = obj.Get(uint32_t(42));
|
|
32
32
|
Value val3 = obj.Get("Douglas Adams");
|
|
33
33
|
|
|
34
34
|
// Test if objects have properties.
|
|
@@ -108,7 +108,7 @@ Napi::Value Napi::Object::Get(____ key);
|
|
|
108
108
|
```
|
|
109
109
|
- `[in] key`: The name of the property to return the value for.
|
|
110
110
|
|
|
111
|
-
Returns the [`Napi::Value`](value.md) associated with the key property. Returns
|
|
111
|
+
Returns the [`Napi::Value`](value.md) associated with the key property. Returns the value *undefined* if the key does not exist.
|
|
112
112
|
|
|
113
113
|
The `key` can be any of the following types:
|
|
114
114
|
- `napi_value`
|
|
@@ -142,7 +142,7 @@ Note: This is equivalent to the JavaScript instanceof operator.
|
|
|
142
142
|
```cpp
|
|
143
143
|
void Napi::Object::DefineProperty (const Napi::PropertyDescriptor& property);
|
|
144
144
|
```
|
|
145
|
-
- `[in] property`: A [`Napi::PropertyDescriptor`](
|
|
145
|
+
- `[in] property`: A [`Napi::PropertyDescriptor`](property_descriptor.md).
|
|
146
146
|
|
|
147
147
|
Define a property on the object.
|
|
148
148
|
|
|
@@ -151,7 +151,7 @@ Define a property on the object.
|
|
|
151
151
|
```cpp
|
|
152
152
|
void Napi::Object::DefineProperties (____ properties)
|
|
153
153
|
```
|
|
154
|
-
- `[in] properties`: A list of [`Napi::PropertyDescriptor`](
|
|
154
|
+
- `[in] properties`: A list of [`Napi::PropertyDescriptor`](property_descriptor.md). Can be one of the following types:
|
|
155
155
|
- const std::initializer_list<Napi::PropertyDescriptor>&
|
|
156
156
|
- const std::vector<Napi::PropertyDescriptor>&
|
|
157
157
|
|
package/doc/object_reference.md
CHANGED
|
@@ -40,7 +40,7 @@ static Napi::ObjectReference Napi::ObjectReference::New(const Napi::Object& valu
|
|
|
40
40
|
Returns the newly created reference.
|
|
41
41
|
|
|
42
42
|
```cpp
|
|
43
|
-
static Napi::ObjectReference Napi::
|
|
43
|
+
static Napi::ObjectReference Napi::Weak(const Napi::Object& value);
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
Creates a "weak" reference to the value, in that the initial count of number of references is set to 0.
|
|
@@ -50,7 +50,7 @@ Creates a "weak" reference to the value, in that the initial count of number of
|
|
|
50
50
|
Returns the newly created reference.
|
|
51
51
|
|
|
52
52
|
```cpp
|
|
53
|
-
static Napi::ObjectReference Napi::
|
|
53
|
+
static Napi::ObjectReference Napi::Persistent(const Napi::Object& value);
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
Creates a "persistent" reference to the value, in that the initial count of number of references is set to 1.
|
package/doc/object_wrap.md
CHANGED
|
@@ -78,7 +78,7 @@ Napi::Object Init (Napi::Env env, Napi::Object exports) {
|
|
|
78
78
|
return exports;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
//
|
|
81
|
+
// Register and initialize native add-on
|
|
82
82
|
NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)
|
|
83
83
|
```
|
|
84
84
|
|
|
@@ -116,7 +116,7 @@ against the class constructor.
|
|
|
116
116
|
|
|
117
117
|
## Methods
|
|
118
118
|
|
|
119
|
-
###
|
|
119
|
+
### Constructor
|
|
120
120
|
|
|
121
121
|
Creates a new instance of a JavaScript object that wraps native instance.
|
|
122
122
|
|
package/doc/prebuild_tools.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
The distribution of a native add-on is just as important as its implementation.
|
|
4
4
|
In order to install a native add-on it's important to have all the necessary
|
|
5
|
-
dependencies installed and well configured (see the [setup](
|
|
5
|
+
dependencies installed and well configured (see the [setup](setup.md) section).
|
|
6
6
|
The end-user will need to compile the add-on when they will do an `npm install`
|
|
7
7
|
and in some cases this could create problems. To avoid the compilation process it's
|
|
8
8
|
possible to ditribute the native add-on in pre-built form for different platform
|
|
@@ -192,7 +192,7 @@ static Napi::PropertyDescriptor Napi::PropertyDescriptor::Function (
|
|
|
192
192
|
void *data = nullptr);
|
|
193
193
|
```
|
|
194
194
|
|
|
195
|
-
* `[in] env`: The
|
|
195
|
+
* `[in] env`: The environment in which to create this accessor.
|
|
196
196
|
* `[in] name`: The name of the Callable function.
|
|
197
197
|
* `[in] cb`: The function
|
|
198
198
|
* `[in] attributes`: Potential attributes for the getter function.
|
package/doc/setup.md
CHANGED
|
@@ -55,8 +55,19 @@ To use **N-API** in a native module:
|
|
|
55
55
|
```gyp
|
|
56
56
|
'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],
|
|
57
57
|
```
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
4. If you would like your native addon to support OSX, please also add the
|
|
59
|
+
following settings in the `binding.gyp` file:
|
|
60
|
+
|
|
61
|
+
```gyp
|
|
62
|
+
['OS=="mac"', {
|
|
63
|
+
'cflags+': ['-fvisibility=hidden'],
|
|
64
|
+
'xcode_settings': {
|
|
65
|
+
'GCC_SYMBOLS_PRIVATE_EXTERN': 'YES', # -fvisibility=hidden
|
|
66
|
+
}
|
|
67
|
+
}]
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
5. Include `napi.h` in the native module code.
|
|
60
71
|
To ensure only ABI-stable APIs are used, DO NOT include
|
|
61
72
|
`node.h`, `nan.h`, or `v8.h`.
|
|
62
73
|
|
package/doc/string.md
CHANGED
|
@@ -56,6 +56,8 @@ Napi::String::New(napi_env env, const std::string& value);
|
|
|
56
56
|
Napi::String::New(napi_env env, const std::u16::string& value);
|
|
57
57
|
Napi::String::New(napi_env env, const char* value);
|
|
58
58
|
Napi::String::New(napi_env env, const char16_t* value);
|
|
59
|
+
Napi::String::New(napi_env env, const char* value, size_t length);
|
|
60
|
+
Napi::String::New(napi_env env, const char16_t* value, size_t length);
|
|
59
61
|
```
|
|
60
62
|
|
|
61
63
|
- `[in] env`: The `napi_env` environment in which to construct the `Napi::Value` object.
|
|
@@ -64,6 +66,7 @@ Napi::String::New(napi_env env, const char16_t* value);
|
|
|
64
66
|
- `std::u16string&` - represents a UTF16-LE string.
|
|
65
67
|
- `const char*` - represents a UTF8 string.
|
|
66
68
|
- `const char16_t*` - represents a UTF16-LE string.
|
|
69
|
+
- `[in] length`: The length of the string (not necessarily null-terminated) in code units.
|
|
67
70
|
|
|
68
71
|
Returns a new `Napi::String` that represents the passed in C++ string.
|
|
69
72
|
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
# ThreadSafeFunction
|
|
2
|
+
|
|
3
|
+
JavaScript functions can normally only be called from a native addon's main
|
|
4
|
+
thread. If an addon creates additional threads, then node-addon-api functions
|
|
5
|
+
that require a `Napi::Env`, `Napi::Value`, or `Napi::Reference` must not be
|
|
6
|
+
called from those threads.
|
|
7
|
+
|
|
8
|
+
When an addon has additional threads and JavaScript functions need to be invoked
|
|
9
|
+
based on the processing completed by those threads, those threads must
|
|
10
|
+
communicate with the addon's main thread so that the main thread can invoke the
|
|
11
|
+
JavaScript function on their behalf. The thread-safe function APIs provide an
|
|
12
|
+
easy way to do this.
|
|
13
|
+
|
|
14
|
+
These APIs provide the type `Napi::ThreadSafeFunction` as well as APIs to
|
|
15
|
+
create, destroy, and call objects of this type.
|
|
16
|
+
`Napi::ThreadSafeFunction::New()` creates a persistent reference that holds a
|
|
17
|
+
JavaScript function which can be called from multiple threads. The calls happen
|
|
18
|
+
asynchronously. This means that values with which the JavaScript callback is to
|
|
19
|
+
be called will be placed in a queue, and, for each value in the queue, a call
|
|
20
|
+
will eventually be made to the JavaScript function.
|
|
21
|
+
|
|
22
|
+
`Napi::ThreadSafeFunction` objects are destroyed when every thread which uses
|
|
23
|
+
the object has called `Release()` or has received a return status of
|
|
24
|
+
`napi_closing` in response to a call to `BlockingCall()` or `NonBlockingCall()`.
|
|
25
|
+
The queue is emptied before the `Napi::ThreadSafeFunction` is destroyed. It is
|
|
26
|
+
important that `Release()` be the last API call made in conjunction with a given
|
|
27
|
+
`Napi::ThreadSafeFunction`, because after the call completes, there is no
|
|
28
|
+
guarantee that the `Napi::ThreadSafeFunction` is still allocated. For the same
|
|
29
|
+
reason it is also important that no more use be made of a thread-safe function
|
|
30
|
+
after receiving a return value of `napi_closing` in response to a call to
|
|
31
|
+
`BlockingCall()` or `NonBlockingCall()`. Data associated with the
|
|
32
|
+
`Napi::ThreadSafeFunction` can be freed in its `Finalizer` callback which was
|
|
33
|
+
passed to `ThreadSafeFunction::New()`.
|
|
34
|
+
|
|
35
|
+
Once the number of threads making use of a `Napi::ThreadSafeFunction` reaches
|
|
36
|
+
zero, no further threads can start making use of it by calling `Acquire()`. In
|
|
37
|
+
fact, all subsequent API calls associated with it, except `Release()`, will
|
|
38
|
+
return an error value of `napi_closing`.
|
|
39
|
+
|
|
40
|
+
## Methods
|
|
41
|
+
|
|
42
|
+
### Constructor
|
|
43
|
+
|
|
44
|
+
Creates a new empty instance of `Napi::ThreadSafeFunction`.
|
|
45
|
+
|
|
46
|
+
```cpp
|
|
47
|
+
Napi::Function::ThreadSafeFunction();
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Constructor
|
|
51
|
+
|
|
52
|
+
Creates a new instance of the `Napi::ThreadSafeFunction` object.
|
|
53
|
+
|
|
54
|
+
```cpp
|
|
55
|
+
Napi::ThreadSafeFunction::ThreadSafeFunction(napi_threadsafe_function tsfn);
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
- `tsfn`: The `napi_threadsafe_function` which is a handle for an existing
|
|
59
|
+
thread-safe function.
|
|
60
|
+
|
|
61
|
+
Returns a non-empty `Napi::ThreadSafeFunction` instance.
|
|
62
|
+
|
|
63
|
+
### New
|
|
64
|
+
|
|
65
|
+
Creates a new instance of the `Napi::ThreadSafeFunction` object. The `New`
|
|
66
|
+
function has several overloads for the various optional parameters: skip the
|
|
67
|
+
optional parameter for that specific overload.
|
|
68
|
+
|
|
69
|
+
```cpp
|
|
70
|
+
New(napi_env env,
|
|
71
|
+
const Function& callback,
|
|
72
|
+
const Object& resource,
|
|
73
|
+
ResourceString resourceName,
|
|
74
|
+
size_t maxQueueSize,
|
|
75
|
+
size_t initialThreadCount,
|
|
76
|
+
ContextType* context,
|
|
77
|
+
Finalizer finalizeCallback,
|
|
78
|
+
FinalizerDataType* data);
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
- `env`: The `napi_env` environment in which to construct the
|
|
82
|
+
`Napi::ThreadSafeFunction` object.
|
|
83
|
+
- `callback`: The `Function` to call from another thread.
|
|
84
|
+
- `[optional] resource`: An object associated with the async work that will be
|
|
85
|
+
passed to possible async_hooks init hooks.
|
|
86
|
+
- `resourceName`: A JavaScript string to provide an identifier for the kind of
|
|
87
|
+
resource that is being provided for diagnostic information exposed by the
|
|
88
|
+
async_hooks API.
|
|
89
|
+
- `maxQueueSize`: Maximum size of the queue. `0` for no limit.
|
|
90
|
+
- `initialThreadCount`: The initial number of threads, including the main
|
|
91
|
+
thread, which will be making use of this function.
|
|
92
|
+
- `[optional] context`: Data to attach to the resulting `ThreadSafeFunction`.
|
|
93
|
+
- `[optional] finalizeCallback`: Function to call when the `ThreadSafeFunction`
|
|
94
|
+
is being destroyed. This callback will be invoked on the main thread when the
|
|
95
|
+
thread-safe function is about to be destroyed. It receives the context and the
|
|
96
|
+
finalize data given during construction (if given), and provides an
|
|
97
|
+
opportunity for cleaning up after the threads e.g. by calling
|
|
98
|
+
`uv_thread_join()`. It is important that, aside from the main loop thread,
|
|
99
|
+
there be no threads left using the thread-safe function after the finalize
|
|
100
|
+
callback completes. Must implement `void operator()(Env env, DataType* data,
|
|
101
|
+
Context* hint)`, skipping `data` or `hint` if they are not provided.
|
|
102
|
+
Can be retreived via `GetContext()`.
|
|
103
|
+
- `[optional] data`: Data to be passed to `finalizeCallback`.
|
|
104
|
+
|
|
105
|
+
Returns a non-empty `Napi::ThreadSafeFunction` instance.
|
|
106
|
+
|
|
107
|
+
### Acquire
|
|
108
|
+
|
|
109
|
+
Add a thread to this thread-safe function object, indicating that a new thread
|
|
110
|
+
will start making use of the thread-safe function.
|
|
111
|
+
|
|
112
|
+
```cpp
|
|
113
|
+
napi_status Napi::ThreadSafeFunction::Acquire()
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Returns one of:
|
|
117
|
+
- `napi_ok`: The thread has successfully acquired the thread-safe function
|
|
118
|
+
for its use.
|
|
119
|
+
- `napi_closing`: The thread-safe function has been marked as closing via a
|
|
120
|
+
previous call to `Abort()`.
|
|
121
|
+
|
|
122
|
+
### Release
|
|
123
|
+
|
|
124
|
+
Indicate that an existing thread will stop making use of the thread-safe
|
|
125
|
+
function. A thread should call this API when it stops making use of this
|
|
126
|
+
thread-safe function. Using any thread-safe APIs after having called this API
|
|
127
|
+
has undefined results in the current thread, as it may have been destroyed.
|
|
128
|
+
|
|
129
|
+
```cpp
|
|
130
|
+
napi_status Napi::ThreadSafeFunction::Release()
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Returns one of:
|
|
134
|
+
- `napi_ok`: The thread-safe function has been successfully released.
|
|
135
|
+
- `napi_invalid_arg`: The thread-safe function's thread-count is zero.
|
|
136
|
+
- `napi_generic_failure`: A generic error occurred when attemping to release
|
|
137
|
+
the thread-safe function.
|
|
138
|
+
|
|
139
|
+
### Abort
|
|
140
|
+
|
|
141
|
+
"Abort" the thread-safe function. This will cause all subsequent APIs associated
|
|
142
|
+
with the thread-safe function except `Release()` to return `napi_closing` even
|
|
143
|
+
before its reference count reaches zero. In particular, `BlockingCall` and
|
|
144
|
+
`NonBlockingCall()` will return `napi_closing`, thus informing the threads that
|
|
145
|
+
it is no longer possible to make asynchronous calls to the thread-safe function.
|
|
146
|
+
This can be used as a criterion for terminating the thread. Upon receiving a
|
|
147
|
+
return value of `napi_closing` from a thread-safe function call a thread must
|
|
148
|
+
make no further use of the thread-safe function because it is no longer
|
|
149
|
+
guaranteed to be allocated.
|
|
150
|
+
|
|
151
|
+
```cpp
|
|
152
|
+
napi_status Napi::ThreadSafeFunction::Abort()
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Returns one of:
|
|
156
|
+
- `napi_ok`: The thread-safe function has been successfully aborted.
|
|
157
|
+
- `napi_invalid_arg`: The thread-safe function's thread-count is zero.
|
|
158
|
+
- `napi_generic_failure`: A generic error occurred when attemping to abort
|
|
159
|
+
the thread-safe function.
|
|
160
|
+
|
|
161
|
+
### BlockingCall / NonBlockingCall
|
|
162
|
+
|
|
163
|
+
Calls the Javascript function in either a blocking or non-blocking fashion.
|
|
164
|
+
- `BlockingCall()`: the API blocks until space becomes available in the queue.
|
|
165
|
+
Will never block if the thread-safe function was created with a maximum queue
|
|
166
|
+
size of `0`.
|
|
167
|
+
- `NonBlockingCall()`: will return `napi_queue_full` if the queue was full,
|
|
168
|
+
preventing data from being successfully added to the queue.
|
|
169
|
+
|
|
170
|
+
There are several overloaded implementations of `BlockingCall()` and
|
|
171
|
+
`NonBlockingCall()` for use with optional parameters: skip the optional
|
|
172
|
+
parameter for that specific overload.
|
|
173
|
+
|
|
174
|
+
```cpp
|
|
175
|
+
napi_status Napi::ThreadSafeFunction::BlockingCall(DataType* data, Callback callback) const
|
|
176
|
+
|
|
177
|
+
napi_status Napi::ThreadSafeFunction::NonBlockingCall(DataType* data, Callback callback) const
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
- `[optional] data`: Data to pass to `callback`.
|
|
181
|
+
- `[optional] callback`: C++ function that is invoked on the main thread. The
|
|
182
|
+
callback receives the `ThreadSafeFunction`'s JavaScript callback function to
|
|
183
|
+
call as an `Napi::Function` in its parameters and the `DataType*` data pointer
|
|
184
|
+
(if provided). Must implement `void operator()(Napi::Env env, Function
|
|
185
|
+
jsCallback, DataType* data)`, skipping `data` if not provided. It is not
|
|
186
|
+
necessary to call into JavaScript via `MakeCallback()` because N-API runs
|
|
187
|
+
`callback` in a context appropriate for callbacks.
|
|
188
|
+
|
|
189
|
+
Returns one of:
|
|
190
|
+
- `napi_ok`: The call was successfully added to the queue.
|
|
191
|
+
- `napi_queue_full`: The queue was full when trying to call in a non-blocking
|
|
192
|
+
method.
|
|
193
|
+
- `napi_closing`: The thread-safe function is aborted and cannot accept more
|
|
194
|
+
calls.
|
|
195
|
+
- `napi_invalid_arg`: The thread-safe function is closed.
|
|
196
|
+
- `napi_generic_failure`: A generic error occurred when attemping to add to the
|
|
197
|
+
queue.
|
|
198
|
+
|
|
199
|
+
## Example
|
|
200
|
+
|
|
201
|
+
```cpp
|
|
202
|
+
#include <chrono>
|
|
203
|
+
#include <thread>
|
|
204
|
+
#include <napi.h>
|
|
205
|
+
|
|
206
|
+
using namespace Napi;
|
|
207
|
+
|
|
208
|
+
std::thread nativeThread;
|
|
209
|
+
ThreadSafeFunction tsfn;
|
|
210
|
+
|
|
211
|
+
Value Start( const CallbackInfo& info )
|
|
212
|
+
{
|
|
213
|
+
Napi::Env env = info.Env();
|
|
214
|
+
|
|
215
|
+
if ( info.Length() < 2 )
|
|
216
|
+
{
|
|
217
|
+
throw TypeError::New( env, "Expected two arguments" );
|
|
218
|
+
}
|
|
219
|
+
else if ( !info[0].IsFunction() )
|
|
220
|
+
{
|
|
221
|
+
throw TypeError::New( env, "Expected first arg to be function" );
|
|
222
|
+
}
|
|
223
|
+
else if ( !info[1].IsNumber() )
|
|
224
|
+
{
|
|
225
|
+
throw TypeError::New( env, "Expected second arg to be number" );
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
int count = info[1].As<Number>().Int32Value();
|
|
229
|
+
|
|
230
|
+
// Create a ThreadSafeFunction
|
|
231
|
+
tsfn = ThreadSafeFunction::New(
|
|
232
|
+
env,
|
|
233
|
+
info[0].As<Function>(), // JavaScript function called asynchronously
|
|
234
|
+
"Resource Name", // Name
|
|
235
|
+
0, // Unlimited queue
|
|
236
|
+
1, // Only one thread will use this initially
|
|
237
|
+
[]( Napi::Env ) { // Finalizer used to clean threads up
|
|
238
|
+
nativeThread.join();
|
|
239
|
+
} );
|
|
240
|
+
|
|
241
|
+
// Create a native thread
|
|
242
|
+
nativeThread = std::thread( [count] {
|
|
243
|
+
auto callback = []( Napi::Env env, Function jsCallback, int* value ) {
|
|
244
|
+
// Transform native data into JS data, passing it to the provided
|
|
245
|
+
// `jsCallback` -- the TSFN's JavaScript function.
|
|
246
|
+
jsCallback.Call( {Number::New( env, *value )} );
|
|
247
|
+
|
|
248
|
+
// We're finished with the data.
|
|
249
|
+
delete value;
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
for ( int i = 0; i < count; i++ )
|
|
253
|
+
{
|
|
254
|
+
// Create new data
|
|
255
|
+
int* value = new int( clock() );
|
|
256
|
+
|
|
257
|
+
// Perform a blocking call
|
|
258
|
+
napi_status status = tsfn.BlockingCall( value, callback );
|
|
259
|
+
if ( status != napi_ok )
|
|
260
|
+
{
|
|
261
|
+
// Handle error
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
std::this_thread::sleep_for( std::chrono::seconds( 1 ) );
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Release the thread-safe function
|
|
269
|
+
tsfn.Release();
|
|
270
|
+
} );
|
|
271
|
+
|
|
272
|
+
return Boolean::New(env, true);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
Napi::Object Init( Napi::Env env, Object exports )
|
|
276
|
+
{
|
|
277
|
+
exports.Set( "start", Function::New( env, Start ) );
|
|
278
|
+
return exports;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
NODE_API_MODULE( clock, Init )
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
The above code can be used from JavaScript as follows:
|
|
285
|
+
|
|
286
|
+
```js
|
|
287
|
+
const { start } = require('bindings')('clock');
|
|
288
|
+
|
|
289
|
+
start(function () {
|
|
290
|
+
console.log("JavaScript callback called with arguments", Array.from(arguments));
|
|
291
|
+
}, 5);
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
When executed, the output will show the value of `clock()` five times at one
|
|
295
|
+
second intervals:
|
|
296
|
+
|
|
297
|
+
```
|
|
298
|
+
JavaScript callback called with arguments [ 84745 ]
|
|
299
|
+
JavaScript callback called with arguments [ 103211 ]
|
|
300
|
+
JavaScript callback called with arguments [ 104516 ]
|
|
301
|
+
JavaScript callback called with arguments [ 105104 ]
|
|
302
|
+
JavaScript callback called with arguments [ 105691 ]
|
|
303
|
+
```
|
package/index.js
CHANGED
|
@@ -17,6 +17,7 @@ var versionArray = process.version
|
|
|
17
17
|
var isNodeApiBuiltin = (
|
|
18
18
|
versionArray[0] > 8 ||
|
|
19
19
|
(versionArray[0] == 8 && versionArray[1] >= 6) ||
|
|
20
|
+
(versionArray[0] == 6 && versionArray[1] >= 15) ||
|
|
20
21
|
(versionArray[0] == 6 && versionArray[1] >= 14 && versionArray[2] >= 2));
|
|
21
22
|
|
|
22
23
|
// The flag is not needed when the Node version is not 8, nor if the API is
|
package/napi-inl.deprecated.h
CHANGED
|
@@ -73,7 +73,7 @@ inline PropertyDescriptor PropertyDescriptor::Accessor(const char* utf8name,
|
|
|
73
73
|
void* /*data*/) {
|
|
74
74
|
typedef details::AccessorCallbackData<Getter, Setter> CbData;
|
|
75
75
|
// TODO: Delete when the function is destroyed
|
|
76
|
-
auto callbackData = new CbData({ getter, setter });
|
|
76
|
+
auto callbackData = new CbData({ getter, setter, nullptr });
|
|
77
77
|
|
|
78
78
|
return PropertyDescriptor({
|
|
79
79
|
utf8name,
|
|
@@ -104,7 +104,7 @@ inline PropertyDescriptor PropertyDescriptor::Accessor(napi_value name,
|
|
|
104
104
|
void* /*data*/) {
|
|
105
105
|
typedef details::AccessorCallbackData<Getter, Setter> CbData;
|
|
106
106
|
// TODO: Delete when the function is destroyed
|
|
107
|
-
auto callbackData = new CbData({ getter, setter });
|
|
107
|
+
auto callbackData = new CbData({ getter, setter, nullptr });
|
|
108
108
|
|
|
109
109
|
return PropertyDescriptor({
|
|
110
110
|
nullptr,
|