koffi 2.15.0 → 2.15.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.
Files changed (45) 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_arm64/koffi.node +0 -0
  8. package/build/koffi/linux_armhf/koffi.node +0 -0
  9. package/build/koffi/linux_ia32/koffi.node +0 -0
  10. package/build/koffi/linux_loong64/koffi.node +0 -0
  11. package/build/koffi/linux_riscv64d/koffi.node +0 -0
  12. package/build/koffi/linux_x64/koffi.node +0 -0
  13. package/build/koffi/musl_arm64/koffi.node +0 -0
  14. package/build/koffi/musl_x64/koffi.node +0 -0
  15. package/build/koffi/openbsd_ia32/koffi.node +0 -0
  16. package/build/koffi/openbsd_x64/koffi.node +0 -0
  17. package/build/koffi/win32_arm64/koffi.node +0 -0
  18. package/build/koffi/win32_ia32/koffi.node +0 -0
  19. package/build/koffi/win32_x64/koffi.node +0 -0
  20. package/doc/pages/index.md +4 -2
  21. package/doc/pages/misc.md +2 -0
  22. package/doc/templates/code.html +1 -2
  23. package/doc/templates/page.html +1 -2
  24. package/index.js +2 -2
  25. package/indirect.js +2 -2
  26. package/lib/native/base/base.cc +79 -44
  27. package/lib/native/base/base.hh +31 -33
  28. package/package.json +2 -2
  29. package/src/cnoke/assets/FindCNoke.cmake +16 -10
  30. package/src/cnoke/assets/win_delay_hook.c +4 -0
  31. package/src/cnoke/src/builder.js +49 -46
  32. package/src/koffi/CMakeLists.txt +18 -8
  33. package/src/koffi/src/abi_x64_win_asm.S +162 -0
  34. package/src/koffi/src/ffi.cc +2 -1
  35. package/src/koffi/src/ffi.hh +1 -1
  36. package/src/koffi/src/util.cc +6 -5
  37. package/src/koffi/src/util.hh +2 -1
  38. package/vendor/node-api-headers/CHANGELOG.md +22 -0
  39. package/vendor/node-api-headers/README.md +6 -17
  40. package/vendor/node-api-headers/include/js_native_api.h +3 -13
  41. package/vendor/node-api-headers/include/js_native_api_types.h +15 -0
  42. package/vendor/node-api-headers/include/node_api.h +0 -4
  43. package/vendor/node-api-headers/include/node_api_types.h +6 -0
  44. package/vendor/node-api-headers/package.json +1 -1
  45. package/vendor/node-api-headers/scripts/update-headers.js +6 -0
package/CHANGELOG.md CHANGED
@@ -7,6 +7,13 @@
7
7
 
8
8
  ### Koffi 2.15
9
9
 
10
+ #### Koffi 2.15.1
11
+
12
+ *Released on 2025-01-24*
13
+
14
+ - Fix possible union-related crashes
15
+ - Support MinGW-w64 x64 builds on Windows
16
+
10
17
  #### Koffi 2.15.0
11
18
 
12
19
  *Released on 2025-12-21*
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
@@ -9,8 +9,10 @@ Koffi is a **fast and easy-to-use C FFI module for Node.js**, featuring:
9
9
 
10
10
  If you like this project, consider supporting me:
11
11
 
12
- <p style="display: flex; gap: 2em; justify-content: center;">
13
- <a href="https://buymeacoffee.com/koromix" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-orange.png" alt="Buy Me A Coffee" height="41" width="174" style="border-radius: 12px;"></a>
12
+ <p style="display: flex; gap: 1em; justify-content: center; align-items: center;">
13
+ <a href="https://liberapay.com/Koromix/donate" target="_blank"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a>
14
+ <a href="https://github.com/sponsors/koromix" target="_blank"><img src="https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86"></a>
15
+ <a href="https://buymeacoffee.com/koromix" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-yellow.png" alt="Buy Me A Coffee" height="30" width="108" style="border-radius: 12px;"></a>
14
16
  </p>
15
17
 
16
18
  Koffi requires [Node.js](https://nodejs.org/) version 16 or later. Use [NVM](https://github.com/nvm-sh/nvm) to install more recent Node versions on older Linux distributions.
package/doc/pages/misc.md CHANGED
@@ -123,6 +123,8 @@ Async calls run on worker threads, the number of which depends on the number of
123
123
 
124
124
  ## Default settings
125
125
 
126
+ *Changed in Koffi 2.15*
127
+
126
128
  Setting | Default | Maximum | Description
127
129
  -------------------- | ------- | ------- | ----------------------------------------------------
128
130
  sync_stack_size | 1 MiB | 16 MiB | Stack size for synchronous calls
@@ -17,9 +17,8 @@
17
17
  </head>
18
18
 
19
19
  <body>
20
- <div id="deploy"></div>
21
-
22
20
  <nav id="top">
21
+ <div class="deploy"></div>
23
22
  <menu>
24
23
  <a id="logo" href="/"><img src="{{ ASSET static/logo.webp }}" width="370" height="198" alt="" /></a>
25
24
 
@@ -16,9 +16,8 @@
16
16
  </head>
17
17
 
18
18
  <body>
19
- <div id="deploy"></div>
20
-
21
19
  <nav id="top">
20
+ <div class="deploy"></div>
22
21
  <menu>
23
22
  <a id="logo" href="/"><img src="{{ ASSET static/logo.webp }}" width="370" height="198" alt="" /></a>
24
23
 
package/index.js CHANGED
@@ -402,7 +402,7 @@ var require_package = __commonJS({
402
402
  "bin/Koffi/package/src/koffi/package.json"(exports2, module2) {
403
403
  module2.exports = {
404
404
  name: "koffi",
405
- version: "2.15.0",
405
+ version: "2.15.1",
406
406
  description: "Fast and simple C FFI (foreign function interface) for Node.js",
407
407
  keywords: [
408
408
  "foreign",
@@ -439,7 +439,7 @@ var require_package = __commonJS({
439
439
  napi: 8,
440
440
  require: "./index.js"
441
441
  },
442
- funding: "https://buymeacoffee.com/koromix"
442
+ funding: "https://liberapay.com/Koromix"
443
443
  };
444
444
  }
445
445
  });
package/indirect.js CHANGED
@@ -402,7 +402,7 @@ var require_package = __commonJS({
402
402
  "bin/Koffi/package/src/koffi/package.json"(exports2, module2) {
403
403
  module2.exports = {
404
404
  name: "koffi",
405
- version: "2.15.0",
405
+ version: "2.15.1",
406
406
  description: "Fast and simple C FFI (foreign function interface) for Node.js",
407
407
  keywords: [
408
408
  "foreign",
@@ -439,7 +439,7 @@ var require_package = __commonJS({
439
439
  napi: 8,
440
440
  require: "./index.js"
441
441
  },
442
- funding: "https://buymeacoffee.com/koromix"
442
+ funding: "https://liberapay.com/Koromix"
443
443
  };
444
444
  }
445
445
  });
@@ -750,25 +750,6 @@ int64_t GetUnixTime()
750
750
  #endif
751
751
  }
752
752
 
753
- int64_t GetMonotonicTime()
754
- {
755
- #if defined(_WIN32)
756
- return (int64_t)GetTickCount64();
757
- #elif defined(__EMSCRIPTEN__)
758
- return (int64_t)emscripten_get_now();
759
- #elif defined(CLOCK_MONOTONIC_COARSE)
760
- struct timespec ts;
761
- K_CRITICAL(clock_gettime(CLOCK_MONOTONIC_COARSE, &ts) == 0, "clock_gettime(CLOCK_MONOTONIC_COARSE) failed: %1", strerror(errno));
762
-
763
- return (int64_t)ts.tv_sec * 1000 + (int64_t)ts.tv_nsec / 1000000;
764
- #else
765
- struct timespec ts;
766
- K_CRITICAL(clock_gettime(CLOCK_MONOTONIC, &ts) == 0, "clock_gettime(CLOCK_MONOTONIC) failed: %1", strerror(errno));
767
-
768
- return (int64_t)ts.tv_sec * 1000 + (int64_t)ts.tv_nsec / 1000000;
769
- #endif
770
- }
771
-
772
753
  TimeSpec DecomposeTimeUTC(int64_t time)
773
754
  {
774
755
  TimeSpec spec = {};
@@ -862,6 +843,39 @@ int64_t ComposeTimeUTC(const TimeSpec &spec)
862
843
  return time;
863
844
  }
864
845
 
846
+ // ------------------------------------------------------------------------
847
+ // Clock
848
+ // ------------------------------------------------------------------------
849
+
850
+ int64_t GetMonotonicClock()
851
+ {
852
+ static std::atomic_int64_t memory;
853
+
854
+ #if defined(_WIN32)
855
+ int64_t clock = (int64_t)GetTickCount64();
856
+ #elif defined(__EMSCRIPTEN__)
857
+ int64_t clock = emscripten_get_now();
858
+ #elif defined(CLOCK_MONOTONIC_COARSE)
859
+ struct timespec ts;
860
+ K_CRITICAL(clock_gettime(CLOCK_MONOTONIC_COARSE, &ts) == 0, "clock_gettime(CLOCK_MONOTONIC_COARSE) failed: %1", strerror(errno));
861
+
862
+ int64_t clock = (int64_t)ts.tv_sec * 1000 + (int64_t)ts.tv_nsec / 1000000;
863
+ #else
864
+ struct timespec ts;
865
+ K_CRITICAL(clock_gettime(CLOCK_MONOTONIC, &ts) == 0, "clock_gettime(CLOCK_MONOTONIC) failed: %1", strerror(errno));
866
+
867
+ int64_t clock = (int64_t)ts.tv_sec * 1000 + (int64_t)ts.tv_nsec / 1000000;
868
+ #endif
869
+
870
+ // Protect against clock going backwards
871
+ int64_t prev = memory.load(std::memory_order_relaxed);
872
+ if (clock < prev) [[unlikely]]
873
+ return prev;
874
+ memory.compare_exchange_weak(prev, clock, std::memory_order_relaxed, std::memory_order_relaxed);
875
+
876
+ return clock;
877
+ }
878
+
865
879
  // ------------------------------------------------------------------------
866
880
  // Strings
867
881
  // ------------------------------------------------------------------------
@@ -2031,7 +2045,7 @@ FmtArg FmtVersion(int64_t version, int parts, int by)
2031
2045
  // Debug and errors
2032
2046
  // ------------------------------------------------------------------------
2033
2047
 
2034
- static int64_t start_time = GetMonotonicTime();
2048
+ static int64_t start_clock = GetMonotonicClock();
2035
2049
 
2036
2050
  static std::function<LogFunc> log_handler = DefaultLogHandler;
2037
2051
  static bool log_vt100 = FileIsVt100(STDERR_FILENO);
@@ -2130,7 +2144,7 @@ void LogFmt(LogLevel level, const char *ctx, const char *fmt, Span<const FmtArg>
2130
2144
 
2131
2145
  char ctx_buf[512];
2132
2146
  if (log_times) {
2133
- double time = (double)(GetMonotonicTime() - start_time) / 1000;
2147
+ double time = (double)(GetMonotonicClock() - start_clock) / 1000;
2134
2148
  Fmt(ctx_buf, "[%1] %2", FmtDouble(time, 3, 8), ctx ? ctx : "");
2135
2149
 
2136
2150
  ctx = ctx_buf;
@@ -5565,7 +5579,7 @@ bool ExecuteCommandLine(const char *cmd_line, const ExecuteInfo &info,
5565
5579
  // Wait for process exit
5566
5580
  int status;
5567
5581
  {
5568
- int64_t start = GetMonotonicTime();
5582
+ int64_t start = GetMonotonicClock();
5569
5583
 
5570
5584
  for (;;) {
5571
5585
  int ret = K_RESTART_EINTR(waitpid(pid, &status, terminate ? WNOHANG : 0), < 0);
@@ -5574,7 +5588,7 @@ bool ExecuteCommandLine(const char *cmd_line, const ExecuteInfo &info,
5574
5588
  LogError("Failed to wait for process exit: %1", strerror(errno));
5575
5589
  return false;
5576
5590
  } else if (!ret) {
5577
- int64_t delay = GetMonotonicTime() - start;
5591
+ int64_t delay = GetMonotonicClock() - start;
5578
5592
 
5579
5593
  if (delay < 2000) {
5580
5594
  // A timeout on waitpid would be better, but... sigh
@@ -5837,7 +5851,7 @@ WaitResult WaitEvents(Span<const WaitSource> sources, int64_t timeout, uint64_t
5837
5851
  InitInterruptPipe();
5838
5852
  pfds.Append({ interrupt_pfd[0], POLLIN, 0 });
5839
5853
 
5840
- int64_t start = (timeout >= 0) ? GetMonotonicTime() : 0;
5854
+ int64_t start = (timeout >= 0) ? GetMonotonicClock() : 0;
5841
5855
  int64_t until = start + timeout;
5842
5856
  int timeout32 = (int)std::min(until - start, (int64_t)INT_MAX);
5843
5857
 
@@ -5874,10 +5888,10 @@ WaitResult WaitEvents(Span<const WaitSource> sources, int64_t timeout, uint64_t
5874
5888
  }
5875
5889
 
5876
5890
  if (timeout >= 0) {
5877
- int64_t now = GetMonotonicTime();
5878
- if (now >= until)
5891
+ int64_t clock = GetMonotonicClock();
5892
+ if (clock >= until)
5879
5893
  break;
5880
- timeout32 = (int)std::min(until - now, (int64_t)INT_MAX);
5894
+ timeout32 = (int)std::min(until - clock, (int64_t)INT_MAX);
5881
5895
  }
5882
5896
  }
5883
5897
 
@@ -6741,7 +6755,7 @@ bool ParseVersion(Span<const char> str, int parts, int multiplier,
6741
6755
  // ------------------------------------------------------------------------
6742
6756
 
6743
6757
  static thread_local Size rnd_remain;
6744
- static thread_local int64_t rnd_time;
6758
+ static thread_local int64_t rnd_clock;
6745
6759
  #if !defined(_WIN32)
6746
6760
  static thread_local pid_t rnd_pid;
6747
6761
  #endif
@@ -6854,7 +6868,7 @@ void FillRandomSafe(void *out_buf, Size len)
6854
6868
 
6855
6869
  // Reseed every 4 megabytes, or every hour, or after a fork
6856
6870
  reseed |= (rnd_remain <= 0);
6857
- reseed |= (GetMonotonicTime() - rnd_time > 3600 * 1000);
6871
+ reseed |= (GetMonotonicClock() - rnd_clock > 3600 * 1000);
6858
6872
  #if !defined(_WIN32)
6859
6873
  reseed |= (getpid() != rnd_pid);
6860
6874
  #endif
@@ -6882,7 +6896,7 @@ restart:
6882
6896
  ZeroSafe(&buf, K_SIZE(buf));
6883
6897
 
6884
6898
  rnd_remain = Mebibytes(4);
6885
- rnd_time = GetMonotonicTime();
6899
+ rnd_clock = GetMonotonicClock();
6886
6900
  #if !defined(_WIN32)
6887
6901
  rnd_pid = getpid();
6888
6902
  #endif
@@ -9265,12 +9279,14 @@ static HeapArray<TranslationTable> i18n_tables;
9265
9279
  static NoDestroy<HeapArray<TranslationMap>> i18n_maps;
9266
9280
  static HashMap<Span<const char> , const TranslationTable *> i18n_locales;
9267
9281
 
9268
- static const TranslationMap *i18n_default;
9269
- static thread_local const TranslationMap *i18n_thread = i18n_default;
9282
+ static const TranslationTable *i18n_default_table;
9283
+ static const TranslationMap *i18n_default_map;
9284
+ static thread_local const TranslationTable *i18n_thread_table = i18n_default_table;
9285
+ static thread_local const TranslationMap *i18n_thread_map = i18n_default_map;
9270
9286
 
9271
- static void SetDefaultLocale()
9287
+ static void SetDefaultLocale(const char *default_lang)
9272
9288
  {
9273
- if (i18n_default)
9289
+ if (i18n_default_table)
9274
9290
  return;
9275
9291
 
9276
9292
  // Obey environment settings, even on Windows, for easy override
@@ -9283,9 +9299,11 @@ static void SetDefaultLocale()
9283
9299
 
9284
9300
  if (env) {
9285
9301
  ChangeThreadLocale(env);
9286
- i18n_default = i18n_thread;
9287
9302
 
9288
- if (i18n_default)
9303
+ i18n_default_table = i18n_thread_table;
9304
+ i18n_default_map = i18n_thread_map;
9305
+
9306
+ if (i18n_default_table)
9289
9307
  return;
9290
9308
  }
9291
9309
  }
@@ -9303,9 +9321,11 @@ static void SetDefaultLocale()
9303
9321
  ConvertWin32WideToUtf8(buffer, lang);
9304
9322
 
9305
9323
  ChangeThreadLocale(lang);
9306
- i18n_default = i18n_thread;
9307
9324
 
9308
- if (i18n_default)
9325
+ i18n_default_table = i18n_thread_table;
9326
+ i18n_default_map = i18n_thread_map;
9327
+
9328
+ if (i18n_default_table)
9309
9329
  return;
9310
9330
  }
9311
9331
  } else {
@@ -9313,9 +9333,15 @@ static void SetDefaultLocale()
9313
9333
  }
9314
9334
  }
9315
9335
  #endif
9336
+
9337
+ ChangeThreadLocale(default_lang);
9338
+ K_CRITICAL(i18n_thread_table, "Missing default locale");
9339
+
9340
+ i18n_default_table = i18n_thread_table;
9341
+ i18n_default_map = i18n_thread_map;
9316
9342
  }
9317
9343
 
9318
- void InitLocales(Span<const TranslationTable> tables)
9344
+ void InitLocales(Span<const TranslationTable> tables, const char *default_lang)
9319
9345
  {
9320
9346
  K_ASSERT(!i18n_tables.len);
9321
9347
 
@@ -9332,7 +9358,7 @@ void InitLocales(Span<const TranslationTable> tables)
9332
9358
  i18n_locales.Set(table.language, &table);
9333
9359
  }
9334
9360
 
9335
- SetDefaultLocale();
9361
+ SetDefaultLocale(default_lang);
9336
9362
  }
9337
9363
 
9338
9364
  void ChangeThreadLocale(const char *name)
@@ -9342,18 +9368,27 @@ void ChangeThreadLocale(const char *name)
9342
9368
 
9343
9369
  if (table) {
9344
9370
  Size idx = table - i18n_tables.ptr;
9345
- i18n_thread = &(*i18n_maps)[idx];
9371
+
9372
+ i18n_thread_table = table;
9373
+ i18n_thread_map = &(*i18n_maps)[idx];
9346
9374
  } else {
9347
- i18n_thread = i18n_default;
9375
+ i18n_thread_table = i18n_default_table;
9376
+ i18n_thread_map = i18n_default_map;
9348
9377
  }
9349
9378
  }
9350
9379
 
9380
+ const char *GetThreadLocale()
9381
+ {
9382
+ K_ASSERT(i18n_thread_table);
9383
+ return i18n_thread_table->language;
9384
+ }
9385
+
9351
9386
  const char *T(const char *key)
9352
9387
  {
9353
- if (!i18n_thread)
9388
+ if (!i18n_thread_map)
9354
9389
  return key;
9355
9390
 
9356
- return i18n_thread->FindValue(key, key);
9391
+ return i18n_thread_map->FindValue(key, key);
9357
9392
  }
9358
9393
 
9359
9394
  // ------------------------------------------------------------------------
@@ -1388,7 +1388,7 @@ static constexpr inline bool IsAsciiWhite(int c)
1388
1388
  }
1389
1389
  static constexpr inline bool IsAsciiControl(int c)
1390
1390
  {
1391
- return c == 0x7F || (c < ' ' && c != '\t');
1391
+ return c == 0x7F || ((uint8_t)c < ' ' && c != '\t');
1392
1392
  }
1393
1393
 
1394
1394
  static constexpr inline char UpperAscii(int c)
@@ -3395,7 +3395,7 @@ public:
3395
3395
 
3396
3396
  constexpr ConstMap(std::initializer_list<Bucket> l)
3397
3397
  {
3398
- K_CRITICAL(l.size() <= N, "ConstMap<%1> cannot be store %2 values", N, l.size());
3398
+ K_CRITICAL(l.size() <= N, "ConstMap<%1> cannot store %2 values", N, l.size());
3399
3399
 
3400
3400
  for (const Bucket &it: l) {
3401
3401
  Bucket *bucket = Insert(it.key);
@@ -3404,14 +3404,6 @@ public:
3404
3404
  bucket->value = it.value;
3405
3405
  }
3406
3406
  }
3407
- ~ConstMap()
3408
- {
3409
- if constexpr(!std::is_trivial<ValueType>::value) {
3410
- for (Size i = 0; i < N; i++) {
3411
- data[i].~ValueType();
3412
- }
3413
- }
3414
- }
3415
3407
 
3416
3408
  template <typename T = KeyType>
3417
3409
  ValueType *Find(const T &key)
@@ -3587,15 +3579,36 @@ union LocalDate {
3587
3579
  // ------------------------------------------------------------------------
3588
3580
 
3589
3581
  int64_t GetUnixTime();
3590
- int64_t GetMonotonicTime();
3582
+
3583
+ struct TimeSpec {
3584
+ int16_t year;
3585
+ int8_t month;
3586
+ int8_t day;
3587
+ int8_t week_day; // 1 (monday) to 7 (sunday)
3588
+
3589
+ int8_t hour;
3590
+ int8_t min;
3591
+ int8_t sec;
3592
+ int16_t msec;
3593
+
3594
+ int16_t offset; // minutes
3595
+ };
3596
+
3597
+ TimeSpec DecomposeTimeUTC(int64_t time);
3598
+ TimeSpec DecomposeTimeLocal(int64_t time);
3599
+ int64_t ComposeTimeUTC(const TimeSpec &spec);
3600
+
3601
+ // ------------------------------------------------------------------------
3602
+ // Clock
3603
+ // ------------------------------------------------------------------------
3591
3604
 
3592
3605
  #if defined(_MSC_VER) && !defined(_M_ARM64)
3593
- static inline int64_t GetClockCounter()
3606
+ static inline int64_t GetCoreCycles()
3594
3607
  {
3595
3608
  return (int64_t)__rdtsc();
3596
3609
  }
3597
3610
  #elif defined(__i386__) || defined(__x86_64__)
3598
- static inline int64_t GetClockCounter()
3611
+ static inline int64_t GetCoreCycles()
3599
3612
  {
3600
3613
  uint32_t counter_low, counter_high;
3601
3614
  __asm__ __volatile__ ("cpuid; rdtsc"
@@ -3605,7 +3618,7 @@ static inline int64_t GetClockCounter()
3605
3618
  return counter;
3606
3619
  }
3607
3620
  #elif defined(__aarch64__)
3608
- static inline int64_t GetClockCounter()
3621
+ static inline int64_t GetCoreCycles()
3609
3622
  {
3610
3623
  uint64_t counter;
3611
3624
  __asm__ __volatile__ ("mrs %0, cntvct_el0" : "=r" (counter));
@@ -3613,23 +3626,7 @@ static inline int64_t GetClockCounter()
3613
3626
  }
3614
3627
  #endif
3615
3628
 
3616
- struct TimeSpec {
3617
- int16_t year;
3618
- int8_t month;
3619
- int8_t day;
3620
- int8_t week_day; // 1 (monday) to 7 (sunday)
3621
-
3622
- int8_t hour;
3623
- int8_t min;
3624
- int8_t sec;
3625
- int16_t msec;
3626
-
3627
- int16_t offset; // minutes
3628
- };
3629
-
3630
- TimeSpec DecomposeTimeUTC(int64_t time);
3631
- TimeSpec DecomposeTimeLocal(int64_t time);
3632
- int64_t ComposeTimeUTC(const TimeSpec &spec);
3629
+ int64_t GetMonotonicClock();
3633
3630
 
3634
3631
  // ------------------------------------------------------------------------
3635
3632
  // Format
@@ -5572,10 +5569,11 @@ struct TranslationTable {
5572
5569
 
5573
5570
  extern "C" const Span<const TranslationTable> TranslationTables;
5574
5571
 
5575
- void InitLocales(Span<const TranslationTable> tables);
5572
+ void InitLocales(Span<const TranslationTable> tables, const char *default_lang);
5576
5573
 
5577
- // Resets the localgale to the process default if lang is NULL or is unknown
5574
+ // Resets the locale to the process default if lang is NULL or is unknown
5578
5575
  void ChangeThreadLocale(const char *name);
5576
+ const char *GetThreadLocale();
5579
5577
 
5580
5578
  // ------------------------------------------------------------------------
5581
5579
  // Options
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koffi",
3
- "version": "2.15.0",
3
+ "version": "2.15.1",
4
4
  "description": "Fast and simple C FFI (foreign function interface) for Node.js",
5
5
  "keywords": [
6
6
  "foreign",
@@ -34,5 +34,5 @@
34
34
  "napi": 8,
35
35
  "require": "./index.js"
36
36
  },
37
- "funding": "https://buymeacoffee.com/koromix"
37
+ "funding": "https://liberapay.com/Koromix"
38
38
  }
@@ -9,12 +9,19 @@ else()
9
9
  endif()
10
10
 
11
11
  if(NODE_JS_LINK_DEF)
12
- add_custom_command(OUTPUT ${NODE_JS_LINK_LIB}
13
- COMMAND ${CMAKE_AR} ${CMAKE_STATIC_LINKER_FLAGS}
14
- /def:${NODE_JS_LINK_DEF} /out:${NODE_JS_LINK_LIB}
15
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
16
- MAIN_DEPENDENCY ${NODE_JS_LINK_DEF})
17
- add_custom_target(node.lib DEPENDS ${NODE_JS_LINK_LIB})
12
+ set(NODE_JS_LINK_LIB "${CMAKE_CURRENT_BINARY_DIR}/node.lib")
13
+ if (MSVC)
14
+ add_custom_command(OUTPUT node.lib
15
+ COMMAND ${CMAKE_AR} ${CMAKE_STATIC_LINKER_FLAGS}
16
+ /def:${NODE_JS_LINK_DEF} /out:${NODE_JS_LINK_LIB}
17
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
18
+ MAIN_DEPENDENCY ${NODE_JS_LINK_DEF})
19
+ else()
20
+ add_custom_command(OUTPUT node.lib
21
+ COMMAND ${CMAKE_DLLTOOL} -d ${NODE_JS_LINK_DEF} -l ${NODE_JS_LINK_LIB}
22
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
23
+ MAIN_DEPENDENCY ${NODE_JS_LINK_DEF})
24
+ endif()
18
25
  endif()
19
26
 
20
27
  function(add_node_addon)
@@ -26,10 +33,10 @@ endfunction()
26
33
 
27
34
  function(target_link_node TARGET)
28
35
  target_include_directories(${TARGET} PRIVATE ${NODE_JS_INCLUDE_DIRS})
36
+ if(NODE_JS_LINK_DEF)
37
+ target_sources(${TARGET} PRIVATE node.lib)
38
+ endif()
29
39
  if(NODE_JS_LINK_LIB)
30
- if(TARGET node.lib)
31
- add_dependencies(${TARGET} node.lib)
32
- endif()
33
40
  target_link_libraries(${TARGET} PRIVATE ${NODE_JS_LINK_LIB})
34
41
  endif()
35
42
  target_compile_options(${TARGET} PRIVATE ${NODE_JS_COMPILE_FLAGS})
@@ -100,7 +107,6 @@ else()
100
107
  endif()
101
108
 
102
109
  if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
103
- message(STATUS ${CMAKE_SYSTEM_PROCESSOR})
104
110
  if(CMAKE_SYSTEM_PROCESSOR MATCHES "(amd64|x86_64)")
105
111
  foreach(lang C CXX)
106
112
  set(CMAKE_${lang}_FLAGS_RELEASE "${CMAKE_${lang}_FLAGS_RELEASE} -mpopcnt -msse4.1 -msse4.2 -mssse3 -mcx16")
@@ -29,4 +29,8 @@ static FARPROC WINAPI self_exe_hook(unsigned int event, DelayLoadInfo *info)
29
29
  return NULL;
30
30
  }
31
31
 
32
+ #if defined(__MINGW32__)
33
+ PfnDliHook __pfnDliNotifyHook2 = self_exe_hook;
34
+ #else
32
35
  const PfnDliHook __pfnDliNotifyHook2 = self_exe_hook;
36
+ #endif
@@ -106,44 +106,41 @@ function Builder(config = {}) {
106
106
  args.push(`-DNODE_JS_INCLUDE_DIRS=${options.api}/include`);
107
107
  }
108
108
 
109
- // Download or create Node import library (Windows)
110
- if (process.platform == 'win32') {
111
- if (options.api == null) {
112
- let dirname;
113
- switch (arch) {
114
- case 'ia32': { dirname = 'win-x86'; } break;
115
- case 'x64': { dirname = 'win-x64'; } break;
116
- case 'arm64': { dirname = 'win-arm64'; } break;
117
-
118
- default: {
119
- throw new Error(`Unsupported architecture '${arch}' for Node on Windows`);
120
- } break;
121
- }
122
-
123
- let destname = `${cache_dir}/node_v${runtime_version}_${arch}.lib`;
124
-
125
- if (!fs.existsSync(destname)) {
126
- fs.mkdirSync(cache_dir, { recursive: true, mode: 0o755 });
109
+ args.push(`-DCMAKE_MODULE_PATH=${app_dir}/assets`);
127
110
 
128
- let url = `https://nodejs.org/dist/v${runtime_version}/${dirname}/node.lib`;
129
- await tools.download_http(url, destname);
130
- }
111
+ let win32 = (process.platform == 'win32');
112
+ let msvc = (process.platform == 'win32' && process.env.MSYSTEM == null);
113
+ let darwin = (process.platform == 'darwin');
114
+
115
+ // Handle Node import library on Windows
116
+ if (win32) {
117
+ if (msvc) {
118
+ if (options.api == null) {
119
+ let dirname;
120
+ switch (arch) {
121
+ case 'ia32': { dirname = 'win-x86'; } break;
122
+ case 'x64': { dirname = 'win-x64'; } break;
123
+ case 'arm64': { dirname = 'win-arm64'; } break;
124
+
125
+ default: {
126
+ throw new Error(`Unsupported architecture '${arch}' for Node on Windows`);
127
+ } break;
128
+ }
131
129
 
132
- fs.copyFileSync(destname, work_dir + '/node.lib');
133
- } else {
134
- args.push(`-DNODE_JS_LINK_DEF=${options.api}/def/node_api.def`);
135
- }
136
- }
130
+ let destname = `${cache_dir}/node_v${runtime_version}_${arch}.lib`;
137
131
 
138
- args.push(`-DCMAKE_MODULE_PATH=${app_dir}/assets`);
132
+ if (!fs.existsSync(destname)) {
133
+ fs.mkdirSync(cache_dir, { recursive: true, mode: 0o755 });
139
134
 
140
- // Set platform flags
141
- switch (process.platform) {
142
- case 'win32': {
143
- fs.copyFileSync(`${app_dir}/assets/win_delay_hook.c`, work_dir + '/win_delay_hook.c');
135
+ let url = `https://nodejs.org/dist/v${runtime_version}/${dirname}/node.lib`;
136
+ await tools.download_http(url, destname);
137
+ }
144
138
 
145
- args.push(`-DNODE_JS_SOURCES=${work_dir}/win_delay_hook.c`);
146
- args.push(`-DNODE_JS_LINK_LIB=${work_dir}/node.lib`);
139
+ fs.copyFileSync(destname, work_dir + '/node.lib');
140
+ args.push(`-DNODE_JS_LINK_LIB=${work_dir}/node.lib`);
141
+ } else {
142
+ args.push(`-DNODE_JS_LINK_DEF=${options.api}/def/node_api.def`);
143
+ }
147
144
 
148
145
  switch (arch) {
149
146
  case 'ia32': {
@@ -159,22 +156,29 @@ function Builder(config = {}) {
159
156
  args.push('-A', 'x64');
160
157
  } break;
161
158
  }
162
- } break;
163
159
 
164
- case 'darwin': {
165
- args.push('-DNODE_JS_LINK_FLAGS=-undefined;dynamic_lookup');
160
+ fs.copyFileSync(`${app_dir}/assets/win_delay_hook.c`, work_dir + '/win_delay_hook.c');
161
+ args.push(`-DNODE_JS_SOURCES=${work_dir}/win_delay_hook.c`);
162
+ } else {
163
+ args.push(`-DNODE_JS_LINK_LIB=node.dll`);
164
+ }
165
+ }
166
+
167
+ if (darwin) {
168
+ args.push('-DNODE_JS_LINK_FLAGS=-undefined;dynamic_lookup');
166
169
 
167
- switch (arch) {
168
- case 'arm64': { args.push('-DCMAKE_OSX_ARCHITECTURES=arm64'); } break;
169
- case 'x64': { args.push('-DCMAKE_OSX_ARCHITECTURES=x86_64'); } break;
170
- }
171
- } break;
170
+ switch (arch) {
171
+ case 'arm64': { args.push('-DCMAKE_OSX_ARCHITECTURES=arm64'); } break;
172
+ case 'x64': { args.push('-DCMAKE_OSX_ARCHITECTURES=x86_64'); } break;
173
+ }
172
174
  }
173
175
 
174
- if (process.platform != 'win32') {
175
- // Prefer Ninja if available
176
- if (spawnSync('ninja', ['--version']).status === 0)
176
+ if (!msvc) {
177
+ if (spawnSync('ninja', ['--version']).status === 0) {
177
178
  args.push('-G', 'Ninja');
179
+ } else if (process.platform == 'win32') {
180
+ args.push('-G', 'MinGW Makefiles');
181
+ }
178
182
 
179
183
  // Use CCache if available
180
184
  if (spawnSync('ccache', ['--version']).status === 0) {
@@ -182,9 +186,8 @@ function Builder(config = {}) {
182
186
  args.push('-DCMAKE_CXX_COMPILER_LAUNCHER=ccache');
183
187
  }
184
188
  }
185
-
186
189
  if (prefer_clang) {
187
- if (process.platform == 'win32') {
190
+ if (msvc) {
188
191
  args.push('-T', 'ClangCL');
189
192
  } else {
190
193
  args.push('-DCMAKE_C_COMPILER=clang');
@@ -99,7 +99,11 @@ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
99
99
  list(APPEND KOFFI_SRC src/abi_riscv64.cc src/abi_loong64_asm.S)
100
100
  else()
101
101
  if(WIN32)
102
- list(APPEND KOFFI_SRC src/abi_x64_win.cc src/abi_x64_win_asm.asm)
102
+ if(MSVC)
103
+ list(APPEND KOFFI_SRC src/abi_x64_win.cc src/abi_x64_win_asm.asm)
104
+ else()
105
+ list(APPEND KOFFI_SRC src/abi_x64_win.cc src/abi_x64_win_asm.S)
106
+ endif()
103
107
  else()
104
108
  list(APPEND KOFFI_SRC src/abi_x64_sysv.cc src/abi_x64_sysv_asm.S)
105
109
  endif()
@@ -121,13 +125,19 @@ target_include_directories(koffi PRIVATE . ../.. ../../vendor/node-addon-api)
121
125
 
122
126
  if(WIN32)
123
127
  set(UV_LINK_LIB "${CMAKE_CURRENT_BINARY_DIR}/uv.lib")
124
- add_custom_command(OUTPUT ${UV_LINK_LIB}
125
- COMMAND ${CMAKE_AR} ${CMAKE_STATIC_LINKER_FLAGS}
126
- /def:src/uv.def /out:${UV_LINK_LIB}
127
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
128
- MAIN_DEPENDENCY src/uv.def)
129
- add_custom_target(uv.lib DEPENDS ${UV_LINK_LIB})
130
- add_dependencies(koffi uv.lib)
128
+ if(MSVC)
129
+ add_custom_command(OUTPUT uv.lib
130
+ COMMAND ${CMAKE_AR} ${CMAKE_STATIC_LINKER_FLAGS}
131
+ /def:src/uv.def /out:${UV_LINK_LIB}
132
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
133
+ MAIN_DEPENDENCY src/uv.def)
134
+ else()
135
+ add_custom_command(OUTPUT uv.lib
136
+ COMMAND ${CMAKE_DLLTOOL} -d src/uv.def -l ${UV_LINK_LIB}
137
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
138
+ MAIN_DEPENDENCY src/uv.def)
139
+ endif()
140
+ target_sources(koffi PRIVATE uv.lib)
131
141
  target_link_libraries(koffi PRIVATE ${UV_LINK_LIB})
132
142
  endif()
133
143
 
@@ -0,0 +1,162 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # SPDX-FileCopyrightText: 2025 Niels Martignène <niels.martignene@protonmail.com>
3
+
4
+ #define SYMBOL(Symbol) Symbol
5
+
6
+ # Forward
7
+ # ----------------------------
8
+
9
+ .global ForwardCallG
10
+ .global ForwardCallF
11
+ .global ForwardCallD
12
+ .global ForwardCallXG
13
+ .global ForwardCallXF
14
+ .global ForwardCallXD
15
+
16
+ # Copy function pointer to RAX, in order to save it through argument forwarding.
17
+ # Also make a copy of the SP to CallData::old_sp because the callback system might need it.
18
+ # Save RSP in RBX (non-volatile), and use carefully assembled stack provided by caller.
19
+ .macro prologue
20
+ endbr64
21
+ movq %rcx, %rax
22
+ push %rbp
23
+ movq %rsp, %rbp
24
+ movq %rsp, (%r8)
25
+ movq %rdx, %rsp
26
+ .endm
27
+
28
+ # Call native function.
29
+ # Once done, restore normal stack pointer and return.
30
+ # The return value is passed untouched through RAX or XMM0.
31
+ .macro epilogue
32
+ call *%rax
33
+ movq %rbp, %rsp
34
+ pop %rbp
35
+ ret
36
+ .endm
37
+
38
+ # Prepare integer argument registers from array passed by caller.
39
+ .macro forward_gpr
40
+ movq 24(%rdx), %r9
41
+ movq 16(%rdx), %r8
42
+ movq 0(%rdx), %rcx
43
+ movq 8(%rdx), %rdx
44
+ .endm
45
+
46
+ # Prepare XMM argument registers from array passed by caller.
47
+ .macro forward_xmm
48
+ movsd 24(%rdx), %xmm3
49
+ movsd 16(%rdx), %xmm2
50
+ movsd 8(%rdx), %xmm1
51
+ movsd 0(%rdx), %xmm0
52
+ .endm
53
+
54
+ ForwardCallG:
55
+ prologue
56
+ forward_gpr
57
+ epilogue
58
+
59
+ ForwardCallF:
60
+ prologue
61
+ forward_gpr
62
+ epilogue
63
+
64
+ ForwardCallD:
65
+ prologue
66
+ forward_gpr
67
+ epilogue
68
+
69
+ ForwardCallXG:
70
+ prologue
71
+ forward_xmm
72
+ forward_gpr
73
+ epilogue
74
+
75
+ ForwardCallXF:
76
+ prologue
77
+ forward_xmm
78
+ forward_gpr
79
+ epilogue
80
+
81
+ ForwardCallXD:
82
+ prologue
83
+ forward_xmm
84
+ forward_gpr
85
+ epilogue
86
+
87
+ # Callbacks
88
+ # ----------------------------
89
+
90
+ .global RelayCallback
91
+ .global CallSwitchStack
92
+
93
+ # First, make a copy of the GPR argument registers (rcx, rdx, r8, r9).
94
+ # Then call the C function RelayCallback with the following arguments:
95
+ # static trampoline ID, a pointer to the saved GPR array, a pointer to the stack
96
+ # arguments of this call, and a pointer to a struct that will contain the result registers.
97
+ # After the call, simply load these registers from the output struct.
98
+ .macro trampoline id
99
+ endbr64
100
+ subq $120, %rsp
101
+ movq %rcx, 32(%rsp)
102
+ movq %rdx, 40(%rsp)
103
+ movq %r8, 48(%rsp)
104
+ movq %r9, 56(%rsp)
105
+ movq $\id, %rcx
106
+ leaq 32(%rsp), %rdx
107
+ leaq 160(%rsp), %r8
108
+ leaq 96(%rsp), %r9
109
+ call RelayCallback
110
+ movq 96(%rsp), %rax
111
+ addq $120, %rsp
112
+ ret
113
+ .endm
114
+
115
+ # Same thing, but also forward the XMM argument registers and load the XMM result registers.
116
+ .macro trampoline_vec id
117
+ endbr64
118
+ subq $120, %rsp
119
+ movq %rcx, 32(%rsp)
120
+ movq %rdx, 40(%rsp)
121
+ movq %r8, 48(%rsp)
122
+ movq %r9, 56(%rsp)
123
+ movsd %xmm0, 64(%rsp)
124
+ movsd %xmm1, 72(%rsp)
125
+ movsd %xmm2, 80(%rsp)
126
+ movsd %xmm3, 88(%rsp)
127
+ movq $\id, %rcx
128
+ leaq 32(%rsp), %rdx
129
+ leaq 160(%rsp), %r8
130
+ leaq 96(%rsp), %r9
131
+ call RelayCallback
132
+ movq 96(%rsp), %rax
133
+ movsd 104(%rsp), %xmm0
134
+ addq $120, %rsp
135
+ ret
136
+ .endm
137
+
138
+ # When a callback is relayed, Koffi will call into Node.js and V8 to execute Javascript.
139
+ # The problem is that we're still running on the separate Koffi stack, and V8 will
140
+ # probably misdetect this as a "stack overflow". We have to restore the old
141
+ # stack pointer, call Node.js/V8 and go back to ours.
142
+ # The first three parameters (rcx, rdx, r8) are passed through untouched.
143
+ CallSwitchStack:
144
+ endbr64
145
+ push %rbp
146
+ movq %rsp, %rbp
147
+ movq 56(%rsp), %rax
148
+ movq %rsp, %r10
149
+ movq 48(%rsp), %r11
150
+ subq 0(%r11), %r10
151
+ andq $-16, %r10
152
+ movq %r10, 8(%r11)
153
+ leaq -32(%r9), %rsp
154
+ call *%rax
155
+ movq %rbp, %rsp
156
+ pop %rbp
157
+ ret
158
+
159
+ # Trampolines
160
+ # ----------------------------
161
+
162
+ #include "trampolines/gnu.inc"
@@ -2582,7 +2582,8 @@ static Napi::Object InitModule(Napi::Env env, Napi::Object exports)
2582
2582
  instance->str16_type = instance->types_map.FindValue("char16_t *", nullptr);
2583
2583
  instance->str32_type = instance->types_map.FindValue("char32_t *", nullptr);
2584
2584
 
2585
- instance->active_symbol = Napi::Symbol::New(env, "active");
2585
+ Napi::Symbol symbol = Napi::Symbol::New(env, "active");
2586
+ instance->active_symbol.Reset(symbol, 1);
2586
2587
 
2587
2588
  instance->base_types_count = instance->types.count;
2588
2589
  }
@@ -274,7 +274,7 @@ struct InstanceData {
274
274
  const TypeInfo *str16_type;
275
275
  const TypeInfo *str32_type;
276
276
 
277
- Napi::Symbol active_symbol;
277
+ Napi::Reference<Napi::Symbol> active_symbol;
278
278
 
279
279
  std::mutex mem_mutex;
280
280
  LocalArray<InstanceMemory *, 17> memories;
@@ -43,7 +43,7 @@ MagicUnion::MagicUnion(const Napi::CallbackInfo &info)
43
43
  Napi::Env env = info.Env();
44
44
  InstanceData *instance = env.GetInstanceData<InstanceData>();
45
45
 
46
- active_symbol = instance->active_symbol;
46
+ active_symbol.Reset(instance->active_symbol.Value(), 1);
47
47
  }
48
48
 
49
49
  void MagicUnion::SetRaw(const uint8_t *ptr)
@@ -51,7 +51,7 @@ void MagicUnion::SetRaw(const uint8_t *ptr)
51
51
  raw.RemoveFrom(0);
52
52
  raw.Append(MakeSpan(ptr, type->size));
53
53
 
54
- Value().Set(active_symbol, Env().Undefined());
54
+ Value().Set(active_symbol.Value(), Env().Undefined());
55
55
  active_idx = -1;
56
56
  }
57
57
 
@@ -63,7 +63,7 @@ Napi::Value MagicUnion::Getter(const Napi::CallbackInfo &info)
63
63
  Napi::Value value;
64
64
 
65
65
  if (idx == active_idx) {
66
- value = Value().Get(active_symbol);
66
+ value = Value().Get(active_symbol.Value());
67
67
  } else {
68
68
  Napi::Env env = info.Env();
69
69
 
@@ -74,7 +74,7 @@ Napi::Value MagicUnion::Getter(const Napi::CallbackInfo &info)
74
74
 
75
75
  value = Decode(env, raw.ptr, member.type);
76
76
 
77
- Value().Set(active_symbol, value);
77
+ Value().Set(active_symbol.Value(), value);
78
78
  active_idx = idx;
79
79
  }
80
80
 
@@ -86,7 +86,7 @@ void MagicUnion::Setter(const Napi::CallbackInfo &info, const Napi::Value &value
86
86
  {
87
87
  Size idx = (Size)info.Data();
88
88
 
89
- Value().Set(active_symbol, value);
89
+ Value().Set(active_symbol.Value(), value);
90
90
  active_idx = idx;
91
91
 
92
92
  raw.Clear();
@@ -549,6 +549,7 @@ const char *GetValueType(const InstanceData *instance, Napi::Value value)
549
549
  case napi_uint16_array: return "Uint16Array";
550
550
  case napi_int32_array: return "Int32Array";
551
551
  case napi_uint32_array: return "Uint32Array";
552
+ case napi_float16_array: return "Float16Array";
552
553
  case napi_float32_array: return "Float32Array";
553
554
  case napi_float64_array: return "Float64Array";
554
555
  case napi_bigint64_array: return "BigInt64Array";
@@ -17,7 +17,7 @@ extern const napi_type_tag MagicUnionMarker;
17
17
  class MagicUnion: public Napi::ObjectWrap<MagicUnion> {
18
18
  const TypeInfo *type;
19
19
 
20
- napi_value active_symbol;
20
+ Napi::Reference<Napi::Symbol> active_symbol;
21
21
  Size active_idx = -1;
22
22
 
23
23
  HeapArray<uint8_t> raw;
@@ -120,6 +120,7 @@ static inline Span<uint8_t> GetRawBuffer(Napi::Value value)
120
120
  case napi_uint16_array: { length *= 2; } break;
121
121
  case napi_int32_array: { length *= 4; } break;
122
122
  case napi_uint32_array: { length *= 4; } break;
123
+ case napi_float16_array: { length *= 2; } break;
123
124
  case napi_float32_array: { length *= 4; } break;
124
125
  case napi_float64_array: { length *= 8; } break;
125
126
  case napi_bigint64_array: { length *= 8; } break;
@@ -1,5 +1,27 @@
1
1
  # node-api-headers Changelog
2
2
 
3
+ ## [1.8.0](https://github.com/nodejs/node-api-headers/compare/v1.7.0...v1.8.0) (2026-01-23)
4
+
5
+
6
+ ### Features
7
+
8
+ * update headers from nodejs/node tag v25.4.0 ([#70](https://github.com/nodejs/node-api-headers/issues/70)) ([ebc02e1](https://github.com/nodejs/node-api-headers/commit/ebc02e18357a4d49f127f094c144371948b60c84))
9
+
10
+ ## [1.7.0](https://github.com/nodejs/node-api-headers/compare/v1.6.0...v1.7.0) (2025-11-28)
11
+
12
+
13
+ ### Features
14
+
15
+ * update headers from nodejs/node tag v25.1.0 ([#65](https://github.com/nodejs/node-api-headers/issues/65)) ([f90f754](https://github.com/nodejs/node-api-headers/commit/f90f75459375cb4725914895aa418efefdde7af2))
16
+ * update headers from nodejs/node tag v25.2.1 ([#68](https://github.com/nodejs/node-api-headers/issues/68)) ([769031b](https://github.com/nodejs/node-api-headers/commit/769031b208acd820bf3f2c3b2cf9f8b4b2e2bd83))
17
+
18
+ ## [1.6.0](https://github.com/nodejs/node-api-headers/compare/v1.5.0...v1.6.0) (2025-09-26)
19
+
20
+
21
+ ### Features
22
+
23
+ * update headers from nodejs/node tag v24.9.0 ([#60](https://github.com/nodejs/node-api-headers/issues/60)) ([5963ef9](https://github.com/nodejs/node-api-headers/commit/5963ef9937c8f6bd8f33cb45c50f70bd9cbc0ffd))
24
+
3
25
  ## [1.5.0](https://github.com/nodejs/node-api-headers/compare/v1.4.0...v1.5.0) (2025-01-09)
4
26
 
5
27
 
@@ -9,10 +9,6 @@
9
9
  - **[Team](#team)**
10
10
  - **[License](#license)**
11
11
 
12
- ## Current Node-API version: 9
13
-
14
- (See [CHANGELOG.md](CHANGELOG.md) for complete Changelog)
15
-
16
12
  <a name="introduction"></a>
17
13
 
18
14
  ## Introduction
@@ -45,8 +41,8 @@ npm i node-api-headers
45
41
 
46
42
  ## Versions
47
43
 
48
- Node-API C headers are backward-compatible. Its version (e.g. `8`) is released
49
- separately from the Node.js version stream (e.g. `19.8.1`) and changes are
44
+ Node-API C headers are backward-compatible. Its version (e.g. `8`) is released
45
+ separately from the Node.js version stream (e.g. `19.8.1`) and changes are
50
46
  backported to active Node.js LTS lines (e.g. `16.x` and `18.x`).
51
47
 
52
48
  This package publishes semver-minor versions with new Node-API C headers changes.
@@ -57,6 +53,7 @@ JS API breaking changes are published with new semver-major versions.
57
53
  ## API
58
54
 
59
55
  The module exports two properties `include_dir` and `symbols`.
56
+
60
57
  ### `include_dir`
61
58
 
62
59
  This property is a string that represents the include path for the Node-API
@@ -89,18 +86,10 @@ grouped by version and api types.
89
86
 
90
87
  ## Team members
91
88
 
92
- ### Active
93
- | Name | GitHub Link |
94
- | ------------------- | ----------------------------------------------------- |
95
- | Anna Henningsen | [addaleax](https://github.com/addaleax) |
96
- | Chengzhong Wu | [legendecas](https://github.com/legendecas) |
97
- | Gabriel Schulhof | [gabrielschulhof](https://github.com/gabrielschulhof) |
98
- | Hitesh Kanwathirtha | [digitalinfinity](https://github.com/digitalinfinity) |
99
- | Jim Schlight | [jschlight](https://github.com/jschlight) |
100
- | Michael Dawson | [mhdawson](https://github.com/mhdawson) |
101
- | Kevin Eady | [KevinEady](https://github.com/KevinEady)
102
- | Nicola Del Gobbo | [NickNaso](https://github.com/NickNaso) |
89
+ The project is maintained by the [Node-API team members](https://github.com/nodejs/abi-stable-node/?tab=readme-ov-file#project-participants).
103
90
 
104
91
  <a name="license"></a>
105
92
 
93
+ ## License
94
+
106
95
  Licensed under [MIT](./LICENSE.md)
@@ -5,18 +5,6 @@
5
5
  #include <stdbool.h> // NOLINT(modernize-deprecated-headers)
6
6
  #include <stddef.h> // NOLINT(modernize-deprecated-headers)
7
7
 
8
- // Use INT_MAX, this should only be consumed by the pre-processor anyway.
9
- #define NAPI_VERSION_EXPERIMENTAL 2147483647
10
- #ifndef NAPI_VERSION
11
- // The baseline version for N-API.
12
- // The NAPI_VERSION controls which version will be used by default when
13
- // compilling a native addon. If the addon developer specifically wants to use
14
- // functions available in a new version of N-API that is not yet ported in all
15
- // LTS versions, they can set NAPI_VERSION knowing that they have specifically
16
- // depended on that version.
17
- #define NAPI_VERSION 8
18
- #endif
19
-
20
8
  #include "js_native_api_types.h"
21
9
 
22
10
  // If you need __declspec(dllimport), either include <node_api.h> instead, or
@@ -62,6 +50,7 @@ NAPI_EXTERN napi_status NAPI_CDECL napi_get_boolean(napi_env env,
62
50
  // Methods to create Primitive types/Objects
63
51
  NAPI_EXTERN napi_status NAPI_CDECL napi_create_object(napi_env env,
64
52
  napi_value* result);
53
+
65
54
  NAPI_EXTERN napi_status NAPI_CDECL napi_create_array(napi_env env,
66
55
  napi_value* result);
67
56
  NAPI_EXTERN napi_status NAPI_CDECL
@@ -348,7 +337,7 @@ napi_create_reference(napi_env env,
348
337
 
349
338
  // Deletes a reference. The referenced value is released, and may
350
339
  // be GC'd unless there are other references to it.
351
- NAPI_EXTERN napi_status NAPI_CDECL napi_delete_reference(napi_env env,
340
+ NAPI_EXTERN napi_status NAPI_CDECL napi_delete_reference(node_api_basic_env env,
352
341
  napi_ref ref);
353
342
 
354
343
  // Increments the reference count, optionally returning the resulting count.
@@ -470,6 +459,7 @@ napi_get_dataview_info(napi_env env,
470
459
  napi_value* arraybuffer,
471
460
  size_t* byte_offset);
472
461
 
462
+
473
463
  // version management
474
464
  NAPI_EXTERN napi_status NAPI_CDECL napi_get_version(node_api_basic_env env,
475
465
  uint32_t* result);
@@ -1,6 +1,19 @@
1
1
  #ifndef SRC_JS_NATIVE_API_TYPES_H_
2
2
  #define SRC_JS_NATIVE_API_TYPES_H_
3
3
 
4
+ // Use INT_MAX, this should only be consumed by the pre-processor anyway.
5
+ #define NAPI_VERSION_EXPERIMENTAL 2147483647
6
+ #ifndef NAPI_VERSION
7
+ // The baseline version for N-API.
8
+ // The NAPI_VERSION controls which version will be used by default when
9
+ // compilling a native addon. If the addon developer specifically wants to use
10
+ // functions available in a new version of N-API that is not yet ported in all
11
+ // LTS versions, they can set NAPI_VERSION knowing that they have specifically
12
+ // depended on that version.
13
+ #define NAPI_VERSION 8
14
+ #endif
15
+
16
+
4
17
  // This file needs to be compatible with C compilers.
5
18
  // This is a public include file, and these includes have essentially
6
19
  // became part of it's API.
@@ -98,6 +111,8 @@ typedef enum {
98
111
  napi_float64_array,
99
112
  napi_bigint64_array,
100
113
  napi_biguint64_array,
114
+ #define NODE_API_HAS_FLOAT16_ARRAY
115
+ napi_float16_array,
101
116
  } napi_typedarray_type;
102
117
 
103
118
  typedef enum {
@@ -33,10 +33,6 @@ struct uv_loop_s; // Forward declaration.
33
33
  #define NAPI_NO_RETURN
34
34
  #endif
35
35
 
36
- typedef napi_value(NAPI_CDECL* napi_addon_register_func)(napi_env env,
37
- napi_value exports);
38
- typedef int32_t(NAPI_CDECL* node_api_addon_get_api_version_func)(void);
39
-
40
36
  // Used by deprecated registration method napi_module_register.
41
37
  typedef struct napi_module {
42
38
  int nm_version;
@@ -3,6 +3,12 @@
3
3
 
4
4
  #include "js_native_api_types.h"
5
5
 
6
+ typedef napi_value(NAPI_CDECL* napi_addon_register_func)(napi_env env,
7
+ napi_value exports);
8
+ // False positive: https://github.com/cpplint/cpplint/issues/409
9
+ // NOLINTNEXTLINE (readability/casting)
10
+ typedef int32_t(NAPI_CDECL* node_api_addon_get_api_version_func)(void);
11
+
6
12
  typedef struct napi_callback_scope__* napi_callback_scope;
7
13
  typedef struct napi_async_context__* napi_async_context;
8
14
  typedef struct napi_async_work__* napi_async_work;
@@ -54,6 +54,6 @@
54
54
  "write-win32-def": "node --no-warnings scripts/write-win32-def.js",
55
55
  "test": "node test/parse-utils.js "
56
56
  },
57
- "version": "1.5.0",
57
+ "version": "1.8.0",
58
58
  "support": true
59
59
  }
@@ -71,6 +71,12 @@ function removeExperimentals(stream, destination, verbose = false) {
71
71
  const identifier = matches[2];
72
72
  macroStack.push(identifier);
73
73
 
74
+ if (mode.length && mode[mode.length - 1] === 'ignore') {
75
+ debug(`Line ${lineNumber} Continued-Ignored ${identifier}`);
76
+ mode.push('ignore');
77
+ return;
78
+ }
79
+
74
80
  debug(`Line ${lineNumber} Pushed ${identifier}`);
75
81
 
76
82
  if (identifier === 'NAPI_EXPERIMENTAL') {