koffi 2.3.16 → 2.3.18

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 (82) hide show
  1. package/CHANGELOG.md +14 -1
  2. package/build/2.3.18/koffi_darwin_arm64/koffi.node +0 -0
  3. package/build/2.3.18/koffi_darwin_x64/koffi.node +0 -0
  4. package/build/2.3.18/koffi_freebsd_arm64/koffi.node +0 -0
  5. package/build/2.3.18/koffi_freebsd_ia32/koffi.node +0 -0
  6. package/build/2.3.18/koffi_freebsd_x64/koffi.node +0 -0
  7. package/build/2.3.18/koffi_linux_arm32hf/koffi.node +0 -0
  8. package/build/2.3.18/koffi_linux_arm64/koffi.node +0 -0
  9. package/build/2.3.18/koffi_linux_ia32/koffi.node +0 -0
  10. package/build/2.3.18/koffi_linux_riscv64hf64/koffi.node +0 -0
  11. package/build/2.3.18/koffi_linux_x64/koffi.node +0 -0
  12. package/build/2.3.18/koffi_openbsd_ia32/koffi.node +0 -0
  13. package/build/2.3.18/koffi_openbsd_x64/koffi.node +0 -0
  14. package/build/2.3.18/koffi_win32_arm64/koffi.node +0 -0
  15. package/build/2.3.18/koffi_win32_ia32/koffi.node +0 -0
  16. package/build/2.3.18/koffi_win32_x64/koffi.node +0 -0
  17. package/package.json +2 -2
  18. package/src/koffi/src/call.cc +121 -24
  19. package/src/koffi/src/call.hh +13 -0
  20. package/src/koffi/src/ffi.cc +14 -11
  21. package/src/koffi/src/ffi.hh +2 -0
  22. package/src/koffi/src/util.cc +1 -1
  23. package/src/koffi/src/util.hh +2 -0
  24. package/vendor/node-addon-api/CHANGELOG.md +41 -0
  25. package/vendor/node-addon-api/README.md +1 -1
  26. package/vendor/node-addon-api/doc/array_buffer.md +10 -0
  27. package/vendor/node-addon-api/doc/buffer.md +97 -0
  28. package/vendor/node-addon-api/doc/env.md +2 -2
  29. package/vendor/node-addon-api/doc/external.md +2 -2
  30. package/vendor/node-addon-api/doc/external_buffer.md +18 -0
  31. package/vendor/node-addon-api/doc/hierarchy.md +4 -2
  32. package/vendor/node-addon-api/doc/object.md +2 -29
  33. package/vendor/node-addon-api/doc/type_taggable.md +40 -0
  34. package/vendor/node-addon-api/doc/value.md +7 -1
  35. package/vendor/node-addon-api/napi-inl.h +317 -22
  36. package/vendor/node-addon-api/napi.h +84 -7
  37. package/vendor/node-addon-api/package.json +9 -1
  38. package/vendor/node-addon-api/test/async_progress_worker.cc +15 -3
  39. package/vendor/node-addon-api/test/binding.cc +4 -2
  40. package/vendor/node-addon-api/test/binding.gyp +11 -1
  41. package/vendor/node-addon-api/test/buffer.cc +13 -19
  42. package/vendor/node-addon-api/test/buffer.h +26 -0
  43. package/vendor/node-addon-api/test/buffer.js +82 -0
  44. package/vendor/node-addon-api/test/buffer_new_or_copy-inl.h +68 -0
  45. package/vendor/node-addon-api/test/buffer_no_external.cc +24 -0
  46. package/vendor/node-addon-api/test/error.cc +101 -0
  47. package/vendor/node-addon-api/test/error.js +15 -1
  48. package/vendor/node-addon-api/test/index.js +1 -1
  49. package/vendor/node-addon-api/test/object_reference.cc +220 -22
  50. package/vendor/node-addon-api/test/object_reference.js +83 -80
  51. package/vendor/node-addon-api/test/objectwrap.cc +23 -3
  52. package/vendor/node-addon-api/test/objectwrap.js +14 -2
  53. package/vendor/node-addon-api/test/reference.cc +55 -1
  54. package/vendor/node-addon-api/test/reference.js +7 -1
  55. package/vendor/node-addon-api/test/type_taggable.cc +66 -0
  56. package/vendor/node-addon-api/test/type_taggable.js +60 -0
  57. package/vendor/node-addon-api/test/value_type_cast.cc +60 -0
  58. package/vendor/node-addon-api/test/value_type_cast.js +106 -0
  59. package/vendor/node-addon-api/tools/eslint-format.js +2 -2
  60. package/build/2.3.16/koffi_darwin_arm64/koffi.node +0 -0
  61. package/build/2.3.16/koffi_darwin_x64/koffi.node +0 -0
  62. package/build/2.3.16/koffi_freebsd_arm64/koffi.node +0 -0
  63. package/build/2.3.16/koffi_freebsd_ia32/koffi.node +0 -0
  64. package/build/2.3.16/koffi_freebsd_x64/koffi.node +0 -0
  65. package/build/2.3.16/koffi_linux_arm32hf/koffi.node +0 -0
  66. package/build/2.3.16/koffi_linux_arm64/koffi.node +0 -0
  67. package/build/2.3.16/koffi_linux_ia32/koffi.node +0 -0
  68. package/build/2.3.16/koffi_linux_riscv64hf64/koffi.node +0 -0
  69. package/build/2.3.16/koffi_linux_x64/koffi.node +0 -0
  70. package/build/2.3.16/koffi_openbsd_ia32/koffi.node +0 -0
  71. package/build/2.3.16/koffi_openbsd_x64/koffi.node +0 -0
  72. package/build/2.3.16/koffi_win32_arm64/koffi.node +0 -0
  73. package/build/2.3.16/koffi_win32_ia32/koffi.node +0 -0
  74. package/build/2.3.16/koffi_win32_x64/koffi.node +0 -0
  75. package/vendor/node-addon-api/test/object/object_type_tag.cc +0 -39
  76. package/vendor/node-addon-api/test/object/object_type_tag.js +0 -55
  77. /package/build/{2.3.16 → 2.3.18}/koffi_win32_arm64/koffi.exp +0 -0
  78. /package/build/{2.3.16 → 2.3.18}/koffi_win32_arm64/koffi.lib +0 -0
  79. /package/build/{2.3.16 → 2.3.18}/koffi_win32_ia32/koffi.exp +0 -0
  80. /package/build/{2.3.16 → 2.3.18}/koffi_win32_ia32/koffi.lib +0 -0
  81. /package/build/{2.3.16 → 2.3.18}/koffi_win32_x64/koffi.exp +0 -0
  82. /package/build/{2.3.16 → 2.3.18}/koffi_win32_x64/koffi.lib +0 -0
package/CHANGELOG.md CHANGED
@@ -4,6 +4,19 @@
4
4
 
5
5
  ### Koffi 2.3
6
6
 
7
+ #### Koffi 2.3.18
8
+
9
+ **Main fixes:**
10
+
11
+ - Fix possible crash on exit caused by unregistered callbacks
12
+
13
+ #### Koffi 2.3.17
14
+
15
+ **Main changes:**
16
+
17
+ - Allow strings for input `void *`, `int8_t *` and `int16_t *` pointer arguments
18
+ - Support using `[string]` (single-element string arrays) for polymorphic input/output arguments
19
+
7
20
  #### Koffi 2.3.16
8
21
 
9
22
  **Main changes:**
@@ -13,7 +26,7 @@
13
26
 
14
27
  **Other changes:**
15
28
 
16
- - Support null in koffi.free() and koffi.address()
29
+ - Support null in `koffi.free()` and `koffi.address()`
17
30
 
18
31
  #### Koffi 2.3.15
19
32
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koffi",
3
- "version": "2.3.16",
4
- "stable": "2.3.16",
3
+ "version": "2.3.18",
4
+ "stable": "2.3.18",
5
5
  "description": "Fast and simple C FFI (foreign function interface) for Node.js",
6
6
  "keywords": [
7
7
  "foreign",
@@ -77,8 +77,10 @@ void CallData::Dispose()
77
77
  int16_t idx = used_trampolines[i];
78
78
  TrampolineInfo *trampoline = &shared.trampolines[idx];
79
79
 
80
+ RG_ASSERT(trampoline->instance == instance);
80
81
  RG_ASSERT(!trampoline->func.IsEmpty());
81
82
 
83
+ trampoline->instance = nullptr;
82
84
  trampoline->func.Reset();
83
85
  trampoline->recv.Reset();
84
86
 
@@ -147,7 +149,7 @@ bool CallData::PushString(Napi::Value value, int directions, const char **out_st
147
149
  {
148
150
  if (value.IsString()) {
149
151
  if (RG_UNLIKELY(directions & 2)) {
150
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected string", GetValueType(instance, value));
152
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected [string]", GetValueType(instance, value));
151
153
  return false;
152
154
  }
153
155
 
@@ -200,6 +202,7 @@ bool CallData::PushString(Napi::Value value, int directions, const char **out_st
200
202
  napi_status status = napi_create_reference(env, array, 1, &out->ref);
201
203
  RG_ASSERT(status == napi_ok);
202
204
 
205
+ out->kind = OutArgument::Kind::Array;
203
206
  out->ptr = (const uint8_t *)*out_str;
204
207
  out->type = type;
205
208
  }
@@ -301,6 +304,7 @@ bool CallData::PushString16(Napi::Value value, int directions, const char16_t **
301
304
  napi_status status = napi_create_reference(env, array, 1, &out->ref);
302
305
  RG_ASSERT(status == napi_ok);
303
306
 
307
+ out->kind = OutArgument::Kind::Array;
304
308
  out->ptr = (const uint8_t *)*out_str16;
305
309
  out->type = type;
306
310
  }
@@ -973,6 +977,9 @@ bool CallData::PushPointer(Napi::Value value, const TypeInfo *type, int directio
973
977
  case napi_object: {
974
978
  uint8_t *ptr = nullptr;
975
979
 
980
+ OutArgument::Kind out_kind;
981
+ Size out_max_len = -1;
982
+
976
983
  if (value.IsArray()) {
977
984
  if (RG_UNLIKELY(!type->ref.type->size)) {
978
985
  ThrowError<Napi::TypeError>(env, "Cannot pass %1 value to void *, use koffi.as()",
@@ -981,17 +988,25 @@ bool CallData::PushPointer(Napi::Value value, const TypeInfo *type, int directio
981
988
  }
982
989
 
983
990
  Napi::Array array = value.As<Napi::Array>();
991
+ Size len = PushIndirectString(array, type->ref.type, &ptr);
984
992
 
985
- Size len = (Size)array.Length();
986
- Size size = len * type->ref.type->size;
993
+ if (len >= 0) {
994
+ out_kind = (type->ref.type->size == 2) ? OutArgument::Kind::String16 : OutArgument::Kind::String;
995
+ out_max_len = len;
996
+ } else {
997
+ Size len = (Size)array.Length();
998
+ Size size = len * type->ref.type->size;
987
999
 
988
- ptr = AllocHeap(size, 16);
1000
+ ptr = AllocHeap(size, 16);
989
1001
 
990
- if (directions & 1) {
991
- if (!PushNormalArray(array, len, type, ptr))
992
- return false;
993
- } else {
994
- memset_safe(ptr, 0, size);
1002
+ if (directions & 1) {
1003
+ if (!PushNormalArray(array, len, type, ptr))
1004
+ return false;
1005
+ } else {
1006
+ memset_safe(ptr, 0, size);
1007
+ }
1008
+
1009
+ out_kind = OutArgument::Kind::Array;
995
1010
  }
996
1011
  } else if (IsRawBuffer(value)) {
997
1012
  Span<uint8_t> buffer = GetRawBuffer(value);
@@ -1006,6 +1021,8 @@ bool CallData::PushPointer(Napi::Value value, const TypeInfo *type, int directio
1006
1021
  ptr = buffer.ptr;
1007
1022
  directions = 1;
1008
1023
  }
1024
+
1025
+ out_kind = OutArgument::Kind::Buffer;
1009
1026
  } else if (RG_LIKELY(type->ref.type->primitive == PrimitiveKind::Record ||
1010
1027
  type->ref.type->primitive == PrimitiveKind::Union)) {
1011
1028
  if (RG_UNLIKELY(!type->ref.type->size)) {
@@ -1031,6 +1048,8 @@ bool CallData::PushPointer(Napi::Value value, const TypeInfo *type, int directio
1031
1048
 
1032
1049
  memset_safe(ptr, 0, type->size);
1033
1050
  }
1051
+
1052
+ out_kind = OutArgument::Kind::Object;
1034
1053
  } else {
1035
1054
  goto unexpected;
1036
1055
  }
@@ -1041,14 +1060,36 @@ bool CallData::PushPointer(Napi::Value value, const TypeInfo *type, int directio
1041
1060
  napi_status status = napi_create_reference(env, value, 1, &out->ref);
1042
1061
  RG_ASSERT(status == napi_ok);
1043
1062
 
1063
+ out->kind = out_kind;
1044
1064
  out->ptr = ptr;
1045
1065
  out->type = type->ref.type;
1066
+ out->max_len = out_max_len;
1046
1067
  }
1047
1068
 
1048
1069
  *out_ptr = ptr;
1049
1070
  return true;
1050
1071
  } break;
1051
1072
 
1073
+ case napi_string: {
1074
+ RG_ASSERT(type->primitive == PrimitiveKind::Pointer);
1075
+
1076
+ if (RG_UNLIKELY(directions & 2))
1077
+ goto unexpected;
1078
+
1079
+ if (type->ref.type == instance->void_type) {
1080
+ PushStringValue(value, (const char **)out_ptr);
1081
+ return true;
1082
+ } else if (type->ref.type->primitive == PrimitiveKind::Int8) {
1083
+ PushStringValue(value, (const char **)out_ptr);
1084
+ return true;
1085
+ } else if (type->ref.type->primitive == PrimitiveKind::Int16) {
1086
+ PushString16Value(value, (const char16_t **)out_ptr);
1087
+ return true;
1088
+ } else {
1089
+ goto unexpected;
1090
+ }
1091
+ } break;
1092
+
1052
1093
  case napi_number: {
1053
1094
  Napi::Number number = value.As<Napi::Number>();
1054
1095
  intptr_t ptr = (intptr_t)number.Int32Value();
@@ -1075,6 +1116,27 @@ unexpected:
1075
1116
  return false;
1076
1117
  }
1077
1118
 
1119
+ Size CallData::PushIndirectString(Napi::Array array, const TypeInfo *ref, uint8_t **out_ptr)
1120
+ {
1121
+ if (array.Length() != 1)
1122
+ return -1;
1123
+
1124
+ Napi::Value value = array[0u];
1125
+
1126
+ if (!value.IsString())
1127
+ return -1;
1128
+
1129
+ if (ref == instance->void_type) {
1130
+ return PushStringValue(value, (const char **)out_ptr);
1131
+ } else if (ref->primitive == PrimitiveKind::Int8) {
1132
+ return PushStringValue(value, (const char **)out_ptr);
1133
+ } else if (ref->primitive == PrimitiveKind::Int16) {
1134
+ return PushString16Value(value, (const char16_t **)out_ptr);
1135
+ } else {
1136
+ return -1;
1137
+ }
1138
+ }
1139
+
1078
1140
  static inline Napi::Value GetReferenceValue(Napi::Env env, napi_ref ref)
1079
1141
  {
1080
1142
  napi_value value;
@@ -1091,21 +1153,55 @@ void CallData::PopOutArguments()
1091
1153
  Napi::Value value = GetReferenceValue(env, out.ref);
1092
1154
  RG_ASSERT(!value.IsEmpty());
1093
1155
 
1094
- if (value.IsArray()) {
1095
- Napi::Array array(env, value);
1096
- DecodeNormalArray(array, out.ptr, out.type);
1097
- } else if (IsRawBuffer(value)) {
1098
- Span<uint8_t> buffer = GetRawBuffer(value);
1099
- DecodeBuffer(buffer, out.ptr, out.type);
1100
- } else {
1101
- Napi::Object obj = value.As<Napi::Object>();
1102
-
1103
- if (CheckValueTag(instance, value, &MagicUnionMarker)) {
1104
- MagicUnion *u = MagicUnion::Unwrap(obj);
1105
- u->SetRaw(out.ptr);
1106
- } else {
1107
- DecodeObject(obj, out.ptr, out.type);
1108
- }
1156
+ switch (out.kind) {
1157
+ case OutArgument::Kind::Array: {
1158
+ RG_ASSERT(value.IsArray());
1159
+
1160
+ Napi::Array array(env, value);
1161
+ DecodeNormalArray(array, out.ptr, out.type);
1162
+ } break;
1163
+
1164
+ case OutArgument::Kind::Buffer: {
1165
+ RG_ASSERT(IsRawBuffer(value));
1166
+
1167
+ Span<uint8_t> buffer = GetRawBuffer(value);
1168
+ DecodeBuffer(buffer, out.ptr, out.type);
1169
+ } break;
1170
+
1171
+ case OutArgument::Kind::String: {
1172
+ Napi::Array array(env, value);
1173
+
1174
+ RG_ASSERT(array.IsArray());
1175
+ RG_ASSERT(array.Length() == 1);
1176
+
1177
+ Size len = strnlen((const char *)out.ptr, out.max_len);
1178
+ Napi::String str = Napi::String::New(env, (const char *)out.ptr, len);
1179
+
1180
+ array.Set(0u, str);
1181
+ } break;
1182
+
1183
+ case OutArgument::Kind::String16: {
1184
+ Napi::Array array(env, value);
1185
+
1186
+ RG_ASSERT(array.IsArray());
1187
+ RG_ASSERT(array.Length() == 1);
1188
+
1189
+ Size len = WideStringLength((const char16_t *)out.ptr, out.max_len);
1190
+ Napi::String str = Napi::String::New(env, (const char16_t *)out.ptr, len);
1191
+
1192
+ array.Set(0u, str);
1193
+ } break;
1194
+
1195
+ case OutArgument::Kind::Object: {
1196
+ Napi::Object obj = value.As<Napi::Object>();
1197
+
1198
+ if (CheckValueTag(instance, value, &MagicUnionMarker)) {
1199
+ MagicUnion *u = MagicUnion::Unwrap(obj);
1200
+ u->SetRaw(out.ptr);
1201
+ } else {
1202
+ DecodeObject(obj, out.ptr, out.type);
1203
+ }
1204
+ } break;
1109
1205
  }
1110
1206
  }
1111
1207
  }
@@ -1131,6 +1227,7 @@ void *CallData::ReserveTrampoline(const FunctionInfo *proto, Napi::Function func
1131
1227
 
1132
1228
  TrampolineInfo *trampoline = &shared.trampolines[idx];
1133
1229
 
1230
+ trampoline->instance = instance;
1134
1231
  trampoline->proto = proto;
1135
1232
  trampoline->func.Reset(func, 1);
1136
1233
  trampoline->recv.Reset();
@@ -37,9 +37,21 @@ struct BackRegisters;
37
37
  // But on Windows i386, without it, the alignment may not be correct (compiler bug?).
38
38
  class alignas(8) CallData {
39
39
  struct OutArgument {
40
+ enum class Kind {
41
+ Array,
42
+ Buffer,
43
+ String,
44
+ String16,
45
+ Object
46
+ };
47
+
48
+ Kind kind;
49
+
40
50
  napi_ref ref;
41
51
  const uint8_t *ptr;
42
52
  const TypeInfo *type;
53
+
54
+ Size max_len; // Only for indirect strings
43
55
  };
44
56
 
45
57
  Napi::Env env;
@@ -116,6 +128,7 @@ private:
116
128
  bool PushBuffer(Span<const uint8_t> buffer, Size size, const TypeInfo *type, uint8_t *origin);
117
129
  bool PushStringArray(Napi::Value value, const TypeInfo *type, uint8_t *origin);
118
130
  bool PushPointer(Napi::Value value, const TypeInfo *type, int directions, void **out_ptr);
131
+ Size PushIndirectString(Napi::Array array, const TypeInfo *ref, uint8_t **out_ptr);
119
132
 
120
133
  void PopOutArguments();
121
134
 
@@ -605,8 +605,10 @@ static Napi::Value EncodePointerDirection(const Napi::CallbackInfo &info, int di
605
605
  if (!type)
606
606
  return env.Null();
607
607
 
608
- if (type->primitive != PrimitiveKind::Pointer) {
609
- ThrowError<Napi::TypeError>(env, "Unexpected %1 type, expected pointer type", type->name);
608
+ if (type->primitive != PrimitiveKind::Pointer &&
609
+ type->primitive != PrimitiveKind::String &&
610
+ type->primitive != PrimitiveKind::String16) {
611
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 type, expected pointer or string type", type->name);
610
612
  return env.Null();
611
613
  }
612
614
 
@@ -653,9 +655,9 @@ static Napi::Value CreateDisposableType(const Napi::CallbackInfo &info)
653
655
  const TypeInfo *src = ResolveType(info[named]);
654
656
  if (!src)
655
657
  return env.Null();
656
- if (src->primitive != PrimitiveKind::String &&
657
- src->primitive != PrimitiveKind::String16 &&
658
- src->primitive != PrimitiveKind::Pointer) {
658
+ if (src->primitive != PrimitiveKind::Pointer &&
659
+ src->primitive != PrimitiveKind::String &&
660
+ src->primitive != PrimitiveKind::String16) {
659
661
  ThrowError<Napi::TypeError>(env, "Unexpected %1 type, expected pointer or string type", src->name);
660
662
  return env.Null();
661
663
  }
@@ -1652,6 +1654,7 @@ static Napi::Value RegisterCallback(const Napi::CallbackInfo &info)
1652
1654
 
1653
1655
  TrampolineInfo *trampoline = &shared.trampolines[idx];
1654
1656
 
1657
+ trampoline->instance = instance;
1655
1658
  trampoline->proto = type->ref.proto;
1656
1659
  trampoline->func.Reset(func, 1);
1657
1660
  if (!IsNullOrUndefined(recv)) {
@@ -1952,10 +1955,8 @@ InstanceData::~InstanceData()
1952
1955
  for (int16_t idx = 0; idx < MaxTrampolines; idx++) {
1953
1956
  TrampolineInfo *trampoline = &shared.trampolines[idx];
1954
1957
 
1955
- if (trampoline->func.IsEmpty())
1956
- continue;
1957
-
1958
- if (trampoline->func.Env().GetInstanceData<InstanceData>() == this) {
1958
+ if (trampoline->instance == this) {
1959
+ trampoline->instance = nullptr;
1959
1960
  trampoline->func.Reset();
1960
1961
  trampoline->recv.Reset();
1961
1962
  }
@@ -1982,8 +1983,10 @@ static Napi::Value CastValue(const Napi::CallbackInfo &info)
1982
1983
  const TypeInfo *type = ResolveType(info[1]);
1983
1984
  if (RG_UNLIKELY(!type))
1984
1985
  return env.Null();
1985
- if (type->primitive != PrimitiveKind::Pointer) {
1986
- ThrowError<Napi::TypeError>(env, "Only pointer types can be used for casting");
1986
+ if (type->primitive != PrimitiveKind::Pointer &&
1987
+ type->primitive != PrimitiveKind::String &&
1988
+ type->primitive != PrimitiveKind::String16) {
1989
+ ThrowError<Napi::TypeError>(env, "Only pointer or string types can be used for casting");
1987
1990
  return env.Null();
1988
1991
  }
1989
1992
 
@@ -305,6 +305,8 @@ RG_STATIC_ASSERT(DefaultMaxAsyncCalls >= DefaultResidentAsyncPools);
305
305
  RG_STATIC_ASSERT(MaxAsyncCalls >= DefaultMaxAsyncCalls);
306
306
 
307
307
  struct TrampolineInfo {
308
+ InstanceData *instance;
309
+
308
310
  const FunctionInfo *proto;
309
311
  Napi::FunctionReference func;
310
312
  Napi::Reference<Napi::Value> recv;
@@ -647,7 +647,7 @@ void DecodeObject(Napi::Object obj, const uint8_t *origin, const TypeInfo *type)
647
647
  }
648
648
  }
649
649
 
650
- static Size WideStringLength(const char16_t *str16, Size max)
650
+ Size WideStringLength(const char16_t *str16, Size max)
651
651
  {
652
652
  Size len = 0;
653
653
 
@@ -154,6 +154,8 @@ T GetNumber(Napi::Value value)
154
154
  RG_UNREACHABLE();
155
155
  }
156
156
 
157
+ Size WideStringLength(const char16_t *str16, Size max);
158
+
157
159
  Napi::Object DecodeObject(Napi::Env env, const uint8_t *origin, const TypeInfo *type);
158
160
  void DecodeObject(Napi::Object obj, const uint8_t *origin, const TypeInfo *type);
159
161
  Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *type);
@@ -1,5 +1,46 @@
1
1
  # node-addon-api Changelog
2
2
 
3
+ ## 2023-04-20 Version 6.1.0, @NickNaso
4
+
5
+ ### Notable changes
6
+
7
+ #### API
8
+
9
+ - Enforce type checks on `Napi::Value::As()`.
10
+ - Added `Napi::TypeTaggable` class.
11
+ - Defined `NAPI_HAS_THREADS` to make TSFN available on Emscripten.
12
+ - Defined `NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED` and
13
+ `Napi::Buffer::NewOrCopy()` to handle the support for external buffers.
14
+
15
+ #### TEST
16
+
17
+ - Added tests for `Napi::Reference<T>` class.
18
+ - Added tests for copy/move semantics.
19
+ - Added tests for `Napi::RangeError` and `Napi::TypeError` class.
20
+ - Fixed inconsistent failure executing test suite.
21
+ - Added tests for `Napi::ObjectReference<T>` class.
22
+ - Added tests for `Napi::ObjectWrap<T>` class.
23
+
24
+ ### Documentation
25
+
26
+ - Added documentation for `Napi::TypeTaggable`.
27
+ - Some minor fixes all over the documentation.
28
+
29
+ ### Commits
30
+
31
+ - \[[`5adb896782`](https://github.com/nodejs/node-addon-api/commit/5adb896782)] - **src**: enforce type checks on Napi::Value::As() (#1281) (Chengzhong Wu)
32
+ - \[[`d9faac7ec2`](https://github.com/nodejs/node-addon-api/commit/d9faac7ec2)] - Fix exits/exists typo in docs for Env::AddCleanupHook() (#1306) (Mathias Stearn)
33
+ - \[[`164459ca03`](https://github.com/nodejs/node-addon-api/commit/164459ca03)] - **doc**: update class hierarchy for TypeTaggable (Gabriel Schulhof) [#1303](https://github.com/nodejs/node-addon-api/pull/1303)
34
+ - \[[`d01304437c`](https://github.com/nodejs/node-addon-api/commit/d01304437c)] - **src**: interject class TypeTaggable (Gabriel Schulhof) [#1298](https://github.com/nodejs/node-addon-api/pull/1298)
35
+ - \[[`d4942ccd4f`](https://github.com/nodejs/node-addon-api/commit/d4942ccd4f)] - **test**: Complete test coverage for Reference\<T> class (#1277) (Jack)
36
+ - \[[`a8ad7e7a7b`](https://github.com/nodejs/node-addon-api/commit/a8ad7e7a7b)] - **test**: Add tests for copy/move semantics (JckXia) [#1295](https://github.com/nodejs/node-addon-api/pull/1295)
37
+ - \[[`e484327344`](https://github.com/nodejs/node-addon-api/commit/e484327344)] - Add test coverage for typed and range err (#1280) (Jack)
38
+ - \[[`ebc7858593`](https://github.com/nodejs/node-addon-api/commit/ebc7858593)] - **test**: Update wait with a condition (#1297) (Jack)
39
+ - \[[`0b53d885f5`](https://github.com/nodejs/node-addon-api/commit/0b53d885f5)] - **src**: define `NAPI_HAS_THREADS` (toyobayashi) [#1283](https://github.com/nodejs/node-addon-api/pull/1283)
40
+ - \[[`464610babf`](https://github.com/nodejs/node-addon-api/commit/464610babf)] - **test**: complete objectRefs tests (JckXia) [#1274](https://github.com/nodejs/node-addon-api/pull/1274)
41
+ - \[[`b16c762a19`](https://github.com/nodejs/node-addon-api/commit/b16c762a19)] - **src**: handle no support for external buffers (legendecas) [#1273](https://github.com/nodejs/node-addon-api/pull/1273)
42
+ - \[[`61b8e28720`](https://github.com/nodejs/node-addon-api/commit/61b8e28720)] - **test**: Add test covg for obj wrap (#1269) (Jack)
43
+
3
44
  ## 2023-02-03 Version 6.0.0, @NickNaso
4
45
 
5
46
  ### Notable changes
@@ -70,7 +70,7 @@ and node-addon-api.
70
70
  - **[Contributors](#contributors)**
71
71
  - **[License](#license)**
72
72
 
73
- ## **Current version: 6.0.0**
73
+ ## **Current version: 6.1.0**
74
74
 
75
75
  (See [CHANGELOG.md](CHANGELOG.md) for complete Changelog)
76
76
 
@@ -23,6 +23,9 @@ Returns a new `Napi::ArrayBuffer` instance.
23
23
 
24
24
  ### New
25
25
 
26
+ > When `NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED` is defined, this method is not available.
27
+ > See [External Buffer][] for more information.
28
+
26
29
  Wraps the provided external data into a new `Napi::ArrayBuffer` instance.
27
30
 
28
31
  The `Napi::ArrayBuffer` instance does not assume ownership for the data and
@@ -48,6 +51,9 @@ Returns a new `Napi::ArrayBuffer` instance.
48
51
 
49
52
  ### New
50
53
 
54
+ > When `NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED` is defined, this method is not available.
55
+ > See [External Buffer][] for more information.
56
+
51
57
  Wraps the provided external data into a new `Napi::ArrayBuffer` instance.
52
58
 
53
59
  The `Napi::ArrayBuffer` instance does not assume ownership for the data and
@@ -74,6 +80,9 @@ Returns a new `Napi::ArrayBuffer` instance.
74
80
 
75
81
  ### New
76
82
 
83
+ > When `NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED` is defined, this method is not available.
84
+ > See [External Buffer][] for more information.
85
+
77
86
  Wraps the provided external data into a new `Napi::ArrayBuffer` instance.
78
87
 
79
88
  The `Napi::ArrayBuffer` instance does not assume ownership for the data and expects it
@@ -153,3 +162,4 @@ bool Napi::ArrayBuffer::IsDetached() const;
153
162
  Returns `true` if this `ArrayBuffer` has been detached.
154
163
 
155
164
  [`Napi::Object`]: ./object.md
165
+ [External Buffer]: ./external_buffer.md
@@ -22,6 +22,9 @@ Returns a new `Napi::Buffer` object.
22
22
 
23
23
  ### New
24
24
 
25
+ > When `NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED` is defined, this method is not available.
26
+ > See [External Buffer][] for more information.
27
+
25
28
  Wraps the provided external data into a new `Napi::Buffer` object.
26
29
 
27
30
  The `Napi::Buffer` object does not assume ownership for the data and expects it to be
@@ -47,6 +50,9 @@ Returns a new `Napi::Buffer` object.
47
50
 
48
51
  ### New
49
52
 
53
+ > When `NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED` is defined, this method is not available.
54
+ > See [External Buffer][] for more information.
55
+
50
56
  Wraps the provided external data into a new `Napi::Buffer` object.
51
57
 
52
58
  The `Napi::Buffer` object does not assume ownership for the data and expects it
@@ -72,6 +78,9 @@ Returns a new `Napi::Buffer` object.
72
78
 
73
79
  ### New
74
80
 
81
+ > When `NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED` is defined, this method is not available.
82
+ > See [External Buffer][] for more information.
83
+
75
84
  Wraps the provided external data into a new `Napi::Buffer` object.
76
85
 
77
86
  The `Napi::Buffer` object does not assume ownership for the data and expects it to be
@@ -98,6 +107,93 @@ static Napi::Buffer<T> Napi::Buffer::New(napi_env env,
98
107
 
99
108
  Returns a new `Napi::Buffer` object.
100
109
 
110
+ ### NewOrCopy
111
+
112
+ Wraps the provided external data into a new `Napi::Buffer` object. When the
113
+ [external buffer][] is not supported, allocates a new `Napi::Buffer` object and
114
+ copies the provided external data into it.
115
+
116
+ The `Napi::Buffer` object does not assume ownership for the data and expects it to be
117
+ valid for the lifetime of the object. Since the `Napi::Buffer` is subject to garbage
118
+ collection this overload is only suitable for data which is static and never
119
+ needs to be freed.
120
+
121
+ This factory method will not provide the caller with an opportunity to free the
122
+ data when the `Napi::Buffer` gets garbage-collected. If you need to free the
123
+ data retained by the `Napi::Buffer` object please use other variants of the
124
+ `Napi::Buffer::New` factory method that accept `Napi::Finalizer`, which is a
125
+ function that will be invoked when the `Napi::Buffer` object has been
126
+ destroyed.
127
+
128
+ ```cpp
129
+ static Napi::Buffer<T> Napi::Buffer::NewOrCopy(napi_env env, T* data, size_t length);
130
+ ```
131
+
132
+ - `[in] env`: The environment in which to create the `Napi::Buffer` object.
133
+ - `[in] data`: The pointer to the external data to expose.
134
+ - `[in] length`: The number of `T` elements in the external data.
135
+
136
+ Returns a new `Napi::Buffer` object.
137
+
138
+ ### NewOrCopy
139
+
140
+ Wraps the provided external data into a new `Napi::Buffer` object. When the
141
+ [external buffer][] is not supported, allocates a new `Napi::Buffer` object and
142
+ copies the provided external data into it and the `finalizeCallback` is invoked
143
+ immediately.
144
+
145
+ The `Napi::Buffer` object does not assume ownership for the data and expects it
146
+ to be valid for the lifetime of the object. The data can only be freed once the
147
+ `finalizeCallback` is invoked to indicate that the `Napi::Buffer` has been released.
148
+
149
+ ```cpp
150
+ template <typename Finalizer>
151
+ static Napi::Buffer<T> Napi::Buffer::NewOrCopy(napi_env env,
152
+ T* data,
153
+ size_t length,
154
+ Finalizer finalizeCallback);
155
+ ```
156
+
157
+ - `[in] env`: The environment in which to create the `Napi::Buffer` object.
158
+ - `[in] data`: The pointer to the external data to expose.
159
+ - `[in] length`: The number of `T` elements in the external data.
160
+ - `[in] finalizeCallback`: The function to be called when the `Napi::Buffer` is
161
+ destroyed. It must implement `operator()`, accept an Napi::Env, a `T*` (which is the
162
+ external data pointer), and return `void`.
163
+
164
+ Returns a new `Napi::Buffer` object.
165
+
166
+ ### NewOrCopy
167
+
168
+ Wraps the provided external data into a new `Napi::Buffer` object. When the
169
+ [external buffer][] is not supported, allocates a new `Napi::Buffer` object and
170
+ copies the provided external data into it and the `finalizeCallback` is invoked
171
+ immediately.
172
+
173
+ The `Napi::Buffer` object does not assume ownership for the data and expects it to be
174
+ valid for the lifetime of the object. The data can only be freed once the
175
+ `finalizeCallback` is invoked to indicate that the `Napi::Buffer` has been released.
176
+
177
+ ```cpp
178
+ template <typename Finalizer, typename Hint>
179
+ static Napi::Buffer<T> Napi::Buffer::NewOrCopy(napi_env env,
180
+ T* data,
181
+ size_t length,
182
+ Finalizer finalizeCallback,
183
+ Hint* finalizeHint);
184
+ ```
185
+
186
+ - `[in] env`: The environment in which to create the `Napi::Buffer` object.
187
+ - `[in] data`: The pointer to the external data to expose.
188
+ - `[in] length`: The number of `T` elements in the external data.
189
+ - `[in] finalizeCallback`: The function to be called when the `Napi::Buffer` is
190
+ destroyed. It must implement `operator()`, accept an Napi::Env, a `T*` (which is the
191
+ external data pointer) and `Hint*`, and return `void`.
192
+ - `[in] finalizeHint`: The hint to be passed as the second parameter of the
193
+ finalize callback.
194
+
195
+ Returns a new `Napi::Buffer` object.
196
+
101
197
  ### Copy
102
198
 
103
199
  Allocates a new `Napi::Buffer` object and copies the provided external data into it.
@@ -148,3 +244,4 @@ size_t Napi::Buffer::Length() const;
148
244
  Returns the number of `T` elements in the external data.
149
245
 
150
246
  [`Napi::Uint8Array`]: ./typed_array_of.md
247
+ [External Buffer]: ./external_buffer.md