diff --git a/test/test_throw_ex.cpp b/test/test_throw_ex.cpp index 12678546..dc80adbd 100644 --- a/test/test_throw_ex.cpp +++ b/test/test_throw_ex.cpp @@ -1,22 +1,26 @@ #include "v8pp/throw_ex.hpp" +#include "v8pp/json.hpp" #include "test.hpp" namespace { -void test(v8pp::context& context, std::string const& type, - v8::Local (*exception_ctor)(v8::Local)) +void test(v8pp::context& context, std::string type, v8pp::exception_ctor ctor = {}, v8::Local opts = {}) { v8::Isolate* isolate = context.isolate(); v8::HandleScope scope(isolate); v8::TryCatch try_catch(isolate); - v8::Local ex = v8pp::throw_ex(isolate, - "exception message", exception_ctor); + v8::Local ex = v8pp::throw_ex(isolate, "exception message", ctor, opts); check(" has caught", try_catch.HasCaught()); check("the same stack trace", try_catch.Message()->GetStackTrace() == v8::Exception::GetStackTrace(ex)); v8::String::Utf8Value const err_msg(isolate, try_catch.Message()->Get()); - check_eq("message", *err_msg, "Uncaught " + type + ": exception message"); + + if (!type.empty()) + { + type += ": "; + } + check_eq("message", *err_msg, "Uncaught " + type + "exception message"); } } // unnamed namespace @@ -24,9 +28,18 @@ void test(v8pp::context& context, std::string const& type, void test_throw_ex() { v8pp::context context; + v8::Isolate* isolate = context.isolate(); + + test(context, ""); test(context, "Error", v8::Exception::Error); test(context, "RangeError", v8::Exception::RangeError); test(context, "ReferenceError", v8::Exception::ReferenceError); test(context, "SyntaxError", v8::Exception::SyntaxError); test(context, "TypeError", v8::Exception::TypeError); + + if constexpr (v8pp::exception_ctor_with_options) + { + v8::HandleScope scope(isolate); + test(context, "Error", v8::Exception::Error, v8pp::json_parse(isolate, "{ 'opt1': true, 'opt2': 'str' }")); + } } diff --git a/v8pp/throw_ex.hpp b/v8pp/throw_ex.hpp index c3ca2e05..2f4edd00 100644 --- a/v8pp/throw_ex.hpp +++ b/v8pp/throw_ex.hpp @@ -9,10 +9,11 @@ namespace v8pp { -v8::Local throw_ex(v8::Isolate* isolate, std::string_view str); +using exception_ctor = decltype(v8::Exception::Error); // assuming all Exception ctors have the same type +constexpr bool exception_ctor_with_options = V8_MAJOR_VERSION > 11 || (V8_MAJOR_VERSION == 11 && V8_MINOR_VERSION >= 9); -v8::Local throw_ex(v8::Isolate* isolate, std::string_view str, - v8::Local (*exception_ctor)(v8::Local)); +v8::Local throw_ex(v8::Isolate* isolate, std::string_view message, + exception_ctor = {}, v8::Local exception_options = {}); } // namespace v8pp diff --git a/v8pp/throw_ex.ipp b/v8pp/throw_ex.ipp index f650b03f..740076e3 100644 --- a/v8pp/throw_ex.ipp +++ b/v8pp/throw_ex.ipp @@ -2,19 +2,27 @@ namespace v8pp { -V8PP_IMPL v8::Local throw_ex(v8::Isolate* isolate, std::string_view str) +V8PP_IMPL v8::Local throw_ex(v8::Isolate* isolate, std::string_view message, exception_ctor ctor, v8::Local exception_options) { - v8::Local msg = v8::String::NewFromUtf8(isolate, str.data(), - v8::NewStringType::kNormal, static_cast(str.size())).ToLocalChecked(); - return isolate->ThrowException(msg); -} + v8::Local msg = v8::String::NewFromUtf8(isolate, message.data(), + v8::NewStringType::kNormal, static_cast(message.size())).ToLocalChecked(); -V8PP_IMPL v8::Local throw_ex(v8::Isolate* isolate, std::string_view str, - v8::Local (*exception_ctor)(v8::Local)) -{ - v8::Local msg = v8::String::NewFromUtf8(isolate, str.data(), - v8::NewStringType::kNormal, static_cast(str.size())).ToLocalChecked(); - return isolate->ThrowException(exception_ctor(msg)); + v8::Local ex; + if (ctor) + { +// if constexpr (exception_ctor_with_options) doesn't work win VC++ 2022 +#if V8_MAJOR_VERSION > 11 || (V8_MAJOR_VERSION == 11 && V8_MINOR_VERSION >= 9) + ex = ctor(msg, exception_options); +#else + (void)exception_options; + ex = ctor(msg); +#endif + } + else + { + ex = msg; + } + return isolate->ThrowException(ex); } } // namespace v8pp