diff --git a/src/crypto/crypto_keys.cc b/src/crypto/crypto_keys.cc index 0d9d4114b82093..458282b1cdfa7a 100644 --- a/src/crypto/crypto_keys.cc +++ b/src/crypto/crypto_keys.cc @@ -780,7 +780,7 @@ void KeyObjectHandle::InitEDRaw(const FunctionCallbackInfo& args) { Utf8Value name(env->isolate(), args[0]); ArrayBufferOrViewContents key_data(args[1]); - KeyType type = static_cast(args[2].As()->Value()); + KeyType type = FromV8Value(args[2]); MarkPopErrorOnReturn mark_pop_error_on_return; diff --git a/src/node_file.cc b/src/node_file.cc index 794a9ba9120b3f..f4adf404c0bdac 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -2881,10 +2881,10 @@ static void Chown(const FunctionCallbackInfo& args) { ToNamespacedPath(env, &path); CHECK(IsSafeJsInt(args[1])); - const uv_uid_t uid = static_cast(args[1].As()->Value()); + const uv_uid_t uid = FromV8Value(args[1]); CHECK(IsSafeJsInt(args[2])); - const uv_gid_t gid = static_cast(args[2].As()->Value()); + const uv_gid_t gid = FromV8Value(args[2]); if (argc > 3) { // chown(path, uid, gid, req) FSReqBase* req_wrap_async = GetReqWrap(args, 3); @@ -2956,10 +2956,10 @@ static void LChown(const FunctionCallbackInfo& args) { ToNamespacedPath(env, &path); CHECK(IsSafeJsInt(args[1])); - const uv_uid_t uid = static_cast(args[1].As()->Value()); + const uv_uid_t uid = FromV8Value(args[1]); CHECK(IsSafeJsInt(args[2])); - const uv_gid_t gid = static_cast(args[2].As()->Value()); + const uv_gid_t gid = FromV8Value(args[2]); if (argc > 3) { // lchown(path, uid, gid, req) FSReqBase* req_wrap_async = GetReqWrap(args, 3); diff --git a/src/node_util.cc b/src/node_util.cc index 85ef1c205e0d50..2ac4a130cb65fe 100644 --- a/src/node_util.cc +++ b/src/node_util.cc @@ -61,8 +61,7 @@ static void GetOwnNonIndexProperties( Local properties; - PropertyFilter filter = - static_cast(args[1].As()->Value()); + PropertyFilter filter = FromV8Value(args[1]); if (!object->GetPropertyNames( context, KeyCollectionMode::kOwnOnly, diff --git a/src/node_v8.cc b/src/node_v8.cc index 8650a97e31d94c..891dd105f7ed54 100644 --- a/src/node_v8.cc +++ b/src/node_v8.cc @@ -40,7 +40,6 @@ using v8::HandleScope; using v8::HeapCodeStatistics; using v8::HeapSpaceStatistics; using v8::HeapStatistics; -using v8::Int32; using v8::Integer; using v8::Isolate; using v8::Local; @@ -492,8 +491,7 @@ static void GetCppHeapStatistics(const FunctionCallbackInfo& args) { CHECK(args[0]->IsInt32()); cppgc::HeapStatistics stats = isolate->GetCppHeap()->CollectStatistics( - static_cast( - args[0].As()->Value())); + FromV8Value(args[0])); Local result; if (!ConvertHeapStatsToJSObject(isolate, stats).ToLocal(&result)) { diff --git a/src/node_zlib.cc b/src/node_zlib.cc index 7e6b38ecd1aa36..037989397f4a5e 100644 --- a/src/node_zlib.cc +++ b/src/node_zlib.cc @@ -53,7 +53,6 @@ using v8::Function; using v8::FunctionCallbackInfo; using v8::FunctionTemplate; using v8::HandleScope; -using v8::Int32; using v8::Integer; using v8::Isolate; using v8::Local; @@ -687,8 +686,7 @@ class ZlibStream final : public CompressionStream { static void New(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); CHECK(args[0]->IsInt32()); - node_zlib_mode mode = - static_cast(args[0].As()->Value()); + node_zlib_mode mode = FromV8Value(args[0]); new ZlibStream(env, args.This(), mode); } @@ -793,8 +791,7 @@ class BrotliCompressionStream final : static void New(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); CHECK(args[0]->IsInt32()); - node_zlib_mode mode = - static_cast(args[0].As()->Value()); + node_zlib_mode mode = FromV8Value(args[0]); new BrotliCompressionStream(env, args.This(), mode); } diff --git a/src/process_wrap.cc b/src/process_wrap.cc index 52e3759403b5fa..d5ecada1bfcc80 100644 --- a/src/process_wrap.cc +++ b/src/process_wrap.cc @@ -173,7 +173,7 @@ class ProcessWrap : public HandleWrap { return Nothing(); } CHECK(fd_value->IsNumber()); - int fd = static_cast(fd_value.As()->Value()); + int fd = FromV8Value(fd_value); options->stdio[i].flags = UV_INHERIT_FD; options->stdio[i].data.fd = fd; } diff --git a/src/udp_wrap.cc b/src/udp_wrap.cc index 7cdb3340855423..fd77e98b1596cf 100644 --- a/src/udp_wrap.cc +++ b/src/udp_wrap.cc @@ -354,7 +354,7 @@ void UDPWrap::Open(const FunctionCallbackInfo& args) { ASSIGN_OR_RETURN_UNWRAP( &wrap, args.This(), args.GetReturnValue().Set(UV_EBADF)); CHECK(args[0]->IsNumber()); - int fd = static_cast(args[0].As()->Value()); + int fd = FromV8Value(args[0]); int err = uv_udp_open(&wrap->handle_, fd); args.GetReturnValue().Set(err); diff --git a/src/util-inl.h b/src/util-inl.h index 44dbceed5f3d22..ffa5696a44372f 100644 --- a/src/util-inl.h +++ b/src/util-inl.h @@ -591,6 +591,38 @@ constexpr std::string_view FastStringKey::as_string_view() const { return name_; } +// Converts a V8 numeric value to a corresponding C++ primitive or enum type. +template ::is_specialized || + std::is_enum_v>> +T FromV8Value(v8::Local value) { + if constexpr (std::is_enum_v) { + using Underlying = std::underlying_type_t; + return static_cast(FromV8Value(value)); + } else if constexpr (std::is_integral_v && std::is_unsigned_v) { + static_assert( + std::numeric_limits::max() <= std::numeric_limits::max() && + std::numeric_limits::min() >= + std::numeric_limits::min(), + "Type is out of unsigned integer range"); + CHECK(value->IsUint32()); + return static_cast(value.As()->Value()); + } else if constexpr (std::is_integral_v && std::is_signed_v) { + static_assert( + std::numeric_limits::max() <= std::numeric_limits::max() && + std::numeric_limits::min() >= + std::numeric_limits::min(), + "Type is out of signed integer range"); + CHECK(value->IsInt32()); + return static_cast(value.As()->Value()); + } else { + static_assert(std::is_floating_point_v, + "Type must be arithmetic or enum."); + CHECK(value->IsNumber()); + return static_cast(value.As()->Value()); + } +} + #ifdef _WIN32 inline bool IsWindowsBatchFile(const char* filename) { std::string file_with_extension = filename;