koffi 2.5.0-beta.1 → 2.5.0

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.
Files changed (46) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/build/2.5.0/koffi_darwin_arm64/koffi.node +0 -0
  3. package/build/{2.5.0-beta.1 → 2.5.0}/koffi_darwin_x64/koffi.node +0 -0
  4. package/build/{2.5.0-beta.1 → 2.5.0}/koffi_freebsd_arm64/koffi.node +0 -0
  5. package/build/{2.5.0-beta.1 → 2.5.0}/koffi_freebsd_ia32/koffi.node +0 -0
  6. package/build/{2.5.0-beta.1 → 2.5.0}/koffi_freebsd_x64/koffi.node +0 -0
  7. package/build/{2.5.0-beta.1 → 2.5.0}/koffi_linux_arm32hf/koffi.node +0 -0
  8. package/build/{2.5.0-beta.1 → 2.5.0}/koffi_linux_arm64/koffi.node +0 -0
  9. package/build/{2.5.0-beta.1 → 2.5.0}/koffi_linux_ia32/koffi.node +0 -0
  10. package/build/{2.5.0-beta.1 → 2.5.0}/koffi_linux_riscv64hf64/koffi.node +0 -0
  11. package/build/{2.5.0-beta.1 → 2.5.0}/koffi_linux_x64/koffi.node +0 -0
  12. package/build/{2.5.0-beta.1 → 2.5.0}/koffi_openbsd_ia32/koffi.node +0 -0
  13. package/build/{2.5.0-beta.1 → 2.5.0}/koffi_openbsd_x64/koffi.node +0 -0
  14. package/build/2.5.0/koffi_win32_arm64/koffi.node +0 -0
  15. package/build/{2.5.0-beta.1 → 2.5.0}/koffi_win32_ia32/koffi.node +0 -0
  16. package/build/{2.5.0-beta.1 → 2.5.0}/koffi_win32_x64/koffi.node +0 -0
  17. package/doc/functions.md +1 -1
  18. package/doc/index.rst +1 -0
  19. package/doc/parameters.md +1 -0
  20. package/doc/unions.md +187 -0
  21. package/package.json +2 -2
  22. package/src/koffi/src/call.cc +7 -2
  23. package/src/koffi/src/ffi.cc +8 -8
  24. package/src/koffi/src/util.hh +1 -0
  25. package/vendor/node-addon-api/CHANGELOG.md +31 -0
  26. package/vendor/node-addon-api/README.md +3 -2
  27. package/vendor/node-addon-api/doc/async_worker.md +1 -0
  28. package/vendor/node-addon-api/doc/creating_a_release.md +21 -0
  29. package/vendor/node-addon-api/doc/value.md +7 -0
  30. package/vendor/node-addon-api/napi-inl.h +23 -7
  31. package/vendor/node-addon-api/package.json +9 -1
  32. package/vendor/node-addon-api/test/async_progress_queue_worker.cc +155 -0
  33. package/vendor/node-addon-api/test/async_progress_queue_worker.js +134 -0
  34. package/vendor/node-addon-api/test/async_progress_worker.cc +155 -0
  35. package/vendor/node-addon-api/test/async_progress_worker.js +134 -0
  36. package/vendor/node-addon-api/test/common/index.js +45 -0
  37. package/vendor/node-addon-api/test/objectwrap.js +9 -0
  38. package/build/2.5.0-beta.1/koffi_darwin_arm64/koffi.node +0 -0
  39. package/build/2.5.0-beta.1/koffi_win32_arm64/koffi.node +0 -0
  40. /package/build/{2.5.0-beta.1 → 2.5.0}/koffi_win32_arm64/koffi.exp +0 -0
  41. /package/build/{2.5.0-beta.1 → 2.5.0}/koffi_win32_arm64/koffi.lib +0 -0
  42. /package/build/{2.5.0-beta.1 → 2.5.0}/koffi_win32_ia32/koffi.exp +0 -0
  43. /package/build/{2.5.0-beta.1 → 2.5.0}/koffi_win32_ia32/koffi.lib +0 -0
  44. /package/build/{2.5.0-beta.1 → 2.5.0}/koffi_win32_x64/koffi.exp +0 -0
  45. /package/build/{2.5.0-beta.1 → 2.5.0}/koffi_win32_x64/koffi.lib +0 -0
  46. /package/build/{2.5.0-beta.1 → 2.5.0}/koffi_win32_x64/koffi.pdb +0 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  ## Version history
4
4
 
5
+ ### Koffi 2.5
6
+
7
+ #### Koffi 2.5.0
8
+
9
+ **New features:**
10
+
11
+ - Support [union types](unions.md)
12
+
13
+ **Other fixes:**
14
+
15
+ - Fix ABI for single-float aggregate return on i386 BSD systems
16
+ - Don't mess with Node.js signal handling on POSIX systems
17
+
5
18
  ### Koffi 2.4
6
19
 
7
20
  #### Koffi 2.4.2
package/doc/functions.md CHANGED
@@ -9,7 +9,7 @@ const koffi = require('koffi');
9
9
  const lib = koffi.load('/path/to/shared/library'); // File extension depends on platforms: .so, .dll, .dylib, etc.
10
10
  ````
11
11
 
12
- This library will be automatically unloaded once all references to it (including all the functions that use it, as described below).
12
+ This library will be automatically unloaded once all references to it are gone (including all the functions that use it, as described below).
13
13
 
14
14
  Starting with *Koffi 2.3.20*, you can explicitly unload a library by calling `lib.unload()`. Any attempt to find or call a function from this library after unloading it will crash.
15
15
 
package/doc/index.rst CHANGED
@@ -26,6 +26,7 @@ Table of contents
26
26
  functions
27
27
  types
28
28
  pointers
29
+ unions
29
30
  parameters
30
31
  callbacks
31
32
  misc
package/doc/parameters.md CHANGED
@@ -9,6 +9,7 @@ By default, Koffi will only forward arguments from Javascript to C. However, man
9
9
  For simplicity, and because Javascript only has value semantics for primitive types, Koffi can marshal out (or in/out) two types of parameters:
10
10
 
11
11
  - [Structs](types.md#struct-types) (to/from JS objects)
12
+ - [Unions](unions.md)
12
13
  - [Opaque types](types.md#opaque-types)
13
14
  - String buffers
14
15
 
package/doc/unions.md ADDED
@@ -0,0 +1,187 @@
1
+ # Union values
2
+
3
+ *New in Koffi 2.5*
4
+
5
+ ## Union definition
6
+
7
+ You can declare unions with a syntax similar to structs, but with the `koffi.union()` function. This function takes two arguments: the first one is the name of the type, and the second one is an object containing the union member names and types. You can omit the first argument to declare an anonymous union.
8
+
9
+ The following example illustrates how to declare the same union in C and in JS with Koffi:
10
+
11
+ ```c
12
+ typedef union IntOrDouble {
13
+ int64_t i;
14
+ double d;
15
+ } IntOrDouble;
16
+ ```
17
+
18
+ ```js
19
+ const IntOrDouble = koffi.union('IntOrDouble', {
20
+ i: 'int64_t',
21
+ d: 'double'
22
+ });
23
+ ```
24
+
25
+ ## Input unions
26
+
27
+ ### Passing union values to C
28
+
29
+ You can instantiate an union object with `koffi.Union(type)`. This will create a special object that contains at most one active member.
30
+
31
+ Once you have created an instance of your union, you can simply set the member with the dot operator as you would with a basic object. Then, simply pass your union value to the C function you wish.
32
+
33
+ ```js
34
+ const U = koffi.union('U', { i: 'int', str: 'char *' });
35
+
36
+ const DoSomething = lib.func('void DoSomething(const char *type, U u)');
37
+
38
+ const u1 = new koffi.Union('U'); u1.i = 42;
39
+ const u2 = new koffi.Union('U'); u2.str = 'Hello!';
40
+
41
+ DoSomething('int', u1);
42
+ DoSomething('string', u2);
43
+ ```
44
+
45
+ For simplicity, Koffi also accepts object literals with one property (no more, no less) setting the corresponding union member. The example belows uses this to simplify the code shown above:
46
+
47
+ ```js
48
+ const U = koffi.union('U', { i: 'int', str: 'char *' });
49
+
50
+ const DoSomething = lib.func('void DoSomething(const char *type, U u)');
51
+
52
+ DoSomething('int', { .i = 42 });
53
+ DoSomething('string', { .str = 'Hello!' });
54
+ ```
55
+
56
+ ### Win32 example
57
+
58
+ The following example uses the [SendInput](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendinput) Win32 API to emit the Win+D shortcut and hide windows (show the desktop).
59
+
60
+ ```js
61
+ const koffi = require('koffi');
62
+
63
+ // Win32 type and functions
64
+
65
+ const user32 = koffi.load('user32.dll');
66
+
67
+ const INPUT_MOUSE = 0;
68
+ const INPUT_KEYBOARD = 1;
69
+ const INPUT_HARDWARE = 2;
70
+
71
+ const KEYEVENTF_KEYUP = 0x2;
72
+ const KEYEVENTF_SCANCODE = 0x8;
73
+
74
+ const VK_LWIN = 0x5B;
75
+ const VK_D = 0x44;
76
+
77
+ const MOUSEINPUT = koffi.struct('MOUSEINPUT', {
78
+ dx: 'long',
79
+ dy: 'long',
80
+ mouseData: 'uint32_t',
81
+ dwFlags: 'uint32_t',
82
+ time: 'uint32_t',
83
+ dwExtraInfo: 'uintptr_t'
84
+ });
85
+ const KEYBDINPUT = koffi.struct('KEYBDINPUT', {
86
+ wVk: 'uint16_t',
87
+ wScan: 'uint16_t',
88
+ dwFlags: 'uint32_t',
89
+ time: 'uint32_t',
90
+ dwExtraInfo: 'uintptr_t'
91
+ });
92
+ const HARDWAREINPUT = koffi.struct('HARDWAREINPUT', {
93
+ uMsg: 'uint32_t',
94
+ wParamL: 'uint16_t',
95
+ wParamH: 'uint16_t'
96
+ });
97
+
98
+ const INPUT = koffi.struct('INPUT', {
99
+ type: 'uint32_t',
100
+ u: koffi.union({
101
+ mi: MOUSEINPUT,
102
+ ki: KEYBDINPUT,
103
+ hi: HARDWAREINPUT
104
+ })
105
+ });
106
+
107
+ const SendInput = user32.func('unsigned int __stdcall SendInput(unsigned int cInputs, INPUT *pInputs, int cbSize)');
108
+
109
+ // Show/hide desktop with Win+D shortcut
110
+
111
+ let events = [
112
+ make_keyboard_event(VK_LWIN, true),
113
+ make_keyboard_event(VK_D, true),
114
+ make_keyboard_event(VK_D, false),
115
+ make_keyboard_event(VK_LWIN, false)
116
+ ];
117
+
118
+ SendInput(events.length, events, koffi.sizeof(INPUT));
119
+
120
+ // Utility
121
+
122
+ function make_keyboard_event(vk, down) {
123
+ let event = {
124
+ type: INPUT_KEYBOARD,
125
+ u: {
126
+ ki: {
127
+ wVk: vk,
128
+ wScan: 0,
129
+ dwFlags: down ? 0 : KEYEVENTF_KEYUP,
130
+ time: 0,
131
+ dwExtraInfo: 0
132
+ }
133
+ }
134
+ };
135
+
136
+ return event;
137
+ }
138
+ ```
139
+
140
+ ## Output unions
141
+
142
+ Unlike structs, Koffi does not know which union member is valid, and it cannot decode it automatically. You can however use special `koffi.Union` objects for output parameters, and decode the memory after the call.
143
+
144
+ To decode an output union pointer parameter, create a placeholder object with `new koffi.Union(type)` and pass the resulting object to the function.
145
+
146
+ After the call, you can dereference the member value you want on this object and Koffi will decode it at this moment.
147
+
148
+ The following example illustrates the use of `koffi.Union()` to decode output unions after the call.
149
+
150
+ ```c
151
+ #include <stdint.h>
152
+
153
+ typedef union IntOrDouble {
154
+ int64_t i;
155
+ double d;
156
+ } IntOrDouble;
157
+
158
+ void SetUnionInt(int64_t i, IntOrDouble *out)
159
+ {
160
+ out->i = i;
161
+ }
162
+
163
+ void SetUnionDouble(double d, IntOrDouble *out)
164
+ {
165
+ out->d = d;
166
+ }
167
+ ```
168
+
169
+ ```js
170
+ const IntOrDouble = koffi.union('IntOrDouble', {
171
+ i: 'int64_t',
172
+ d: 'double',
173
+ raw: koffi.array('uint8_t', 8)
174
+ });
175
+
176
+ const SetUnionInt = lib.func('void SetUnionInt(int64_t i, _Out_ IntOrDouble *out)');
177
+ const SetUnionDouble = lib.func('void SetUnionDouble(double d, _Out_ IntOrDouble *out)');
178
+
179
+ let u1 = new koffi.Union('IntOrDouble');
180
+ let u2 = new koffi.Union('IntOrDouble');
181
+
182
+ SetUnionInt(123, u1);
183
+ SetUnionDouble(123, u2);
184
+
185
+ console.log(u1.i, '---', u1.raw); // Prints 123 --- Uint8Array(8) [123, 0, 0, 0, 0, 0, 0, 0]
186
+ console.log(u2.d, '---', u2.raw); // Prints 123 --- Uint8Array(8) [0, 0, 0, 0, 0, 0, 69, 64]
187
+ ```
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koffi",
3
- "version": "2.5.0-beta.1",
4
- "stable": "2.4.2",
3
+ "version": "2.5.0",
4
+ "stable": "2.5.0",
5
5
  "description": "Fast and simple C FFI (foreign function interface) for Node.js",
6
6
  "keywords": [
7
7
  "foreign",
@@ -364,6 +364,11 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
364
364
  MagicUnion *u = MagicUnion::Unwrap(obj);
365
365
  const uint8_t *raw = u->GetRaw();
366
366
 
367
+ if (RG_UNLIKELY(u->GetType() != type)) {
368
+ ThrowError<Napi::TypeError>(env, "Expected union type %1, got %2", type->name, u->GetType()->name);
369
+ return false;
370
+ }
371
+
367
372
  // Fast path: encoded value already exists, just copy!
368
373
  if (raw) {
369
374
  memcpy(origin, raw, type->size);
@@ -380,12 +385,12 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
380
385
  } else {
381
386
  Napi::Array properties = obj.GetPropertyNames();
382
387
 
383
- if (RG_UNLIKELY(properties.Length() != 1 || !((Napi::Value)properties[0u]).IsString())) {
388
+ if (RG_UNLIKELY(properties.Length() != 1 || !properties.Get(0u).IsString())) {
384
389
  ThrowError<Napi::Error>(env, "Expected object with single property name for union");
385
390
  return false;
386
391
  }
387
392
 
388
- std::string property = ((Napi::Value)properties[0u]).As<Napi::String>().Utf8Value();
393
+ std::string property = properties.Get(0u).As<Napi::String>();
389
394
 
390
395
  members.ptr = std::find_if(type->members.begin(), type->members.end(),
391
396
  [&](const RecordMember &member) { return TestStr(property.c_str(), member.name); });
@@ -134,7 +134,7 @@ static Napi::Value GetSetConfig(const Napi::CallbackInfo &info)
134
134
  Napi::Array keys = obj.GetPropertyNames();
135
135
 
136
136
  for (uint32_t i = 0; i < keys.Length(); i++) {
137
- std::string key = ((Napi::Value)keys[i]).As<Napi::String>();
137
+ std::string key = keys.Get(i).As<Napi::String>();
138
138
  Napi::Value value = obj[key];
139
139
 
140
140
  if (key == "sync_stack_size") {
@@ -243,7 +243,7 @@ static Napi::Value CreateStructType(const Napi::CallbackInfo &info, bool pad)
243
243
  for (uint32_t i = 0; i < keys.Length(); i++) {
244
244
  RecordMember member = {};
245
245
 
246
- std::string key = ((Napi::Value)keys[i]).As<Napi::String>();
246
+ std::string key = keys.Get(i).As<Napi::String>();
247
247
  Napi::Value value = obj[key];
248
248
  int16_t align = 0;
249
249
 
@@ -252,12 +252,12 @@ static Napi::Value CreateStructType(const Napi::CallbackInfo &info, bool pad)
252
252
  if (value.IsArray()) {
253
253
  Napi::Array array = value.As<Napi::Array>();
254
254
 
255
- if (array.Length() != 2 || !((Napi::Value)array[0u]).IsNumber()) {
255
+ if (array.Length() != 2 || !array.Get(0u).IsNumber()) {
256
256
  ThrowError<Napi::Error>(env, "Member specifier array must contain alignement value and type");
257
257
  return env.Null();
258
258
  }
259
259
 
260
- int64_t align64 = ((Napi::Value)array[0u]).As<Napi::Number>().Int64Value();
260
+ int64_t align64 = array.Get(0u).As<Napi::Number>().Int64Value();
261
261
 
262
262
  if (!CheckAlignment(align64)) {
263
263
  ThrowError<Napi::Error>(env, "Alignment of member '%1' must be 1, 2, 4 or 8", member.name);
@@ -371,7 +371,7 @@ static Napi::Value CreateUnionType(const Napi::CallbackInfo &info)
371
371
  for (uint32_t i = 0; i < keys.Length(); i++) {
372
372
  RecordMember member = {};
373
373
 
374
- std::string key = ((Napi::Value)keys[i]).As<Napi::String>();
374
+ std::string key = keys.Get(i).As<Napi::String>();
375
375
  Napi::Value value = obj[key];
376
376
  int16_t align = 0;
377
377
 
@@ -380,12 +380,12 @@ static Napi::Value CreateUnionType(const Napi::CallbackInfo &info)
380
380
  if (value.IsArray()) {
381
381
  Napi::Array array = value.As<Napi::Array>();
382
382
 
383
- if (array.Length() != 2 || !((Napi::Value)array[0u]).IsNumber()) {
383
+ if (array.Length() != 2 || !array.Get(0u).IsNumber()) {
384
384
  ThrowError<Napi::Error>(env, "Member specifier array must contain alignement value and type");
385
385
  return env.Null();
386
386
  }
387
387
 
388
- int64_t align64 = ((Napi::Value)array[0u]).As<Napi::Number>().Int64Value();
388
+ int64_t align64 = array.Get(0u).As<Napi::Number>().Int64Value();
389
389
 
390
390
  if (!CheckAlignment(align64)) {
391
391
  ThrowError<Napi::Error>(env, "Alignment of member '%1' must be 1, 2, 4 or 8", member.name);
@@ -879,7 +879,7 @@ static bool ParseClassicFunction(Napi::Env env, Napi::String name, Napi::Value r
879
879
  uint32_t parameters_len = parameters.Length();
880
880
 
881
881
  if (parameters_len) {
882
- Napi::String str = ((Napi::Value)parameters[parameters_len - 1]).As<Napi::String>();
882
+ Napi::String str = parameters.Get(parameters_len - 1).As<Napi::String>();
883
883
 
884
884
  if (str.IsString() && str.Utf8Value() == "...") {
885
885
  func->variadic = true;
@@ -48,6 +48,7 @@ public:
48
48
 
49
49
  MagicUnion(const Napi::CallbackInfo &info);
50
50
 
51
+ const TypeInfo *GetType() { return type; }
51
52
  const RecordMember *GetMember() const { return (active_idx >= 0) ? &type->members[active_idx] : nullptr; }
52
53
 
53
54
  void SetRaw(const uint8_t *ptr);
@@ -1,5 +1,36 @@
1
1
  # node-addon-api Changelog
2
2
 
3
+ ## 2023-06-13 Version 7.0.0, @KevinEady
4
+
5
+ ### Notable changes
6
+
7
+ #### API
8
+
9
+ - Drop support for Node.js v14.x and v19.x.
10
+ - Ensure native receiver exists when calling instance methods and properties.
11
+ - Fix issue when creating `Napi::Error` instances that wrap primitives values.
12
+
13
+ #### TEST
14
+
15
+ - Added tests for `Napi::AsyncProgressQueueWorker<T>` class.
16
+ - Added tests for `Napi::AsyncProgressWorker<T>` class.
17
+
18
+ ### Documentation
19
+
20
+ - Added documentation for `Napi::Value::IsBigInt()`.
21
+
22
+ ### Commits
23
+
24
+ * \[[`de5c899400`](https://github.com/nodejs/node-addon-api/commit/de5c899400)] - **doc,chore**: drop support for Node.js v14, v19 (Kevin Eady) [#1324](https://github.com/nodejs/node-addon-api/pull/1324)
25
+ * \[[`3083b7f148`](https://github.com/nodejs/node-addon-api/commit/3083b7f148)] - \[StepSecurity] Apply security best practices (StepSecurity Bot) [#1308](https://github.com/nodejs/node-addon-api/pull/1308)
26
+ * \[[`a198e24a15`](https://github.com/nodejs/node-addon-api/commit/a198e24a15)] - \[Test] Add tests for async progress queue worker (Jack) [#1316](https://github.com/nodejs/node-addon-api/pull/1316)
27
+ * \[[`665f4aa845`](https://github.com/nodejs/node-addon-api/commit/665f4aa845)] - **doc**: add missing Value::IsBigInt (Kevin Eady) [#1319](https://github.com/nodejs/node-addon-api/pull/1319)
28
+ * \[[`358b2d3b4f`](https://github.com/nodejs/node-addon-api/commit/358b2d3b4f)] - **doc**: complete code curly braces in async\_worker.md (wanlu) [#1317](https://github.com/nodejs/node-addon-api/pull/1317)
29
+ * \[[`858942ce31`](https://github.com/nodejs/node-addon-api/commit/858942ce31)] - **src**: avoid calling into C++ with a null this (Caleb Hearon) [#1313](https://github.com/nodejs/node-addon-api/pull/1313)
30
+ * \[[`64f6515331`](https://github.com/nodejs/node-addon-api/commit/64f6515331)] - **src**: handle failure during error wrap of primitive (Gabriel Schulhof) [#1310](https://github.com/nodejs/node-addon-api/pull/1310)
31
+ * \[[`dfad6b45fe`](https://github.com/nodejs/node-addon-api/commit/dfad6b45fe)] - \[test] Add test coverage for AsyncProgressWorker (Jack) [#1307](https://github.com/nodejs/node-addon-api/pull/1307)
32
+ * \[[`0e34f22839`](https://github.com/nodejs/node-addon-api/commit/0e34f22839)] - **release**: v6.1.0. (Nicola Del Gobbo)
33
+
3
34
  ## 2023-04-20 Version 6.1.0, @NickNaso
4
35
 
5
36
  ### Notable changes
@@ -70,7 +70,7 @@ and node-addon-api.
70
70
  - **[Contributors](#contributors)**
71
71
  - **[License](#license)**
72
72
 
73
- ## **Current version: 6.1.0**
73
+ ## **Current version: 7.0.0**
74
74
 
75
75
  (See [CHANGELOG.md](CHANGELOG.md) for complete Changelog)
76
76
 
@@ -83,7 +83,7 @@ This allows addons built with it to run with Node.js versions which support the
83
83
  **However** the node-addon-api support model is to support only the active LTS Node.js versions. This means that
84
84
  every year there will be a new major which drops support for the Node.js LTS version which has gone out of service.
85
85
 
86
- The oldest Node.js version supported by the current version of node-addon-api is Node.js 14.x.
86
+ The oldest Node.js version supported by the current version of node-addon-api is Node.js 16.x.
87
87
 
88
88
  ## Setup
89
89
  - [Installation and usage](doc/setup.md)
@@ -275,6 +275,7 @@ available:
275
275
  ![Node-API v6 Badge](https://github.com/nodejs/abi-stable-node/blob/doc/assets/Node-API%20v6%20Badge.svg)
276
276
  ![Node-API v7 Badge](https://github.com/nodejs/abi-stable-node/blob/doc/assets/Node-API%20v7%20Badge.svg)
277
277
  ![Node-API v8 Badge](https://github.com/nodejs/abi-stable-node/blob/doc/assets/Node-API%20v8%20Badge.svg)
278
+ ![Node-API v9 Badge](https://github.com/nodejs/abi-stable-node/blob/doc/assets/Node-API%20v9%20Badge.svg)
278
279
  ![Node-API Experimental Version Badge](https://github.com/nodejs/abi-stable-node/blob/doc/assets/Node-API%20Experimental%20Version%20Badge.svg)
279
280
 
280
281
  ## **Contributing**
@@ -418,6 +418,7 @@ Value Echo(const CallbackInfo& info) {
418
418
  EchoWorker* wk = new EchoWorker(cb, in);
419
419
  wk->Queue();
420
420
  return info.Env().Undefined();
421
+ }
421
422
  ```
422
423
 
423
424
  Using the implementation of a `Napi::AsyncWorker` is straight forward. You only
@@ -60,3 +60,24 @@ and that the correct version is installed.
60
60
  and close the issue.
61
61
 
62
62
  * Tweet that the release has been created.
63
+
64
+ ## Optional Steps
65
+
66
+ Depending on circumstances for the release, additional steps may be required to
67
+ support the release process.
68
+
69
+ ### Major Releases to Drop Support Node.js Versions
70
+
71
+ `node-addon-api` provides support for Node.js versions following the same
72
+ [release schedule](https://nodejs.dev/en/about/releases/): once a Node.js
73
+ version leaves maintenance mode, the next major version of `node-addon-api`
74
+ published will drop support for that version. These are the steps to follow to
75
+ drop support for a Node.js version:
76
+
77
+ * Update minimum version supported in documentation ([README.md](../README.md))
78
+
79
+ * Remove from GitHub actions ([ci.yml](../.github/workflows/ci.yml) and
80
+ [ci-win.yml](../.github/workflows/ci-win.yml))
81
+
82
+ * Remove from Jenkins CI ([node-test-node-addon-api-LTS versions
83
+ [Jenkins]](https://ci.nodejs.org/view/x%20-%20Abi%20stable%20module%20API/job/node-test-node-addon-api-LTS%20versions/))
@@ -141,6 +141,13 @@ bool Napi::Value::IsArrayBuffer() const;
141
141
  Returns `true` if the underlying value is a JavaScript `Napi::ArrayBuffer` or
142
142
  `false` otherwise.
143
143
 
144
+ ```cpp
145
+ bool Napi::Value::IsBigInt() const;
146
+ ```
147
+
148
+ Returns `true` if the underlying value is a JavaScript `Napi::BigInt` or `false`
149
+ otherwise.
150
+
144
151
  ### IsBoolean
145
152
 
146
153
  ```cpp
@@ -165,7 +165,7 @@ napi_value TemplatedInstanceCallback(napi_env env,
165
165
  return details::WrapCallback([&] {
166
166
  CallbackInfo cbInfo(env, info);
167
167
  T* instance = T::Unwrap(cbInfo.This().As<Object>());
168
- return (instance->*UnwrapCallback)(cbInfo);
168
+ return instance ? (instance->*UnwrapCallback)(cbInfo) : Napi::Value();
169
169
  });
170
170
  }
171
171
 
@@ -175,7 +175,7 @@ napi_value TemplatedInstanceVoidCallback(napi_env env, napi_callback_info info)
175
175
  return details::WrapCallback([&] {
176
176
  CallbackInfo cbInfo(env, info);
177
177
  T* instance = T::Unwrap(cbInfo.This().As<Object>());
178
- (instance->*UnwrapCallback)(cbInfo);
178
+ if (instance) (instance->*UnwrapCallback)(cbInfo);
179
179
  return nullptr;
180
180
  });
181
181
  }
@@ -2937,6 +2937,22 @@ inline Error::Error(napi_env env, napi_value value)
2937
2937
  nullptr};
2938
2938
 
2939
2939
  status = napi_define_properties(env, wrappedErrorObj, 1, &wrapObjFlag);
2940
+ #ifdef NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS
2941
+ if (status == napi_pending_exception) {
2942
+ // Test if the pending exception was reported because the environment is
2943
+ // shutting down. We assume that a status of napi_pending_exception
2944
+ // coupled with the absence of an actual pending exception means that
2945
+ // the environment is shutting down. If so, we replace the
2946
+ // napi_pending_exception status with napi_ok.
2947
+ bool is_exception_pending = false;
2948
+ status = napi_is_exception_pending(env, &is_exception_pending);
2949
+ if (status == napi_ok && !is_exception_pending) {
2950
+ status = napi_ok;
2951
+ } else {
2952
+ status = napi_pending_exception;
2953
+ }
2954
+ }
2955
+ #endif // NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS
2940
2956
  NAPI_FATAL_IF_FAILED(status, "Error::Error", "napi_define_properties");
2941
2957
 
2942
2958
  // Create a reference on the newly wrapped object
@@ -4340,7 +4356,7 @@ inline napi_value InstanceWrap<T>::InstanceVoidMethodCallbackWrapper(
4340
4356
  callbackInfo.SetData(callbackData->data);
4341
4357
  T* instance = T::Unwrap(callbackInfo.This().As<Object>());
4342
4358
  auto cb = callbackData->callback;
4343
- (instance->*cb)(callbackInfo);
4359
+ if (instance) (instance->*cb)(callbackInfo);
4344
4360
  return nullptr;
4345
4361
  });
4346
4362
  }
@@ -4355,7 +4371,7 @@ inline napi_value InstanceWrap<T>::InstanceMethodCallbackWrapper(
4355
4371
  callbackInfo.SetData(callbackData->data);
4356
4372
  T* instance = T::Unwrap(callbackInfo.This().As<Object>());
4357
4373
  auto cb = callbackData->callback;
4358
- return (instance->*cb)(callbackInfo);
4374
+ return instance ? (instance->*cb)(callbackInfo) : Napi::Value();
4359
4375
  });
4360
4376
  }
4361
4377
 
@@ -4369,7 +4385,7 @@ inline napi_value InstanceWrap<T>::InstanceGetterCallbackWrapper(
4369
4385
  callbackInfo.SetData(callbackData->data);
4370
4386
  T* instance = T::Unwrap(callbackInfo.This().As<Object>());
4371
4387
  auto cb = callbackData->getterCallback;
4372
- return (instance->*cb)(callbackInfo);
4388
+ return instance ? (instance->*cb)(callbackInfo) : Napi::Value();
4373
4389
  });
4374
4390
  }
4375
4391
 
@@ -4383,7 +4399,7 @@ inline napi_value InstanceWrap<T>::InstanceSetterCallbackWrapper(
4383
4399
  callbackInfo.SetData(callbackData->data);
4384
4400
  T* instance = T::Unwrap(callbackInfo.This().As<Object>());
4385
4401
  auto cb = callbackData->setterCallback;
4386
- (instance->*cb)(callbackInfo, callbackInfo[0]);
4402
+ if (instance) (instance->*cb)(callbackInfo, callbackInfo[0]);
4387
4403
  return nullptr;
4388
4404
  });
4389
4405
  }
@@ -4395,7 +4411,7 @@ inline napi_value InstanceWrap<T>::WrappedMethod(
4395
4411
  return details::WrapCallback([&] {
4396
4412
  const CallbackInfo cbInfo(env, info);
4397
4413
  T* instance = T::Unwrap(cbInfo.This().As<Object>());
4398
- (instance->*method)(cbInfo, cbInfo[0]);
4414
+ if (instance) (instance->*method)(cbInfo, cbInfo[0]);
4399
4415
  return nullptr;
4400
4416
  });
4401
4417
  }
@@ -399,6 +399,14 @@
399
399
  {
400
400
  "name": "Feng Yu",
401
401
  "url": "https://github.com/F3n67u"
402
+ },
403
+ {
404
+ "name": "wanlu wang",
405
+ "url": "https://github.com/wanlu"
406
+ },
407
+ {
408
+ "name": "Caleb Hearon",
409
+ "url": "https://github.com/chearon"
402
410
  }
403
411
  ],
404
412
  "description": "Node.js API (Node-API)",
@@ -459,6 +467,6 @@
459
467
  "lint:fix": "node tools/clang-format --fix && node tools/eslint-format --fix"
460
468
  },
461
469
  "pre-commit": "lint",
462
- "version": "6.1.0",
470
+ "version": "7.0.0",
463
471
  "support": true
464
472
  }