Skip to content

Commit e68d34f

Browse files
author
Roland Eischer
committed
Fixed handling of an exception within a class constructor
1 parent 930e498 commit e68d34f

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

test/test_class.cpp

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,15 @@ static X_ptr create_X(v8::FunctionCallbackInfo<v8::Value> const& args)
5454
return x;
5555
}
5656

57+
template<typename Traits, typename E_ptr = typename v8pp::class_<E, Traits>::object_pointer_type>
58+
static E_ptr create_E(v8::FunctionCallbackInfo<v8::Value> const& args)
59+
{
60+
E_ptr e(new E);
61+
if (args.Length() == 0)
62+
v8pp::throw_ex(args.GetIsolate(), "MyException");
63+
return e;
64+
}
65+
5766
struct Y : X
5867
{
5968
static int instance_count;
@@ -71,6 +80,8 @@ int Y::instance_count = 0;
7180

7281
struct Z {};
7382

83+
struct E {};
84+
7485
namespace v8pp {
7586
template<>
7687
struct factory<Y, v8pp::raw_ptr_traits>
@@ -150,6 +161,22 @@ void test_class_()
150161
.set("useX_ptr", &Y::useX_ptr<Traits>)
151162
;
152163

164+
auto const E_ctor = [](v8::FunctionCallbackInfo<v8::Value> const& args)
165+
{
166+
return create_E<Traits>(args);
167+
};
168+
169+
auto const E_dtor = [](v8::Isolate* isolate, typename Traits::template object_pointer_type<E> const& obj)
170+
{
171+
Traits::destroy(obj);
172+
};
173+
174+
v8pp::class_<E, Traits> E_class(isolate, E_dtor);
175+
E_class
176+
.template ctor<v8::FunctionCallbackInfo<v8::Value> const&>(E_ctor)
177+
.set_const("konst", 42)
178+
;
179+
153180
check_ex<std::runtime_error>("already wrapped class X", [isolate]()
154181
{
155182
v8pp::class_<X, Traits> X_class(isolate);
@@ -166,6 +193,7 @@ void test_class_()
166193
context
167194
.set("X", X_class)
168195
.set("Y", Y_class)
196+
.set("E", E_class)
169197
;
170198

171199
check_eq("X object", run_script<int>(context, "x = new X(); x.var += x.konst"), 100);
@@ -248,6 +276,9 @@ void test_class_()
248276
v8pp::class_<Y, Traits>::destroy(isolate);
249277
check_eq("Y count after class_<Y>::destroy", Y::instance_count,
250278
1 + 2 * use_shared_ptr); // y1 + (y2 + y3 when use_shared_ptr)
279+
280+
check_eq("E ctor class with exception", run_script<std::string>(context, "retError = ""; try { var e = new E(); } catch(err) { retError = err; } retError"), "MyException");
281+
check_eq("E ctor class without exception", run_script<std::string>(context, "retError = ""; try { var e = new E(1); } catch(err) { retError = err; } retError"), "");
251282
}
252283

253284
template<typename Traits>
@@ -370,4 +401,4 @@ void test_class()
370401

371402
test_const_instance_in_module<v8pp::raw_ptr_traits>();
372403
test_const_instance_in_module<v8pp::shared_ptr_traits>();
373-
}
404+
}

v8pp/class.hpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,18 @@ class object_registry final : public class_info
259259
//assert(false && "create not allowed");
260260
throw std::runtime_error(class_name() + " has no constructor");
261261
}
262-
return wrap_object(ctor_(args), true);
262+
263+
v8::EscapableHandleScope scope(args.GetIsolate());
264+
v8::TryCatch try_catch(args.GetIsolate());
265+
v8::Local<v8::Object> result;
266+
267+
auto ctorRes = ctor_(args);
268+
if (try_catch.HasCaught())
269+
try_catch.ReThrow();
270+
else
271+
result = wrap_object(ctorRes, true);
272+
273+
return scope.Escape(result);
263274
}
264275

265276
pointer_type unwrap_object(v8::Local<v8::Value> value)

0 commit comments

Comments
 (0)