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:
parent
6cc89f2613
commit
ee5f48672f
6 changed files with 97 additions and 70 deletions
|
@ -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>
|
||||||
|
|
|
@ -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{}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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}
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue