From fd0f925459e68e2efa615cd0bb463a1b676d68f9 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Mon, 24 Oct 2016 22:14:39 -0700 Subject: [PATCH] ircd::js: Add handle typedefs in object wrappers to clean up arguments. --- include/ircd/js/call.h | 12 ++-- include/ircd/js/del.h | 4 +- include/ircd/js/for_each.h | 12 ++-- include/ircd/js/function.h | 3 + include/ircd/js/get.h | 4 +- include/ircd/js/has.h | 4 +- include/ircd/js/id.h | 3 + include/ircd/js/object.h | 7 +- include/ircd/js/script.h | 3 + include/ircd/js/set.h | 4 +- include/ircd/js/string.h | 3 + include/ircd/js/trap.h | 16 ++--- include/ircd/js/value.h | 3 + include/ircd/js/vector.h | 36 ++++++++++ ircd/js.cc | 137 +++++++++++++++++++------------------ 15 files changed, 153 insertions(+), 98 deletions(-) diff --git a/include/ircd/js/call.h b/include/ircd/js/call.h index 987cd014d..5d4c72da8 100644 --- a/include/ircd/js/call.h +++ b/include/ircd/js/call.h @@ -27,23 +27,23 @@ namespace js { value call(const object &obj, - const JS::HandleFunction &func, - const JS::HandleValueArray &args = JS::HandleValueArray::empty()); + const function::handle &func, + const vector::handle &args = {}); value call(const object &obj, - const JS::HandleValue &val, - const JS::HandleValueArray &args = JS::HandleValueArray::empty()); + const value::handle &val, + const vector::handle &args = {}); value call(const object &obj, const char *const &name, - const JS::HandleValueArray &args = JS::HandleValueArray::empty()); + const vector::handle &args = {}); value call(const object &obj, const std::string &name, - const JS::HandleValueArray &args = JS::HandleValueArray::empty()); + const vector::handle &args = {}); } // namespace js } // namespace ircd diff --git a/include/ircd/js/del.h b/include/ircd/js/del.h index 285bdb87f..4a648af46 100644 --- a/include/ircd/js/del.h +++ b/include/ircd/js/del.h @@ -25,8 +25,8 @@ namespace ircd { namespace js { -void del(const JS::HandleObject &obj, const id &id); -void del(const JS::HandleObject &src, const char *const path); +void del(const object::handle &obj, const id::handle &id); +void del(const object::handle &src, const char *const path); } // namespace js } // namespace ircd diff --git a/include/ircd/js/for_each.h b/include/ircd/js/for_each.h index bfd1ba367..8b1514cbe 100644 --- a/include/ircd/js/for_each.h +++ b/include/ircd/js/for_each.h @@ -29,13 +29,13 @@ using closure_id = std::function; using closure_key_val = std::function; using closure_mutable_key_val = std::function; -void for_each(const object &, const closure_id &); -void for_each(const object &, const closure_key_val &); -void for_each(object &, const closure_mutable_key_val &); +void for_each(object::handle, const closure_id &); +void for_each(object::handle, const closure_key_val &); +void for_each(object::handle_mutable, const closure_mutable_key_val &); inline void -for_each(object &obj, +for_each(object::handle_mutable obj, const closure_mutable_key_val &closure) { for_each(obj, [&obj, &closure] @@ -48,7 +48,7 @@ for_each(object &obj, } inline void -for_each(const object &obj, +for_each(object::handle obj, const closure_key_val &closure) { for_each(obj, [&obj, &closure] @@ -61,7 +61,7 @@ for_each(const object &obj, } inline void -for_each(const object &obj, +for_each(object::handle obj, const closure_id &closure) { JS::Rooted props(*cx, JS::IdVector(cx->ptr())); diff --git a/include/ircd/js/function.h b/include/ircd/js/function.h index 9fa326632..1b381262a 100644 --- a/include/ircd/js/function.h +++ b/include/ircd/js/function.h @@ -32,6 +32,9 @@ string name(const JSFunction &); struct function :JS::Rooted { + using handle = JS::HandleFunction; + using handle_mutable = JS::MutableHandleFunction; + operator JSObject *() const; explicit operator script() const; explicit operator string() const; diff --git a/include/ircd/js/get.h b/include/ircd/js/get.h index 05a24e8a0..f9fb70954 100644 --- a/include/ircd/js/get.h +++ b/include/ircd/js/get.h @@ -25,8 +25,8 @@ namespace ircd { namespace js { -value get(const JS::HandleObject &obj, const id &id); -value get(const JS::HandleObject &src, const char *const path); +value get(const object::handle &obj, const id &id); +value get(const object::handle &src, const char *const path); } // namespace js } // namespace ircd diff --git a/include/ircd/js/has.h b/include/ircd/js/has.h index 7b9d69b6c..facc22c56 100644 --- a/include/ircd/js/has.h +++ b/include/ircd/js/has.h @@ -25,8 +25,8 @@ namespace ircd { namespace js { -bool has(const JS::HandleObject &obj, const id &id); -bool has(const JS::HandleObject &src, const char *const path); +bool has(const object::handle &obj, const id::handle &id); +bool has(const object::handle &src, const char *const path); } // namespace js } // namespace ircd diff --git a/include/ircd/js/id.h b/include/ircd/js/id.h index c8a5a496f..e0a97e4c3 100644 --- a/include/ircd/js/id.h +++ b/include/ircd/js/id.h @@ -28,6 +28,9 @@ namespace js { struct id :JS::Rooted { + using handle = JS::HandleId; + using handle_mutable = JS::MutableHandleId; + id(const JSProtoKey &); id(const uint32_t &); id(const jsid &); diff --git a/include/ircd/js/object.h b/include/ircd/js/object.h index e85d19b29..0db4b2e21 100644 --- a/include/ircd/js/object.h +++ b/include/ircd/js/object.h @@ -28,14 +28,17 @@ namespace js { struct object :JS::Rooted { + using handle = JS::HandleObject; + using handle_mutable = JS::MutableHandleObject; + operator JS::Value() const; // new object object(const JSClass *const &, const object &proto); object(const JSClass *const &); - object(const JS::MutableHandleObject &h): object{h.get()} {} - object(const JS::HandleObject &h): object{h.get()} {} + object(const object::handle_mutable &h): object{h.get()} {} + object(const object::handle &h): object{h.get()} {} explicit object(const value &); object(JSFunction *const &); object(JSObject *const &); diff --git a/include/ircd/js/script.h b/include/ircd/js/script.h index c96df1d65..73302278e 100644 --- a/include/ircd/js/script.h +++ b/include/ircd/js/script.h @@ -28,6 +28,9 @@ namespace js { struct script :JS::Rooted { + using handle = JS::HandleScript; + using handle_mutable = JS::MutableHandleScript; + value operator()(JS::AutoObjectVector &stack) const; value operator()() const; diff --git a/include/ircd/js/set.h b/include/ircd/js/set.h index 8b0192b8c..16e712b1a 100644 --- a/include/ircd/js/set.h +++ b/include/ircd/js/set.h @@ -25,8 +25,8 @@ namespace ircd { namespace js { -void set(const JS::HandleObject &obj, const id &id, const value &val); -void set(const JS::HandleObject &src, const char *const path, const value &val); +void set(const object::handle &obj, const id::handle &id, const value &val); +void set(const object::handle &src, const char *const path, const value &val); } // namespace js } // namespace ircd diff --git a/include/ircd/js/string.h b/include/ircd/js/string.h index 39d3901ab..63d1a1b48 100644 --- a/include/ircd/js/string.h +++ b/include/ircd/js/string.h @@ -28,6 +28,9 @@ namespace js { struct string :JS::Rooted { + using handle = JS::HandleString; + using handle_mutable = JS::MutableHandleString; + // SpiderMonkey may use utf-16/char16_t strings; these will help you then static size_t convert(const char16_t *const &, char *const &buf, const size_t &max); static std::string convert(const char16_t *const &); diff --git a/include/ircd/js/trap.h b/include/ircd/js/trap.h index cd30945d6..c40a76b87 100644 --- a/include/ircd/js/trap.h +++ b/include/ircd/js/trap.h @@ -31,14 +31,14 @@ class trap std::unique_ptr _class; // Override these to define JS objects in C - 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 &); - virtual bool on_enu(const JSObject &); - virtual value on_call(const JSObject &, const JS::CallArgs &); - virtual void on_ctor(object &, const JS::CallArgs &); + virtual value on_call(object::handle, const args &); + virtual value on_set(object::handle, id::handle, value::handle); + virtual value on_get(object::handle, id::handle, value::handle); + virtual void on_add(object::handle, id::handle, value::handle); + virtual bool on_del(object::handle, id::handle); + virtual bool on_has(object::handle, id::handle); + virtual bool on_enu(object::handle); + virtual void on_ctor(object &, const args &); private: void host_exception(const char *fmt, ...) const AFP(2, 3); diff --git a/include/ircd/js/value.h b/include/ircd/js/value.h index 12a5bd254..c76771202 100644 --- a/include/ircd/js/value.h +++ b/include/ircd/js/value.h @@ -34,6 +34,9 @@ std::string native(const JSString *const &); struct value :JS::Rooted { + using handle = JS::HandleValue; + using handle_mutable = JS::MutableHandleValue; + explicit operator JSType() const; explicit operator std::string() const; diff --git a/include/ircd/js/vector.h b/include/ircd/js/vector.h index 1a26f1161..3681b2a8c 100644 --- a/include/ircd/js/vector.h +++ b/include/ircd/js/vector.h @@ -27,11 +27,47 @@ namespace js { template struct vector +:JS::AutoVectorRooter +{ + using jsapi_type = T; + using local_type = T; + + vector(const size_t &size) + :JS::AutoVectorRooter{*cx} + { + this->resize(size); + } + + vector() + :JS::AutoVectorRooter{*cx} + { + } + + vector(vector &&other) noexcept + :JS::AutoVectorRooter{*cx} + { + this->reserve(other.length()); + for(auto &t : other) + this->infallibleAppend(t); + + other.clear(); + } +}; + +template<> +struct vector :JS::AutoVectorRooter { using jsapi_type = JS::Value; using local_type = value; + struct handle + :JS::HandleValueArray + { + using JS::HandleValueArray::HandleValueArray; + handle(): JS::HandleValueArray{JS::HandleValueArray::empty()} {} + }; + // Construct vector from initializer list of raw `JS::Value` // ex: JS::Value a; vector foo {{ a, a, ... }}; vector(const std::initializer_list &list) diff --git a/ircd/js.cc b/ircd/js.cc index 886b8db43..86f433b8a 100644 --- a/ircd/js.cc +++ b/ircd/js.cc @@ -211,15 +211,15 @@ noexcept try { assert(&our(c) == cx); - auto ca(JS::CallArgsFromVp(argc, argv)); - object that(ca.callee()); + const struct args args(argc, argv); + object that(args.callee()); auto &trap(from(that)); trap.debug("ctor: '%s'", trap.name().c_str()); - object ret(JS_NewObjectForConstructor(*cx, &trap.jsclass(), ca)); - trap.on_ctor(ret, ca); - ca.rval().set(ret); + object ret(JS_NewObjectForConstructor(*cx, &trap.jsclass(), args)); + trap.on_ctor(ret, args); + args.rval().set(ret); return true; } catch(const jserror &e) @@ -243,9 +243,9 @@ noexcept try { assert(&our(c) == cx); - auto ca(JS::CallArgsFromVp(argc, argv)); - object that(ca.computeThis(c)); - object func(ca.callee()); + const struct args args(argc, argv); + object that(args.computeThis(c)); + object func(args.callee()); auto &trap_that(from(that)); auto &trap_func(from(func)); @@ -253,7 +253,7 @@ noexcept try trap_that.debug("call: '%s'", trap_func.name().c_str()); trap_func.debug("call"); - ca.rval().set(trap_func.on_call(*func.get(), ca)); + args.rval().set(trap_func.on_call(func, args)); return true; } catch(const jserror &e) @@ -278,7 +278,7 @@ noexcept try auto &trap(from(obj)); trap.debug("enu"); - return trap.on_enu(*obj.get()); + return trap.on_enu(obj); } catch(const jserror &e) { @@ -303,7 +303,7 @@ noexcept try auto &trap(from(obj)); trap.debug("has: '%s'", string(id).c_str()); - *resolved = trap.on_has(*obj.get(), id.get()); + *resolved = trap.on_has(obj, id); return true; } catch(const jserror &e) @@ -331,7 +331,7 @@ noexcept try auto &trap(from(obj)); trap.debug("del: '%s'", string(id).c_str()); - if(trap.on_del(*obj.get(), id.get())) + if(trap.on_del(obj, id)) res.succeed(); return true; @@ -361,7 +361,8 @@ noexcept try auto &trap(from(obj)); trap.debug("get: '%s'", string(id).c_str()); - val.set(trap.on_get(*obj.get(), id.get(), val)); + const value ret(trap.on_get(obj, id, val)); + val.set(ret.get()); return true; } catch(const jserror &e) @@ -390,7 +391,8 @@ noexcept try auto &trap(from(obj)); trap.debug("set: '%s'", string(id).c_str()); - val.set(trap.on_set(*obj.get(), id.get(), val)); + const value ret(trap.on_set(obj, id, val)); + val.set(ret.get()); if(!val.isUndefined()) res.succeed(); @@ -421,7 +423,7 @@ noexcept try auto &trap(from(obj)); trap.debug("add: '%s'", string(id).c_str()); - trap.on_add(*obj.get(), id.get(), val.get()); + trap.on_add(obj, id, val); return true; } catch(const jserror &e) @@ -546,59 +548,58 @@ const void ircd::js::trap::on_ctor(object &obj, - const JS::CallArgs &) + const args &) { } -ircd::js::value -ircd::js::trap::on_call(const JSObject &, - const JS::CallArgs &) -{ - return {}; -} - bool -ircd::js::trap::on_enu(const JSObject &obj) -{ - return false; -} - -bool -ircd::js::trap::on_has(const JSObject &obj, - const jsid &id) -{ - return false; -} - -bool -ircd::js::trap::on_del(const JSObject &obj, - const jsid &id) +ircd::js::trap::on_enu(object::handle) { return true; } -JS::Value -ircd::js::trap::on_get(const JSObject &obj, - const jsid &id, - const JS::Value &val) +bool +ircd::js::trap::on_has(object::handle, + id::handle) +{ + return false; +} + +bool +ircd::js::trap::on_del(object::handle, + id::handle) +{ + return true; +} + +void +ircd::js::trap::on_add(object::handle, + id::handle, + value::handle) +{ +} + +ircd::js::value +ircd::js::trap::on_get(object::handle, + id::handle, + value::handle val) { return val; } -JS::Value -ircd::js::trap::on_set(const JSObject &obj, - const jsid &id, - const JS::Value &val) +ircd::js::value +ircd::js::trap::on_set(object::handle, + id::handle, + value::handle val) { return val; } -JS::Value -ircd::js::trap::on_add(const JSObject &obj, - const jsid &id, - const JS::Value &val) +ircd::js::value +ircd::js::trap::on_call(object::handle, + const args &) { - return val; + return {}; } /////////////////////////////////////////////////////////////////////////////// @@ -737,8 +738,8 @@ const ircd::js::value ircd::js::call(const object &obj, - const JS::HandleFunction &func, - const JS::HandleValueArray &args) + const function::handle &func, + const vector::handle &args) { value ret; if(!JS_CallFunction(*cx, obj, func, args, &ret)) @@ -749,8 +750,8 @@ ircd::js::call(const object &obj, ircd::js::value ircd::js::call(const object &obj, - const JS::HandleValue &val, - const JS::HandleValueArray &args) + const value::handle &val, + const vector::handle &args) { value ret; if(!JS_CallFunctionValue(*cx, obj, val, args, &ret)) @@ -762,7 +763,7 @@ ircd::js::call(const object &obj, ircd::js::value ircd::js::call(const object &obj, const char *const &name, - const JS::HandleValueArray &args) + const vector::handle &args) { value ret; if(!JS_CallFunctionName(*cx, obj, name, args, &ret)) @@ -774,7 +775,7 @@ ircd::js::call(const object &obj, ircd::js::value ircd::js::call(const object &obj, const std::string &name, - const JS::HandleValueArray &args) + const vector::handle &args) { return call(obj, name.c_str(), args); } @@ -785,7 +786,7 @@ ircd::js::call(const object &obj, // void -ircd::js::del(const JS::HandleObject &src, +ircd::js::del(const object::handle &src, const char *const path) { value val; @@ -812,8 +813,8 @@ ircd::js::del(const JS::HandleObject &src, } void -ircd::js::del(const JS::HandleObject &obj, - const id &id) +ircd::js::del(const object::handle &obj, + const id::handle &id) { JS::ObjectOpResult res; if(!JS_DeletePropertyById(*cx, obj, id, res)) @@ -829,7 +830,7 @@ ircd::js::del(const JS::HandleObject &obj, // void -ircd::js::set(const JS::HandleObject &src, +ircd::js::set(const object::handle &src, const char *const path, const value &val) { @@ -862,8 +863,8 @@ ircd::js::set(const JS::HandleObject &src, } void -ircd::js::set(const JS::HandleObject &obj, - const id &id, +ircd::js::set(const object::handle &obj, + const id::handle &id, const value &val) { if(!JS_SetPropertyById(*cx, obj, id, val)) @@ -876,7 +877,7 @@ ircd::js::set(const JS::HandleObject &obj, // ircd::js::value -ircd::js::get(const JS::HandleObject &src, +ircd::js::get(const object::handle &src, const char *const path) { value ret; @@ -899,7 +900,7 @@ ircd::js::get(const JS::HandleObject &src, } ircd::js::value -ircd::js::get(const JS::HandleObject &obj, +ircd::js::get(const object::handle &obj, const id &id) { value ret; @@ -915,7 +916,7 @@ ircd::js::get(const JS::HandleObject &obj, // bool -ircd::js::has(const JS::HandleObject &src, +ircd::js::has(const object::handle &src, const char *const path) { bool ret(true); @@ -945,8 +946,8 @@ ircd::js::has(const JS::HandleObject &src, } bool -ircd::js::has(const JS::HandleObject &obj, - const id &id) +ircd::js::has(const object::handle &obj, + const id::handle &id) { bool ret; if(!JS_HasPropertyById(*cx, obj, id, &ret))