0
0
Fork 0
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:
Jason Volk 2016-11-24 18:21:46 -08:00
parent 8895bb57c3
commit 4edfd51106
10 changed files with 189 additions and 86 deletions

View file

@ -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

View file

@ -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

View file

@ -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>");
}

View file

@ -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

View file

@ -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;
}

View file

@ -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>

View file

@ -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);

View file

@ -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)
{

View file

@ -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);
}
};

View file

@ -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);