Skip to content

Commit bf49519

Browse files
authored
src: improve messages on CheckCast (#1507)
* src: improve messages on CheckCast Print actual value type if the check failed. * fixup!
1 parent 40bcb09 commit bf49519

File tree

2 files changed

+51
-24
lines changed

2 files changed

+51
-24
lines changed

napi-inl.h

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@
99
////////////////////////////////////////////////////////////////////////////////
1010

1111
// Note: Do not include this file directly! Include "napi.h" instead.
12+
// This should be a no-op and is intended for better IDE integration.
13+
#include "napi.h"
1214

1315
#include <algorithm>
16+
#include <cstdarg>
1417
#include <cstring>
1518
#if NAPI_HAS_THREADS
1619
#include <mutex>
@@ -358,6 +361,18 @@ struct AccessorCallbackData {
358361
void* data;
359362
};
360363

364+
// Debugging-purpose C++-style variant of sprintf().
365+
inline std::string StringFormat(const char* format, ...) {
366+
std::string result;
367+
va_list args;
368+
va_start(args, format);
369+
int len = vsnprintf(nullptr, 0, format, args);
370+
result.resize(len);
371+
vsnprintf(&result[0], len + 1, format, args);
372+
va_end(args);
373+
return result;
374+
}
375+
361376
} // namespace details
362377

363378
#ifndef NODE_ADDON_API_DISABLE_DEPRECATED
@@ -826,8 +841,7 @@ inline void Boolean::CheckCast(napi_env env, napi_value value) {
826841
napi_valuetype type;
827842
napi_status status = napi_typeof(env, value, &type);
828843
NAPI_CHECK(status == napi_ok, "Boolean::CheckCast", "napi_typeof failed");
829-
NAPI_CHECK(
830-
type == napi_boolean, "Boolean::CheckCast", "value is not napi_boolean");
844+
NAPI_INTERNAL_CHECK_EQ(type, napi_boolean, "%d", "Boolean::CheckCast");
831845
}
832846

833847
inline Boolean::Boolean() : Napi::Value() {}
@@ -863,8 +877,7 @@ inline void Number::CheckCast(napi_env env, napi_value value) {
863877
napi_valuetype type;
864878
napi_status status = napi_typeof(env, value, &type);
865879
NAPI_CHECK(status == napi_ok, "Number::CheckCast", "napi_typeof failed");
866-
NAPI_CHECK(
867-
type == napi_number, "Number::CheckCast", "value is not napi_number");
880+
NAPI_INTERNAL_CHECK_EQ(type, napi_number, "%d", "Number::CheckCast");
868881
}
869882

870883
inline Number::Number() : Value() {}
@@ -959,8 +972,7 @@ inline void BigInt::CheckCast(napi_env env, napi_value value) {
959972
napi_valuetype type;
960973
napi_status status = napi_typeof(env, value, &type);
961974
NAPI_CHECK(status == napi_ok, "BigInt::CheckCast", "napi_typeof failed");
962-
NAPI_CHECK(
963-
type == napi_bigint, "BigInt::CheckCast", "value is not napi_bigint");
975+
NAPI_INTERNAL_CHECK_EQ(type, napi_bigint, "%d", "BigInt::CheckCast");
964976
}
965977

966978
inline BigInt::BigInt() : Value() {}
@@ -1046,9 +1058,10 @@ inline void Name::CheckCast(napi_env env, napi_value value) {
10461058
napi_valuetype type;
10471059
napi_status status = napi_typeof(env, value, &type);
10481060
NAPI_CHECK(status == napi_ok, "Name::CheckCast", "napi_typeof failed");
1049-
NAPI_CHECK(type == napi_string || type == napi_symbol,
1050-
"Name::CheckCast",
1051-
"value is not napi_string or napi_symbol");
1061+
NAPI_INTERNAL_CHECK(type == napi_string || type == napi_symbol,
1062+
"Name::CheckCast",
1063+
"value is not napi_string or napi_symbol, got %d.",
1064+
type);
10521065
}
10531066

10541067
inline Name::Name() : Value() {}
@@ -1115,8 +1128,7 @@ inline void String::CheckCast(napi_env env, napi_value value) {
11151128
napi_valuetype type;
11161129
napi_status status = napi_typeof(env, value, &type);
11171130
NAPI_CHECK(status == napi_ok, "String::CheckCast", "napi_typeof failed");
1118-
NAPI_CHECK(
1119-
type == napi_string, "String::CheckCast", "value is not napi_string");
1131+
NAPI_INTERNAL_CHECK_EQ(type, napi_string, "%d", "String::CheckCast");
11201132
}
11211133

11221134
inline String::String() : Name() {}
@@ -1252,8 +1264,7 @@ inline void Symbol::CheckCast(napi_env env, napi_value value) {
12521264
napi_valuetype type;
12531265
napi_status status = napi_typeof(env, value, &type);
12541266
NAPI_CHECK(status == napi_ok, "Symbol::CheckCast", "napi_typeof failed");
1255-
NAPI_CHECK(
1256-
type == napi_symbol, "Symbol::CheckCast", "value is not napi_symbol");
1267+
NAPI_INTERNAL_CHECK_EQ(type, napi_symbol, "%d", "Symbol::CheckCast");
12571268
}
12581269

12591270
inline Symbol::Symbol() : Name() {}
@@ -1424,8 +1435,7 @@ inline void Object::CheckCast(napi_env env, napi_value value) {
14241435
napi_valuetype type;
14251436
napi_status status = napi_typeof(env, value, &type);
14261437
NAPI_CHECK(status == napi_ok, "Object::CheckCast", "napi_typeof failed");
1427-
NAPI_CHECK(
1428-
type == napi_object, "Object::CheckCast", "value is not napi_object");
1438+
NAPI_INTERNAL_CHECK_EQ(type, napi_object, "%d", "Object::CheckCast");
14291439
}
14301440

14311441
inline Object::Object() : TypeTaggable() {}
@@ -1837,9 +1847,7 @@ inline void External<T>::CheckCast(napi_env env, napi_value value) {
18371847
napi_valuetype type;
18381848
napi_status status = napi_typeof(env, value, &type);
18391849
NAPI_CHECK(status == napi_ok, "External::CheckCast", "napi_typeof failed");
1840-
NAPI_CHECK(type == napi_external,
1841-
"External::CheckCast",
1842-
"value is not napi_external");
1850+
NAPI_INTERNAL_CHECK_EQ(type, napi_external, "%d", "External::CheckCast");
18431851
}
18441852

18451853
template <typename T>
@@ -2295,12 +2303,13 @@ inline void TypedArrayOf<T>::CheckCast(napi_env env, napi_value value) {
22952303
"TypedArrayOf::CheckCast",
22962304
"napi_is_typedarray failed");
22972305

2298-
NAPI_CHECK(
2306+
NAPI_INTERNAL_CHECK(
22992307
(type == TypedArrayTypeForPrimitiveType<T>() ||
23002308
(type == napi_uint8_clamped_array && std::is_same<T, uint8_t>::value)),
23012309
"TypedArrayOf::CheckCast",
2302-
"Array type must match the template parameter. (Uint8 arrays may "
2303-
"optionally have the \"clamped\" array type.)");
2310+
"Array type must match the template parameter, (Uint8 arrays may "
2311+
"optionally have the \"clamped\" array type.), got %d.",
2312+
type);
23042313
}
23052314

23062315
template <typename T>
@@ -2481,9 +2490,7 @@ inline void Function::CheckCast(napi_env env, napi_value value) {
24812490
napi_valuetype type;
24822491
napi_status status = napi_typeof(env, value, &type);
24832492
NAPI_CHECK(status == napi_ok, "Function::CheckCast", "napi_typeof failed");
2484-
NAPI_CHECK(type == napi_function,
2485-
"Function::CheckCast",
2486-
"value is not napi_function");
2493+
NAPI_INTERNAL_CHECK_EQ(type, napi_function, "%d", "Function::CheckCast");
24872494
}
24882495

24892496
inline Function::Function() : Object() {}

napi.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,26 @@ static_assert(sizeof(char16_t) == sizeof(wchar_t),
142142
} \
143143
} while (0)
144144

145+
// Internal check helper. Be careful that the formatted message length should be
146+
// max 255 size and null terminated.
147+
#define NAPI_INTERNAL_CHECK(expr, location, ...) \
148+
do { \
149+
if (!(expr)) { \
150+
std::string msg = Napi::details::StringFormat(__VA_ARGS__); \
151+
Napi::Error::Fatal(location, msg.c_str()); \
152+
} \
153+
} while (0)
154+
155+
#define NAPI_INTERNAL_CHECK_EQ(actual, expected, value_format, location) \
156+
do { \
157+
auto actual_value = (actual); \
158+
NAPI_INTERNAL_CHECK(actual_value == (expected), \
159+
location, \
160+
"Expected " #actual " to be equal to " #expected \
161+
", but got " value_format ".", \
162+
actual_value); \
163+
} while (0)
164+
145165
#define NAPI_FATAL_IF_FAILED(status, location, message) \
146166
NAPI_CHECK((status) == napi_ok, location, message)
147167

0 commit comments

Comments
 (0)