Skip to content

Commit 74ef07f

Browse files
Aditi-1400aduh95
authored andcommitted
src: add FromV8Value<T>() for integral and enum types
Add a template utility method FromV8Value<T>() to replace the repetitive static_cast<...>(value.As<>()‑>Value()) pattern. It also additionally adds compile‑time range checks for integers. Refs: #57146 (comment) PR-URL: #57931 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Joyee Cheung <[email protected]>
1 parent 2c205d8 commit 74ef07f

File tree

8 files changed

+43
-17
lines changed

8 files changed

+43
-17
lines changed

src/crypto/crypto_keys.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -807,7 +807,7 @@ void KeyObjectHandle::InitEDRaw(const FunctionCallbackInfo<Value>& args) {
807807
Utf8Value name(env->isolate(), args[0]);
808808

809809
ArrayBufferOrViewContents<unsigned char> key_data(args[1]);
810-
KeyType type = static_cast<KeyType>(args[2].As<Int32>()->Value());
810+
KeyType type = FromV8Value<KeyType>(args[2]);
811811

812812
MarkPopErrorOnReturn mark_pop_error_on_return;
813813

src/node_file.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2768,10 +2768,10 @@ static void Chown(const FunctionCallbackInfo<Value>& args) {
27682768
ToNamespacedPath(env, &path);
27692769

27702770
CHECK(IsSafeJsInt(args[1]));
2771-
const uv_uid_t uid = static_cast<uv_uid_t>(args[1].As<Integer>()->Value());
2771+
const uv_uid_t uid = FromV8Value<uv_uid_t>(args[1]);
27722772

27732773
CHECK(IsSafeJsInt(args[2]));
2774-
const uv_gid_t gid = static_cast<uv_gid_t>(args[2].As<Integer>()->Value());
2774+
const uv_gid_t gid = FromV8Value<uv_gid_t>(args[2]);
27752775

27762776
if (argc > 3) { // chown(path, uid, gid, req)
27772777
FSReqBase* req_wrap_async = GetReqWrap(args, 3);
@@ -2843,10 +2843,10 @@ static void LChown(const FunctionCallbackInfo<Value>& args) {
28432843
ToNamespacedPath(env, &path);
28442844

28452845
CHECK(IsSafeJsInt(args[1]));
2846-
const uv_uid_t uid = static_cast<uv_uid_t>(args[1].As<Integer>()->Value());
2846+
const uv_uid_t uid = FromV8Value<uv_uid_t>(args[1]);
28472847

28482848
CHECK(IsSafeJsInt(args[2]));
2849-
const uv_gid_t gid = static_cast<uv_gid_t>(args[2].As<Integer>()->Value());
2849+
const uv_gid_t gid = FromV8Value<uv_gid_t>(args[2]);
28502850

28512851
if (argc > 3) { // lchown(path, uid, gid, req)
28522852
FSReqBase* req_wrap_async = GetReqWrap(args, 3);

src/node_util.cc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,7 @@ static void GetOwnNonIndexProperties(
6161

6262
Local<Array> properties;
6363

64-
PropertyFilter filter =
65-
static_cast<PropertyFilter>(args[1].As<Uint32>()->Value());
64+
PropertyFilter filter = FromV8Value<PropertyFilter>(args[1]);
6665

6766
if (!object->GetPropertyNames(
6867
context, KeyCollectionMode::kOwnOnly,

src/node_v8.cc

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ using v8::HandleScope;
4040
using v8::HeapCodeStatistics;
4141
using v8::HeapSpaceStatistics;
4242
using v8::HeapStatistics;
43-
using v8::Int32;
4443
using v8::Integer;
4544
using v8::Isolate;
4645
using v8::Local;
@@ -482,8 +481,7 @@ static void GetCppHeapStatistics(const FunctionCallbackInfo<Value>& args) {
482481
CHECK(args[0]->IsInt32());
483482

484483
cppgc::HeapStatistics stats = isolate->GetCppHeap()->CollectStatistics(
485-
static_cast<cppgc::HeapStatistics::DetailLevel>(
486-
args[0].As<Int32>()->Value()));
484+
FromV8Value<cppgc::HeapStatistics::DetailLevel>(args[0]));
487485

488486
Local<Object> result;
489487
if (!ConvertHeapStatsToJSObject(isolate, stats).ToLocal(&result)) {

src/node_zlib.cc

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ using v8::Function;
5353
using v8::FunctionCallbackInfo;
5454
using v8::FunctionTemplate;
5555
using v8::HandleScope;
56-
using v8::Int32;
5756
using v8::Integer;
5857
using v8::Isolate;
5958
using v8::Local;
@@ -687,8 +686,7 @@ class ZlibStream final : public CompressionStream<ZlibContext> {
687686
static void New(const FunctionCallbackInfo<Value>& args) {
688687
Environment* env = Environment::GetCurrent(args);
689688
CHECK(args[0]->IsInt32());
690-
node_zlib_mode mode =
691-
static_cast<node_zlib_mode>(args[0].As<Int32>()->Value());
689+
node_zlib_mode mode = FromV8Value<node_zlib_mode>(args[0]);
692690
new ZlibStream(env, args.This(), mode);
693691
}
694692

@@ -793,8 +791,7 @@ class BrotliCompressionStream final :
793791
static void New(const FunctionCallbackInfo<Value>& args) {
794792
Environment* env = Environment::GetCurrent(args);
795793
CHECK(args[0]->IsInt32());
796-
node_zlib_mode mode =
797-
static_cast<node_zlib_mode>(args[0].As<Int32>()->Value());
794+
node_zlib_mode mode = FromV8Value<node_zlib_mode>(args[0]);
798795
new BrotliCompressionStream(env, args.This(), mode);
799796
}
800797

src/process_wrap.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ class ProcessWrap : public HandleWrap {
173173
return Nothing<void>();
174174
}
175175
CHECK(fd_value->IsNumber());
176-
int fd = static_cast<int>(fd_value.As<Integer>()->Value());
176+
int fd = FromV8Value<int>(fd_value);
177177
options->stdio[i].flags = UV_INHERIT_FD;
178178
options->stdio[i].data.fd = fd;
179179
}

src/udp_wrap.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ void UDPWrap::Open(const FunctionCallbackInfo<Value>& args) {
354354
ASSIGN_OR_RETURN_UNWRAP(
355355
&wrap, args.This(), args.GetReturnValue().Set(UV_EBADF));
356356
CHECK(args[0]->IsNumber());
357-
int fd = static_cast<int>(args[0].As<Integer>()->Value());
357+
int fd = FromV8Value<int>(args[0]);
358358
int err = uv_udp_open(&wrap->handle_, fd);
359359

360360
args.GetReturnValue().Set(err);

src/util-inl.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,38 @@ constexpr std::string_view FastStringKey::as_string_view() const {
605605
return name_;
606606
}
607607

608+
// Converts a V8 numeric value to a corresponding C++ primitive or enum type.
609+
template <typename T,
610+
typename = std::enable_if_t<std::numeric_limits<T>::is_specialized ||
611+
std::is_enum_v<T>>>
612+
T FromV8Value(v8::Local<v8::Value> value) {
613+
if constexpr (std::is_enum_v<T>) {
614+
using Underlying = std::underlying_type_t<T>;
615+
return static_cast<T>(FromV8Value<Underlying>(value));
616+
} else if constexpr (std::is_integral_v<T> && std::is_unsigned_v<T>) {
617+
static_assert(
618+
std::numeric_limits<T>::max() <= std::numeric_limits<uint32_t>::max() &&
619+
std::numeric_limits<T>::min() >=
620+
std::numeric_limits<uint32_t>::min(),
621+
"Type is out of unsigned integer range");
622+
CHECK(value->IsUint32());
623+
return static_cast<T>(value.As<v8::Uint32>()->Value());
624+
} else if constexpr (std::is_integral_v<T> && std::is_signed_v<T>) {
625+
static_assert(
626+
std::numeric_limits<T>::max() <= std::numeric_limits<int32_t>::max() &&
627+
std::numeric_limits<T>::min() >=
628+
std::numeric_limits<int32_t>::min(),
629+
"Type is out of signed integer range");
630+
CHECK(value->IsInt32());
631+
return static_cast<T>(value.As<v8::Int32>()->Value());
632+
} else {
633+
static_assert(std::is_floating_point_v<T>,
634+
"Type must be arithmetic or enum.");
635+
CHECK(value->IsNumber());
636+
return static_cast<T>(value.As<v8::Number>()->Value());
637+
}
638+
}
639+
608640
#ifdef _WIN32
609641
inline bool IsWindowsBatchFile(const char* filename) {
610642
std::string file_with_extension = filename;

0 commit comments

Comments
 (0)