From ee5f48672f3f26be7a8c2da83a0741a5122e31bf Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Tue, 1 Nov 2016 07:21:30 -0700 Subject: [PATCH] ircd::js: Various type and conversion tweaks. --- include/ircd/js/function.h | 8 +-- include/ircd/js/id.h | 14 +++++ include/ircd/js/object.h | 110 +++++++++++++++++++------------------ include/ircd/js/string.h | 2 +- include/ircd/js/value.h | 24 ++++---- include/ircd/js/vector.h | 9 ++- 6 files changed, 97 insertions(+), 70 deletions(-) diff --git a/include/ircd/js/function.h b/include/ircd/js/function.h index 9ebdd5aae..51080c0a1 100644 --- a/include/ircd/js/function.h +++ b/include/ircd/js/function.h @@ -42,7 +42,7 @@ struct function explicit operator string() const; // js::value/js::object == lifetime::stack - js::value operator()(const js::object &, const vector::handle &args) const; + js::value operator()(const js::object &, const vector::handle &) const; template js::value operator()(const js::object &, args&&...) const; // new function @@ -136,16 +136,16 @@ const std::forward(a)... }}; - return call(*this, that, decltype(argv)::handle()); + return call(*this, that, decltype(argv)::handle(argv)); } template js::value function::operator()(const js::object &that, - const vector::handle &args) + const vector::handle &argv) const { - return call(*this, that, args); + return call(*this, that, argv); } template diff --git a/include/ircd/js/id.h b/include/ircd/js/id.h index 022824ad6..baaf101e5 100644 --- a/include/ircd/js/id.h +++ b/include/ircd/js/id.h @@ -35,6 +35,8 @@ struct id explicit id(const std::string &); // creates new id id(const typename string::handle &); id(const typename value::handle &); + id(const value &); + id(const string &); id(const JSProtoKey &); id(const uint32_t &); id(const jsid &); @@ -97,6 +99,18 @@ id::id(const char *const &str) throw type_error("Failed to create id from native string"); } +template +id::id(const string &h) +:id::id(typename string::handle(h)) +{ +} + +template +id::id(const value &h) +:id::id(typename value::handle(h)) +{ +} + template id::id(const typename value::handle &h) :id::root::type{} diff --git a/include/ircd/js/object.h b/include/ircd/js/object.h index 8b8cfd9c9..b4c906a73 100644 --- a/include/ircd/js/object.h +++ b/include/ircd/js/object.h @@ -24,6 +24,27 @@ namespace ircd { namespace js { + +using object_handle = JS::Handle; +using object_handle_mutable = JS::MutableHandle; + +// Get the JSClass from which the trap can also be derived. +const JSClass &jsclass(const object_handle &); + +bool is_extensible(const object_handle &); +bool is_array(const object_handle &); +uint32_t size(const object_handle &); + +// Private data slot (trap must have flag JSCLASS_HAS_PRIVATE) +template T &priv(const object_handle &); +void priv(const object_handle &, void *const &); +void priv(const object_handle &, const void *const &); + +bool deep_freeze(const object_handle &); +bool freeze(const object_handle &); + +IRCD_STRONG_TYPEDEF(uint, reserved) + namespace basic { template @@ -32,8 +53,8 @@ struct object { IRCD_OVERLOAD(array) IRCD_OVERLOAD(uninitialized) - using handle = typename root::handle; - using handle_mutable = typename root::handle_mutable; + using handle = object_handle; + using handle_mutable = object_handle_mutable; operator JS::Value() const; @@ -58,28 +79,10 @@ struct object object(); }; -// Get the JSClass from which the trap can also be derived. -template const JSClass &jsclass(const object &); - -// Private data slot (trap must have flag JSCLASS_HAS_PRIVATE) -template T &priv(const object &); -template void priv(object &, void *const &); -template void priv(object &, const void *const &); - -template bool is_extensible(const object &); -template bool is_array(const object &); -template uint32_t size(const object &); - -template bool deep_freeze(const object &); -template bool freeze(const object &); - } // namespace basic using object = basic::object; using heap_object = basic::object; -using basic::priv; - -IRCD_STRONG_TYPEDEF(uint, reserved) // // Implementation @@ -107,6 +110,8 @@ template object::object(JSObject &obj) :object::root::type{&obj} { + if(unlikely(!this->get())) + throw internal_error("NULL object (ref)"); } template @@ -154,6 +159,8 @@ template::object(const root &o) :object{o.get()} { + if(unlikely(!this->get())) + throw internal_error("NULL object (cross-lifetime)"); } template @@ -208,7 +215,7 @@ template void object::resize(const uint32_t &length) { - if(!JS_SetArrayLength(*cx, &(*this), length)) + if(!JS_SetArrayLength(*cx, *this, length)) throw internal_error("Failed to set array object length"); } @@ -217,11 +224,7 @@ uint32_t object::size() const { - uint32_t ret; - if(!JS_GetArrayLength(*cx, handle(*this), &ret)) - throw internal_error("Failed to get array object length"); - - return ret; + return js::size(*this); } template @@ -231,23 +234,32 @@ const return this->get()? JS::ObjectValue(*this->get()) : JS::NullValue(); } -template -bool -freeze(const object & obj) +} // namespace basic + +inline bool +freeze(const object_handle &obj) { return JS_FreezeObject(*cx, obj); } -template -bool -deep_freeze(const object & obj) +inline bool +deep_freeze(const object_handle &obj) { return JS_DeepFreezeObject(*cx, obj); } -template -bool -is_array(const object & obj) +inline uint32_t +size(const object_handle &obj) +{ + uint32_t ret; + if(!JS_GetArrayLength(*cx, obj, &ret)) + throw internal_error("Failed to get array object length"); + + return ret; +} + +inline bool +is_array(const object_handle &obj) { bool ret; if(!JS_IsArrayObject(*cx, obj, &ret)) @@ -256,9 +268,8 @@ is_array(const object & obj) return ret; } -template -bool -is_extensible(const object & obj) +inline bool +is_extensible(const object_handle &obj) { bool ret; if(!JS_IsExtensible(*cx, obj, &ret)) @@ -267,26 +278,23 @@ is_extensible(const object & obj) return ret; } -template -void -priv(object &obj, +inline void +priv(const object_handle &obj, const void *const &ptr) { - priv(obj, const_cast(ptr)); + JS_SetPrivate(obj, const_cast(ptr)); } -template -void -priv(object &obj, +inline void +priv(const object_handle &obj, void *const &ptr) { JS_SetPrivate(obj, ptr); } -template +template T & -priv(const object &obj) +priv(const object_handle &obj) { const auto &jsc(jsclass(obj)); const auto ret(JS_GetInstancePrivate(*cx, obj, &jsc, nullptr)); @@ -296,9 +304,8 @@ priv(const object &obj) return *reinterpret_cast(ret); } -template -const JSClass & -jsclass(const object &obj) +inline const JSClass & +jsclass(const object_handle &obj) { const auto jsc(JS_GetClass(obj)); if(unlikely(!jsc)) @@ -307,6 +314,5 @@ jsclass(const object &obj) return *const_cast(jsc); } -} // namespace basic } // namespace js } // namespace ircd diff --git a/include/ircd/js/string.h b/include/ircd/js/string.h index 15eb560de..e0a403248 100644 --- a/include/ircd/js/string.h +++ b/include/ircd/js/string.h @@ -48,7 +48,7 @@ struct string bool empty() const; char16_t operator[](const size_t &at) const; - explicit operator std::string() const; + operator std::string() const; operator JS::Value() const; using root::root; diff --git a/include/ircd/js/value.h b/include/ircd/js/value.h index 1e0a7f5b4..c195ca8a9 100644 --- a/include/ircd/js/value.h +++ b/include/ircd/js/value.h @@ -70,15 +70,15 @@ struct value value(const value &); }; -template JSType type(const value &); -template bool undefined(const value &); -template bool is_array(typename value::handle); - } // namespace basic using value = basic::value; using heap_value = basic::value; +template JSType type(const value &); +template bool undefined(const value &val); +template bool is_array(const value &val); + // // Implementation // @@ -317,9 +317,11 @@ const return s? native(s) : throw type_error("Failed to cast to string"); } -template +} // namespace basic + +template bool -is_array(const value &val) +is_array(const value &val) { bool ret; if(!JS_IsArrayObject(*cx, val, &ret)) @@ -328,22 +330,20 @@ is_array(const value &val) return ret; } -template +template bool -undefined(const value &val) +undefined(const value &val) { return type(val) == JSTYPE_VOID; } -template +template JSType -type(const value &val) +type(const value &val) { return JS_TypeOfValue(*cx, val); } -} // namespace basic - inline JS::Value pointer_value(const void *const &ptr) { diff --git a/include/ircd/js/vector.h b/include/ircd/js/vector.h index b1c27cc79..6125d2044 100644 --- a/include/ircd/js/vector.h +++ b/include/ircd/js/vector.h @@ -101,7 +101,8 @@ struct vector infallibleAppend(value(t)); } - vector(const object &obj) + template + vector(const basic::object &obj) :JS::AutoVectorRooter{*cx} { if(!is_array(obj)) @@ -113,6 +114,12 @@ struct vector infallibleAppend(get(obj, i)); } + template + vector(const basic::value &val) + :vector(basic::object(val)) + { + } + vector(const size_t &size) :JS::AutoVectorRooter{*cx} {