0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2025-01-13 08:23:56 +01:00

ircd::js: Improve trap exceptions; noexcept all jsapi callbacks.

This commit is contained in:
Jason Volk 2016-10-17 18:43:23 -07:00
parent 4171a9c834
commit 7fa3777a57
4 changed files with 209 additions and 43 deletions

View file

@ -31,7 +31,7 @@ struct compartment
using closure = std::function<void (JSCompartment *)>;
private:
static void handle_iterate(JSRuntime *, void *, JSCompartment *);
static void handle_iterate(JSRuntime *, void *, JSCompartment *) noexcept;
context *c;
JSCompartment *prev;

View file

@ -28,15 +28,18 @@ namespace js {
class runtime
:custom_ptr<JSRuntime>
{
static void handle_error(JSContext *, const char *msg, JSErrorReport *);
static void handle_out_of_memory(JSContext *, void *);
static void handle_large_allocation_failure(void *);
static void handle_gc(JSRuntime *, JSGCStatus, void *);
static void handle_finalize(JSFreeOp *, JSFinalizeStatus, bool is_compartment, void *);
static void handle_compartment_name(JSRuntime *, JSCompartment *, char *buf, size_t);
static void handle_compartment_destroy(JSFreeOp *, JSCompartment *);
static bool handle_context(JSContext *, uint op, void *);
static bool handle_interrupt(JSContext *);
static void handle_error(JSContext *, const char *msg, JSErrorReport *) noexcept;
static void handle_out_of_memory(JSContext *, void *) noexcept;
static void handle_large_allocation_failure(void *) noexcept;
static void handle_gc(JSRuntime *, JSGCStatus, void *) noexcept;
static void handle_finalize(JSFreeOp *, JSFinalizeStatus, bool is_compartment, void *) noexcept;
static void handle_compartment_name(JSRuntime *, JSCompartment *, char *buf, size_t) noexcept;
static void handle_compartment_destroy(JSFreeOp *, JSCompartment *) noexcept;
static bool handle_context(JSContext *, uint op, void *) noexcept;
static bool handle_interrupt(JSContext *) noexcept;
friend struct error_handler;
struct error_handler *error_handler; // Error reports directed at handler
public:
struct opts

View file

@ -31,38 +31,42 @@ class trap
const JSClass _class;
// Override these to define JS objects in C
virtual bool on_add(const JSObject &, const jsid &, const JS::Value &);
virtual bool on_set(const JSObject &, const jsid &, JS::MutableHandleValue);
virtual bool on_get(const JSObject &, const jsid &, JS::MutableHandleValue);
virtual JS::Value on_add(const JSObject &, const jsid &, const JS::Value &);
virtual JS::Value on_set(const JSObject &, const jsid &, const JS::Value &);
virtual JS::Value on_get(const JSObject &, const jsid &, const JS::Value &);
virtual bool on_del(const JSObject &, const jsid &);
virtual bool on_has(const JSObject &, const jsid &, bool &resolved);
virtual bool on_has(const JSObject &, const jsid &);
virtual bool on_enu(const JSObject &);
virtual bool on_call(const unsigned &argc, JS::Value &argv);
virtual bool on_ctor(const unsigned &argc, JS::Value &argv);
private:
void host_exception(const char *fmt, ...) const AFP(2, 3);
void debug(const char *fmt, ...) const AFP(2, 3);
static trap &from(const JSObject &);
static trap &from(const JS::HandleObject &);
// Internal callback interface
static void handle_trace(JSTracer *, JSObject *);
static bool handle_inst(JSContext *, JS::HandleObject, JS::MutableHandleValue, bool *yesno);
static bool handle_add(JSContext *, JS::HandleObject, JS::HandleId, JS::HandleValue);
static bool handle_set(JSContext *, JS::HandleObject, JS::HandleId, JS::MutableHandleValue, JS::ObjectOpResult &);
static bool handle_get(JSContext *, JS::HandleObject, JS::HandleId, JS::MutableHandleValue);
static bool handle_del(JSContext *, JS::HandleObject, JS::HandleId, JS::ObjectOpResult &);
static bool handle_has(JSContext *, JS::HandleObject, JS::HandleId, bool *resolved);
static bool handle_enu(JSContext *, JS::HandleObject);
static bool handle_call(JSContext *, unsigned argc, JS::Value *argv);
static bool handle_ctor(JSContext *, unsigned argc, JS::Value *argv);
static void handle_dtor(JSFreeOp *, JSObject *);
static void handle_trace(JSTracer *, JSObject *) noexcept;
static bool handle_inst(JSContext *, JS::HandleObject, JS::MutableHandleValue, bool *yesno) noexcept;
static bool handle_add(JSContext *, JS::HandleObject, JS::HandleId, JS::HandleValue) noexcept;
static bool handle_set(JSContext *, JS::HandleObject, JS::HandleId, JS::MutableHandleValue, JS::ObjectOpResult &) noexcept;
static bool handle_get(JSContext *, JS::HandleObject, JS::HandleId, JS::MutableHandleValue) noexcept;
static bool handle_del(JSContext *, JS::HandleObject, JS::HandleId, JS::ObjectOpResult &) noexcept;
static bool handle_has(JSContext *, JS::HandleObject, JS::HandleId, bool *resolved) noexcept;
static bool handle_enu(JSContext *, JS::HandleObject) noexcept;
static bool handle_call(JSContext *, unsigned argc, JS::Value *argv) noexcept;
static bool handle_ctor(JSContext *, unsigned argc, JS::Value *argv) noexcept;
static void handle_dtor(JSFreeOp *, JSObject *) noexcept;
public:
auto &name() const { return _name; }
auto &jsclass() const { return _class; }
operator const JSClass &() const { return jsclass(); }
operator const JSClass *() const { return &jsclass(); }
JSObject *operator()(JS::HandleObject proto);
JSObject *operator()();

View file

@ -157,35 +157,73 @@ ircd::js::trap::operator()(JS::HandleObject proto)
void
ircd::js::trap::handle_dtor(JSFreeOp *const op,
JSObject *const obj)
noexcept try
{
//debug("dtor");
auto &trap(from(*obj));
trap.debug("dtor");
}
catch(const jserror &e)
{
e.set_pending();
return;
}
catch(const std::exception &e)
{
auto &trap(from(*obj));
trap.host_exception("dtor: %s", e.what());
return;
}
bool
ircd::js::trap::handle_ctor(JSContext *const c,
unsigned argc,
JS::Value *const argv)
noexcept try
{
assert(&our(c) == cx);
//debug("ctor");
return false;
}
catch(const jserror &e)
{
e.set_pending();
return false;
}
catch(const std::exception &e)
{
//auto &trap(from(obj));
//trap.host_exception("call: %s", e.what());
return false;
}
bool
ircd::js::trap::handle_call(JSContext *const c,
unsigned argc,
JS::Value *const argv)
noexcept try
{
assert(&our(c) == cx);
//debug("call");
return false;
}
catch(const jserror &e)
{
e.set_pending();
return false;
}
catch(const std::exception &e)
{
//auto &trap(from(obj));
//trap.host_exception("call: %s", e.what());
return false;
}
bool
ircd::js::trap::handle_enu(JSContext *const c,
JS::HandleObject obj)
noexcept try
{
assert(&our(c) == cx);
@ -193,18 +231,44 @@ ircd::js::trap::handle_enu(JSContext *const c,
trap.debug("enu");
return trap.on_enu(*obj.get());
}
catch(const jserror &e)
{
e.set_pending();
return false;
}
catch(const std::exception &e)
{
auto &trap(from(obj));
trap.host_exception("enu: %s", e.what());
return false;
}
bool
ircd::js::trap::handle_has(JSContext *const c,
JS::HandleObject obj,
JS::HandleId id,
bool *const resolved)
noexcept try
{
assert(&our(c) == cx);
auto &trap(from(obj));
trap.debug("has: %s", string(id).c_str());
return trap.on_has(*obj.get(), id.get(), *resolved);
*resolved = trap.on_has(*obj.get(), id.get());
return true;
}
catch(const jserror &e)
{
e.set_pending();
return false;
}
catch(const std::exception &e)
{
auto &trap(from(obj));
trap.host_exception("has: '%s': %s",
string(id).c_str(),
e.what());
return false;
}
bool
@ -212,29 +276,57 @@ ircd::js::trap::handle_del(JSContext *const c,
JS::HandleObject obj,
JS::HandleId id,
JS::ObjectOpResult &res)
noexcept try
{
assert(&our(c) == cx);
auto &trap(from(obj));
trap.debug("del: %s", string(id).c_str());
if(!trap.on_del(*obj.get(), id.get()))
return false;
if(trap.on_del(*obj.get(), id.get()))
res.succeed();
res.succeed();
return true;
}
catch(const jserror &e)
{
e.set_pending();
return false;
}
catch(const std::exception &e)
{
auto &trap(from(obj));
trap.host_exception("del '%s': %s",
string(id).c_str(),
e.what());
return false;
}
bool
ircd::js::trap::handle_get(JSContext *const c,
JS::HandleObject obj,
JS::HandleId id,
JS::MutableHandleValue val)
noexcept try
{
assert(&our(c) == cx);
auto &trap(from(obj));
trap.debug("get: %s", string(id).c_str());
return trap.on_get(*obj.get(), id.get(), val);
val.set(trap.on_get(*obj.get(), id.get(), val));
return true;
}
catch(const jserror &e)
{
e.set_pending();
return false;
}
catch(const std::exception &e)
{
auto &trap(from(obj));
trap.host_exception("get: '%s': %s",
string(id).c_str(),
e.what());
return false;
}
bool
@ -243,12 +335,30 @@ ircd::js::trap::handle_set(JSContext *const c,
JS::HandleId id,
JS::MutableHandleValue val,
JS::ObjectOpResult &res)
noexcept try
{
assert(&our(c) == cx);
auto &trap(from(obj));
trap.debug("set: %s", string(id).c_str());
return trap.on_get(*obj.get(), id.get(), val);
val.set(trap.on_set(*obj.get(), id.get(), val));
if(!val.isUndefined())
res.succeed();
return true;
}
catch(const jserror &e)
{
e.set_pending();
return false;
}
catch(const std::exception &e)
{
auto &trap(from(obj));
trap.host_exception("get: '%s': %s",
string(id).c_str(),
e.what());
return false;
}
bool
@ -256,12 +366,27 @@ ircd::js::trap::handle_add(JSContext *const c,
JS::HandleObject obj,
JS::HandleId id,
JS::HandleValue val)
noexcept try
{
assert(&our(c) == cx);
auto &trap(from(obj));
trap.debug("add: %s", string(id).c_str());
return trap.on_add(*obj.get(), id.get(), val.get());
trap.on_add(*obj.get(), id.get(), val.get());
return true;
}
catch(const jserror &e)
{
e.set_pending();
return false;
}
catch(const std::exception &e)
{
auto &trap(from(obj));
trap.host_exception("add: '%s': %s",
string(id).c_str(),
e.what());
return false;
}
bool
@ -269,6 +394,7 @@ ircd::js::trap::handle_inst(JSContext *const c,
JS::HandleObject obj,
JS::MutableHandleValue val,
bool *const has_instance)
noexcept try
{
assert(&our(c) == cx);
@ -277,11 +403,36 @@ ircd::js::trap::handle_inst(JSContext *const c,
return false;
}
catch(const jserror &e)
{
e.set_pending();
return false;
}
catch(const std::exception &e)
{
auto &trap(from(obj));
trap.host_exception("inst: %s", e.what());
return false;
}
void
ircd::js::trap::handle_trace(JSTracer *const tracer,
JSObject *const obj)
noexcept try
{
auto &trap(from(*obj));
trap.debug("trace");
}
catch(const jserror &e)
{
e.set_pending();
return;
}
catch(const std::exception &e)
{
auto &trap(from(*obj));
trap.host_exception("trace: %s", e.what());
return;
}
ircd::js::trap &
@ -366,8 +517,7 @@ ircd::js::trap::on_enu(const JSObject &obj)
bool
ircd::js::trap::on_has(const JSObject &obj,
const jsid &id,
bool &resolved)
const jsid &id)
{
return false;
}
@ -379,28 +529,28 @@ ircd::js::trap::on_del(const JSObject &obj,
return false;
}
bool
JS::Value
ircd::js::trap::on_get(const JSObject &obj,
const jsid &id,
JS::MutableHandleValue val)
const JS::Value &val)
{
return false;
return val;
}
bool
JS::Value
ircd::js::trap::on_set(const JSObject &obj,
const jsid &id,
JS::MutableHandleValue val)
const JS::Value &val)
{
return false;
return val;
}
bool
JS::Value
ircd::js::trap::on_add(const JSObject &obj,
const jsid &id,
const JS::Value &val)
{
return false;
return val;
}
///////////////////////////////////////////////////////////////////////////////
@ -731,6 +881,7 @@ void
ircd::js::compartment::handle_iterate(JSRuntime *const rt,
void *const priv,
JSCompartment *const c)
noexcept
{
const auto &closure(*static_cast<compartment::closure *>(priv));
closure(c);
@ -905,6 +1056,7 @@ noexcept
bool
ircd::js::runtime::handle_interrupt(JSContext *const ctx)
noexcept
{
auto &runtime(our(ctx).runtime());
JS_SetInterruptCallback(runtime, nullptr);
@ -915,6 +1067,7 @@ bool
ircd::js::runtime::handle_context(JSContext *const c,
const uint op,
void *const priv)
noexcept
{
return true;
}
@ -922,6 +1075,7 @@ ircd::js::runtime::handle_context(JSContext *const c,
void
ircd::js::runtime::handle_compartment_destroy(JSFreeOp *const fop,
JSCompartment *const compartment)
noexcept
{
}
@ -930,6 +1084,7 @@ ircd::js::runtime::handle_compartment_name(JSRuntime *const rt,
JSCompartment *const compartment,
char *const buf,
const size_t max)
noexcept
{
}
@ -938,6 +1093,7 @@ ircd::js::runtime::handle_finalize(JSFreeOp *const fop,
const JSFinalizeStatus status,
const bool is_compartment,
void *const priv)
noexcept
{
log.debug("fop(%p): %s %s",
(const void *)fop,
@ -949,6 +1105,7 @@ void
ircd::js::runtime::handle_gc(JSRuntime *const rt,
const JSGCStatus status,
void *const priv)
noexcept
{
log.debug("runtime(%p): GC %s",
(const void *)rt,
@ -957,6 +1114,7 @@ ircd::js::runtime::handle_gc(JSRuntime *const rt,
void
ircd::js::runtime::handle_large_allocation_failure(void *const priv)
noexcept
{
log.error("Large allocation failure");
}
@ -964,6 +1122,7 @@ ircd::js::runtime::handle_large_allocation_failure(void *const priv)
void
ircd::js::runtime::handle_out_of_memory(JSContext *const ctx,
void *const priv)
noexcept
{
log.error("JSContext(%p): out of memory", (const void *)ctx);
}