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.
@@ -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. If necessary you can ask the build
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
- the intent to create a new release. Give people some
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
- * Use https://ci.nodejs.org/view/x%20-%20Abi%20stable%20module%20API/job/node-test-node-addon-api/
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 version in package.json appropriately.
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
- * Update the README.md to show the new version as the latest.
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
- * Add any new contributors to the "contributors" section in
27
- the package.json
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
- and that the correct version is installed.
57
+ and that the correct version is installed.
37
58
 
38
- * Comment on the issue opened in the first step that the
39
- release has been created and close the issue.
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.
@@ -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::FunctionReference::Weak(const Napi::Function& value);
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::FunctionReference::Persistent(const Napi::Function& value);
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::Nuber` object.
28
- - `[in] value`: The `napi_value` which is a handle for a JavaScript `Number`.
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::Nuber` object.
40
- - `[in] value`: The `napi_value` which is a handle for a JavaScript `Number`.
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 `uint32_t` primitive type.
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 NULL if no such key exists.
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`](propertydescriptor.md).
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`](propertydescriptor.md). Can be one of the following types:
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
 
@@ -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::ObjectReference::Weak(const Napi::Object& value);
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::ObjectReference::Persistent(const Napi::Object& value);
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.
@@ -78,7 +78,7 @@ Napi::Object Init (Napi::Env env, Napi::Object exports) {
78
78
  return exports;
79
79
  }
80
80
 
81
- // Regisgter and initialize native add-on
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
- ### Contructor
119
+ ### Constructor
120
120
 
121
121
  Creates a new instance of a JavaScript object that wraps native instance.
122
122
 
@@ -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](doc/setum.md) section).
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 environemnt in which to create this accessor.
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
- 4. Include `napi.h` in the native module code.
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
@@ -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,