Skip to content

Commit faada65

Browse files
authored
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 6145ba7 commit faada65

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
@@ -780,7 +780,7 @@ void KeyObjectHandle::InitEDRaw(const FunctionCallbackInfo<Value>& args) {
780780
Utf8Value name(env->isolate(), args[0]);
781781

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

785785
MarkPopErrorOnReturn mark_pop_error_on_return;
786786

src/node_file.cc

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

28612861
CHECK(IsSafeJsInt(args[1]));
2862-
const uv_uid_t uid = static_cast<uv_uid_t>(args[1].As<Integer>()->Value());
2862+
const uv_uid_t uid = FromV8Value<uv_uid_t>(args[1]);
28632863

28642864
CHECK(IsSafeJsInt(args[2]));
2865-
const uv_gid_t gid = static_cast<uv_gid_t>(args[2].As<Integer>()->Value());
2865+
const uv_gid_t gid = FromV8Value<uv_gid_t>(args[2]);
28662866

28672867
if (argc > 3) { // chown(path, uid, gid, req)
28682868
FSReqBase* req_wrap_async = GetReqWrap(args, 3);
@@ -2934,10 +2934,10 @@ static void LChown(const FunctionCallbackInfo<Value>& args) {
29342934
ToNamespacedPath(env, &path);
29352935

29362936
CHECK(IsSafeJsInt(args[1]));
2937-
const uv_uid_t uid = static_cast<uv_uid_t>(args[1].As<Integer>()->Value());
2937+
const uv_uid_t uid = FromV8Value<uv_uid_t>(args[1]);
29382938

29392939
CHECK(IsSafeJsInt(args[2]));
2940-
const uv_gid_t gid = static_cast<uv_gid_t>(args[2].As<Integer>()->Value());
2940+
const uv_gid_t gid = FromV8Value<uv_gid_t>(args[2]);
29412941

29422942
if (argc > 3) { // lchown(path, uid, gid, req)
29432943
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
@@ -41,7 +41,6 @@ using v8::HandleScope;
4141
using v8::HeapCodeStatistics;
4242
using v8::HeapSpaceStatistics;
4343
using v8::HeapStatistics;
44-
using v8::Int32;
4544
using v8::Integer;
4645
using v8::Isolate;
4746
using v8::Local;
@@ -489,8 +488,7 @@ static void GetCppHeapStatistics(const FunctionCallbackInfo<Value>& args) {
489488
CHECK(args[0]->IsInt32());
490489

491490
cppgc::HeapStatistics stats = isolate->GetCppHeap()->CollectStatistics(
492-
static_cast<cppgc::HeapStatistics::DetailLevel>(
493-
args[0].As<Int32>()->Value()));
491+
FromV8Value<cppgc::HeapStatistics::DetailLevel>(args[0]));
494492

495493
Local<Object> result;
496494
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;
@@ -688,8 +687,7 @@ class ZlibStream final : public CompressionStream<ZlibContext> {
688687
static void New(const FunctionCallbackInfo<Value>& args) {
689688
Environment* env = Environment::GetCurrent(args);
690689
CHECK(args[0]->IsInt32());
691-
node_zlib_mode mode =
692-
static_cast<node_zlib_mode>(args[0].As<Int32>()->Value());
690+
node_zlib_mode mode = FromV8Value<node_zlib_mode>(args[0]);
693691
new ZlibStream(env, args.This(), mode);
694692
}
695693

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

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
@@ -370,7 +370,7 @@ void UDPWrap::Open(const FunctionCallbackInfo<Value>& args) {
370370
ASSIGN_OR_RETURN_UNWRAP(
371371
&wrap, args.This(), args.GetReturnValue().Set(UV_EBADF));
372372
CHECK(args[0]->IsNumber());
373-
int fd = static_cast<int>(args[0].As<Integer>()->Value());
373+
int fd = FromV8Value<int>(args[0]);
374374
int err = uv_udp_open(&wrap->handle_, fd);
375375

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

src/util-inl.h

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

628+
// Converts a V8 numeric value to a corresponding C++ primitive or enum type.
629+
template <typename T,
630+
typename = std::enable_if_t<std::numeric_limits<T>::is_specialized ||
631+
std::is_enum_v<T>>>
632+
T FromV8Value(v8::Local<v8::Value> value) {
633+
if constexpr (std::is_enum_v<T>) {
634+
using Underlying = std::underlying_type_t<T>;
635+
return static_cast<T>(FromV8Value<Underlying>(value));
636+
} else if constexpr (std::is_integral_v<T> && std::is_unsigned_v<T>) {
637+
static_assert(
638+
std::numeric_limits<T>::max() <= std::numeric_limits<uint32_t>::max() &&
639+
std::numeric_limits<T>::min() >=
640+
std::numeric_limits<uint32_t>::min(),
641+
"Type is out of unsigned integer range");
642+
CHECK(value->IsUint32());
643+
return static_cast<T>(value.As<v8::Uint32>()->Value());
644+
} else if constexpr (std::is_integral_v<T> && std::is_signed_v<T>) {
645+
static_assert(
646+
std::numeric_limits<T>::max() <= std::numeric_limits<int32_t>::max() &&
647+
std::numeric_limits<T>::min() >=
648+
std::numeric_limits<int32_t>::min(),
649+
"Type is out of signed integer range");
650+
CHECK(value->IsInt32());
651+
return static_cast<T>(value.As<v8::Int32>()->Value());
652+
} else {
653+
static_assert(std::is_floating_point_v<T>,
654+
"Type must be arithmetic or enum.");
655+
CHECK(value->IsNumber());
656+
return static_cast<T>(value.As<v8::Number>()->Value());
657+
}
658+
}
659+
628660
#ifdef _WIN32
629661
inline bool IsWindowsBatchFile(const char* filename) {
630662
std::string file_with_extension = filename;

0 commit comments

Comments
 (0)