Skip to content

Commit

Permalink
allow options in v8::Exception ctors (#202)
Browse files Browse the repository at this point in the history
... since V8 version 11.9. Use single `v8pp::throw_ex()` function with optional
arguments for exception constructor and options
  • Loading branch information
pmed authored Oct 19, 2023
1 parent c0c93bd commit 388ce0e
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 19 deletions.
23 changes: 18 additions & 5 deletions test/test_throw_ex.cpp
Original file line number Diff line number Diff line change
@@ -1,32 +1,45 @@
#include "v8pp/throw_ex.hpp"
#include "v8pp/json.hpp"
#include "test.hpp"

namespace {

void test(v8pp::context& context, std::string const& type,
v8::Local<v8::Value> (*exception_ctor)(v8::Local<v8::String>))
void test(v8pp::context& context, std::string type, v8pp::exception_ctor ctor = {}, v8::Local<v8::Value> opts = {})
{
v8::Isolate* isolate = context.isolate();

v8::HandleScope scope(isolate);

v8::TryCatch try_catch(isolate);
v8::Local<v8::Value> ex = v8pp::throw_ex(isolate,
"exception message", exception_ctor);
v8::Local<v8::Value> 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

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' }"));
}
}
7 changes: 4 additions & 3 deletions v8pp/throw_ex.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@

namespace v8pp {

v8::Local<v8::Value> 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<v8::Value> throw_ex(v8::Isolate* isolate, std::string_view str,
v8::Local<v8::Value> (*exception_ctor)(v8::Local<v8::String>));
v8::Local<v8::Value> throw_ex(v8::Isolate* isolate, std::string_view message,
exception_ctor = {}, v8::Local<v8::Value> exception_options = {});

} // namespace v8pp

Expand Down
30 changes: 19 additions & 11 deletions v8pp/throw_ex.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,27 @@

namespace v8pp {

V8PP_IMPL v8::Local<v8::Value> throw_ex(v8::Isolate* isolate, std::string_view str)
V8PP_IMPL v8::Local<v8::Value> throw_ex(v8::Isolate* isolate, std::string_view message, exception_ctor ctor, v8::Local<v8::Value> exception_options)
{
v8::Local<v8::String> msg = v8::String::NewFromUtf8(isolate, str.data(),
v8::NewStringType::kNormal, static_cast<int>(str.size())).ToLocalChecked();
return isolate->ThrowException(msg);
}
v8::Local<v8::String> msg = v8::String::NewFromUtf8(isolate, message.data(),
v8::NewStringType::kNormal, static_cast<int>(message.size())).ToLocalChecked();

V8PP_IMPL v8::Local<v8::Value> throw_ex(v8::Isolate* isolate, std::string_view str,
v8::Local<v8::Value> (*exception_ctor)(v8::Local<v8::String>))
{
v8::Local<v8::String> msg = v8::String::NewFromUtf8(isolate, str.data(),
v8::NewStringType::kNormal, static_cast<int>(str.size())).ToLocalChecked();
return isolate->ThrowException(exception_ctor(msg));
v8::Local<v8::Value> 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

0 comments on commit 388ce0e

Please sign in to comment.