0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-17 23:40:57 +01:00

ircd::js: Various type and conversion tweaks.

This commit is contained in:
Jason Volk 2016-11-01 07:21:30 -07:00
parent 6cc89f2613
commit ee5f48672f
6 changed files with 97 additions and 70 deletions

View file

@ -42,7 +42,7 @@ struct function
explicit operator string<L>() const; explicit operator string<L>() const;
// js::value/js::object == lifetime::stack // js::value/js::object == lifetime::stack
js::value operator()(const js::object &, const vector<js::value>::handle &args) const; js::value operator()(const js::object &, const vector<js::value>::handle &) const;
template<class... args> js::value operator()(const js::object &, args&&...) const; template<class... args> js::value operator()(const js::object &, args&&...) const;
// new function // new function
@ -136,16 +136,16 @@ const
std::forward<args>(a)... std::forward<args>(a)...
}}; }};
return call(*this, that, decltype(argv)::handle()); return call(*this, that, decltype(argv)::handle(argv));
} }
template<lifetime L> template<lifetime L>
js::value js::value
function<L>::operator()(const js::object &that, function<L>::operator()(const js::object &that,
const vector<js::value>::handle &args) const vector<js::value>::handle &argv)
const const
{ {
return call(*this, that, args); return call(*this, that, argv);
} }
template<lifetime L> template<lifetime L>

View file

@ -35,6 +35,8 @@ struct id
explicit id(const std::string &); // creates new id explicit id(const std::string &); // creates new id
id(const typename string<L>::handle &); id(const typename string<L>::handle &);
id(const typename value<L>::handle &); id(const typename value<L>::handle &);
id(const value<L> &);
id(const string<L> &);
id(const JSProtoKey &); id(const JSProtoKey &);
id(const uint32_t &); id(const uint32_t &);
id(const jsid &); id(const jsid &);
@ -97,6 +99,18 @@ id<L>::id(const char *const &str)
throw type_error("Failed to create id from native string"); throw type_error("Failed to create id from native string");
} }
template<lifetime L>
id<L>::id(const string<L> &h)
:id<L>::id(typename string<L>::handle(h))
{
}
template<lifetime L>
id<L>::id(const value<L> &h)
:id<L>::id(typename value<L>::handle(h))
{
}
template<lifetime L> template<lifetime L>
id<L>::id(const typename value<L>::handle &h) id<L>::id(const typename value<L>::handle &h)
:id<L>::root::type{} :id<L>::root::type{}

View file

@ -24,6 +24,27 @@
namespace ircd { namespace ircd {
namespace js { namespace js {
using object_handle = JS::Handle<JSObject *>;
using object_handle_mutable = JS::MutableHandle<JSObject *>;
// 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<class T> 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 { namespace basic {
template<lifetime L> template<lifetime L>
@ -32,8 +53,8 @@ struct object
{ {
IRCD_OVERLOAD(array) IRCD_OVERLOAD(array)
IRCD_OVERLOAD(uninitialized) IRCD_OVERLOAD(uninitialized)
using handle = typename root<JSObject *, L>::handle; using handle = object_handle;
using handle_mutable = typename root<JSObject *, L>::handle_mutable; using handle_mutable = object_handle_mutable;
operator JS::Value() const; operator JS::Value() const;
@ -58,28 +79,10 @@ struct object
object(); object();
}; };
// Get the JSClass from which the trap can also be derived.
template<lifetime L> const JSClass &jsclass(const object<L> &);
// Private data slot (trap must have flag JSCLASS_HAS_PRIVATE)
template<class T, lifetime L> T &priv(const object<L> &);
template<lifetime L> void priv(object<L> &, void *const &);
template<lifetime L> void priv(object<L> &, const void *const &);
template<lifetime L> bool is_extensible(const object<L> &);
template<lifetime L> bool is_array(const object<L> &);
template<lifetime L> uint32_t size(const object<L> &);
template<lifetime L> bool deep_freeze(const object<L> &);
template<lifetime L> bool freeze(const object<L> &);
} // namespace basic } // namespace basic
using object = basic::object<lifetime::stack>; using object = basic::object<lifetime::stack>;
using heap_object = basic::object<lifetime::heap>; using heap_object = basic::object<lifetime::heap>;
using basic::priv;
IRCD_STRONG_TYPEDEF(uint, reserved)
// //
// Implementation // Implementation
@ -107,6 +110,8 @@ template<lifetime L>
object<L>::object(JSObject &obj) object<L>::object(JSObject &obj)
:object<L>::root::type{&obj} :object<L>::root::type{&obj}
{ {
if(unlikely(!this->get()))
throw internal_error("NULL object (ref)");
} }
template<lifetime L> template<lifetime L>
@ -154,6 +159,8 @@ template<class T,
object<L>::object(const root<T, LL> &o) object<L>::object(const root<T, LL> &o)
:object{o.get()} :object{o.get()}
{ {
if(unlikely(!this->get()))
throw internal_error("NULL object (cross-lifetime)");
} }
template<lifetime L> template<lifetime L>
@ -208,7 +215,7 @@ template<lifetime L>
void void
object<L>::resize(const uint32_t &length) object<L>::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"); throw internal_error("Failed to set array object length");
} }
@ -217,11 +224,7 @@ uint32_t
object<L>::size() object<L>::size()
const const
{ {
uint32_t ret; return js::size(*this);
if(!JS_GetArrayLength(*cx, handle(*this), &ret))
throw internal_error("Failed to get array object length");
return ret;
} }
template<lifetime L> template<lifetime L>
@ -231,23 +234,32 @@ const
return this->get()? JS::ObjectValue(*this->get()) : JS::NullValue(); return this->get()? JS::ObjectValue(*this->get()) : JS::NullValue();
} }
template<lifetime L> } // namespace basic
bool
freeze(const object<L> & obj) inline bool
freeze(const object_handle &obj)
{ {
return JS_FreezeObject(*cx, obj); return JS_FreezeObject(*cx, obj);
} }
template<lifetime L> inline bool
bool deep_freeze(const object_handle &obj)
deep_freeze(const object<L> & obj)
{ {
return JS_DeepFreezeObject(*cx, obj); return JS_DeepFreezeObject(*cx, obj);
} }
template<lifetime L> inline uint32_t
bool size(const object_handle &obj)
is_array(const object<L> & 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; bool ret;
if(!JS_IsArrayObject(*cx, obj, &ret)) if(!JS_IsArrayObject(*cx, obj, &ret))
@ -256,9 +268,8 @@ is_array(const object<L> & obj)
return ret; return ret;
} }
template<lifetime L> inline bool
bool is_extensible(const object_handle &obj)
is_extensible(const object<L> & obj)
{ {
bool ret; bool ret;
if(!JS_IsExtensible(*cx, obj, &ret)) if(!JS_IsExtensible(*cx, obj, &ret))
@ -267,26 +278,23 @@ is_extensible(const object<L> & obj)
return ret; return ret;
} }
template<lifetime L> inline void
void priv(const object_handle &obj,
priv(object<L> &obj,
const void *const &ptr) const void *const &ptr)
{ {
priv(obj, const_cast<void *>(ptr)); JS_SetPrivate(obj, const_cast<void *>(ptr));
} }
template<lifetime L> inline void
void priv(const object_handle &obj,
priv(object<L> &obj,
void *const &ptr) void *const &ptr)
{ {
JS_SetPrivate(obj, ptr); JS_SetPrivate(obj, ptr);
} }
template<class T, template<class T>
lifetime L>
T & T &
priv(const object<L> &obj) priv(const object_handle &obj)
{ {
const auto &jsc(jsclass(obj)); const auto &jsc(jsclass(obj));
const auto ret(JS_GetInstancePrivate(*cx, obj, &jsc, nullptr)); const auto ret(JS_GetInstancePrivate(*cx, obj, &jsc, nullptr));
@ -296,9 +304,8 @@ priv(const object<L> &obj)
return *reinterpret_cast<T *>(ret); return *reinterpret_cast<T *>(ret);
} }
template<lifetime L> inline const JSClass &
const JSClass & jsclass(const object_handle &obj)
jsclass(const object<L> &obj)
{ {
const auto jsc(JS_GetClass(obj)); const auto jsc(JS_GetClass(obj));
if(unlikely(!jsc)) if(unlikely(!jsc))
@ -307,6 +314,5 @@ jsclass(const object<L> &obj)
return *const_cast<JSClass *>(jsc); return *const_cast<JSClass *>(jsc);
} }
} // namespace basic
} // namespace js } // namespace js
} // namespace ircd } // namespace ircd

View file

@ -48,7 +48,7 @@ struct string
bool empty() const; bool empty() const;
char16_t operator[](const size_t &at) const; char16_t operator[](const size_t &at) const;
explicit operator std::string() const; operator std::string() const;
operator JS::Value() const; operator JS::Value() const;
using root<JSString *, L>::root; using root<JSString *, L>::root;

View file

@ -70,15 +70,15 @@ struct value
value(const value &); value(const value &);
}; };
template<lifetime L> JSType type(const value<L> &);
template<lifetime L> bool undefined(const value<L> &);
template<lifetime L> bool is_array(typename value<L>::handle);
} // namespace basic } // namespace basic
using value = basic::value<lifetime::stack>; using value = basic::value<lifetime::stack>;
using heap_value = basic::value<lifetime::heap>; using heap_value = basic::value<lifetime::heap>;
template<class value> JSType type(const value &);
template<class value> bool undefined(const value &val);
template<class value> bool is_array(const value &val);
// //
// Implementation // Implementation
// //
@ -317,9 +317,11 @@ const
return s? native(s) : throw type_error("Failed to cast to string"); return s? native(s) : throw type_error("Failed to cast to string");
} }
template<lifetime L> } // namespace basic
template<class value>
bool bool
is_array(const value<L> &val) is_array(const value &val)
{ {
bool ret; bool ret;
if(!JS_IsArrayObject(*cx, val, &ret)) if(!JS_IsArrayObject(*cx, val, &ret))
@ -328,22 +330,20 @@ is_array(const value<L> &val)
return ret; return ret;
} }
template<lifetime L> template<class value>
bool bool
undefined(const value<L> &val) undefined(const value &val)
{ {
return type(val) == JSTYPE_VOID; return type(val) == JSTYPE_VOID;
} }
template<lifetime L> template<class value>
JSType JSType
type(const value<L> &val) type(const value &val)
{ {
return JS_TypeOfValue(*cx, val); return JS_TypeOfValue(*cx, val);
} }
} // namespace basic
inline JS::Value inline JS::Value
pointer_value(const void *const &ptr) pointer_value(const void *const &ptr)
{ {

View file

@ -101,7 +101,8 @@ struct vector<value>
infallibleAppend(value(t)); infallibleAppend(value(t));
} }
vector(const object &obj) template<lifetime L>
vector(const basic::object<L> &obj)
:JS::AutoVectorRooter<jsapi_type>{*cx} :JS::AutoVectorRooter<jsapi_type>{*cx}
{ {
if(!is_array(obj)) if(!is_array(obj))
@ -113,6 +114,12 @@ struct vector<value>
infallibleAppend(get(obj, i)); infallibleAppend(get(obj, i));
} }
template<lifetime L>
vector(const basic::value<L> &val)
:vector(basic::object<L>(val))
{
}
vector(const size_t &size) vector(const size_t &size)
:JS::AutoVectorRooter<jsapi_type>{*cx} :JS::AutoVectorRooter<jsapi_type>{*cx}
{ {