@@ -687,14 +687,56 @@ inline bool Object::InstanceOf(const Function& constructor) const {
687
687
// //////////////////////////////////////////////////////////////////////////////
688
688
689
689
template <typename T>
690
- inline External<T> External<T>::New(
691
- napi_env env, T* data, napi_finalize finalizeCallback, void * finalizeHint) {
690
+ inline External<T> External<T>::New(napi_env env, T* data) {
692
691
napi_value value;
693
- napi_status status = napi_create_external (env, data, finalizeCallback, finalizeHint , &value);
692
+ napi_status status = napi_create_external (env, data, nullptr , nullptr , &value);
694
693
if (status != napi_ok) throw Error::New (env);
695
694
return External (env, value);
696
695
}
697
696
697
+ template <typename T>
698
+ template <typename Finalizer>
699
+ inline External<T> External<T>::New(napi_env env,
700
+ T* data,
701
+ Finalizer finalizeCallback) {
702
+ napi_value value;
703
+ details::FinalizeData<T, Finalizer>* finalizeData =
704
+ new details::FinalizeData<T, Finalizer>({ finalizeCallback, nullptr });
705
+ napi_status status = napi_create_external (
706
+ env,
707
+ data,
708
+ details::FinalizeData<T, Finalizer>::Wrapper,
709
+ finalizeData,
710
+ &value);
711
+ if (status != napi_ok) {
712
+ delete finalizeData;
713
+ throw Error::New (env);
714
+ }
715
+ return External (env, value);
716
+ }
717
+
718
+ template <typename T>
719
+ template <typename Finalizer, typename Hint>
720
+ inline External<T> External<T>::New(napi_env env,
721
+ T* data,
722
+ Finalizer finalizeCallback,
723
+ Hint* finalizeHint) {
724
+ napi_value value;
725
+ details::FinalizeData<T, Finalizer, Hint>* finalizeData =
726
+ new details::FinalizeData<T, Finalizer, Hint>({ finalizeCallback, finalizeHint });
727
+ napi_status status = napi_create_external (
728
+ env,
729
+ data,
730
+ details::FinalizeData<T, Finalizer, Hint>::WrapperWithHint,
731
+ finalizeData,
732
+ &value);
733
+ if (status != napi_ok) {
734
+ delete finalizeData;
735
+ throw Error::New (env);
736
+ }
737
+ return External (env, value);
738
+ }
739
+
698
740
template <typename T>
699
741
inline External<T>::External() : Value() {
700
742
}
@@ -752,26 +794,65 @@ inline ArrayBuffer ArrayBuffer::New(napi_env env, size_t byteLength) {
752
794
napi_status status = napi_create_arraybuffer (env, byteLength, &data, &value);
753
795
if (status != napi_ok) throw Error::New (env);
754
796
755
- ArrayBuffer arrayBuffer (env, value);
756
- arrayBuffer._data = data;
757
- arrayBuffer._length = byteLength;
758
- return arrayBuffer;
797
+ return ArrayBuffer (env, value, data, byteLength);
759
798
}
760
799
761
800
inline ArrayBuffer ArrayBuffer::New (napi_env env,
762
801
void * externalData,
763
- size_t byteLength,
764
- napi_finalize finalizeCallback,
765
- void * finalizeHint) {
802
+ size_t byteLength) {
766
803
napi_value value;
767
804
napi_status status = napi_create_external_arraybuffer (
768
- env, externalData, byteLength, finalizeCallback, finalizeHint , &value);
805
+ env, externalData, byteLength, nullptr , nullptr , &value);
769
806
if (status != napi_ok) throw Error::New (env);
770
807
771
- ArrayBuffer arrayBuffer (env, value);
772
- arrayBuffer._data = externalData;
773
- arrayBuffer._length = byteLength;
774
- return arrayBuffer;
808
+ return ArrayBuffer (env, value, externalData, byteLength);
809
+ }
810
+
811
+ template <typename Finalizer>
812
+ inline ArrayBuffer ArrayBuffer::New (napi_env env,
813
+ void * externalData,
814
+ size_t byteLength,
815
+ Finalizer finalizeCallback) {
816
+ napi_value value;
817
+ details::FinalizeData<void , Finalizer>* finalizeData =
818
+ new details::FinalizeData<void , Finalizer>({ finalizeCallback, nullptr });
819
+ napi_status status = napi_create_external_arraybuffer (
820
+ env,
821
+ externalData,
822
+ byteLength,
823
+ details::FinalizeData<void , Finalizer>::Wrapper,
824
+ finalizeData,
825
+ &value);
826
+ if (status != napi_ok) {
827
+ delete finalizeData;
828
+ throw Error::New (env);
829
+ }
830
+
831
+ return ArrayBuffer (env, value, externalData, byteLength);
832
+ }
833
+
834
+ template <typename Finalizer, typename Hint>
835
+ inline ArrayBuffer ArrayBuffer::New (napi_env env,
836
+ void * externalData,
837
+ size_t byteLength,
838
+ Finalizer finalizeCallback,
839
+ Hint* finalizeHint) {
840
+ napi_value value;
841
+ details::FinalizeData<void , Finalizer, Hint>* finalizeData =
842
+ new details::FinalizeData<void , Finalizer, Hint>({ finalizeCallback, finalizeHint });
843
+ napi_status status = napi_create_external_arraybuffer (
844
+ env,
845
+ externalData,
846
+ byteLength,
847
+ details::FinalizeData<void , Finalizer, Hint>::WrapperWithHint,
848
+ finalizeData,
849
+ &value);
850
+ if (status != napi_ok) {
851
+ delete finalizeData;
852
+ throw Error::New (env);
853
+ }
854
+
855
+ return ArrayBuffer (env, value, externalData, byteLength);
775
856
}
776
857
777
858
inline ArrayBuffer::ArrayBuffer () : Object(), _data(nullptr ), _length(0 ) {
@@ -781,14 +862,30 @@ inline ArrayBuffer::ArrayBuffer(napi_env env, napi_value value)
781
862
: Object(env, value), _data(nullptr ), _length(0 ) {
782
863
}
783
864
865
+ inline ArrayBuffer::ArrayBuffer (napi_env env, napi_value value, void * data, size_t length)
866
+ : Object(env, value), _data(data), _length(length) {
867
+ }
868
+
784
869
inline void * ArrayBuffer::Data () {
870
+ EnsureInfo ();
785
871
return _data;
786
872
}
787
873
788
874
inline size_t ArrayBuffer::ByteLength () {
875
+ EnsureInfo ();
789
876
return _length;
790
877
}
791
878
879
+ inline void ArrayBuffer::EnsureInfo () const {
880
+ // The ArrayBuffer instance may have been constructed from a napi_value whose
881
+ // length/data are not yet known. Fetch and cache these values just once,
882
+ // since they can never change during the lifetime of the ArrayBuffer.
883
+ if (_data == nullptr ) {
884
+ napi_status status = napi_get_arraybuffer_info (_env, _value, &_data, &_length);
885
+ if (status != napi_ok) throw Error::New (_env);
886
+ }
887
+ }
888
+
792
889
// //////////////////////////////////////////////////////////////////////////////
793
890
// TypedArray class
794
891
// //////////////////////////////////////////////////////////////////////////////
@@ -979,12 +1076,14 @@ struct CallbackData {
979
1076
CallbackInfo callbackInfo (env, info);
980
1077
CallbackData* callbackData =
981
1078
static_cast <CallbackData*>(callbackInfo.Data ());
1079
+ callbackInfo.SetData (callbackData->data );
982
1080
return callbackData->callback (callbackInfo);
983
1081
}
984
1082
NAPI_RETHROW_JS_ERROR (env)
985
1083
}
986
1084
987
1085
Callable callback;
1086
+ void * data;
988
1087
};
989
1088
990
1089
template <typename Callable>
@@ -995,27 +1094,49 @@ struct CallbackData<Callable, void> {
995
1094
CallbackInfo callbackInfo (env, info);
996
1095
CallbackData* callbackData =
997
1096
static_cast <CallbackData*>(callbackInfo.Data ());
1097
+ callbackInfo.SetData (callbackData->data );
998
1098
callbackData->callback (callbackInfo);
999
1099
return nullptr ;
1000
1100
}
1001
1101
NAPI_RETHROW_JS_ERROR (env)
1002
1102
}
1003
1103
1004
1104
Callable callback;
1105
+ void * data;
1106
+ };
1107
+
1108
+ template <typename T, typename Finalizer, typename Hint = void >
1109
+ struct FinalizeData {
1110
+ static inline
1111
+ void Wrapper (napi_env env, void * data, void * finalizeHint) {
1112
+ FinalizeData* finalizeData = static_cast <FinalizeData*>(finalizeHint);
1113
+ finalizeData->callback (Env (env), static_cast <T*>(data));
1114
+ delete finalizeData;
1115
+ }
1116
+
1117
+ static inline
1118
+ void WrapperWithHint (napi_env env, void * data, void * finalizeHint) {
1119
+ FinalizeData* finalizeData = static_cast <FinalizeData*>(finalizeHint);
1120
+ finalizeData->callback (Env (env), static_cast <T*>(data), finalizeData->hint );
1121
+ delete finalizeData;
1122
+ }
1123
+
1124
+ Finalizer callback;
1125
+ Hint* hint;
1005
1126
};
1006
1127
1007
1128
} // namespace details
1008
1129
1009
1130
template <typename Callable>
1010
1131
inline Function Function::New (napi_env env,
1011
1132
Callable cb,
1012
- const char * utf8name) {
1133
+ const char * utf8name,
1134
+ void * data) {
1013
1135
typedef decltype (cb (CallbackInfo (nullptr , nullptr ))) ReturnType;
1014
1136
typedef details::CallbackData<Callable, ReturnType> CbData;
1015
1137
// TODO: Delete when the function is destroyed
1016
- auto callbackData = new CbData ({ cb });
1138
+ auto callbackData = new CbData ({ cb, data });
1017
1139
1018
- // TODO: set the function name
1019
1140
napi_value value;
1020
1141
napi_status status = napi_create_function (
1021
1142
env, utf8name, CbData::Wrapper, callbackData, &value);
@@ -1026,8 +1147,9 @@ inline Function Function::New(napi_env env,
1026
1147
template <typename Callable>
1027
1148
inline Function Function::New (napi_env env,
1028
1149
Callable cb,
1029
- const std::string& utf8name) {
1030
- return New (env, cb, utf8name.c_str ());
1150
+ const std::string& utf8name,
1151
+ void * data) {
1152
+ return New (env, cb, utf8name.c_str (), data);
1031
1153
}
1032
1154
1033
1155
inline Function::Function () : Object() {
@@ -1116,26 +1238,72 @@ inline Buffer<T> Buffer<T>::New(napi_env env, size_t length) {
1116
1238
void * data;
1117
1239
napi_status status = napi_create_buffer (env, length * sizeof (T), &data, &value);
1118
1240
if (status != napi_ok) throw Error::New (env);
1119
- return Buffer (env, value, length, data);
1241
+ return Buffer (env, value, length, static_cast <T*>( data) );
1120
1242
}
1121
1243
1122
1244
template <typename T>
1123
- inline Buffer<T> Buffer<T>::New(
1124
- napi_env env, T* data, size_t length, napi_finalize finalizeCallback, void * finalizeHint) {
1245
+ inline Buffer<T> Buffer<T>::New(napi_env env, T* data, size_t length) {
1125
1246
napi_value value;
1126
1247
napi_status status = napi_create_external_buffer (
1127
- env, length * sizeof (T), data, finalizeCallback, finalizeHint , &value);
1248
+ env, length * sizeof (T), data, nullptr , nullptr , &value);
1128
1249
if (status != napi_ok) throw Error::New (env);
1129
1250
return Buffer (env, value, length, data);
1130
1251
}
1131
1252
1253
+ template <typename T>
1254
+ template <typename Finalizer>
1255
+ inline Buffer<T> Buffer<T>::New(napi_env env,
1256
+ T* data,
1257
+ size_t length,
1258
+ Finalizer finalizeCallback) {
1259
+ napi_value value;
1260
+ details::FinalizeData<T, Finalizer>* finalizeData =
1261
+ new details::FinalizeData<T, Finalizer>({ finalizeCallback, nullptr });
1262
+ napi_status status = napi_create_external_buffer (
1263
+ env,
1264
+ length * sizeof (T),
1265
+ data,
1266
+ details::FinalizeData<T, Finalizer>::Wrapper,
1267
+ finalizeData,
1268
+ &value);
1269
+ if (status != napi_ok) {
1270
+ delete finalizeData;
1271
+ throw Error::New (env);
1272
+ }
1273
+ return Buffer (env, value, length, data);
1274
+ }
1275
+
1276
+ template <typename T>
1277
+ template <typename Finalizer, typename Hint>
1278
+ inline Buffer<T> Buffer<T>::New(napi_env env,
1279
+ T* data,
1280
+ size_t length,
1281
+ Finalizer finalizeCallback,
1282
+ Hint* finalizeHint) {
1283
+ napi_value value;
1284
+ details::FinalizeData<T, Finalizer, Hint>* finalizeData =
1285
+ new details::FinalizeData<T, Finalizer, Hint>({ finalizeCallback, finalizeHint });
1286
+ napi_status status = napi_create_external_buffer (
1287
+ env,
1288
+ length * sizeof (T),
1289
+ data,
1290
+ details::FinalizeData<T, Finalizer, Hint>::WrapperWithHint,
1291
+ finalizeData,
1292
+ &value);
1293
+ if (status != napi_ok) {
1294
+ delete finalizeData;
1295
+ throw Error::New (env);
1296
+ }
1297
+ return Buffer (env, value, length, data);
1298
+ }
1299
+
1132
1300
template <typename T>
1133
1301
inline Buffer<T> Buffer<T>::Copy(napi_env env, const T* data, size_t length) {
1134
1302
napi_value value;
1135
1303
napi_status status = napi_create_buffer_copy (
1136
1304
env, length * sizeof (T), data, nullptr , &value);
1137
1305
if (status != napi_ok) throw Error::New (env);
1138
- return Buffer (env, value);
1306
+ return Buffer<T> (env, value);
1139
1307
}
1140
1308
1141
1309
template <typename T>
0 commit comments