1818#if NAPI_HAS_THREADS
1919#include < mutex>
2020#endif // NAPI_HAS_THREADS
21+ #include < string_view>
2122#include < type_traits>
2223#include < utility>
2324
25+ #if defined(__clang__) || defined(__GNUC__)
26+ #define NAPI_NO_SANITIZE_VPTR __attribute__ ((no_sanitize(" vptr" )))
27+ #else
28+ #define NAPI_NO_SANITIZE_VPTR
29+ #endif
30+
2431namespace Napi {
2532
2633#ifdef NAPI_CPP_CUSTOM_NAMESPACE
@@ -939,6 +946,19 @@ inline bool Value::IsExternal() const {
939946 return Type () == napi_external;
940947}
941948
949+ #ifdef NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER
950+ inline bool Value::IsSharedArrayBuffer () const {
951+ if (IsEmpty ()) {
952+ return false ;
953+ }
954+
955+ bool result;
956+ napi_status status = node_api_is_sharedarraybuffer (_env, _value, &result);
957+ NAPI_THROW_IF_FAILED (_env, status, false );
958+ return result;
959+ }
960+ #endif
961+
942962template <typename T>
943963inline T Value::As () const {
944964#ifdef NODE_ADDON_API_ENABLE_TYPE_CHECK_ON_AS
@@ -1185,6 +1205,13 @@ inline Date Date::New(napi_env env, double val) {
11851205 return Date (env, value);
11861206}
11871207
1208+ inline Date Date::New (napi_env env, std::chrono::system_clock::time_point tp) {
1209+ using namespace std ::chrono;
1210+ auto ms = static_cast <double >(
1211+ duration_cast<milliseconds>(tp.time_since_epoch ()).count ());
1212+ return Date::New (env, ms);
1213+ }
1214+
11881215inline void Date::CheckCast (napi_env env, napi_value value) {
11891216 NAPI_CHECK (value != nullptr , " Date::CheckCast" , " empty value" );
11901217
@@ -1241,6 +1268,10 @@ inline String String::New(napi_env env, const std::u16string& val) {
12411268 return String::New (env, val.c_str (), val.size ());
12421269}
12431270
1271+ inline String String::New (napi_env env, std::string_view val) {
1272+ return String::New (env, val.data (), val.size ());
1273+ }
1274+
12441275inline String String::New (napi_env env, const char * val) {
12451276 // TODO(@gabrielschulhof) Remove if-statement when core's error handling is
12461277 // available in all supported versions.
@@ -1350,6 +1381,11 @@ inline Symbol Symbol::New(napi_env env, const std::string& description) {
13501381 return Symbol::New (env, descriptionValue);
13511382}
13521383
1384+ inline Symbol Symbol::New (napi_env env, std::string_view description) {
1385+ napi_value descriptionValue = String::New (env, description);
1386+ return Symbol::New (env, descriptionValue);
1387+ }
1388+
13531389inline Symbol Symbol::New (napi_env env, String description) {
13541390 napi_value descriptionValue = description;
13551391 return Symbol::New (env, descriptionValue);
@@ -1391,6 +1427,12 @@ inline MaybeOrValue<Symbol> Symbol::For(napi_env env,
13911427 return Symbol::For (env, descriptionValue);
13921428}
13931429
1430+ inline MaybeOrValue<Symbol> Symbol::For (napi_env env,
1431+ std::string_view description) {
1432+ napi_value descriptionValue = String::New (env, description);
1433+ return Symbol::For (env, descriptionValue);
1434+ }
1435+
13941436inline MaybeOrValue<Symbol> Symbol::For (napi_env env, const char * description) {
13951437 napi_value descriptionValue = String::New (env, description);
13961438 return Symbol::For (env, descriptionValue);
@@ -1952,6 +1994,19 @@ inline MaybeOrValue<bool> Object::Seal() const {
19521994}
19531995#endif // NAPI_VERSION >= 8
19541996
1997+ inline MaybeOrValue<Object> Object::GetPrototype () const {
1998+ napi_value result;
1999+ napi_status status = napi_get_prototype (_env, _value, &result);
2000+ NAPI_RETURN_OR_THROW_IF_FAILED (_env, status, Object (_env, result), Object);
2001+ }
2002+
2003+ #ifdef NODE_API_EXPERIMENTAL_HAS_SET_PROTOTYPE
2004+ inline MaybeOrValue<bool > Object::SetPrototype (const Object& value) const {
2005+ napi_status status = node_api_set_prototype (_env, _value, value);
2006+ NAPI_RETURN_OR_THROW_IF_FAILED (_env, status, status == napi_ok, bool );
2007+ }
2008+ #endif
2009+
19552010// //////////////////////////////////////////////////////////////////////////////
19562011// External class
19572012// //////////////////////////////////////////////////////////////////////////////
@@ -2073,6 +2128,55 @@ inline uint32_t Array::Length() const {
20732128 return result;
20742129}
20752130
2131+ #ifdef NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER
2132+ // //////////////////////////////////////////////////////////////////////////////
2133+ // SharedArrayBuffer class
2134+ // //////////////////////////////////////////////////////////////////////////////
2135+
2136+ inline SharedArrayBuffer::SharedArrayBuffer () : Object () {}
2137+
2138+ inline SharedArrayBuffer::SharedArrayBuffer (napi_env env, napi_value value)
2139+ : Object (env, value) {}
2140+
2141+ inline void SharedArrayBuffer::CheckCast (napi_env env, napi_value value) {
2142+ NAPI_CHECK (value != nullptr , " SharedArrayBuffer::CheckCast" , " empty value" );
2143+
2144+ bool result;
2145+ napi_status status = node_api_is_sharedarraybuffer (env, value, &result);
2146+ NAPI_CHECK (status == napi_ok,
2147+ " SharedArrayBuffer::CheckCast" ,
2148+ " node_api_is_sharedarraybuffer failed" );
2149+ NAPI_CHECK (
2150+ result, " SharedArrayBuffer::CheckCast" , " value is not sharedarraybuffer" );
2151+ }
2152+
2153+ inline SharedArrayBuffer SharedArrayBuffer::New (napi_env env,
2154+ size_t byteLength) {
2155+ napi_value value;
2156+ void * data;
2157+ napi_status status =
2158+ node_api_create_sharedarraybuffer (env, byteLength, &data, &value);
2159+ NAPI_THROW_IF_FAILED (env, status, SharedArrayBuffer ());
2160+
2161+ return SharedArrayBuffer (env, value);
2162+ }
2163+
2164+ inline void * SharedArrayBuffer::Data () {
2165+ void * data;
2166+ napi_status status = napi_get_arraybuffer_info (_env, _value, &data, nullptr );
2167+ NAPI_THROW_IF_FAILED (_env, status, nullptr );
2168+ return data;
2169+ }
2170+
2171+ inline size_t SharedArrayBuffer::ByteLength () {
2172+ size_t length;
2173+ napi_status status =
2174+ napi_get_arraybuffer_info (_env, _value, nullptr , &length);
2175+ NAPI_THROW_IF_FAILED (_env, status, 0 );
2176+ return length;
2177+ }
2178+ #endif // NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER
2179+
20762180// //////////////////////////////////////////////////////////////////////////////
20772181// ArrayBuffer class
20782182// //////////////////////////////////////////////////////////////////////////////
@@ -2227,6 +2331,39 @@ inline DataView DataView::New(napi_env env,
22272331 return DataView (env, value);
22282332}
22292333
2334+ #ifdef NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER
2335+ inline DataView DataView::New (napi_env env,
2336+ Napi::SharedArrayBuffer arrayBuffer) {
2337+ return New (env, arrayBuffer, 0 , arrayBuffer.ByteLength ());
2338+ }
2339+
2340+ inline DataView DataView::New (napi_env env,
2341+ Napi::SharedArrayBuffer arrayBuffer,
2342+ size_t byteOffset) {
2343+ if (byteOffset > arrayBuffer.ByteLength ()) {
2344+ NAPI_THROW (RangeError::New (
2345+ env, " Start offset is outside the bounds of the buffer" ),
2346+ DataView ());
2347+ }
2348+ return New (
2349+ env, arrayBuffer, byteOffset, arrayBuffer.ByteLength () - byteOffset);
2350+ }
2351+
2352+ inline DataView DataView::New (napi_env env,
2353+ Napi::SharedArrayBuffer arrayBuffer,
2354+ size_t byteOffset,
2355+ size_t byteLength) {
2356+ if (byteOffset + byteLength > arrayBuffer.ByteLength ()) {
2357+ NAPI_THROW (RangeError::New (env, " Invalid DataView length" ), DataView ());
2358+ }
2359+ napi_value value;
2360+ napi_status status =
2361+ napi_create_dataview (env, byteLength, arrayBuffer, byteOffset, &value);
2362+ NAPI_THROW_IF_FAILED (env, status, DataView ());
2363+ return DataView (env, value);
2364+ }
2365+ #endif // NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER
2366+
22302367inline void DataView::CheckCast (napi_env env, napi_value value) {
22312368 NAPI_CHECK (value != nullptr , " DataView::CheckCast" , " empty value" );
22322369
@@ -2250,15 +2387,19 @@ inline DataView::DataView(napi_env env, napi_value value) : Object(env, value) {
22502387}
22512388
22522389inline Napi::ArrayBuffer DataView::ArrayBuffer () const {
2390+ return Buffer ().As <Napi::ArrayBuffer>();
2391+ }
2392+
2393+ inline Napi::Value DataView::Buffer () const {
22532394 napi_value arrayBuffer;
22542395 napi_status status = napi_get_dataview_info (_env,
22552396 _value /* dataView */ ,
22562397 nullptr /* byteLength */ ,
22572398 nullptr /* data */ ,
22582399 &arrayBuffer /* arrayBuffer */ ,
22592400 nullptr /* byteOffset */ );
2260- NAPI_THROW_IF_FAILED (_env, status, Napi::ArrayBuffer ());
2261- return Napi::ArrayBuffer (_env, arrayBuffer);
2401+ NAPI_THROW_IF_FAILED (_env, status, Napi::Value ());
2402+ return Napi::Value (_env, arrayBuffer);
22622403}
22632404
22642405inline size_t DataView::ByteOffset () const {
@@ -2819,8 +2960,95 @@ inline void Promise::CheckCast(napi_env env, napi_value value) {
28192960 NAPI_CHECK (result, " Promise::CheckCast" , " value is not promise" );
28202961}
28212962
2963+ inline Promise::Promise () : Object () {}
2964+
28222965inline Promise::Promise (napi_env env, napi_value value) : Object (env, value) {}
28232966
2967+ inline MaybeOrValue<Promise> Promise::Then (napi_value onFulfilled) const {
2968+ EscapableHandleScope scope (_env);
2969+ #ifdef NODE_ADDON_API_ENABLE_MAYBE
2970+ Value thenMethod;
2971+ if (!Get (" then" ).UnwrapTo (&thenMethod)) {
2972+ return Nothing<Promise>();
2973+ }
2974+ MaybeOrValue<Value> result =
2975+ thenMethod.As <Function>().Call (*this , {onFulfilled});
2976+ if (result.IsJust ()) {
2977+ return Just (scope.Escape (result.Unwrap ()).As <Promise>());
2978+ }
2979+ return Nothing<Promise>();
2980+ #else
2981+ Function thenMethod = Get (" then" ).As <Function>();
2982+ MaybeOrValue<Value> result = thenMethod.Call (*this , {onFulfilled});
2983+ if (scope.Env ().IsExceptionPending ()) {
2984+ return Promise ();
2985+ }
2986+ return scope.Escape (result).As <Promise>();
2987+ #endif
2988+ }
2989+
2990+ inline MaybeOrValue<Promise> Promise::Then (napi_value onFulfilled,
2991+ napi_value onRejected) const {
2992+ EscapableHandleScope scope (_env);
2993+ #ifdef NODE_ADDON_API_ENABLE_MAYBE
2994+ Value thenMethod;
2995+ if (!Get (" then" ).UnwrapTo (&thenMethod)) {
2996+ return Nothing<Promise>();
2997+ }
2998+ MaybeOrValue<Value> result =
2999+ thenMethod.As <Function>().Call (*this , {onFulfilled, onRejected});
3000+ if (result.IsJust ()) {
3001+ return Just (scope.Escape (result.Unwrap ()).As <Promise>());
3002+ }
3003+ return Nothing<Promise>();
3004+ #else
3005+ Function thenMethod = Get (" then" ).As <Function>();
3006+ MaybeOrValue<Value> result =
3007+ thenMethod.Call (*this , {onFulfilled, onRejected});
3008+ if (scope.Env ().IsExceptionPending ()) {
3009+ return Promise ();
3010+ }
3011+ return scope.Escape (result).As <Promise>();
3012+ #endif
3013+ }
3014+
3015+ inline MaybeOrValue<Promise> Promise::Catch (napi_value onRejected) const {
3016+ EscapableHandleScope scope (_env);
3017+ #ifdef NODE_ADDON_API_ENABLE_MAYBE
3018+ Value catchMethod;
3019+ if (!Get (" catch" ).UnwrapTo (&catchMethod)) {
3020+ return Nothing<Promise>();
3021+ }
3022+ MaybeOrValue<Value> result =
3023+ catchMethod.As <Function>().Call (*this , {onRejected});
3024+ if (result.IsJust ()) {
3025+ return Just (scope.Escape (result.Unwrap ()).As <Promise>());
3026+ }
3027+ return Nothing<Promise>();
3028+ #else
3029+ Function catchMethod = Get (" catch" ).As <Function>();
3030+ MaybeOrValue<Value> result = catchMethod.Call (*this , {onRejected});
3031+ if (scope.Env ().IsExceptionPending ()) {
3032+ return Promise ();
3033+ }
3034+ return scope.Escape (result).As <Promise>();
3035+ #endif
3036+ }
3037+
3038+ inline MaybeOrValue<Promise> Promise::Then (const Function& onFulfilled) const {
3039+ return Then (static_cast <napi_value>(onFulfilled));
3040+ }
3041+
3042+ inline MaybeOrValue<Promise> Promise::Then (const Function& onFulfilled,
3043+ const Function& onRejected) const {
3044+ return Then (static_cast <napi_value>(onFulfilled),
3045+ static_cast <napi_value>(onRejected));
3046+ }
3047+
3048+ inline MaybeOrValue<Promise> Promise::Catch (const Function& onRejected) const {
3049+ return Catch (static_cast <napi_value>(onRejected));
3050+ }
3051+
28243052// //////////////////////////////////////////////////////////////////////////////
28253053// Buffer<T> class
28263054// //////////////////////////////////////////////////////////////////////////////
@@ -3670,8 +3898,8 @@ inline MaybeOrValue<bool> ObjectReference::Set(const std::string& utf8name,
36703898 return Value ().Set (utf8name, value);
36713899}
36723900
3673- inline MaybeOrValue<bool > ObjectReference::Set (const std::string& utf8name,
3674- std::string& utf8value) const {
3901+ inline MaybeOrValue<bool > ObjectReference::Set (
3902+ const std::string& utf8name, const std::string& utf8value) const {
36753903 HandleScope scope (_env);
36763904 return Value ().Set (utf8name, utf8value);
36773905}
@@ -4653,7 +4881,8 @@ inline napi_value InstanceWrap<T>::WrappedMethod(
46534881// //////////////////////////////////////////////////////////////////////////////
46544882
46554883template <typename T>
4656- inline ObjectWrap<T>::ObjectWrap (const Napi::CallbackInfo& callbackInfo) {
4884+ inline NAPI_NO_SANITIZE_VPTR ObjectWrap<T>::ObjectWrap (
4885+ const Napi::CallbackInfo& callbackInfo) {
46574886 napi_env env = callbackInfo.Env ();
46584887 napi_value wrapper = callbackInfo.This ();
46594888 napi_status status;
@@ -4671,7 +4900,7 @@ inline ObjectWrap<T>::ObjectWrap(const Napi::CallbackInfo& callbackInfo) {
46714900}
46724901
46734902template <typename T>
4674- inline ObjectWrap<T>::~ObjectWrap () {
4903+ inline NAPI_NO_SANITIZE_VPTR ObjectWrap<T>::~ObjectWrap () {
46754904 // If the JS object still exists at this point, remove the finalizer added
46764905 // through `napi_wrap()`.
46774906 if (!IsEmpty () && !_finalized) {
@@ -4684,8 +4913,12 @@ inline ObjectWrap<T>::~ObjectWrap() {
46844913 }
46854914}
46864915
4916+ // with RTTI turned on, modern compilers check to see if virtual function
4917+ // pointers are stripped of RTTI by void casts. this is intrinsic to how Unwrap
4918+ // works, so we inject a compiler pragma to turn off that check just for the
4919+ // affected methods. this compiler check is on by default in Android NDK 29.
46874920template <typename T>
4688- inline T* ObjectWrap<T>::Unwrap (Object wrapper) {
4921+ inline NAPI_NO_SANITIZE_VPTR T* ObjectWrap<T>::Unwrap (Object wrapper) {
46894922 void * unwrapped;
46904923 napi_status status = napi_unwrap (wrapper.Env (), wrapper, &unwrapped);
46914924 NAPI_THROW_IF_FAILED (wrapper.Env (), status, nullptr );
@@ -6984,4 +7217,6 @@ inline void BasicEnv::PostFinalizer(FinalizerType finalizeCallback,
69847217
69857218} // namespace Napi
69867219
7220+ #undef NAPI_NO_SANITIZE_VPTR
7221+
69877222#endif // SRC_NAPI_INL_H_
0 commit comments