mirror of
https://github.com/matrix-construct/construct
synced 2025-03-17 06:50:23 +01:00
ircd::js: Various fixes for conversions and root-ordering through calls.
This commit is contained in:
parent
8895bb57c3
commit
4edfd51106
10 changed files with 189 additions and 86 deletions
|
@ -49,7 +49,7 @@ inline value
|
|||
args::operator[](const size_t &at)
|
||||
const
|
||||
{
|
||||
return length() > at? JS::CallArgs::operator[](at) : value{};
|
||||
return value{length() > at? JS::CallArgs::operator[](at) : JS::UndefinedValue()};
|
||||
}
|
||||
|
||||
inline value
|
||||
|
|
|
@ -27,23 +27,32 @@ namespace js {
|
|||
|
||||
value
|
||||
call(const function::handle &func,
|
||||
const object &that,
|
||||
const object::handle &that,
|
||||
const vector<value>::handle &args = {});
|
||||
|
||||
value
|
||||
call(const value::handle &val,
|
||||
const object &that,
|
||||
const object::handle &that,
|
||||
const vector<value>::handle &args = {});
|
||||
|
||||
value
|
||||
call(const char *const &name,
|
||||
const object &that,
|
||||
const object::handle &that,
|
||||
const vector<value>::handle &args = {});
|
||||
|
||||
value
|
||||
call(const std::string &name,
|
||||
const object &that,
|
||||
const object::handle &that,
|
||||
const vector<value>::handle &args = {});
|
||||
|
||||
inline value
|
||||
call(const function::handle &func,
|
||||
const value::handle &that,
|
||||
const vector<value>::handle &args = {})
|
||||
{
|
||||
const object _that(that);
|
||||
return call(func, _that, args);
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
} // namespace ircd
|
||||
|
|
|
@ -26,10 +26,10 @@ namespace ircd {
|
|||
namespace js {
|
||||
|
||||
string decompile(const JS::Handle<JSFunction *> &, const bool &pretty = false);
|
||||
string display_name(const JSFunction &);
|
||||
string name(const JSFunction &);
|
||||
uint16_t arity(const JSFunction &f);
|
||||
bool is_ctor(const JSFunction &f);
|
||||
string display_name(const JSFunction *const &);
|
||||
string name(const JSFunction *const *);
|
||||
uint16_t arity(const JSFunction *const &);
|
||||
bool is_ctor(const JSFunction *const &);
|
||||
|
||||
namespace basic {
|
||||
|
||||
|
@ -42,8 +42,8 @@ struct function
|
|||
explicit operator string<L>() const;
|
||||
|
||||
// js::value/js::object == lifetime::stack
|
||||
js::value operator()(const js::object &, const vector<js::value>::handle &) const;
|
||||
template<class... args> js::value operator()(const js::object &, args&&...) const;
|
||||
value<L> operator()(const js::object::handle &, const vector<js::value>::handle &) const;
|
||||
template<class... args> value<L> operator()(const js::object::handle &, args&&...) const;
|
||||
|
||||
// new function
|
||||
template<class string_t>
|
||||
|
@ -54,7 +54,8 @@ struct function
|
|||
const string_t &src);
|
||||
|
||||
using root<JSFunction *, L>::root;
|
||||
explicit function(const value<L> &);
|
||||
function(const handle<value<L>> &);
|
||||
function(const js::value &);
|
||||
function(JSFunction *const &);
|
||||
function(JSFunction &);
|
||||
};
|
||||
|
@ -84,7 +85,13 @@ function<L>::function(JSFunction *const &func)
|
|||
}
|
||||
|
||||
template<lifetime L>
|
||||
function<L>::function(const value<L> &val)
|
||||
function<L>::function(const js::value &val)
|
||||
:function{static_cast<js::value::handle>(val)}
|
||||
{
|
||||
}
|
||||
|
||||
template<lifetime L>
|
||||
function<L>::function(const handle<value<L>> &val)
|
||||
:function<L>::root::type
|
||||
{
|
||||
JS_ValueToFunction(*cx, val)
|
||||
|
@ -126,8 +133,8 @@ function<L>::function(JS::AutoObjectVector &stack,
|
|||
|
||||
template<lifetime L>
|
||||
template<class... args>
|
||||
js::value
|
||||
function<L>::operator()(const js::object &that,
|
||||
value<L>
|
||||
function<L>::operator()(const js::object::handle &that,
|
||||
args&&... a)
|
||||
const
|
||||
{
|
||||
|
@ -140,8 +147,8 @@ const
|
|||
}
|
||||
|
||||
template<lifetime L>
|
||||
js::value
|
||||
function<L>::operator()(const js::object &that,
|
||||
value<L>
|
||||
function<L>::operator()(const js::object::handle &that,
|
||||
const vector<js::value>::handle &argv)
|
||||
const
|
||||
{
|
||||
|
@ -176,28 +183,28 @@ const
|
|||
} // namespace basic
|
||||
|
||||
inline bool
|
||||
is_ctor(const JSFunction &f)
|
||||
is_ctor(const JSFunction *const &f)
|
||||
{
|
||||
return JS_IsConstructor(const_cast<JSFunction *>(&f));
|
||||
return JS_IsConstructor(const_cast<JSFunction *>(f));
|
||||
}
|
||||
|
||||
inline uint16_t
|
||||
arity(const JSFunction &f)
|
||||
arity(const JSFunction *const &f)
|
||||
{
|
||||
return JS_GetFunctionArity(const_cast<JSFunction *>(&f));
|
||||
return JS_GetFunctionArity(const_cast<JSFunction *>(f));
|
||||
}
|
||||
|
||||
inline string
|
||||
name(const JSFunction &f)
|
||||
name(const JSFunction *const &f)
|
||||
{
|
||||
const auto ret(JS_GetFunctionId(const_cast<JSFunction *>(&f)));
|
||||
const auto ret(JS_GetFunctionId(const_cast<JSFunction *>(f)));
|
||||
return ret? string(ret) : string("<unnamed>");
|
||||
}
|
||||
|
||||
inline string
|
||||
display_name(const JSFunction &f)
|
||||
display_name(const JSFunction *const &f)
|
||||
{
|
||||
const auto ret(JS_GetFunctionDisplayId(const_cast<JSFunction *>(&f)));
|
||||
const auto ret(JS_GetFunctionDisplayId(const_cast<JSFunction *>(f)));
|
||||
return ret? string(ret) : string("<anonymous>");
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@ template<lifetime L>
|
|||
struct id
|
||||
:root<jsid, L>
|
||||
{
|
||||
operator value<L>() const;
|
||||
|
||||
using root<jsid, L>::root;
|
||||
explicit id(const char *const &); // creates new id
|
||||
explicit id(const std::string &); // creates new id
|
||||
|
@ -127,6 +129,17 @@ id<L>::id(const typename string<L>::handle &h)
|
|||
throw type_error("Failed to construct id from String");
|
||||
}
|
||||
|
||||
template<lifetime L>
|
||||
id<L>::operator value<L>()
|
||||
const
|
||||
{
|
||||
value<L> ret;
|
||||
if(!JS_IdToValue(*cx, *this, &ret))
|
||||
throw type_error("Failed to construct id from String");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace basic
|
||||
|
||||
inline bool
|
||||
|
|
|
@ -60,6 +60,7 @@ struct object
|
|||
using handle = object_handle;
|
||||
using handle_mutable = object_handle_mutable;
|
||||
|
||||
explicit operator JSString *() const;
|
||||
operator JS::Value() const;
|
||||
|
||||
// for array objects
|
||||
|
@ -285,11 +286,20 @@ const
|
|||
return js::size(*this);
|
||||
}
|
||||
|
||||
template<lifetime L>
|
||||
object<L>::operator JSString *()
|
||||
const
|
||||
{
|
||||
assert(this->get());
|
||||
return JS_BasicObjectToString(*cx, *this);
|
||||
}
|
||||
|
||||
template<lifetime L>
|
||||
object<L>::operator JS::Value()
|
||||
const
|
||||
{
|
||||
return this->get()? JS::ObjectValue(*this->get()) : JS::NullValue();
|
||||
assert(this->get());
|
||||
return JS::ObjectValue(*this->get());
|
||||
}
|
||||
|
||||
} // namespace basic
|
||||
|
@ -359,6 +369,7 @@ jsclass(JSObject *const &obj)
|
|||
inline bool
|
||||
has_jsclass(const JSObject *const &obj)
|
||||
{
|
||||
assert(obj);
|
||||
return JS_GetClass(const_cast<JSObject *>(obj)) != nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,40 @@ struct root
|
|||
template<class T>
|
||||
using handle = typename T::handle;
|
||||
|
||||
// This conversion is missing in the jsapi. Is this object not gc rooted? Can it not have a handle?
|
||||
template<class T>
|
||||
JS::Handle<T>
|
||||
operator&(const JS::Heap<T> &h)
|
||||
{
|
||||
return JS::Handle<T>::fromMarkedLocation(h.address());
|
||||
}
|
||||
|
||||
// This conversion is missing in the jsapi. Is this object not gc rooted? Can it not have a handle?
|
||||
template<class T>
|
||||
JS::MutableHandle<T>
|
||||
operator&(JS::Heap<T> &h)
|
||||
{
|
||||
const auto ptr(const_cast<T *>(h.address()));
|
||||
return JS::MutableHandle<T>::fromMarkedLocation(ptr);
|
||||
}
|
||||
|
||||
// This conversion is missing in the jsapi. Is this object not gc rooted? Can it not have a handle?
|
||||
template<class T>
|
||||
JS::Handle<T>
|
||||
operator&(const JS::TenuredHeap<T> &h)
|
||||
{
|
||||
return JS::Handle<T>::fromMarkedLocation(h.address());
|
||||
}
|
||||
|
||||
// This conversion is missing in the jsapi. Is this object not gc rooted? Can it not have a handle?
|
||||
template<class T>
|
||||
JS::MutableHandle<T>
|
||||
operator&(JS::TenuredHeap<T> &h)
|
||||
{
|
||||
const auto ptr(const_cast<T *>(h.address()));
|
||||
return JS::MutableHandle<T>::fromMarkedLocation(ptr);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
struct root<T, lifetime::stack>
|
||||
:JS::Rooted<T>
|
||||
|
@ -53,6 +87,17 @@ struct root<T, lifetime::stack>
|
|||
using handle_mutable = JS::MutableHandle<T>;
|
||||
using handle = JS::Handle<T>;
|
||||
|
||||
operator handle() const
|
||||
{
|
||||
return JS::Handle<T>::fromMarkedLocation(this->address());
|
||||
}
|
||||
|
||||
operator handle_mutable()
|
||||
{
|
||||
const auto ptr(this->address());
|
||||
return JS::MutableHandle<T>::fromMarkedLocation(ptr);
|
||||
}
|
||||
|
||||
root(const handle &h)
|
||||
:JS::Rooted<T>{*cx, h}
|
||||
{
|
||||
|
@ -82,6 +127,12 @@ struct root<T, lifetime::stack>
|
|||
root(root&& other)
|
||||
noexcept
|
||||
:JS::Rooted<T>{*cx, other.get()}
|
||||
{
|
||||
other.set(nullptr);
|
||||
}
|
||||
|
||||
root(const root &other)
|
||||
:JS::Rooted<T>{*cx, other.get()}
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -89,30 +140,19 @@ struct root<T, lifetime::stack>
|
|||
noexcept
|
||||
{
|
||||
this->set(other.get());
|
||||
other.set(nullptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
root(const root &) = delete;
|
||||
root &operator=(const root &) = delete;
|
||||
root &operator=(const root &other)
|
||||
{
|
||||
this->set(other.get());
|
||||
return *this;
|
||||
}
|
||||
|
||||
~root() noexcept = default;
|
||||
};
|
||||
|
||||
// This conversion is missing in the jsapi. Is this object not gc rooted? Can it not have a handle?
|
||||
template<class T>
|
||||
JS::Handle<T>
|
||||
operator&(const JS::Heap<T> &h)
|
||||
{
|
||||
return JS::Handle<T>::fromMarkedLocation(h.address());
|
||||
}
|
||||
|
||||
// This conversion is missing in the jsapi. Is this object not gc rooted? Can it not have a handle?
|
||||
template<class T>
|
||||
JS::MutableHandle<T>
|
||||
operator&(JS::Heap<T> &h)
|
||||
{
|
||||
const auto ptr(const_cast<T *>(h.address()));
|
||||
return JS::MutableHandle<T>::fromMarkedLocation(ptr);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
struct root<T, lifetime::heap>
|
||||
:JS::Heap<T>
|
||||
|
@ -213,23 +253,6 @@ struct root<T, lifetime::heap>
|
|||
}
|
||||
};
|
||||
|
||||
// This conversion is missing in the jsapi. Is this object not gc rooted? Can it not have a handle?
|
||||
template<class T>
|
||||
JS::Handle<T>
|
||||
operator&(const JS::TenuredHeap<T> &h)
|
||||
{
|
||||
return JS::Handle<T>::fromMarkedLocation(h.address());
|
||||
}
|
||||
|
||||
// This conversion is missing in the jsapi. Is this object not gc rooted? Can it not have a handle?
|
||||
template<class T>
|
||||
JS::MutableHandle<T>
|
||||
operator&(JS::TenuredHeap<T> &h)
|
||||
{
|
||||
const auto ptr(const_cast<T *>(h.address()));
|
||||
return JS::MutableHandle<T>::fromMarkedLocation(ptr);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
struct root<T, lifetime::tenured>
|
||||
:JS::TenuredHeap<T>
|
||||
|
|
|
@ -32,6 +32,7 @@ void set(JSObject *const &obj, const reserved &slot, const JS::Value &);
|
|||
void set(JSObject *const &obj, priv_data &);
|
||||
void set(JSObject *const &obj, const std::shared_ptr<priv_data> &);
|
||||
|
||||
void set(const object::handle &obj, const id::handle &id, const value::handle &val);
|
||||
void set(const object::handle &obj, const id::handle &id, const value &val);
|
||||
void set(const object::handle &obj, const id &id, const value &val);
|
||||
template<class T> void set(const object::handle &obj, const uint32_t &idx, T&& t);
|
||||
|
|
|
@ -32,7 +32,7 @@ JS::Value pointer_value(void *const &);
|
|||
|
||||
namespace basic {
|
||||
|
||||
template<lifetime L>
|
||||
template<lifetime L = lifetime::stack>
|
||||
struct value
|
||||
:root<JS::Value, L>
|
||||
{
|
||||
|
@ -70,13 +70,39 @@ struct value
|
|||
value(const value &);
|
||||
};
|
||||
|
||||
template<lifetime L>
|
||||
JSType
|
||||
type(const value<L> &val)
|
||||
{
|
||||
return JS_TypeOfValue(*cx, val);
|
||||
}
|
||||
|
||||
inline JSType
|
||||
type(const handle<value<>> &val)
|
||||
{
|
||||
return JS_TypeOfValue(*cx, val);
|
||||
}
|
||||
|
||||
template<lifetime L>
|
||||
bool
|
||||
undefined(const value<L> &val)
|
||||
{
|
||||
return type(val) == JSTYPE_VOID;
|
||||
}
|
||||
|
||||
inline bool
|
||||
undefined(const JS::Handle<JS::Value> &val)
|
||||
{
|
||||
return type(val) == JSTYPE_VOID;
|
||||
}
|
||||
|
||||
} // namespace basic
|
||||
|
||||
using value = basic::value<lifetime::stack>;
|
||||
using heap_value = basic::value<lifetime::heap>;
|
||||
|
||||
template<class value> JSType type(const value &);
|
||||
template<class value> bool undefined(const value &val);
|
||||
using basic::type;
|
||||
using basic::undefined;
|
||||
template<class value> bool is_array(const value &val);
|
||||
|
||||
//
|
||||
|
@ -331,21 +357,14 @@ is_array(const value &val)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
template<class value>
|
||||
bool
|
||||
undefined(const value &val)
|
||||
{
|
||||
return type(val) == JSTYPE_VOID;
|
||||
return basic::type(val) == JSTYPE_VOID;
|
||||
}
|
||||
|
||||
template<class value>
|
||||
JSType
|
||||
type(const value &val)
|
||||
{
|
||||
return JS_TypeOfValue(*cx, val);
|
||||
}
|
||||
|
||||
*/
|
||||
inline JS::Value
|
||||
pointer_value(const void *const &ptr)
|
||||
{
|
||||
|
|
|
@ -82,7 +82,8 @@ struct vector<value>
|
|||
|
||||
// Construct from initializer list of our `struct value` wrapper
|
||||
// ex: value a(1); vector foo {{ a, a, ... }};
|
||||
vector(const std::initializer_list<local_type> &list)
|
||||
|
||||
vector(const std::initializer_list<heap_value> &list)
|
||||
:JS::AutoVectorRooter<jsapi_type>{*cx}
|
||||
{
|
||||
reserve(list.size());
|
||||
|
@ -92,6 +93,7 @@ struct vector<value>
|
|||
|
||||
// Construct from initializer list of any type passed through `struct value` ctor
|
||||
// ex: int a; vector foo {{ a, 3, 123, ... }};
|
||||
/*
|
||||
template<class U>
|
||||
vector(const std::initializer_list<U> &list)
|
||||
:JS::AutoVectorRooter<jsapi_type>{*cx}
|
||||
|
@ -100,7 +102,7 @@ struct vector<value>
|
|||
for(auto &t : list)
|
||||
infallibleAppend(value(t));
|
||||
}
|
||||
|
||||
*/
|
||||
template<lifetime L>
|
||||
vector(const basic::object<L> &obj)
|
||||
:JS::AutoVectorRooter<jsapi_type>{*cx}
|
||||
|
@ -120,6 +122,14 @@ struct vector<value>
|
|||
{
|
||||
}
|
||||
|
||||
vector(const handle &h)
|
||||
:JS::AutoVectorRooter<jsapi_type>{*cx}
|
||||
{
|
||||
reserve(h.length());
|
||||
for(size_t i(0); i < h.length(); ++i)
|
||||
infallibleAppend(h[i]);
|
||||
}
|
||||
|
||||
vector(const size_t &size)
|
||||
:JS::AutoVectorRooter<jsapi_type>{*cx}
|
||||
{
|
||||
|
@ -184,7 +194,8 @@ struct vector<id>
|
|||
{
|
||||
using jsapi_type = jsid;
|
||||
using local_type = id;
|
||||
|
||||
using base_type = JS::AutoVectorRooter<jsapi_type>;
|
||||
/*
|
||||
vector(const std::initializer_list<jsapi_type> &list)
|
||||
:JS::AutoVectorRooter<jsapi_type>{*cx}
|
||||
{
|
||||
|
@ -192,9 +203,9 @@ struct vector<id>
|
|||
for(auto &t : list)
|
||||
infallibleAppend(t);
|
||||
}
|
||||
|
||||
*/
|
||||
vector(const std::initializer_list<local_type> &list)
|
||||
:JS::AutoVectorRooter<jsapi_type>{*cx}
|
||||
:base_type{*cx}
|
||||
{
|
||||
reserve(list.size());
|
||||
for(auto &t : list)
|
||||
|
@ -202,14 +213,15 @@ struct vector<id>
|
|||
}
|
||||
|
||||
vector(const size_t &size)
|
||||
:JS::AutoVectorRooter<jsapi_type>{*cx}
|
||||
:base_type{*cx}
|
||||
{
|
||||
resize(size);
|
||||
}
|
||||
|
||||
vector()
|
||||
:JS::AutoVectorRooter<jsapi_type>{*cx}
|
||||
:base_type{*cx}
|
||||
{
|
||||
reserve(8);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
16
ircd/js.cc
16
ircd/js.cc
|
@ -1335,7 +1335,7 @@ noexcept
|
|||
|
||||
ircd::js::value
|
||||
ircd::js::call(const std::string &name,
|
||||
const object &that,
|
||||
const object::handle &that,
|
||||
const vector<value>::handle &args)
|
||||
{
|
||||
return call(name.c_str(), that, args);
|
||||
|
@ -1343,7 +1343,7 @@ ircd::js::call(const std::string &name,
|
|||
|
||||
ircd::js::value
|
||||
ircd::js::call(const char *const &name,
|
||||
const object &that,
|
||||
const object::handle &that,
|
||||
const vector<value>::handle &args)
|
||||
{
|
||||
value ret;
|
||||
|
@ -1355,7 +1355,7 @@ ircd::js::call(const char *const &name,
|
|||
|
||||
ircd::js::value
|
||||
ircd::js::call(const value::handle &val,
|
||||
const object &that,
|
||||
const object::handle &that,
|
||||
const vector<value>::handle &args)
|
||||
{
|
||||
value ret;
|
||||
|
@ -1367,7 +1367,7 @@ ircd::js::call(const value::handle &val,
|
|||
|
||||
ircd::js::value
|
||||
ircd::js::call(const function::handle &func,
|
||||
const object &that,
|
||||
const object::handle &that,
|
||||
const vector<value>::handle &args)
|
||||
{
|
||||
value ret;
|
||||
|
@ -1502,6 +1502,14 @@ void
|
|||
ircd::js::set(const object::handle &obj,
|
||||
const id::handle &id,
|
||||
const value &val)
|
||||
{
|
||||
set(obj, id, value::handle(val));
|
||||
}
|
||||
|
||||
void
|
||||
ircd::js::set(const object::handle &obj,
|
||||
const id::handle &id,
|
||||
const value::handle &val)
|
||||
{
|
||||
if(!JS_SetPropertyById(*cx, obj, id, val))
|
||||
throw jserror(jserror::pending);
|
||||
|
|
Loading…
Add table
Reference in a new issue