koffi 3.0.0 → 3.0.2

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.
@@ -5,6 +5,7 @@
5
5
  #include "ffi.hh"
6
6
  #include "call.hh"
7
7
  #include "parser.hh"
8
+ #include "type.hh"
8
9
  #include "util.hh"
9
10
  #include "uv.hh"
10
11
  #if defined(_WIN32)
@@ -35,21 +36,28 @@
35
36
 
36
37
  namespace K {
37
38
 
39
+ // Value does not matter, the tag system uses memory addresses
40
+ const napi_type_tag LibraryHandleMarker = { 0xdb9b066e6f700474, 0x0aecd7e4c63fbda9 };
41
+ const napi_type_tag TypeObjectMarker = { 0x1cc449675b294374, 0xbb13a50e97dcb017 };
42
+ const napi_type_tag DirectionMarker = { 0xf9c306238b480580, 0xc2e168524a0823f5 };
43
+ const napi_type_tag UnionValueMarker = { 0x5eaf2245526a4c7d, 0x8c86c9ee2b96ffc8 };
44
+ const napi_type_tag CastMarker = { 0x77f459614a0a412f, 0x80b3dda1341dc8df };
45
+
38
46
  SharedData shared;
39
47
 
40
- // Some N-API functions are loaded dynamically to work around bugs or because they are recent
48
+ // Some Node-API functions are loaded dynamically to work around bugs or because they are recent
41
49
  napi_status (NAPI_CDECL *node_api_get_buffer_info)(napi_env env, napi_value value, void **data, size_t *length);
42
50
  napi_status (NAPI_CDECL *node_api_create_property_key_utf8)(napi_env env, const char* str, size_t length, napi_value* result);
43
51
  napi_status (NAPI_CDECL *node_api_post_finalizer)(node_api_basic_env env, napi_finalize finalize_cb, void* finalize_data, void* finalize_hint);
52
+ napi_status (NAPI_CDECL *node_api_create_object_with_properties)(napi_env env, napi_value prototype_or_null, const napi_value *property_names,
53
+ const napi_value *property_values, size_t property_count, napi_value *result);
44
54
  napi_value (*translate_zero_call)(napi_env env, napi_callback_info info);
45
55
 
46
- static bool ChangeSize(const char *name, Napi::Value value, Size min_size, Size max_size, Size *out_size)
56
+ static bool ChangeSize(InstanceData *instance, const char *name, Napi::Value value, Size min_size, Size max_size, Size *out_size)
47
57
  {
48
- Napi::Env env = value.Env();
58
+ Napi::Env env = instance->env;
49
59
 
50
60
  if (!value.IsNumber()) {
51
- InstanceData *instance = env.GetInstanceData<InstanceData>();
52
-
53
61
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for '%2', expected number", GetValueType(instance, value), name);
54
62
  return false;
55
63
  }
@@ -65,21 +73,19 @@ static bool ChangeSize(const char *name, Napi::Value value, Size min_size, Size
65
73
  return true;
66
74
  }
67
75
 
68
- static bool ChangeMemorySize(const char *name, Napi::Value value, Size *out_size)
76
+ static bool ChangeMemorySize(InstanceData *instance, const char *name, Napi::Value value, Size *out_size)
69
77
  {
70
78
  const Size MinSize = Kibibytes(1);
71
79
  const Size MaxSize = Mebibytes(16);
72
80
 
73
- return ChangeSize(name, value, MinSize, MaxSize, out_size);
81
+ return ChangeSize(instance, name, value, MinSize, MaxSize, out_size);
74
82
  }
75
83
 
76
- static bool ChangeAsyncLimit(const char *name, Napi::Value value, int max, int *out_limit)
84
+ static bool ChangeAsyncLimit(InstanceData *instance, const char *name, Napi::Value value, int max, int *out_limit)
77
85
  {
78
86
  Napi::Env env = value.Env();
79
87
 
80
88
  if (!value.IsNumber()) {
81
- InstanceData *instance = env.GetInstanceData<InstanceData>();
82
-
83
89
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for '%2', expected number", GetValueType(instance, value), name);
84
90
  return false;
85
91
  }
@@ -98,7 +104,7 @@ static bool ChangeAsyncLimit(const char *name, Napi::Value value, int max, int *
98
104
  static Napi::Value GetSetConfig(const Napi::CallbackInfo &info)
99
105
  {
100
106
  Napi::Env env = info.Env();
101
- InstanceData *instance = env.GetInstanceData<InstanceData>();
107
+ InstanceData *instance = (InstanceData *)info.Data();
102
108
 
103
109
  if (info.Length()) {
104
110
  if (instance->memories.len) {
@@ -122,25 +128,25 @@ static Napi::Value GetSetConfig(const Napi::CallbackInfo &info)
122
128
  Napi::Value value = obj[key];
123
129
 
124
130
  if (key == "sync_stack_size") {
125
- if (!ChangeMemorySize(key.c_str(), value, &new_config.sync_stack_size))
131
+ if (!ChangeMemorySize(instance, key.c_str(), value, &new_config.sync_stack_size))
126
132
  return env.Null();
127
133
  } else if (key == "sync_heap_size") {
128
- if (!ChangeMemorySize(key.c_str(), value, &new_config.sync_heap_size))
134
+ if (!ChangeMemorySize(instance, key.c_str(), value, &new_config.sync_heap_size))
129
135
  return env.Null();
130
136
  } else if (key == "async_stack_size") {
131
- if (!ChangeMemorySize(key.c_str(), value, &new_config.async_stack_size))
137
+ if (!ChangeMemorySize(instance, key.c_str(), value, &new_config.async_stack_size))
132
138
  return env.Null();
133
139
  } else if (key == "async_heap_size") {
134
- if (!ChangeMemorySize(key.c_str(), value, &new_config.async_heap_size))
140
+ if (!ChangeMemorySize(instance, key.c_str(), value, &new_config.async_heap_size))
135
141
  return env.Null();
136
142
  } else if (key == "resident_async_pools") {
137
- if (!ChangeAsyncLimit(key.c_str(), value, K_LEN(instance->memories.data) - 1, &new_config.resident_async_pools))
143
+ if (!ChangeAsyncLimit(instance, key.c_str(), value, K_LEN(instance->memories.data) - 1, &new_config.resident_async_pools))
138
144
  return env.Null();
139
145
  } else if (key == "max_async_calls") {
140
- if (!ChangeAsyncLimit(key.c_str(), value, MaxAsyncCalls, &max_async_calls))
146
+ if (!ChangeAsyncLimit(instance, key.c_str(), value, MaxAsyncCalls, &max_async_calls))
141
147
  return env.Null();
142
148
  } else if (key == "max_type_size") {
143
- if (!ChangeSize(key.c_str(), value, 32, Mebibytes(512), &new_config.max_type_size))
149
+ if (!ChangeSize(instance, key.c_str(), value, 32, Mebibytes(512), &new_config.max_type_size))
144
150
  return env.Null();
145
151
  } else {
146
152
  ThrowError<Napi::Error>(env, "Unexpected config member '%1'", key.c_str());
@@ -173,7 +179,7 @@ static Napi::Value GetSetConfig(const Napi::CallbackInfo &info)
173
179
  static Napi::Value GetStats(const Napi::CallbackInfo &info)
174
180
  {
175
181
  Napi::Env env = info.Env();
176
- InstanceData *instance = env.GetInstanceData<InstanceData>();
182
+ InstanceData *instance = (InstanceData *)info.Data();
177
183
 
178
184
  Napi::Object obj = Napi::Object::New(env);
179
185
 
@@ -226,9 +232,9 @@ static bool FinalizeCompositeType(Napi::Env env, TypeInfo *type, PrimitiveKind p
226
232
  if (node_api_create_property_key_utf8) {
227
233
  for (RecordMember &member: type->members) {
228
234
  napi_value key = nullptr;
229
- node_api_create_property_key_utf8(env, member.name, NAPI_AUTO_LENGTH, &key);
230
235
 
231
- napi_create_reference(env, key, 1, &member.key);
236
+ NAPI_OK(node_api_create_property_key_utf8(env, member.name, NAPI_AUTO_LENGTH, &key));
237
+ NAPI_OK(napi_create_reference(env, key, 1, &member.key));
232
238
  }
233
239
  }
234
240
 
@@ -245,7 +251,7 @@ static bool FinalizeCompositeType(Napi::Env env, TypeInfo *type, PrimitiveKind p
245
251
  static Napi::Value CreateStructType(const Napi::CallbackInfo &info, bool pad)
246
252
  {
247
253
  Napi::Env env = info.Env();
248
- InstanceData *instance = env.GetInstanceData<InstanceData>();
254
+ InstanceData *instance = (InstanceData *)info.Data();
249
255
 
250
256
  if (info.Length() < 1) {
251
257
  ThrowError<Napi::TypeError>(env, "Expected 1 or 2 arguments, got %1", info.Length());
@@ -254,7 +260,11 @@ static Napi::Value CreateStructType(const Napi::CallbackInfo &info, bool pad)
254
260
 
255
261
  bool skip = (info.Length() > 1);
256
262
  bool named = skip && !IsNullOrUndefined(env, info[0]);
263
+ #if defined(EXTERNAL_TYPES)
264
+ bool redefine = named && info[0].IsExternal() && CheckValueTag(env, info[0], &TypeObjectMarker);
265
+ #else
257
266
  bool redefine = named && info[0].IsObject() && CheckValueTag(env, info[0], &TypeObjectMarker);
267
+ #endif
258
268
 
259
269
  if (named && !info[0].IsString() && !redefine) {
260
270
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for name, expected string", GetValueType(instance, info[0]));
@@ -288,10 +298,16 @@ static Napi::Value CreateStructType(const Napi::CallbackInfo &info, bool pad)
288
298
  TypeInfo *replace = nullptr;
289
299
 
290
300
  if (redefine) {
301
+ #if defined(EXTERNAL_TYPES)
302
+ Napi::External<TypeInfo> external = name.As<Napi::External<TypeInfo>>();
303
+ replace = external.Data();
304
+ #else
291
305
  TypeObject *defn = nullptr;
292
- napi_unwrap(env, name, (void **)&defn);
306
+ NAPI_OK(napi_unwrap(env, name, (void **)&defn));
293
307
 
294
308
  replace = (TypeInfo *)defn->GetType();
309
+ #endif
310
+
295
311
  type->name = replace->name;
296
312
 
297
313
  if (replace->primitive != PrimitiveKind::Void || replace == instance->void_type) {
@@ -341,7 +357,7 @@ static Napi::Value CreateStructType(const Napi::CallbackInfo &info, bool pad)
341
357
  align = (int16_t)align64;
342
358
  }
343
359
 
344
- member.type = ResolveType(value);
360
+ member.type = ResolveType(instance, value);
345
361
  if (!member.type)
346
362
  return env.Null();
347
363
  if (!CanStoreType(member.type)) {
@@ -417,7 +433,8 @@ static Napi::Value CreateStructType(const Napi::CallbackInfo &info, bool pad)
417
433
  type = replace;
418
434
  }
419
435
 
420
- return WrapType(env, type);
436
+ napi_value wrapper = WrapType(env, type);
437
+ return Napi::Value(env, wrapper);
421
438
  }
422
439
 
423
440
  static Napi::Value CreatePaddedStructType(const Napi::CallbackInfo &info)
@@ -433,7 +450,7 @@ static Napi::Value CreatePackedStructType(const Napi::CallbackInfo &info)
433
450
  static Napi::Value CreateUnionType(const Napi::CallbackInfo &info)
434
451
  {
435
452
  Napi::Env env = info.Env();
436
- InstanceData *instance = env.GetInstanceData<InstanceData>();
453
+ InstanceData *instance = (InstanceData *)info.Data();
437
454
 
438
455
  if (info.Length() < 1) {
439
456
  ThrowError<Napi::TypeError>(env, "Expected 1 or 2 arguments, got %1", info.Length());
@@ -442,7 +459,11 @@ static Napi::Value CreateUnionType(const Napi::CallbackInfo &info)
442
459
 
443
460
  bool skip = (info.Length() > 1);
444
461
  bool named = skip && !IsNullOrUndefined(env, info[0]);
462
+ #if defined(EXTERNAL_TYPES)
463
+ bool redefine = named && info[0].IsExternal() && CheckValueTag(env, info[0], &TypeObjectMarker);
464
+ #else
445
465
  bool redefine = named && info[0].IsObject() && CheckValueTag(env, info[0], &TypeObjectMarker);
466
+ #endif
446
467
 
447
468
  if (named && !info[0].IsString() && !redefine) {
448
469
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for name, expected string", GetValueType(instance, info[0]));
@@ -476,10 +497,16 @@ static Napi::Value CreateUnionType(const Napi::CallbackInfo &info)
476
497
  TypeInfo *replace = nullptr;
477
498
 
478
499
  if (redefine) {
500
+ #if defined(EXTERNAL_TYPES)
501
+ Napi::External<TypeInfo> external = name.As<Napi::External<TypeInfo>>();
502
+ replace = external.Data();
503
+ #else
479
504
  TypeObject *defn = nullptr;
480
- napi_unwrap(env, name, (void **)&defn);
505
+ NAPI_OK(napi_unwrap(env, name, (void **)&defn));
481
506
 
482
507
  replace = (TypeInfo *)defn->GetType();
508
+ #endif
509
+
483
510
  type->name = replace->name;
484
511
 
485
512
  if (replace->primitive != PrimitiveKind::Void || replace == instance->void_type) {
@@ -529,7 +556,7 @@ static Napi::Value CreateUnionType(const Napi::CallbackInfo &info)
529
556
  align = (int16_t)align64;
530
557
  }
531
558
 
532
- member.type = ResolveType(value);
559
+ member.type = ResolveType(instance, value);
533
560
  if (!member.type)
534
561
  return env.Null();
535
562
  if (!CanStoreType(member.type)) {
@@ -570,19 +597,21 @@ static Napi::Value CreateUnionType(const Napi::CallbackInfo &info)
570
597
  return env.Null();
571
598
  err_guard.Disable();
572
599
 
573
- type->construct = Napi::Persistent(UnionValue::InitClass(env, type));
600
+ type->construct = Napi::Persistent(UnionValue::InitClass(instance, type));
574
601
 
575
602
  if (replace) {
576
603
  std::swap(*type, *replace);
577
604
  type = replace;
578
605
  }
579
606
 
580
- return WrapType(env, type);
607
+ napi_value wrapper = WrapType(env, type);
608
+ return Napi::Value(env, wrapper);
581
609
  }
582
610
 
583
611
  Napi::Value InstantiateUnion(const Napi::CallbackInfo &info)
584
612
  {
585
613
  Napi::Env env = info.Env();
614
+ InstanceData *instance = (InstanceData *)info.Data();
586
615
 
587
616
  if (!info.IsConstructCall()) {
588
617
  ThrowError<Napi::TypeError>(env, "This function is a constructor and must be called with new");
@@ -593,7 +622,7 @@ Napi::Value InstantiateUnion(const Napi::CallbackInfo &info)
593
622
  return env.Null();
594
623
  }
595
624
 
596
- const TypeInfo *type = ResolveType(info[0]);
625
+ const TypeInfo *type = ResolveType(instance, info[0]);
597
626
  if (!type)
598
627
  return env.Null();
599
628
  if (type->primitive != PrimitiveKind::Union) {
@@ -610,7 +639,7 @@ Napi::Value InstantiateUnion(const Napi::CallbackInfo &info)
610
639
  static Napi::Value CreateOpaqueType(const Napi::CallbackInfo &info)
611
640
  {
612
641
  Napi::Env env = info.Env();
613
- InstanceData *instance = env.GetInstanceData<InstanceData>();
642
+ InstanceData *instance = (InstanceData *)info.Data();
614
643
 
615
644
  bool named = (info.Length() >= 1) && !IsNullOrUndefined(env, info[0]);
616
645
 
@@ -636,13 +665,14 @@ static Napi::Value CreateOpaqueType(const Napi::CallbackInfo &info)
636
665
  return env.Null();
637
666
  err_guard.Disable();
638
667
 
639
- return WrapType(env, type);
668
+ napi_value wrapper = WrapType(env, type);
669
+ return Napi::Value(env, wrapper);
640
670
  }
641
671
 
642
672
  static Napi::Value CreatePointerType(const Napi::CallbackInfo &info)
643
673
  {
644
674
  Napi::Env env = info.Env();
645
- InstanceData *instance = env.GetInstanceData<InstanceData>();
675
+ InstanceData *instance = (InstanceData *)info.Data();
646
676
 
647
677
  if (info.Length() < 1) {
648
678
  ThrowError<Napi::TypeError>(env, "Expected 1 to 3 arguments, got %1", info.Length());
@@ -659,7 +689,7 @@ static Napi::Value CreatePointerType(const Napi::CallbackInfo &info)
659
689
 
660
690
  std::string name = named ? info[0].As<Napi::String>() : std::string();
661
691
 
662
- const TypeInfo *ref = ResolveType(info[skip]);
692
+ const TypeInfo *ref = ResolveType(instance, info[skip]);
663
693
  if (!ref)
664
694
  return env.Null();
665
695
 
@@ -708,7 +738,8 @@ static Napi::Value CreatePointerType(const Napi::CallbackInfo &info)
708
738
  type = copy;
709
739
  }
710
740
 
711
- return WrapType(env, type);
741
+ napi_value wrapper = WrapType(env, type);
742
+ return Napi::Value(env, wrapper);
712
743
  }
713
744
 
714
745
  static Napi::Value EncodePointerDirection(const Napi::CallbackInfo &info, int directions)
@@ -716,13 +747,14 @@ static Napi::Value EncodePointerDirection(const Napi::CallbackInfo &info, int di
716
747
  K_ASSERT(directions >= 1 && directions <= 3);
717
748
 
718
749
  Napi::Env env = info.Env();
750
+ InstanceData *instance = (InstanceData *)info.Data();
719
751
 
720
752
  if (info.Length() < 1) {
721
753
  ThrowError<Napi::TypeError>(env, "Expected 1 argument, got %1", info.Length());
722
754
  return env.Null();
723
755
  }
724
756
 
725
- const TypeInfo *type = ResolveType(info[0]);
757
+ const TypeInfo *type = ResolveType(instance, info[0]);
726
758
  if (!type)
727
759
  return env.Null();
728
760
 
@@ -761,7 +793,7 @@ static Napi::Value MarkInOut(const Napi::CallbackInfo &info)
761
793
  static Napi::Value CreateDisposableType(const Napi::CallbackInfo &info)
762
794
  {
763
795
  Napi::Env env = info.Env();
764
- InstanceData *instance = env.GetInstanceData<InstanceData>();
796
+ InstanceData *instance = (InstanceData *)info.Data();
765
797
 
766
798
  if (info.Length() < 1) {
767
799
  ThrowError<Napi::TypeError>(env, "Expected 1 or 2 arguments, got %1", info.Length());
@@ -778,7 +810,7 @@ static Napi::Value CreateDisposableType(const Napi::CallbackInfo &info)
778
810
 
779
811
  Napi::String name = info[0].As<Napi::String>();
780
812
 
781
- const TypeInfo *src = ResolveType(info[skip]);
813
+ const TypeInfo *src = ResolveType(instance, info[skip]);
782
814
  if (!src)
783
815
  return env.Null();
784
816
  if (src->primitive != PrimitiveKind::Pointer &&
@@ -807,12 +839,10 @@ static Napi::Value CreateDisposableType(const Napi::CallbackInfo &info)
807
839
  InstanceData *instance = env.GetInstanceData<InstanceData>();
808
840
  const Napi::FunctionReference &ref = type->dispose_ref;
809
841
 
810
- Napi::Value p = WrapPointer(env, type->ref.type, (void *)ptr);
811
-
812
842
  napi_value self = env.Null();
813
- napi_value args[] = { p };
843
+ napi_value wrapper = WrapPointer(env, type->ref.type, (void *)ptr);
814
844
 
815
- ref.Call(self, K_LEN(args), args);
845
+ ref.Call(self, 1, &wrapper);
816
846
  instance->stats.disposed++;
817
847
  };
818
848
  dispose_func = func;
@@ -853,13 +883,14 @@ static Napi::Value CreateDisposableType(const Napi::CallbackInfo &info)
853
883
  }
854
884
  err_guard.Disable();
855
885
 
856
- return WrapType(env, type);
886
+ napi_value wrapper = WrapType(env, type);
887
+ return Napi::Value(env, wrapper);
857
888
  }
858
889
 
859
890
  static Napi::Value CallAlloc(const Napi::CallbackInfo &info)
860
891
  {
861
892
  Napi::Env env = info.Env();
862
- InstanceData *instance = env.GetInstanceData<InstanceData>();
893
+ InstanceData *instance = (InstanceData *)info.Data();
863
894
 
864
895
  if (info.Length() < 2) {
865
896
  ThrowError<Napi::TypeError>(env, "Expected 2 arguments, got %1", info.Length());
@@ -870,7 +901,7 @@ static Napi::Value CallAlloc(const Napi::CallbackInfo &info)
870
901
  return env.Null();
871
902
  }
872
903
 
873
- const TypeInfo *type = ResolveType(info[0]);
904
+ const TypeInfo *type = ResolveType(instance, info[0]);
874
905
  if (!type)
875
906
  return env.Null();
876
907
 
@@ -899,12 +930,14 @@ static Napi::Value CallAlloc(const Napi::CallbackInfo &info)
899
930
  return env.Null();
900
931
  }
901
932
 
902
- return WrapPointer(env, type, ptr);
933
+ napi_value wrapper = WrapPointer(env, type, ptr);
934
+ return Napi::Value(env, wrapper);
903
935
  }
904
936
 
905
937
  static Napi::Value CallFree(const Napi::CallbackInfo &info)
906
938
  {
907
939
  Napi::Env env = info.Env();
940
+ InstanceData *instance = (InstanceData *)info.Data();
908
941
 
909
942
  if (info.Length() < 1) {
910
943
  ThrowError<Napi::TypeError>(env, "Expected 1 argument, got %1", info.Length());
@@ -913,8 +946,6 @@ static Napi::Value CallFree(const Napi::CallbackInfo &info)
913
946
 
914
947
  void *ptr = nullptr;
915
948
  if (!TryPointer(env, info[0], &ptr)) {
916
- InstanceData *instance = Napi::Env(env).GetInstanceData<InstanceData>();
917
-
918
949
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for ptr, expected pointer", GetValueType(instance, info[0]));
919
950
  return env.Null();
920
951
  }
@@ -927,7 +958,7 @@ static Napi::Value CallFree(const Napi::CallbackInfo &info)
927
958
  static Napi::Value GetOrSetErrNo(const Napi::CallbackInfo &info)
928
959
  {
929
960
  Napi::Env env = info.Env();
930
- InstanceData *instance = env.GetInstanceData<InstanceData>();
961
+ InstanceData *instance = (InstanceData *)info.Data();
931
962
 
932
963
  if (info.Length() >= 1) {
933
964
  Napi::Number value = info[0].As<Napi::Number>();
@@ -947,14 +978,14 @@ static Napi::Value GetOrSetErrNo(const Napi::CallbackInfo &info)
947
978
  static Napi::Value CreateArrayType(const Napi::CallbackInfo &info)
948
979
  {
949
980
  Napi::Env env = info.Env();
950
- InstanceData *instance = env.GetInstanceData<InstanceData>();
981
+ InstanceData *instance = (InstanceData *)info.Data();
951
982
 
952
983
  if (info.Length() < 2) {
953
984
  ThrowError<Napi::TypeError>(env, "Expected 2 to 4 arguments, got %1", info.Length());
954
985
  return env.Null();
955
986
  }
956
987
 
957
- const TypeInfo *ref = ResolveType(info[0]);
988
+ const TypeInfo *ref = ResolveType(instance, info[0]);
958
989
  if (!ref)
959
990
  return env.Null();
960
991
 
@@ -1002,10 +1033,19 @@ static Napi::Value CreateArrayType(const Napi::CallbackInfo &info)
1002
1033
  }
1003
1034
 
1004
1035
  hint = ArrayHint::Typed;
1036
+ } else if (str == "Buffer" || str == "buffer") {
1037
+ if (!(ref->flags & (int)TypeFlag::HasTypedArray)) {
1038
+ ThrowError<Napi::Error>(env, "Array hint 'Buffer' cannot be used with type %1", ref->name);
1039
+ return env.Null();
1040
+ }
1041
+
1042
+ hint = ArrayHint::Buffer;
1005
1043
  } else if (str == "Array" || str == "array") {
1006
1044
  hint = ArrayHint::Array;
1007
1045
  } else if (str == "String" || str == "string") {
1008
- if (ref->primitive != PrimitiveKind::Int8 && ref->primitive != PrimitiveKind::Int16) {
1046
+ if (ref->primitive != PrimitiveKind::Int8 &&
1047
+ ref->primitive != PrimitiveKind::Int16 &&
1048
+ ref->primitive != PrimitiveKind::Int32) {
1009
1049
  ThrowError<Napi::Error>(env, "Array hint 'String' can only be used with 8, 16 and 32-bit signed integer types");
1010
1050
  return env.Null();
1011
1051
  }
@@ -1026,7 +1066,8 @@ static Napi::Value CreateArrayType(const Napi::CallbackInfo &info)
1026
1066
  type->countedby = DuplicateString(str.Utf8Value().c_str(), &instance->str_alloc).ptr;
1027
1067
  }
1028
1068
 
1029
- return WrapType(env, type);
1069
+ napi_value wrapper = WrapType(env, type);
1070
+ return Napi::Value(env, wrapper);
1030
1071
  }
1031
1072
 
1032
1073
  static bool ParseClassicFunction(const Napi::CallbackInfo &info, bool concrete, FunctionInfo *out_func)
@@ -1034,7 +1075,7 @@ static bool ParseClassicFunction(const Napi::CallbackInfo &info, bool concrete,
1034
1075
  K_ASSERT(info.Length() >= 2);
1035
1076
 
1036
1077
  Napi::Env env = info.Env();
1037
- InstanceData *instance = env.GetInstanceData<InstanceData>();
1078
+ InstanceData *instance = (InstanceData *)info.Data();
1038
1079
 
1039
1080
  Napi::String name = info[0u].As<Napi::String>();
1040
1081
  Napi::Value ret = info[1u];
@@ -1077,7 +1118,7 @@ static bool ParseClassicFunction(const Napi::CallbackInfo &info, bool concrete,
1077
1118
  // Leave anonymous naming responsibility to caller
1078
1119
  out_func->name = named ? DuplicateString(name.Utf8Value().c_str(), &instance->str_alloc).ptr : nullptr;
1079
1120
 
1080
- out_func->ret.type = ResolveType(ret);
1121
+ out_func->ret.type = ResolveType(instance, ret);
1081
1122
  if (!out_func->ret.type)
1082
1123
  return false;
1083
1124
  if (!CanReturnType(out_func->ret.type)) {
@@ -1104,7 +1145,7 @@ static bool ParseClassicFunction(const Napi::CallbackInfo &info, bool concrete,
1104
1145
  for (uint32_t j = 0; j < parameters_len; j++) {
1105
1146
  ParameterInfo param = {};
1106
1147
 
1107
- param.type = ResolveType(parameters[j], &param.directions);
1148
+ param.type = ResolveType(instance, parameters[j].AsValue(), &param.directions);
1108
1149
 
1109
1150
  if (!param.type)
1110
1151
  return false;
@@ -1130,7 +1171,7 @@ static bool ParseClassicFunction(const Napi::CallbackInfo &info, bool concrete,
1130
1171
  static Napi::Value CreateFunctionType(const Napi::CallbackInfo &info)
1131
1172
  {
1132
1173
  Napi::Env env = info.Env();
1133
- InstanceData *instance = env.GetInstanceData<InstanceData>();
1174
+ InstanceData *instance = (InstanceData *)info.Data();
1134
1175
 
1135
1176
  FunctionInfo *func = instance->callbacks.AppendDefault();
1136
1177
  K_DEFER_N(err_guard) { instance->callbacks.RemoveLast(1); };
@@ -1182,13 +1223,14 @@ static Napi::Value CreateFunctionType(const Napi::CallbackInfo &info)
1182
1223
 
1183
1224
  instance->types_map.Set(type->name, type);
1184
1225
 
1185
- return WrapType(env, type);
1226
+ napi_value wrapper = WrapType(env, type);
1227
+ return Napi::Value(env, wrapper);
1186
1228
  }
1187
1229
 
1188
1230
  static Napi::Value CreateEnumType(const Napi::CallbackInfo &info)
1189
1231
  {
1190
1232
  Napi::Env env = info.Env();
1191
- InstanceData *instance = env.GetInstanceData<InstanceData>();
1233
+ InstanceData *instance = (InstanceData *)info.Data();
1192
1234
 
1193
1235
  if (info.Length() < 1) {
1194
1236
  ThrowError<Napi::TypeError>(env, "Expected 1 or 2 arguments, got %1", info.Length());
@@ -1221,7 +1263,7 @@ static Napi::Value CreateEnumType(const Napi::CallbackInfo &info)
1221
1263
 
1222
1264
  // Determine needed storage type
1223
1265
  if (typed) {
1224
- const TypeInfo *storage = ResolveType(info[1 + named]);
1266
+ const TypeInfo *storage = ResolveType(instance, info[1 + named]);
1225
1267
  if (!storage)
1226
1268
  return env.Null();
1227
1269
 
@@ -1338,18 +1380,19 @@ static Napi::Value CreateEnumType(const Napi::CallbackInfo &info)
1338
1380
  return env.Null();
1339
1381
  err_guard.Disable();
1340
1382
 
1341
- Napi::Object defn = WrapType(env, type, false);
1383
+ napi_value wrapper = WrapType(env, type, false);
1384
+ Napi::Object defn = type->defn.Value();
1342
1385
 
1343
1386
  defn.Set("values", values);
1344
1387
  defn.Freeze();
1345
1388
 
1346
- return defn;
1389
+ return Napi::Value(env, wrapper);
1347
1390
  }
1348
1391
 
1349
1392
  static Napi::Value CreateTypeAlias(const Napi::CallbackInfo &info)
1350
1393
  {
1351
1394
  Napi::Env env = info.Env();
1352
- InstanceData *instance = env.GetInstanceData<InstanceData>();
1395
+ InstanceData *instance = (InstanceData *)info.Data();
1353
1396
 
1354
1397
  if (info.Length() < 2) {
1355
1398
  ThrowError<Napi::TypeError>(env, "Expected 2 arguments, got %1", info.Length());
@@ -1363,7 +1406,7 @@ static Napi::Value CreateTypeAlias(const Napi::CallbackInfo &info)
1363
1406
  std::string name = info[0].As<Napi::String>();
1364
1407
  const char *alias = DuplicateString(name.c_str(), &instance->str_alloc).ptr;
1365
1408
 
1366
- const TypeInfo *type = ResolveType(info[1]);
1409
+ const TypeInfo *type = ResolveType(instance, info[1]);
1367
1410
  if (!type)
1368
1411
  return env.Null();
1369
1412
 
@@ -1371,25 +1414,51 @@ static Napi::Value CreateTypeAlias(const Napi::CallbackInfo &info)
1371
1414
  if (!MapType(env, instance, type, alias))
1372
1415
  return env.Null();
1373
1416
 
1374
- return WrapType(env, type);
1417
+ napi_value wrapper = WrapType(env, type);
1418
+ return Napi::Value(env, wrapper);
1375
1419
  }
1376
1420
 
1377
1421
  static Napi::Value GetResolvedType(const Napi::CallbackInfo &info)
1378
1422
  {
1379
1423
  Napi::Env env = info.Env();
1424
+ InstanceData *instance = (InstanceData *)info.Data();
1380
1425
 
1381
1426
  if (info.Length() < 1) {
1382
1427
  ThrowError<Napi::TypeError>(env, "Expected 1 argument, got %1", info.Length());
1383
1428
  return env.Null();
1384
1429
  }
1385
1430
 
1386
- const TypeInfo *type = ResolveType(info[0]);
1431
+ const TypeInfo *type = ResolveType(instance, info[0]);
1387
1432
  if (!type)
1388
1433
  return env.Null();
1389
1434
 
1390
- return WrapType(env, type);
1435
+ napi_value wrapper = WrapType(env, type);
1436
+ return Napi::Value(env, wrapper);
1391
1437
  }
1392
1438
 
1439
+ #if defined(EXTERNAL_TYPES)
1440
+
1441
+ static Napi::Value GetTypeDefinition(const Napi::CallbackInfo &info)
1442
+ {
1443
+ Napi::Env env = info.Env();
1444
+
1445
+ if (info.Length() < 1) {
1446
+ ThrowError<Napi::TypeError>(env, "Expected 1 argument, got %1", info.Length());
1447
+ return env.Null();
1448
+ }
1449
+
1450
+ const TypeInfo *type = ResolveType(instance, info[0]);
1451
+ if (!type)
1452
+ return env.Null();
1453
+
1454
+ // Make sure definition is available
1455
+ WrapType(env, type);
1456
+
1457
+ return type->defn.Value();
1458
+ }
1459
+
1460
+ #endif
1461
+
1393
1462
  InstanceMemory *AllocateMemory(InstanceData *instance, Size stack_size, Size heap_size)
1394
1463
  {
1395
1464
  std::lock_guard<std::mutex> lock(instance->mem_mutex);
@@ -1484,13 +1553,15 @@ void ReleaseMemory(InstanceData *instance, InstanceMemory *mem)
1484
1553
  }
1485
1554
  }
1486
1555
 
1487
- Napi::Function LibraryHandle::InitClass(Napi::Env env)
1556
+ Napi::Function LibraryHandle::InitClass(InstanceData *instance)
1488
1557
  {
1558
+ Napi::Env env = instance->env;
1559
+
1489
1560
  // node-addon-api wants std::vector
1490
1561
  std::vector<Napi::ClassPropertyDescriptor<LibraryHandle>> properties = {
1491
- InstanceMethod("func", &LibraryHandle::Func),
1492
- InstanceMethod("symbol", &LibraryHandle::Symbol),
1493
- InstanceMethod("unload", &LibraryHandle::Unload)
1562
+ InstanceMethod("func", &LibraryHandle::Func, napi_default, instance),
1563
+ InstanceMethod("symbol", &LibraryHandle::Symbol, napi_default, instance),
1564
+ InstanceMethod("unload", &LibraryHandle::Unload, napi_default, instance)
1494
1565
  };
1495
1566
 
1496
1567
  if (Napi::Value dispose = env.RunScript("Symbol.dispose"); !IsNullOrUndefined(env, dispose)) {
@@ -1527,7 +1598,7 @@ void LibraryHandle::Finalize(Napi::BasicEnv env)
1527
1598
  Napi::Value LibraryHandle::Func(const Napi::CallbackInfo &info)
1528
1599
  {
1529
1600
  Napi::Env env = info.Env();
1530
- InstanceData *instance = env.GetInstanceData<InstanceData>();
1601
+ InstanceData *instance = (InstanceData *)info.Data();
1531
1602
 
1532
1603
  FunctionInfo *func = new FunctionInfo();
1533
1604
  K_DEFER { func->Unref(); };
@@ -1589,13 +1660,14 @@ Napi::Value LibraryHandle::Func(const Napi::CallbackInfo &info)
1589
1660
  return env.Null();
1590
1661
  }
1591
1662
 
1592
- return WrapFunction(env, func);
1663
+ napi_value wrapper = WrapFunction(env, func);
1664
+ return Napi::Value(env, wrapper);
1593
1665
  }
1594
1666
 
1595
1667
  Napi::Value LibraryHandle::Symbol(const Napi::CallbackInfo &info)
1596
1668
  {
1597
1669
  Napi::Env env = info.Env();
1598
- InstanceData *instance = env.GetInstanceData<InstanceData>();
1670
+ InstanceData *instance = (InstanceData *)info.Data();
1599
1671
 
1600
1672
  if (info.Length() < 2) {
1601
1673
  ThrowError<Napi::TypeError>(env, "Expected 2, got %1", info.Length());
@@ -1608,7 +1680,7 @@ Napi::Value LibraryHandle::Symbol(const Napi::CallbackInfo &info)
1608
1680
 
1609
1681
  std::string name = info[0].As<Napi::String>();
1610
1682
 
1611
- const TypeInfo *type = ResolveType(info[1]);
1683
+ const TypeInfo *type = ResolveType(instance, info[1]);
1612
1684
  if (!type)
1613
1685
  return env.Null();
1614
1686
 
@@ -1622,7 +1694,8 @@ Napi::Value LibraryHandle::Symbol(const Napi::CallbackInfo &info)
1622
1694
  return env.Null();
1623
1695
  }
1624
1696
 
1625
- return WrapPointer(env, type, ptr);
1697
+ napi_value wrapper = WrapPointer(env, type, ptr);
1698
+ return Napi::Value(env, wrapper);
1626
1699
  }
1627
1700
 
1628
1701
  Napi::Value LibraryHandle::Unload(const Napi::CallbackInfo &info)
@@ -1637,7 +1710,7 @@ Napi::Value LibraryHandle::Unload(const Napi::CallbackInfo &info)
1637
1710
  static Napi::Value LoadSharedLibrary(const Napi::CallbackInfo &info)
1638
1711
  {
1639
1712
  Napi::Env env = info.Env();
1640
- InstanceData *instance = env.GetInstanceData<InstanceData>();
1713
+ InstanceData *instance = (InstanceData *)info.Data();
1641
1714
 
1642
1715
  if (info.Length() < 1) {
1643
1716
  ThrowError<Napi::TypeError>(env, "Expected 1 or 2 arguments, got %1", info.Length());
@@ -1722,7 +1795,7 @@ static Napi::Value LoadSharedLibrary(const Napi::CallbackInfo &info)
1722
1795
  static Napi::Value RegisterCallback(const Napi::CallbackInfo &info)
1723
1796
  {
1724
1797
  Napi::Env env = info.Env();
1725
- InstanceData *instance = env.GetInstanceData<InstanceData>();
1798
+ InstanceData *instance = (InstanceData *)info.Data();
1726
1799
 
1727
1800
  if (!InitAsyncBroker(env, instance)) [[unlikely]]
1728
1801
  return env.Null();
@@ -1738,7 +1811,7 @@ static Napi::Value RegisterCallback(const Napi::CallbackInfo &info)
1738
1811
 
1739
1812
  Napi::Function func = info[0].As<Napi::Function>();
1740
1813
 
1741
- const TypeInfo *type = ResolveType(info[1]);
1814
+ const TypeInfo *type = ResolveType(instance, info[1]);
1742
1815
  if (!type)
1743
1816
  return env.Null();
1744
1817
  if (type->primitive != PrimitiveKind::Callback) {
@@ -1765,20 +1838,21 @@ static Napi::Value RegisterCallback(const Napi::CallbackInfo &info)
1765
1838
  trampoline->instance = instance;
1766
1839
  trampoline->stack0 = instance->memories[0]->stack0;
1767
1840
  trampoline->proto = type->proto;
1768
- napi_create_reference(env, func, 1, &trampoline->func);
1841
+ NAPI_OK(napi_create_reference(env, func, 1, &trampoline->func));
1769
1842
 
1770
1843
  void *ptr = GetTrampoline(idx);
1771
1844
 
1772
1845
  // Cache index for fast unregistration
1773
1846
  instance->trampolines_map.Set(ptr, idx);
1774
1847
 
1775
- return WrapPointer(env, type->ref.type, ptr);
1848
+ napi_value wrapper = WrapPointer(env, type->ref.type, ptr);
1849
+ return Napi::Value(env, wrapper);
1776
1850
  }
1777
1851
 
1778
1852
  static Napi::Value UnregisterCallback(const Napi::CallbackInfo &info)
1779
1853
  {
1780
1854
  Napi::Env env = info.Env();
1781
- InstanceData *instance = env.GetInstanceData<InstanceData>();
1855
+ InstanceData *instance = (InstanceData *)info.Data();
1782
1856
 
1783
1857
  if (info.Length() < 1) {
1784
1858
  ThrowError<Napi::TypeError>(env, "Expected 1 argument, got %1", info.Length());
@@ -1824,6 +1898,7 @@ static Napi::Value UnregisterCallback(const Napi::CallbackInfo &info)
1824
1898
  static Napi::Value CastValue(const Napi::CallbackInfo &info)
1825
1899
  {
1826
1900
  Napi::Env env = info.Env();
1901
+ InstanceData *instance = (InstanceData *)info.Data();
1827
1902
 
1828
1903
  if (info.Length() < 2) [[unlikely]] {
1829
1904
  ThrowError<Napi::TypeError>(env, "Expected 2 arguments, got %1", info.Length());
@@ -1832,7 +1907,7 @@ static Napi::Value CastValue(const Napi::CallbackInfo &info)
1832
1907
 
1833
1908
  Napi::Value value = info[0];
1834
1909
 
1835
- const TypeInfo *type = ResolveType(info[1]);
1910
+ const TypeInfo *type = ResolveType(instance, info[1]);
1836
1911
  if (!type) [[unlikely]]
1837
1912
  return env.Null();
1838
1913
  if (type->primitive != PrimitiveKind::Pointer &&
@@ -1847,7 +1922,7 @@ static Napi::Value CastValue(const Napi::CallbackInfo &info)
1847
1922
  ValueCast *cast = new ValueCast();
1848
1923
 
1849
1924
  cast->env = env;
1850
- napi_create_reference(env, value, 1, &cast->ref);
1925
+ NAPI_OK(napi_create_reference(env, value, 1, &cast->ref));
1851
1926
  cast->type = type;
1852
1927
 
1853
1928
  Napi::External<ValueCast> external = Napi::External<ValueCast>::New(env, cast, [](Napi::Env, ValueCast *cast) { delete cast; });
@@ -1859,6 +1934,7 @@ static Napi::Value CastValue(const Napi::CallbackInfo &info)
1859
1934
  static Napi::Value DecodeValue(const Napi::CallbackInfo &info)
1860
1935
  {
1861
1936
  Napi::Env env = info.Env();
1937
+ InstanceData *instance = (InstanceData *)info.Data();
1862
1938
 
1863
1939
  bool has_offset = (info.Length() >= 2 && info[1].IsNumber());
1864
1940
  bool has_len = (info.Length() >= 3u + has_offset && info[2 + has_offset].IsNumber());
@@ -1868,22 +1944,78 @@ static Napi::Value DecodeValue(const Napi::CallbackInfo &info)
1868
1944
  return env.Null();
1869
1945
  }
1870
1946
 
1871
- const TypeInfo *type = ResolveType(info[1u + has_offset]);
1947
+ const TypeInfo *type = ResolveType(instance, info[1u + has_offset]);
1872
1948
  if (!type) [[unlikely]]
1873
1949
  return env.Null();
1874
1950
 
1875
- Napi::Value value = info[0];
1951
+ napi_value ref = info[0];
1876
1952
  int64_t offset = has_offset ? info[1].As<Napi::Number>().Int64Value() : 0;
1877
1953
 
1954
+ const void *src = nullptr;
1955
+ Size len = 0;
1956
+
1957
+ if (!TryPointer(env, ref, (void **)&src, &len)) {
1958
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value for reference, expected pointer", GetValueType(instance, ref));
1959
+ return env.Null();
1960
+ }
1961
+
1962
+ if (len >= 0) {
1963
+ if (offset < 0) [[unlikely]] {
1964
+ ThrowError<Napi::Error>(env, "Offset must be >= 0");
1965
+ return env.Null();
1966
+ }
1967
+ if (len - offset < type->size) [[unlikely]] {
1968
+ ThrowError<Napi::Error>(env, "Expected buffer with size superior or equal to type %1 (%2 bytes)",
1969
+ type->name, type->size + offset);
1970
+ return env.Null();
1971
+ }
1972
+ }
1973
+
1974
+ if (!src) [[unlikely]] {
1975
+ ThrowError<Napi::Error>(env, "Cannot encode data in NULL pointer");
1976
+ return env.Null();
1977
+ }
1978
+
1979
+ src = (const void *)((const uint8_t *)src + offset);
1980
+
1878
1981
  if (has_len) {
1879
1982
  Size len = info[2 + has_offset].As<Napi::Number>();
1880
1983
 
1881
- Napi::Value ret = Decode(value, (Size)offset, type, &len);
1882
- return ret;
1883
- } else {
1884
- Napi::Value ret = Decode(value, (Size)offset, type);
1885
- return ret;
1984
+ if (len >= 0) {
1985
+ type = MakeArrayType(instance, type, len);
1986
+ } else {
1987
+ switch (type->primitive) {
1988
+ case PrimitiveKind::Int8:
1989
+ case PrimitiveKind::UInt8: {
1990
+ Size count = strlen((const char *)src);
1991
+ type = MakeArrayType(instance, type, count);
1992
+ } break;
1993
+ case PrimitiveKind::Int16:
1994
+ case PrimitiveKind::UInt16: {
1995
+ Size count = NullTerminatedLength((const char16_t *)src);
1996
+ type = MakeArrayType(instance, type, count);
1997
+ } break;
1998
+ case PrimitiveKind::Int32:
1999
+ case PrimitiveKind::UInt32: {
2000
+ Size count = NullTerminatedLength((const char32_t *)src);
2001
+ type = MakeArrayType(instance, type, count);
2002
+ } break;
2003
+
2004
+ case PrimitiveKind::Pointer: {
2005
+ Size count = NullTerminatedLength((const void **)src);
2006
+ type = MakeArrayType(instance, type, count);
2007
+ } break;
2008
+
2009
+ default: {
2010
+ ThrowError<Napi::TypeError>(env, "Cannot determine null-terminated length for type %1", type->name);
2011
+ return env.Null();
2012
+ } break;
2013
+ }
2014
+ }
1886
2015
  }
2016
+
2017
+ napi_value ret = Decode(instance, (const uint8_t *)src, type);
2018
+ return Napi::Value(env, ret);
1887
2019
  }
1888
2020
 
1889
2021
  template <typename T>
@@ -1892,8 +2024,7 @@ static FORCE_INLINE napi_value DecodeInteger(napi_env env, napi_callback_info in
1892
2024
  napi_value arg;
1893
2025
  size_t count = 1;
1894
2026
 
1895
- napi_status status = napi_get_cb_info(env, info, &count, &arg, nullptr, nullptr);
1896
- K_ASSERT(status == napi_ok);
2027
+ NAPI_OK(napi_get_cb_info(env, info, &count, &arg, nullptr, nullptr));
1897
2028
 
1898
2029
  if (count < 1) [[unlikely]] {
1899
2030
  ThrowError<Napi::TypeError>(env, "Expected 1 argument, got %1", count);
@@ -1919,8 +2050,7 @@ static napi_value DecodeFloat(napi_env env, napi_callback_info info)
1919
2050
  napi_value arg;
1920
2051
  size_t count = 1;
1921
2052
 
1922
- napi_status status = napi_get_cb_info(env, info, &count, &arg, nullptr, nullptr);
1923
- K_ASSERT(status == napi_ok);
2053
+ NAPI_OK(napi_get_cb_info(env, info, &count, &arg, nullptr, nullptr));
1924
2054
 
1925
2055
  if (count < 1) [[unlikely]] {
1926
2056
  ThrowError<Napi::TypeError>(env, "Expected 1 argument, got %1", count);
@@ -1946,8 +2076,7 @@ static napi_value DecodeDouble(napi_env env, napi_callback_info info)
1946
2076
  napi_value arg;
1947
2077
  size_t count = 1;
1948
2078
 
1949
- napi_status status = napi_get_cb_info(env, info, &count, &arg, nullptr, nullptr);
1950
- K_ASSERT(status == napi_ok);
2079
+ NAPI_OK(napi_get_cb_info(env, info, &count, &arg, nullptr, nullptr));
1951
2080
 
1952
2081
  if (count < 1) [[unlikely]] {
1953
2082
  ThrowError<Napi::TypeError>(env, "Expected 1 argument, got %1", count);
@@ -1973,8 +2102,7 @@ static napi_value DecodeString(napi_env env, napi_callback_info info)
1973
2102
  napi_value args[2];
1974
2103
  size_t count = 2;
1975
2104
 
1976
- napi_status status = napi_get_cb_info(env, info, &count, args, nullptr, nullptr);
1977
- K_ASSERT(status == napi_ok);
2105
+ NAPI_OK(napi_get_cb_info(env, info, &count, args, nullptr, nullptr));
1978
2106
 
1979
2107
  if (count < 1) [[unlikely]] {
1980
2108
  ThrowError<Napi::TypeError>(env, "Expected 1 to 2 arguments, got %1", count);
@@ -2009,8 +2137,7 @@ static napi_value DecodeString16(napi_env env, napi_callback_info info)
2009
2137
  napi_value args[2];
2010
2138
  size_t count = 2;
2011
2139
 
2012
- napi_status status = napi_get_cb_info(env, info, &count, args, nullptr, nullptr);
2013
- K_ASSERT(status == napi_ok);
2140
+ NAPI_OK(napi_get_cb_info(env, info, &count, args, nullptr, nullptr));
2014
2141
 
2015
2142
  if (count < 1) [[unlikely]] {
2016
2143
  ThrowError<Napi::TypeError>(env, "Expected 1 to 2 arguments, got %1", count);
@@ -2045,8 +2172,7 @@ static napi_value DecodeString32(napi_env env, napi_callback_info info)
2045
2172
  napi_value args[2];
2046
2173
  size_t count = 2;
2047
2174
 
2048
- napi_status status = napi_get_cb_info(env, info, &count, args, nullptr, nullptr);
2049
- K_ASSERT(status == napi_ok);
2175
+ NAPI_OK(napi_get_cb_info(env, info, &count, args, nullptr, nullptr));
2050
2176
 
2051
2177
  if (count < 1) [[unlikely]] {
2052
2178
  ThrowError<Napi::TypeError>(env, "Expected 1 to 2 arguments, got %1", count);
@@ -2079,6 +2205,7 @@ static napi_value DecodeString32(napi_env env, napi_callback_info info)
2079
2205
  static Napi::Value GetPointerAddress(const Napi::CallbackInfo &info)
2080
2206
  {
2081
2207
  Napi::Env env = info.Env();
2208
+ InstanceData *instance = (InstanceData *)info.Data();
2082
2209
 
2083
2210
  if (info.Length() < 1) {
2084
2211
  ThrowError<Napi::TypeError>(env, "Expected 1 argument, got %1", info.Length());
@@ -2087,8 +2214,6 @@ static Napi::Value GetPointerAddress(const Napi::CallbackInfo &info)
2087
2214
 
2088
2215
  void *ptr = nullptr;
2089
2216
  if (!TryPointer(env, info[0], &ptr)) {
2090
- InstanceData *instance = Napi::Env(env).GetInstanceData<InstanceData>();
2091
-
2092
2217
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for ptr, expected pointer", GetValueType(instance, info[0]));
2093
2218
  return env.Null();
2094
2219
  }
@@ -2102,6 +2227,7 @@ static Napi::Value GetPointerAddress(const Napi::CallbackInfo &info)
2102
2227
  static Napi::Value CallPointerSync(const Napi::CallbackInfo &info)
2103
2228
  {
2104
2229
  Napi::Env env = info.Env();
2230
+ InstanceData *instance = (InstanceData *)info.Data();
2105
2231
 
2106
2232
  if (info.Length() < 2) [[unlikely]] {
2107
2233
  ThrowError<Napi::TypeError>(env, "Expected 2 or more arguments, got %1", info.Length());
@@ -2110,18 +2236,14 @@ static Napi::Value CallPointerSync(const Napi::CallbackInfo &info)
2110
2236
 
2111
2237
  void *ptr = nullptr;
2112
2238
  if (!TryPointer(env, info[0], &ptr)) {
2113
- InstanceData *instance = Napi::Env(env).GetInstanceData<InstanceData>();
2114
-
2115
2239
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for ptr, expected pointer", GetValueType(instance, info[0]));
2116
2240
  return env.Null();
2117
2241
  }
2118
2242
 
2119
- const TypeInfo *type = ResolveType(info[1]);
2243
+ const TypeInfo *type = ResolveType(instance, info[1]);
2120
2244
  if (!type) [[unlikely]]
2121
2245
  return env.Null();
2122
2246
  if (type->primitive != PrimitiveKind::Prototype) [[unlikely]] {
2123
- InstanceData *instance = env.GetInstanceData<InstanceData>();
2124
-
2125
2247
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for type, expected function type", GetValueType(instance, info[1]));
2126
2248
  return env.Null();
2127
2249
  }
@@ -2133,6 +2255,7 @@ static Napi::Value CallPointerSync(const Napi::CallbackInfo &info)
2133
2255
  static Napi::Value EncodeValue(const Napi::CallbackInfo &info)
2134
2256
  {
2135
2257
  Napi::Env env = info.Env();
2258
+ InstanceData *instance = (InstanceData *)info.Data();
2136
2259
 
2137
2260
  bool has_offset = (info.Length() >= 2 && info[1].IsNumber());
2138
2261
  bool has_len = (info.Length() >= 4u + has_offset && info[3 + has_offset].IsNumber());
@@ -2142,7 +2265,7 @@ static Napi::Value EncodeValue(const Napi::CallbackInfo &info)
2142
2265
  return env.Null();
2143
2266
  }
2144
2267
 
2145
- const TypeInfo *type = ResolveType(info[1u + has_offset]);
2268
+ const TypeInfo *type = ResolveType(instance, info[1u + has_offset]);
2146
2269
  if (!type) [[unlikely]]
2147
2270
  return env.Null();
2148
2271
 
@@ -2150,38 +2273,71 @@ static Napi::Value EncodeValue(const Napi::CallbackInfo &info)
2150
2273
  int64_t offset = has_offset ? info[1].As<Napi::Number>().Int64Value() : 0;
2151
2274
  Napi::Value value = info[2 + has_offset];
2152
2275
 
2153
- if (has_len) {
2154
- Size len = info[3 + has_offset].As<Napi::Number>();
2276
+ void *dest = nullptr;
2277
+ Size len = 0;
2278
+
2279
+ if (!TryPointer(env, ref, &dest, &len)) {
2280
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value for reference, expected pointer", GetValueType(instance, ref));
2281
+ return env.Null();
2282
+ }
2155
2283
 
2156
- if (!Encode(ref, (Size)offset, value, type, &len))
2284
+ if (len >= 0) {
2285
+ if (offset < 0) [[unlikely]] {
2286
+ ThrowError<Napi::Error>(env, "Offset must be >= 0");
2157
2287
  return env.Null();
2158
- } else {
2159
- if (!Encode(ref, (Size)offset, value, type))
2288
+ }
2289
+ if (len - offset < type->size) [[unlikely]] {
2290
+ ThrowError<Napi::Error>(env, "Expected buffer with size superior or equal to type %1 (%2 bytes)",
2291
+ type->name, type->size + offset);
2160
2292
  return env.Null();
2293
+ }
2294
+ }
2295
+
2296
+ if (!dest) [[unlikely]] {
2297
+ ThrowError<Napi::Error>(env, "Cannot encode data in NULL pointer");
2298
+ return env.Null();
2161
2299
  }
2162
2300
 
2301
+ dest = (void *)((uint8_t *)dest + offset);
2302
+
2303
+ if (has_len) {
2304
+ Size len = info[3 + has_offset].As<Napi::Number>();
2305
+
2306
+ if (type->primitive != PrimitiveKind::String &&
2307
+ type->primitive != PrimitiveKind::String16 &&
2308
+ type->primitive != PrimitiveKind::String32 &&
2309
+ type->primitive != PrimitiveKind::Prototype) {
2310
+ if (len < 0) [[unlikely]] {
2311
+ ThrowError<Napi::TypeError>(env, "Automatic (negative) length is only supported when decoding");
2312
+ return env.Null();
2313
+ }
2314
+
2315
+ type = MakeArrayType(instance, type, len);
2316
+ }
2317
+ }
2318
+
2319
+ if (!Encode(instance, (uint8_t *)dest, value, type))
2320
+ return env.Null();
2321
+
2163
2322
  return env.Undefined();
2164
2323
  }
2165
2324
 
2166
2325
  static Napi::Value CreateView(const Napi::CallbackInfo &info)
2167
2326
  {
2168
2327
  Napi::Env env = info.Env();
2328
+ InstanceData *instance = (InstanceData *)info.Data();
2169
2329
 
2170
2330
  if (info.Length() < 1) {
2171
2331
  ThrowError<Napi::TypeError>(env, "Expected 2 arguments, got %1", info.Length());
2172
2332
  return env.Null();
2173
2333
  }
2174
2334
  if (!info[1].IsNumber()) {
2175
- InstanceData *instance = env.GetInstanceData<InstanceData>();
2176
-
2177
2335
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for length, expected integer", GetValueType(instance, info[1]));
2178
2336
  return env.Null();
2179
2337
  }
2180
2338
 
2181
2339
  void *ptr = nullptr;
2182
2340
  if (!TryPointer(env, info[0], &ptr)) {
2183
- InstanceData *instance = Napi::Env(env).GetInstanceData<InstanceData>();
2184
-
2185
2341
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for ptr, expected pointer", GetValueType(instance, info[0]));
2186
2342
  return env.Null();
2187
2343
  }
@@ -2210,7 +2366,7 @@ static Napi::Value CreateView(const Napi::CallbackInfo &info)
2210
2366
  static Napi::Value ResetKoffi(const Napi::CallbackInfo &info)
2211
2367
  {
2212
2368
  Napi::Env env = info.Env();
2213
- InstanceData *instance = env.GetInstanceData<InstanceData>();
2369
+ InstanceData *instance = (InstanceData *)info.Data();
2214
2370
 
2215
2371
  if (instance->broker) {
2216
2372
  napi_release_threadsafe_function(instance->broker, napi_tsfn_abort);
@@ -2292,13 +2448,13 @@ InstanceMemory::~InstanceMemory()
2292
2448
  #endif
2293
2449
  }
2294
2450
 
2295
- static void RegisterPrimitiveType(Napi::Env env, Napi::Object map, std::initializer_list<const char *> names,
2451
+ static void RegisterPrimitiveType(InstanceData *instance, Napi::Object map, std::initializer_list<const char *> names,
2296
2452
  PrimitiveKind primitive, int32_t size, int16_t align, const char *ref = nullptr)
2297
2453
  {
2298
2454
  K_ASSERT(names.size() > 0);
2299
2455
  K_ASSERT(align <= size);
2300
2456
 
2301
- InstanceData *instance = env.GetInstanceData<InstanceData>();
2457
+ Napi::Env env = instance->env;
2302
2458
 
2303
2459
  TypeInfo *type = instance->types.AppendDefault();
2304
2460
 
@@ -2323,7 +2479,7 @@ static void RegisterPrimitiveType(Napi::Env env, Napi::Object map, std::initiali
2323
2479
  K_ASSERT(type->ref.type);
2324
2480
  }
2325
2481
 
2326
- Napi::Value wrapper = WrapType(env, type);
2482
+ napi_value wrapper = WrapType(env, type);
2327
2483
 
2328
2484
  for (const char *name: names) {
2329
2485
  bool inserted;
@@ -2405,19 +2561,19 @@ static bool CanDeleteReferenceInFinalizer(const napi_node_version &node, uint32_
2405
2561
  return false;
2406
2562
  }
2407
2563
 
2408
- static napi_value CreateFunction(napi_env env, napi_callback native, const char *name = nullptr)
2564
+ static napi_value CreateFunction(InstanceData *instance, napi_callback native, const char *name = nullptr)
2409
2565
  {
2410
- napi_value func;
2566
+ Napi::Env env = instance->env;
2411
2567
 
2412
- napi_status status = napi_create_function(env, name, NAPI_AUTO_LENGTH, native, nullptr, &func);
2413
- K_ASSERT(status == napi_ok);
2568
+ napi_value func;
2569
+ NAPI_OK(napi_create_function(env, name, NAPI_AUTO_LENGTH, native, instance, &func));
2414
2570
 
2415
2571
  return func;
2416
2572
  }
2417
2573
 
2418
2574
  static Napi::Object InitModule(Napi::Env env, Napi::Object exports)
2419
2575
  {
2420
- // Load recent N-API functions (version >= 9) functions dynamically
2576
+ // Load recent Node-API functions (version >= 9) functions dynamically
2421
2577
  {
2422
2578
  static std::once_flag flag;
2423
2579
 
@@ -2464,6 +2620,8 @@ static Napi::Object InitModule(Napi::Env env, Napi::Object exports)
2464
2620
  node_api_post_finalizer = SYMBOL(node_api_post_finalizer);
2465
2621
  }
2466
2622
 
2623
+ node_api_create_object_with_properties = SYMBOL(node_api_create_object_with_properties);
2624
+
2467
2625
  #undef SYMBOL
2468
2626
  });
2469
2627
  }
@@ -2480,74 +2638,77 @@ static Napi::Object InitModule(Napi::Env env, Napi::Object exports)
2480
2638
  Napi::Number::New(env, 0.0);
2481
2639
  #endif
2482
2640
 
2483
- exports.Set("config", Napi::Function::New(env, GetSetConfig, "config"));
2484
- exports.Set("stats", Napi::Function::New(env, GetStats, "stats"));
2485
-
2486
- exports.Set("struct", Napi::Function::New(env, CreatePaddedStructType, "struct"));
2487
- exports.Set("pack", Napi::Function::New(env, CreatePackedStructType, "pack"));
2488
- exports.Set("union", Napi::Function::New(env, CreateUnionType, "union"));
2489
- exports.Set("Union", Napi::Function::New(env, InstantiateUnion, "Union"));
2490
- exports.Set("opaque", Napi::Function::New(env, CreateOpaqueType, "opaque"));
2491
- exports.Set("pointer", Napi::Function::New(env, CreatePointerType, "pointer"));
2492
- exports.Set("array", Napi::Function::New(env, CreateArrayType, "array"));
2493
- exports.Set("proto", Napi::Function::New(env, CreateFunctionType, "proto"));
2494
- exports.Set("alias", Napi::Function::New(env, CreateTypeAlias, "alias"));
2495
- exports.Set("enumeration", Napi::Function::New(env, CreateEnumType, "enumeration"));
2496
-
2497
- exports.Set("type", Napi::Function::New(env, GetResolvedType, "type"));
2641
+ exports.Set("config", Napi::Function::New(env, GetSetConfig, "config", instance));
2642
+ exports.Set("stats", Napi::Function::New(env, GetStats, "stats", instance));
2643
+
2644
+ exports.Set("struct", Napi::Function::New(env, CreatePaddedStructType, "struct", instance));
2645
+ exports.Set("pack", Napi::Function::New(env, CreatePackedStructType, "pack", instance));
2646
+ exports.Set("union", Napi::Function::New(env, CreateUnionType, "union", instance));
2647
+ exports.Set("Union", Napi::Function::New(env, InstantiateUnion, "Union", instance));
2648
+ exports.Set("opaque", Napi::Function::New(env, CreateOpaqueType, "opaque", instance));
2649
+ exports.Set("pointer", Napi::Function::New(env, CreatePointerType, "pointer", instance));
2650
+ exports.Set("array", Napi::Function::New(env, CreateArrayType, "array", instance));
2651
+ exports.Set("proto", Napi::Function::New(env, CreateFunctionType, "proto", instance));
2652
+ exports.Set("alias", Napi::Function::New(env, CreateTypeAlias, "alias", instance));
2653
+ exports.Set("enumeration", Napi::Function::New(env, CreateEnumType, "enumeration", instance));
2654
+
2655
+ exports.Set("type", Napi::Function::New(env, GetResolvedType, "type", instance));
2656
+ #if defined(EXTERNAL_TYPES)
2657
+ exports.Set("introspect", Napi::Function::New(env, GetTypeDefinition, "introspect", instance));
2658
+ #endif
2498
2659
 
2499
- exports.Set("load", Napi::Function::New(env, LoadSharedLibrary, "load"));
2660
+ exports.Set("load", Napi::Function::New(env, LoadSharedLibrary, "load", instance));
2500
2661
 
2501
- exports.Set("in", Napi::Function::New(env, MarkIn, "in"));
2502
- exports.Set("out", Napi::Function::New(env, MarkOut, "out"));
2503
- exports.Set("inout", Napi::Function::New(env, MarkInOut, "inout"));
2662
+ exports.Set("in", Napi::Function::New(env, MarkIn, "in", instance));
2663
+ exports.Set("out", Napi::Function::New(env, MarkOut, "out", instance));
2664
+ exports.Set("inout", Napi::Function::New(env, MarkInOut, "inout", instance));
2504
2665
 
2505
- exports.Set("disposable", Napi::Function::New(env, CreateDisposableType, "disposable"));
2506
- exports.Set("alloc", Napi::Function::New(env, CallAlloc, "alloc"));
2507
- exports.Set("free", Napi::Function::New(env, CallFree, "free"));
2666
+ exports.Set("disposable", Napi::Function::New(env, CreateDisposableType, "disposable", instance));
2667
+ exports.Set("alloc", Napi::Function::New(env, CallAlloc, "alloc", instance));
2668
+ exports.Set("free", Napi::Function::New(env, CallFree, "free", instance));
2508
2669
 
2509
- exports.Set("register", Napi::Function::New(env, RegisterCallback, "register"));
2510
- exports.Set("unregister", Napi::Function::New(env, UnregisterCallback, "unregister"));
2670
+ exports.Set("register", Napi::Function::New(env, RegisterCallback, "register", instance));
2671
+ exports.Set("unregister", Napi::Function::New(env, UnregisterCallback, "unregister", instance));
2511
2672
 
2512
- exports.Set("as", Napi::Function::New(env, CastValue, "as"));
2513
- exports.Set("address", Napi::Function::New(env, GetPointerAddress, "address"));
2514
- exports.Set("call", Napi::Function::New(env, CallPointerSync, "call"));
2515
- exports.Set("encode", Napi::Function::New(env, EncodeValue, "encode"));
2516
- exports.Set("view", Napi::Function::New(env, CreateView, "view"));
2673
+ exports.Set("as", Napi::Function::New(env, CastValue, "as", instance));
2674
+ exports.Set("address", Napi::Function::New(env, GetPointerAddress, "address", instance));
2675
+ exports.Set("call", Napi::Function::New(env, CallPointerSync, "call", instance));
2676
+ exports.Set("encode", Napi::Function::New(env, EncodeValue, "encode", instance));
2677
+ exports.Set("view", Napi::Function::New(env, CreateView, "view", instance));
2517
2678
 
2518
2679
  {
2519
- Napi::Function decode = Napi::Function::New(env, DecodeValue, "decode");
2520
-
2521
- decode.Set("char", CreateFunction(env, [](napi_env env, napi_callback_info info) { return DecodeInteger<char>(env, info); }, "char"));
2522
- decode.Set("uchar", CreateFunction(env, [](napi_env env, napi_callback_info info) { return DecodeInteger<unsigned char>(env, info); }, "uchar"));
2523
- decode.Set("short", CreateFunction(env, [](napi_env env, napi_callback_info info) { return DecodeInteger<short>(env, info); }, "short"));
2524
- decode.Set("ushort", CreateFunction(env, [](napi_env env, napi_callback_info info) { return DecodeInteger<unsigned short>(env, info); }, "ushort"));
2525
- decode.Set("int", CreateFunction(env, [](napi_env env, napi_callback_info info) { return DecodeInteger<int>(env, info); }, "int"));
2526
- decode.Set("uint", CreateFunction(env, [](napi_env env, napi_callback_info info) { return DecodeInteger<unsigned int>(env, info); }, "uint"));
2527
- decode.Set("long", CreateFunction(env, [](napi_env env, napi_callback_info info) { return DecodeInteger<long>(env, info); }, "long"));
2528
- decode.Set("ulong", CreateFunction(env, [](napi_env env, napi_callback_info info) { return DecodeInteger<unsigned long>(env, info); }, "ulong"));
2529
- decode.Set("longlong", CreateFunction(env, [](napi_env env, napi_callback_info info) { return DecodeInteger<long long>(env, info); }, "longlong"));
2530
- decode.Set("ulonglong", CreateFunction(env, [](napi_env env, napi_callback_info info) { return DecodeInteger<unsigned long long>(env, info); }, "ulonglong"));
2531
- decode.Set("int8", CreateFunction(env, [](napi_env env, napi_callback_info info) { return DecodeInteger<int8_t>(env, info); }, "int8"));
2532
- decode.Set("uint8", CreateFunction(env, [](napi_env env, napi_callback_info info) { return DecodeInteger<uint8_t>(env, info); }, "uint8"));
2533
- decode.Set("int16", CreateFunction(env, [](napi_env env, napi_callback_info info) { return DecodeInteger<int16_t>(env, info); }, "int16"));
2534
- decode.Set("uint16", CreateFunction(env, [](napi_env env, napi_callback_info info) { return DecodeInteger<uint16_t>(env, info); }, "uint16"));
2535
- decode.Set("int32", CreateFunction(env, [](napi_env env, napi_callback_info info) { return DecodeInteger<int32_t>(env, info); }, "int32"));
2536
- decode.Set("uint32", CreateFunction(env, [](napi_env env, napi_callback_info info) { return DecodeInteger<uint32_t>(env, info); }, "uint32"));
2537
- decode.Set("int64", CreateFunction(env, [](napi_env env, napi_callback_info info) { return DecodeInteger<int64_t>(env, info); }, "int64"));
2538
- decode.Set("uint64", CreateFunction(env, [](napi_env env, napi_callback_info info) { return DecodeInteger<uint64_t>(env, info); }, "uint64"));
2539
- decode.Set("float", CreateFunction(env, DecodeFloat, "float"));
2540
- decode.Set("double", CreateFunction(env, DecodeDouble, "double"));
2541
- decode.Set("string", CreateFunction(env, DecodeString, "string"));
2542
- decode.Set("string16", CreateFunction(env, DecodeString16, "string16"));
2543
- decode.Set("string32", CreateFunction(env, DecodeString32, "string32"));
2680
+ Napi::Function decode = Napi::Function::New(env, DecodeValue, "decode", instance);
2681
+
2682
+ decode.Set("char", CreateFunction(instance, [](napi_env env, napi_callback_info info) { return DecodeInteger<char>(env, info); }, "char"));
2683
+ decode.Set("uchar", CreateFunction(instance, [](napi_env env, napi_callback_info info) { return DecodeInteger<unsigned char>(env, info); }, "uchar"));
2684
+ decode.Set("short", CreateFunction(instance, [](napi_env env, napi_callback_info info) { return DecodeInteger<short>(env, info); }, "short"));
2685
+ decode.Set("ushort", CreateFunction(instance, [](napi_env env, napi_callback_info info) { return DecodeInteger<unsigned short>(env, info); }, "ushort"));
2686
+ decode.Set("int", CreateFunction(instance, [](napi_env env, napi_callback_info info) { return DecodeInteger<int>(env, info); }, "int"));
2687
+ decode.Set("uint", CreateFunction(instance, [](napi_env env, napi_callback_info info) { return DecodeInteger<unsigned int>(env, info); }, "uint"));
2688
+ decode.Set("long", CreateFunction(instance, [](napi_env env, napi_callback_info info) { return DecodeInteger<long>(env, info); }, "long"));
2689
+ decode.Set("ulong", CreateFunction(instance, [](napi_env env, napi_callback_info info) { return DecodeInteger<unsigned long>(env, info); }, "ulong"));
2690
+ decode.Set("longlong", CreateFunction(instance, [](napi_env env, napi_callback_info info) { return DecodeInteger<long long>(env, info); }, "longlong"));
2691
+ decode.Set("ulonglong", CreateFunction(instance, [](napi_env env, napi_callback_info info) { return DecodeInteger<unsigned long long>(env, info); }, "ulonglong"));
2692
+ decode.Set("int8", CreateFunction(instance, [](napi_env env, napi_callback_info info) { return DecodeInteger<int8_t>(env, info); }, "int8"));
2693
+ decode.Set("uint8", CreateFunction(instance, [](napi_env env, napi_callback_info info) { return DecodeInteger<uint8_t>(env, info); }, "uint8"));
2694
+ decode.Set("int16", CreateFunction(instance, [](napi_env env, napi_callback_info info) { return DecodeInteger<int16_t>(env, info); }, "int16"));
2695
+ decode.Set("uint16", CreateFunction(instance, [](napi_env env, napi_callback_info info) { return DecodeInteger<uint16_t>(env, info); }, "uint16"));
2696
+ decode.Set("int32", CreateFunction(instance, [](napi_env env, napi_callback_info info) { return DecodeInteger<int32_t>(env, info); }, "int32"));
2697
+ decode.Set("uint32", CreateFunction(instance, [](napi_env env, napi_callback_info info) { return DecodeInteger<uint32_t>(env, info); }, "uint32"));
2698
+ decode.Set("int64", CreateFunction(instance, [](napi_env env, napi_callback_info info) { return DecodeInteger<int64_t>(env, info); }, "int64"));
2699
+ decode.Set("uint64", CreateFunction(instance, [](napi_env env, napi_callback_info info) { return DecodeInteger<uint64_t>(env, info); }, "uint64"));
2700
+ decode.Set("float", CreateFunction(instance, DecodeFloat, "float"));
2701
+ decode.Set("double", CreateFunction(instance, DecodeDouble, "double"));
2702
+ decode.Set("string", CreateFunction(instance, DecodeString, "string"));
2703
+ decode.Set("string16", CreateFunction(instance, DecodeString16, "string16"));
2704
+ decode.Set("string32", CreateFunction(instance, DecodeString32, "string32"));
2544
2705
 
2545
2706
  exports.Set("decode", decode);
2546
2707
  }
2547
2708
 
2548
- exports.Set("reset", Napi::Function::New(env, ResetKoffi, "reset"));
2709
+ exports.Set("reset", Napi::Function::New(env, ResetKoffi, "reset", instance));
2549
2710
 
2550
- exports.Set("errno", Napi::Function::New(env, GetOrSetErrNo, "errno"));
2711
+ exports.Set("errno", Napi::Function::New(env, GetOrSetErrNo, "errno", instance));
2551
2712
 
2552
2713
  // Export useful OS info
2553
2714
  {
@@ -2573,13 +2734,18 @@ static Napi::Object InitModule(Napi::Env env, Napi::Object exports)
2573
2734
 
2574
2735
  // Init object classes and symbols
2575
2736
  {
2576
- instance->construct_lib = Napi::Persistent(LibraryHandle::InitClass(env));
2577
- instance->construct_type = Napi::Persistent(TypeObject::InitClass(env));
2578
- instance->construct_poll = Napi::Persistent(PollHandle::InitClass(env));
2737
+ instance->object_constructor = Napi::Persistent(env.RunScript("Object.prototype").As<Napi::Object>());
2738
+ instance->construct_lib = Napi::Persistent(LibraryHandle::InitClass(instance));
2739
+ #if !defined(EXTERNAL_TYPES)
2740
+ instance->construct_type = Napi::Persistent(TypeObject::InitClass(instance));
2741
+ #endif
2742
+ instance->construct_poll = Napi::Persistent(PollHandle::InitClass(instance));
2579
2743
  instance->active_symbol = Napi::Persistent(Napi::Symbol::New(env, "active"));
2580
2744
 
2581
2745
  exports.Set("LibraryHandle", instance->construct_lib.Value());
2746
+ #if !defined(EXTERNAL_TYPES)
2582
2747
  exports.Set("TypeObject", instance->construct_type.Value());
2748
+ #endif
2583
2749
  }
2584
2750
 
2585
2751
  // Init base types
@@ -2587,57 +2753,57 @@ static Napi::Object InitModule(Napi::Env env, Napi::Object exports)
2587
2753
  Napi::Object types = Napi::Object::New(env);
2588
2754
  exports.Set("types", types);
2589
2755
 
2590
- RegisterPrimitiveType(env, types, {"void"}, PrimitiveKind::Void, 0, 0);
2591
- RegisterPrimitiveType(env, types, {"bool"}, PrimitiveKind::Bool, K_SIZE(bool), alignof(bool));
2592
- RegisterPrimitiveType(env, types, {"int8_t", "int8"}, PrimitiveKind::Int8, 1, 1);
2593
- RegisterPrimitiveType(env, types, {"uint8_t", "uint8"}, PrimitiveKind::UInt8, 1, 1);
2594
- RegisterPrimitiveType(env, types, {"char"}, PrimitiveKind::Int8, 1, 1);
2595
- RegisterPrimitiveType(env, types, {"unsigned char", "uchar"}, PrimitiveKind::UInt8, 1, 1);
2596
- RegisterPrimitiveType(env, types, {"char16_t", "char16"}, PrimitiveKind::Int16, 2, 2);
2597
- RegisterPrimitiveType(env, types, {"char32_t", "char32"}, PrimitiveKind::Int32, 4, 4);
2756
+ RegisterPrimitiveType(instance, types, {"void"}, PrimitiveKind::Void, 0, 0);
2757
+ RegisterPrimitiveType(instance, types, {"bool"}, PrimitiveKind::Bool, K_SIZE(bool), alignof(bool));
2758
+ RegisterPrimitiveType(instance, types, {"int8_t", "int8"}, PrimitiveKind::Int8, 1, 1);
2759
+ RegisterPrimitiveType(instance, types, {"uint8_t", "uint8"}, PrimitiveKind::UInt8, 1, 1);
2760
+ RegisterPrimitiveType(instance, types, {"char"}, PrimitiveKind::Int8, 1, 1);
2761
+ RegisterPrimitiveType(instance, types, {"unsigned char", "uchar"}, PrimitiveKind::UInt8, 1, 1);
2762
+ RegisterPrimitiveType(instance, types, {"char16_t", "char16"}, PrimitiveKind::Int16, 2, 2);
2763
+ RegisterPrimitiveType(instance, types, {"char32_t", "char32"}, PrimitiveKind::Int32, 4, 4);
2598
2764
  if (K_SIZE(wchar_t) == 2) {
2599
- RegisterPrimitiveType(env, types, {"wchar_t", "wchar"}, PrimitiveKind::Int16, 2, 2);
2765
+ RegisterPrimitiveType(instance, types, {"wchar_t", "wchar"}, PrimitiveKind::Int16, 2, 2);
2600
2766
  } else if (K_SIZE(wchar_t) == 4) {
2601
- RegisterPrimitiveType(env, types, {"wchar_t", "wchar"}, PrimitiveKind::Int32, 4, 4);
2602
- }
2603
- RegisterPrimitiveType(env, types, {"int16_t", "int16"}, PrimitiveKind::Int16, 2, 2);
2604
- RegisterPrimitiveType(env, types, {"int16_le_t", "int16_le"}, GetLittleEndianPrimitive(PrimitiveKind::Int16), 2, 2);
2605
- RegisterPrimitiveType(env, types, {"int16_be_t", "int16_be"}, GetBigEndianPrimitive(PrimitiveKind::Int16), 2, 2);
2606
- RegisterPrimitiveType(env, types, {"uint16_t", "uint16"}, PrimitiveKind::UInt16, 2, 2);
2607
- RegisterPrimitiveType(env, types, {"uint16_le_t", "uint16_le"}, GetLittleEndianPrimitive(PrimitiveKind::UInt16), 2, 2);
2608
- RegisterPrimitiveType(env, types, {"uint16_be_t", "uint16_be"}, GetBigEndianPrimitive(PrimitiveKind::UInt16), 2, 2);
2609
- RegisterPrimitiveType(env, types, {"short"}, PrimitiveKind::Int16, 2, 2);
2610
- RegisterPrimitiveType(env, types, {"unsigned short", "ushort"}, PrimitiveKind::UInt16, 2, 2);
2611
- RegisterPrimitiveType(env, types, {"int32_t", "int32"}, PrimitiveKind::Int32, 4, 4);
2612
- RegisterPrimitiveType(env, types, {"int32_le_t", "int32_le"}, GetLittleEndianPrimitive(PrimitiveKind::Int32), 4, 4);
2613
- RegisterPrimitiveType(env, types, {"int32_be_t", "int32_be"}, GetBigEndianPrimitive(PrimitiveKind::Int32), 4, 4);
2614
- RegisterPrimitiveType(env, types, {"uint32_t", "uint32"}, PrimitiveKind::UInt32, 4, 4);
2615
- RegisterPrimitiveType(env, types, {"uint32_le_t", "uint32_le"}, GetLittleEndianPrimitive(PrimitiveKind::UInt32), 4, 4);
2616
- RegisterPrimitiveType(env, types, {"uint32_be_t", "uint32_be"}, GetBigEndianPrimitive(PrimitiveKind::UInt32), 4, 4);
2617
- RegisterPrimitiveType(env, types, {"int"}, PrimitiveKind::Int32, 4, 4);
2618
- RegisterPrimitiveType(env, types, {"unsigned int", "uint"}, PrimitiveKind::UInt32, 4, 4);
2619
- RegisterPrimitiveType(env, types, {"int64_t", "int64"}, PrimitiveKind::Int64, 8, alignof(int64_t));
2620
- RegisterPrimitiveType(env, types, {"int64_le_t", "int64_le"}, GetLittleEndianPrimitive(PrimitiveKind::Int64), 8, alignof(int64_t));
2621
- RegisterPrimitiveType(env, types, {"int64_be_t", "int64_be"}, GetBigEndianPrimitive(PrimitiveKind::Int64), 8, alignof(int64_t));
2622
- RegisterPrimitiveType(env, types, {"uint64_t", "uint64"}, PrimitiveKind::UInt64, 8, alignof(int64_t));
2623
- RegisterPrimitiveType(env, types, {"uint64_le_t", "uint64_le"}, GetLittleEndianPrimitive(PrimitiveKind::UInt64), 8, alignof(int64_t));
2624
- RegisterPrimitiveType(env, types, {"uint64_be_t", "uint64_be"}, GetBigEndianPrimitive(PrimitiveKind::UInt64), 8, alignof(int64_t));
2625
- RegisterPrimitiveType(env, types, {"intptr_t", "intptr"}, GetSignPrimitive(K_SIZE(intptr_t), true), K_SIZE(intptr_t), alignof(intptr_t));
2626
- RegisterPrimitiveType(env, types, {"uintptr_t", "uintptr"}, GetSignPrimitive(K_SIZE(intptr_t), false), K_SIZE(intptr_t), alignof(intptr_t));
2627
- RegisterPrimitiveType(env, types, {"size_t"}, GetSignPrimitive(K_SIZE(size_t), false), K_SIZE(size_t), alignof(size_t));
2628
- RegisterPrimitiveType(env, types, {"long"}, GetSignPrimitive(K_SIZE(long), true), K_SIZE(long), alignof(long));
2629
- RegisterPrimitiveType(env, types, {"unsigned long", "ulong"}, GetSignPrimitive(K_SIZE(long), false), K_SIZE(long), alignof(long));
2630
- RegisterPrimitiveType(env, types, {"long long", "longlong"}, PrimitiveKind::Int64, K_SIZE(int64_t), alignof(int64_t));
2631
- RegisterPrimitiveType(env, types, {"unsigned long long", "ulonglong"}, PrimitiveKind::UInt64, K_SIZE(uint64_t), alignof(uint64_t));
2632
- RegisterPrimitiveType(env, types, {"float", "float32"}, PrimitiveKind::Float32, 4, alignof(float));
2633
- RegisterPrimitiveType(env, types, {"double", "float64"}, PrimitiveKind::Float64, 8, alignof(double));
2634
- RegisterPrimitiveType(env, types, {"char *", "str", "string"}, PrimitiveKind::String, K_SIZE(void *), alignof(void *), "char");
2635
- RegisterPrimitiveType(env, types, {"char16_t *", "char16 *", "str16", "string16"}, PrimitiveKind::String16, K_SIZE(void *), alignof(void *), "char16_t");
2636
- RegisterPrimitiveType(env, types, {"char32_t *", "char32 *", "str32", "string32"}, PrimitiveKind::String32, K_SIZE(void *), alignof(void *), "char32_t");
2767
+ RegisterPrimitiveType(instance, types, {"wchar_t", "wchar"}, PrimitiveKind::Int32, 4, 4);
2768
+ }
2769
+ RegisterPrimitiveType(instance, types, {"int16_t", "int16"}, PrimitiveKind::Int16, 2, 2);
2770
+ RegisterPrimitiveType(instance, types, {"int16_le_t", "int16_le"}, GetLittleEndianPrimitive(PrimitiveKind::Int16), 2, 2);
2771
+ RegisterPrimitiveType(instance, types, {"int16_be_t", "int16_be"}, GetBigEndianPrimitive(PrimitiveKind::Int16), 2, 2);
2772
+ RegisterPrimitiveType(instance, types, {"uint16_t", "uint16"}, PrimitiveKind::UInt16, 2, 2);
2773
+ RegisterPrimitiveType(instance, types, {"uint16_le_t", "uint16_le"}, GetLittleEndianPrimitive(PrimitiveKind::UInt16), 2, 2);
2774
+ RegisterPrimitiveType(instance, types, {"uint16_be_t", "uint16_be"}, GetBigEndianPrimitive(PrimitiveKind::UInt16), 2, 2);
2775
+ RegisterPrimitiveType(instance, types, {"short"}, PrimitiveKind::Int16, 2, 2);
2776
+ RegisterPrimitiveType(instance, types, {"unsigned short", "ushort"}, PrimitiveKind::UInt16, 2, 2);
2777
+ RegisterPrimitiveType(instance, types, {"int32_t", "int32"}, PrimitiveKind::Int32, 4, 4);
2778
+ RegisterPrimitiveType(instance, types, {"int32_le_t", "int32_le"}, GetLittleEndianPrimitive(PrimitiveKind::Int32), 4, 4);
2779
+ RegisterPrimitiveType(instance, types, {"int32_be_t", "int32_be"}, GetBigEndianPrimitive(PrimitiveKind::Int32), 4, 4);
2780
+ RegisterPrimitiveType(instance, types, {"uint32_t", "uint32"}, PrimitiveKind::UInt32, 4, 4);
2781
+ RegisterPrimitiveType(instance, types, {"uint32_le_t", "uint32_le"}, GetLittleEndianPrimitive(PrimitiveKind::UInt32), 4, 4);
2782
+ RegisterPrimitiveType(instance, types, {"uint32_be_t", "uint32_be"}, GetBigEndianPrimitive(PrimitiveKind::UInt32), 4, 4);
2783
+ RegisterPrimitiveType(instance, types, {"int"}, PrimitiveKind::Int32, 4, 4);
2784
+ RegisterPrimitiveType(instance, types, {"unsigned int", "uint"}, PrimitiveKind::UInt32, 4, 4);
2785
+ RegisterPrimitiveType(instance, types, {"int64_t", "int64"}, PrimitiveKind::Int64, 8, alignof(int64_t));
2786
+ RegisterPrimitiveType(instance, types, {"int64_le_t", "int64_le"}, GetLittleEndianPrimitive(PrimitiveKind::Int64), 8, alignof(int64_t));
2787
+ RegisterPrimitiveType(instance, types, {"int64_be_t", "int64_be"}, GetBigEndianPrimitive(PrimitiveKind::Int64), 8, alignof(int64_t));
2788
+ RegisterPrimitiveType(instance, types, {"uint64_t", "uint64"}, PrimitiveKind::UInt64, 8, alignof(int64_t));
2789
+ RegisterPrimitiveType(instance, types, {"uint64_le_t", "uint64_le"}, GetLittleEndianPrimitive(PrimitiveKind::UInt64), 8, alignof(int64_t));
2790
+ RegisterPrimitiveType(instance, types, {"uint64_be_t", "uint64_be"}, GetBigEndianPrimitive(PrimitiveKind::UInt64), 8, alignof(int64_t));
2791
+ RegisterPrimitiveType(instance, types, {"intptr_t", "intptr"}, GetSignPrimitive(K_SIZE(intptr_t), true), K_SIZE(intptr_t), alignof(intptr_t));
2792
+ RegisterPrimitiveType(instance, types, {"uintptr_t", "uintptr"}, GetSignPrimitive(K_SIZE(intptr_t), false), K_SIZE(intptr_t), alignof(intptr_t));
2793
+ RegisterPrimitiveType(instance, types, {"size_t"}, GetSignPrimitive(K_SIZE(size_t), false), K_SIZE(size_t), alignof(size_t));
2794
+ RegisterPrimitiveType(instance, types, {"long"}, GetSignPrimitive(K_SIZE(long), true), K_SIZE(long), alignof(long));
2795
+ RegisterPrimitiveType(instance, types, {"unsigned long", "ulong"}, GetSignPrimitive(K_SIZE(long), false), K_SIZE(long), alignof(long));
2796
+ RegisterPrimitiveType(instance, types, {"long long", "longlong"}, PrimitiveKind::Int64, K_SIZE(int64_t), alignof(int64_t));
2797
+ RegisterPrimitiveType(instance, types, {"unsigned long long", "ulonglong"}, PrimitiveKind::UInt64, K_SIZE(uint64_t), alignof(uint64_t));
2798
+ RegisterPrimitiveType(instance, types, {"float", "float32"}, PrimitiveKind::Float32, 4, alignof(float));
2799
+ RegisterPrimitiveType(instance, types, {"double", "float64"}, PrimitiveKind::Float64, 8, alignof(double));
2800
+ RegisterPrimitiveType(instance, types, {"char *", "str", "string"}, PrimitiveKind::String, K_SIZE(void *), alignof(void *), "char");
2801
+ RegisterPrimitiveType(instance, types, {"char16_t *", "char16 *", "str16", "string16"}, PrimitiveKind::String16, K_SIZE(void *), alignof(void *), "char16_t");
2802
+ RegisterPrimitiveType(instance, types, {"char32_t *", "char32 *", "str32", "string32"}, PrimitiveKind::String32, K_SIZE(void *), alignof(void *), "char32_t");
2637
2803
  if (K_SIZE(wchar_t) == 2) {
2638
- RegisterPrimitiveType(env, types, {"wchar_t *", "wchar *"}, PrimitiveKind::String16, K_SIZE(void *), alignof(void *), "wchar_t");
2804
+ RegisterPrimitiveType(instance, types, {"wchar_t *", "wchar *"}, PrimitiveKind::String16, K_SIZE(void *), alignof(void *), "wchar_t");
2639
2805
  } else if (K_SIZE(wchar_t) == 4) {
2640
- RegisterPrimitiveType(env, types, {"wchar_t *", "wchar *"}, PrimitiveKind::String32, K_SIZE(void *), alignof(void *), "wchar_t");
2806
+ RegisterPrimitiveType(instance, types, {"wchar_t *", "wchar *"}, PrimitiveKind::String32, K_SIZE(void *), alignof(void *), "wchar_t");
2641
2807
  }
2642
2808
 
2643
2809
  instance->void_type = instance->types_map.FindValue("void", nullptr);
@@ -2658,7 +2824,7 @@ static Napi::Object InitModule(Napi::Env env, Napi::Object exports)
2658
2824
 
2659
2825
  node.Set("env", WrapPointer(env, instance->void_type, (napi_env)env));
2660
2826
 
2661
- node.Set("poll", Napi::Function::New(env, &Poll, "poll"));
2827
+ node.Set("poll", Napi::Function::New(env, &Poll, "poll", instance));
2662
2828
  node.Set("PollHandle", instance->construct_poll.Value());
2663
2829
  }
2664
2830