koffi 2.6.6 → 2.6.8

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 (35) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/build/koffi/darwin_arm64/koffi.node +0 -0
  3. package/build/koffi/darwin_x64/koffi.node +0 -0
  4. package/build/koffi/freebsd_arm64/koffi.node +0 -0
  5. package/build/koffi/freebsd_ia32/koffi.node +0 -0
  6. package/build/koffi/freebsd_x64/koffi.node +0 -0
  7. package/build/koffi/linux_arm32hf/koffi.node +0 -0
  8. package/build/koffi/linux_arm64/koffi.node +0 -0
  9. package/build/koffi/linux_ia32/koffi.node +0 -0
  10. package/build/koffi/linux_riscv64hf64/koffi.node +0 -0
  11. package/build/koffi/linux_x64/koffi.node +0 -0
  12. package/build/koffi/openbsd_ia32/koffi.node +0 -0
  13. package/build/koffi/openbsd_x64/koffi.node +0 -0
  14. package/build/koffi/win32_arm64/koffi.exp +0 -0
  15. package/build/koffi/win32_arm64/koffi.lib +0 -0
  16. package/build/koffi/win32_arm64/koffi.node +0 -0
  17. package/build/koffi/win32_ia32/koffi.exp +0 -0
  18. package/build/koffi/win32_ia32/koffi.lib +0 -0
  19. package/build/koffi/win32_ia32/koffi.node +0 -0
  20. package/build/koffi/win32_x64/koffi.exp +0 -0
  21. package/build/koffi/win32_x64/koffi.lib +0 -0
  22. package/build/koffi/win32_x64/koffi.node +0 -0
  23. package/build/koffi/win32_x64/koffi.pdb +0 -0
  24. package/doc/pointers.md +1 -1
  25. package/index.js +4 -4
  26. package/indirect.js +4 -4
  27. package/package.json +2 -2
  28. package/src/cnoke/package.json +1 -1
  29. package/src/core/libcc/libcc.cc +13 -4
  30. package/src/core/libcc/libcc.hh +8 -0
  31. package/src/koffi/src/call.cc +1 -1
  32. package/src/koffi/src/ffi.cc +17 -7
  33. package/src/koffi/src/util.hh +13 -0
  34. package/src/koffi/src/win32.cc +1 -1
  35. package/src/koffi/src/win32.hh +1 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,13 @@
4
4
 
5
5
  ### Koffi 2.6
6
6
 
7
+ #### Koffi 2.6.8 (2023-11-24)
8
+
9
+ - Search in DLL directory for additional dependencies on Windows
10
+ - Ignore prototype properties when making structs or unions
11
+ - Show detected version of Node when not adequate
12
+ - Minor documentation fixes
13
+
7
14
  #### Koffi 2.6.6 (2023-10-28)
8
15
 
9
16
  - Better handle errors while making struct or union types
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/doc/pointers.md CHANGED
@@ -19,7 +19,7 @@ The following Win32 example uses `GetCursorPos()` (with an output parameter) to
19
19
  // ES6 syntax: import koffi from 'koffi';
20
20
  const koffi = require('koffi');
21
21
 
22
- const lib = koffi.load('kernel32.dll');
22
+ const lib = koffi.load('user32.dll');
23
23
 
24
24
  // Type declarations
25
25
  const POINT = koffi.struct('POINT', {
package/index.js CHANGED
@@ -378,8 +378,8 @@ var require_package = __commonJS({
378
378
  "build/dist/src/koffi/package.json"(exports2, module2) {
379
379
  module2.exports = {
380
380
  name: "koffi",
381
- version: "2.6.6",
382
- stable: "2.6.6",
381
+ version: "2.6.8",
382
+ stable: "2.6.8",
383
383
  description: "Fast and simple C FFI (foreign function interface) for Node.js",
384
384
  keywords: [
385
385
  "foreign",
@@ -438,9 +438,9 @@ if (process.versions.napi == null || process.versions.napi < pkg.cnoke.napi) {
438
438
  let major = parseInt(process.versions.node, 10);
439
439
  let required = get_napi_version(pkg.cnoke.napi, major);
440
440
  if (required != null) {
441
- throw new Error(`Project ${pkg.name} requires Node >= ${required} in the Node ${major}.x branch (N-API >= ${pkg.cnoke.napi})`);
441
+ throw new Error(`This engine is based on Node ${process.versions.node}, but ${pkg.name} requires Node >= ${required} in the Node ${major}.x branch (N-API >= ${pkg.cnoke.napi})`);
442
442
  } else {
443
- throw new Error(`Project ${pkg.name} does not support the Node ${major}.x branch (N-API < ${pkg.cnoke.napi})`);
443
+ throw new Error(`This engine is based on Node ${process.versions.node}, but ${pkg.name} does not support the Node ${major}.x branch (N-API < ${pkg.cnoke.napi})`);
444
444
  }
445
445
  }
446
446
  var arch = determine_arch();
package/indirect.js CHANGED
@@ -378,8 +378,8 @@ var require_package = __commonJS({
378
378
  "build/dist/src/koffi/package.json"(exports2, module2) {
379
379
  module2.exports = {
380
380
  name: "koffi",
381
- version: "2.6.6",
382
- stable: "2.6.6",
381
+ version: "2.6.8",
382
+ stable: "2.6.8",
383
383
  description: "Fast and simple C FFI (foreign function interface) for Node.js",
384
384
  keywords: [
385
385
  "foreign",
@@ -438,9 +438,9 @@ if (process.versions.napi == null || process.versions.napi < pkg.cnoke.napi) {
438
438
  let major = parseInt(process.versions.node, 10);
439
439
  let required = get_napi_version(pkg.cnoke.napi, major);
440
440
  if (required != null) {
441
- throw new Error(`Project ${pkg.name} requires Node >= ${required} in the Node ${major}.x branch (N-API >= ${pkg.cnoke.napi})`);
441
+ throw new Error(`This engine is based on Node ${process.versions.node}, but ${pkg.name} requires Node >= ${required} in the Node ${major}.x branch (N-API >= ${pkg.cnoke.napi})`);
442
442
  } else {
443
- throw new Error(`Project ${pkg.name} does not support the Node ${major}.x branch (N-API < ${pkg.cnoke.napi})`);
443
+ throw new Error(`This engine is based on Node ${process.versions.node}, but ${pkg.name} does not support the Node ${major}.x branch (N-API < ${pkg.cnoke.napi})`);
444
444
  }
445
445
  }
446
446
  var arch = determine_arch();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koffi",
3
- "version": "2.6.6",
4
- "stable": "2.6.6",
3
+ "version": "2.6.8",
4
+ "stable": "2.6.8",
5
5
  "description": "Fast and simple C FFI (foreign function interface) for Node.js",
6
6
  "keywords": [
7
7
  "foreign",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cnoke",
3
- "version": "4.0.2",
3
+ "version": "4.0.3",
4
4
  "description": "Build native Node addons based on CMake, without extra dependency",
5
5
  "keywords": [
6
6
  "native",
@@ -2067,11 +2067,17 @@ bool IsWin32Utf8()
2067
2067
 
2068
2068
  Size ConvertUtf8ToWin32Wide(Span<const char> str, Span<wchar_t> out_str_w)
2069
2069
  {
2070
- RG_ASSERT(out_str_w.len >= 2);
2070
+ if (!out_str_w.len) {
2071
+ LogError("Output buffer is too small");
2072
+ return -1;
2073
+ }
2071
2074
 
2072
- if (!str.len) [[unlikely]] {
2075
+ if (!str.len) {
2073
2076
  out_str_w[0] = 0;
2074
2077
  return 0;
2078
+ } else if (out_str_w.len == 1) {
2079
+ LogError("Output buffer is too small");
2080
+ return -1;
2075
2081
  }
2076
2082
 
2077
2083
  int len = MultiByteToWideChar(CP_UTF8, 0, str.ptr, (int)str.len, out_str_w.ptr, (int)out_str_w.len - 1);
@@ -2092,7 +2098,10 @@ Size ConvertUtf8ToWin32Wide(Span<const char> str, Span<wchar_t> out_str_w)
2092
2098
 
2093
2099
  Size ConvertWin32WideToUtf8(LPCWSTR str_w, Span<char> out_str)
2094
2100
  {
2095
- RG_ASSERT(out_str.len >= 1);
2101
+ if (!out_str.len) {
2102
+ LogError("Output buffer is too small");
2103
+ return -1;
2104
+ }
2096
2105
 
2097
2106
  int len = WideCharToMultiByte(CP_UTF8, 0, str_w, -1, out_str.ptr, (int)out_str.len - 1, nullptr, nullptr);
2098
2107
  if (!len) {
@@ -5218,7 +5227,7 @@ restart:
5218
5227
  int ret = syscall(SYS_getrandom, &buf, RG_SIZE(buf), 0);
5219
5228
  RG_CRITICAL(ret >= 0, "getentropy() failed: %1", strerror(errno));
5220
5229
 
5221
- if (ret < RG_SIZE(buf))
5230
+ if (ret < RG_SIZE(buf)) [[unlikely]]
5222
5231
  goto restart;
5223
5232
  }
5224
5233
  #else
@@ -4595,6 +4595,10 @@ public:
4595
4595
  CompressionType compression_type = CompressionType::None,
4596
4596
  CompressionSpeed compression_speed = CompressionSpeed::Default)
4597
4597
  : StreamWriter() { Open(mem, filename, compression_type, compression_speed); }
4598
+ StreamWriter(HeapArray<char> *mem, const char *filename = nullptr,
4599
+ CompressionType compression_type = CompressionType::None,
4600
+ CompressionSpeed compression_speed = CompressionSpeed::Default)
4601
+ : StreamWriter() { Open(mem, filename, compression_type, compression_speed); }
4598
4602
  StreamWriter(FILE *fp, const char *filename,
4599
4603
  CompressionType compression_type = CompressionType::None,
4600
4604
  CompressionSpeed compression_speed = CompressionSpeed::Default)
@@ -4612,6 +4616,10 @@ public:
4612
4616
  bool Open(HeapArray<uint8_t> *mem, const char *filename = nullptr,
4613
4617
  CompressionType compression_type = CompressionType::None,
4614
4618
  CompressionSpeed compression_speed = CompressionSpeed::Default);
4619
+ bool Open(HeapArray<char> *mem, const char *filename = nullptr,
4620
+ CompressionType compression_type = CompressionType::None,
4621
+ CompressionSpeed compression_speed = CompressionSpeed::Default)
4622
+ { return Open((HeapArray<uint8_t> *)mem, filename, compression_type, compression_speed); }
4615
4623
  bool Open(FILE *fp, const char *filename,
4616
4624
  CompressionType compression_type = CompressionType::None,
4617
4625
  CompressionSpeed compression_speed = CompressionSpeed::Default);
@@ -383,7 +383,7 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
383
383
  return false;
384
384
  }
385
385
  } else {
386
- Napi::Array properties = obj.GetPropertyNames();
386
+ Napi::Array properties = GetOwnPropertyNames(obj);
387
387
 
388
388
  if (properties.Length() != 1 || !properties.Get(0u).IsString()) [[unlikely]] {
389
389
  ThrowError<Napi::Error>(env, "Expected object with single property name for union");
@@ -131,7 +131,7 @@ static Napi::Value GetSetConfig(const Napi::CallbackInfo &info)
131
131
  int max_async_calls = new_config.resident_async_pools + new_config.max_temporaries;
132
132
 
133
133
  Napi::Object obj = info[0].As<Napi::Object>();
134
- Napi::Array keys = obj.GetPropertyNames();
134
+ Napi::Array keys = GetOwnPropertyNames(obj);
135
135
 
136
136
  for (uint32_t i = 0; i < keys.Length(); i++) {
137
137
  std::string key = keys.Get(i).As<Napi::String>();
@@ -227,7 +227,7 @@ static Napi::Value CreateStructType(const Napi::CallbackInfo &info, bool pad)
227
227
 
228
228
  Napi::String name = info[0].As<Napi::String>();
229
229
  Napi::Object obj = info[named].As<Napi::Object>();
230
- Napi::Array keys = obj.GetPropertyNames();
230
+ Napi::Array keys = GetOwnPropertyNames(obj);
231
231
 
232
232
  RG_DEFER_NC(err_guard, len = instance->types.len) {
233
233
  Size start = len + !named;
@@ -373,7 +373,7 @@ static Napi::Value CreateUnionType(const Napi::CallbackInfo &info)
373
373
 
374
374
  Napi::String name = info[0].As<Napi::String>();
375
375
  Napi::Object obj = info[named].As<Napi::Object>();
376
- Napi::Array keys = obj.GetPropertyNames();
376
+ Napi::Array keys = GetOwnPropertyNames(obj);
377
377
 
378
378
  RG_DEFER_NC(err_guard, len = instance->types.len) {
379
379
  Size start = len + !named;
@@ -1640,14 +1640,24 @@ static Napi::Value UnloadLibrary(const Napi::CallbackInfo &info)
1640
1640
  }
1641
1641
 
1642
1642
  #ifdef _WIN32
1643
- static HANDLE LoadWindowsLibrary(Napi::Env env, const char16_t *filename)
1643
+ static HANDLE LoadWindowsLibrary(Napi::Env env, const char *path)
1644
1644
  {
1645
- HANDLE module = LoadLibraryW((LPCWSTR)filename);
1645
+ BlockAllocator temp_alloc;
1646
+
1647
+ DWORD flags = LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR;
1648
+
1649
+ Span<const char> filename = NormalizePath(path, GetWorkingDirectory(), &temp_alloc);
1650
+ Span<wchar_t> filename_w = AllocateSpan<wchar_t>(&temp_alloc, filename.len + 1);
1651
+
1652
+ if (ConvertUtf8ToWin32Wide(filename, filename_w) < 0)
1653
+ return nullptr;
1654
+
1655
+ HMODULE module = LoadLibraryExW(filename_w.ptr, nullptr, flags);
1646
1656
 
1647
1657
  if (!module) {
1648
1658
  if (GetLastError() == ERROR_BAD_EXE_FORMAT) {
1649
1659
  int process = GetSelfMachine();
1650
- int dll = GetDllMachine(filename);
1660
+ int dll = GetDllMachine(filename_w.ptr);
1651
1661
 
1652
1662
  if (process >= 0 && dll >= 0 && dll != process) {
1653
1663
  ThrowError<Napi::Error>(env, "Cannot load '%1' DLL in '%2' process",
@@ -1700,7 +1710,7 @@ static Napi::Value LoadSharedLibrary(const Napi::CallbackInfo &info)
1700
1710
  void *module = nullptr;
1701
1711
  #ifdef _WIN32
1702
1712
  if (info[0].IsString()) {
1703
- std::u16string filename = info[0].As<Napi::String>();
1713
+ std::string filename = info[0].As<Napi::String>();
1704
1714
  module = LoadWindowsLibrary(env, filename.c_str());
1705
1715
 
1706
1716
  if (!module)
@@ -193,6 +193,19 @@ static inline Napi::Value NewBigInt(Napi::Env env, uint64_t value)
193
193
  }
194
194
  }
195
195
 
196
+ static inline Napi::Array GetOwnPropertyNames(Napi::Object obj)
197
+ {
198
+ Napi::Env env = obj.Env();
199
+
200
+ napi_value result;
201
+ napi_status status = napi_get_all_property_names(env, obj, napi_key_own_only,
202
+ (napi_key_filter)(napi_key_enumerable | napi_key_skip_symbols),
203
+ napi_key_numbers_to_strings, &result);
204
+ RG_ASSERT(status == napi_ok);
205
+
206
+ return Napi::Array(env, result);
207
+ }
208
+
196
209
  Napi::Function WrapFunction(Napi::Env env, const FunctionInfo *func);
197
210
 
198
211
  int AnalyseFlat(const TypeInfo *type, FunctionRef<void(const TypeInfo *type, int offset, int count)> func);
@@ -136,7 +136,7 @@ int GetSelfMachine()
136
136
  return GetFileMachine(h, false);
137
137
  }
138
138
 
139
- int GetDllMachine(const char16_t *filename)
139
+ int GetDllMachine(const wchar_t *filename)
140
140
  {
141
141
  HANDLE h = CreateFileW((LPCWSTR)filename, GENERIC_READ,
142
142
  FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
@@ -112,6 +112,6 @@ static inline TEB *GetTEB()
112
112
  extern const HashMap<int, const char *> WindowsMachineNames;
113
113
 
114
114
  int GetSelfMachine();
115
- int GetDllMachine(const char16_t *filename);
115
+ int GetDllMachine(const wchar_t *filename);
116
116
 
117
117
  }