diff --git a/include/ircd/js/function.h b/include/ircd/js/function.h index 569f115b2..b2dbd83a2 100644 --- a/include/ircd/js/function.h +++ b/include/ircd/js/function.h @@ -28,9 +28,15 @@ namespace js { struct function :JS::Rooted { + operator JSObject *() const; + explicit operator script() const; + value operator()(const object &, const JS::HandleValueArray &args) const; value operator()(const object &) const; + string display_name() const; + string name() const; + // new function function(JS::AutoObjectVector &stack, const JS::CompileOptions &opts, @@ -38,8 +44,9 @@ struct function const std::vector &args, const std::string &src); - function(JSFunction *const &); explicit function(const value &); + function(JSFunction *const &); + function(JSFunction &); function(); function(function &&) noexcept; function(const function &) = delete; @@ -72,6 +79,20 @@ noexcept return *this; } +inline +function::function(JSFunction &func) +:JS::Rooted{*cx, &func} +{ +} + +inline +function::function(JSFunction *const &func) +:JS::Rooted{*cx, func} +{ + if(unlikely(!get())) + throw internal_error("NULL function"); +} + inline function::function(const value &val) :JS::Rooted @@ -81,25 +102,53 @@ function::function(const value &val) } { if(!get()) - throw type_error("Value is not an Function"); + throw type_error("value is not a function"); +} + +inline string +function::name() +const +{ + const auto ret(JS_GetFunctionId(*this)); + return ret? string(ret) : string(""); +} + +inline string +function::display_name() +const +{ + const auto ret(JS_GetFunctionDisplayId(*this)); + return ret? string(ret) : string(""); } inline -function::function(JSFunction *const &func) -:JS::Rooted{*cx, func} +function::operator script() +const { + return JS_GetFunctionScript(*cx, *this); +} + +inline +function::operator JSObject *() +const +{ + const auto ret(JS_GetFunctionObject(get())); + if(unlikely(!ret)) + throw type_error("function cannot cast to Object"); + + return ret; } inline string name(const function &f) { - return JS_GetFunctionId(f); + return f.name(); } inline string display_name(const function &f) { - return JS_GetFunctionDisplayId(f); + return f.display_name(); } } // namespace js diff --git a/include/ircd/js/js.h b/include/ircd/js/js.h index f919c4f83..96b56526c 100644 --- a/include/ircd/js/js.h +++ b/include/ircd/js/js.h @@ -64,12 +64,12 @@ inline JSVersion version(const char *const &v) { return JS_StringToVersion(v); #include "string.h" #include "id.h" #include "object.h" +#include "script.h" #include "function.h" #include "vector.h" #include "priv.h" #include "get.h" #include "call.h" -#include "script.h" #include "for_each.h" #include "debug.h" #include "trap.h" diff --git a/include/ircd/js/object.h b/include/ircd/js/object.h index b026d4b8b..e85d19b29 100644 --- a/include/ircd/js/object.h +++ b/include/ircd/js/object.h @@ -34,8 +34,12 @@ struct object object(const JSClass *const &, const object &proto); object(const JSClass *const &); + object(const JS::MutableHandleObject &h): object{h.get()} {} + object(const JS::HandleObject &h): object{h.get()} {} + explicit object(const value &); + object(JSFunction *const &); object(JSObject *const &); - object(const value &); + object(JSObject &); object(); object(object &&) noexcept; object(const object &) = delete; @@ -44,7 +48,11 @@ struct object inline object::object() -:JS::Rooted{*cx} +:JS::Rooted +{ + *cx, + JS_NewPlainObject(*cx) +} { } @@ -65,6 +73,20 @@ noexcept return *this; } +inline +object::object(JSObject &obj) +:JS::Rooted{*cx, &obj} +{ +} + +inline +object::object(JSObject *const &obj) +:JS::Rooted{*cx, obj} +{ + if(unlikely(!get())) + throw internal_error("NULL object"); +} + inline object::object(const value &val) :JS::Rooted{*cx} @@ -74,9 +96,15 @@ object::object(const value &val) } inline -object::object(JSObject *const &obj) -:JS::Rooted{*cx, obj} +object::object(JSFunction *const &val) +:JS::Rooted { + *cx, + val? JS_GetFunctionObject(val) : nullptr +} +{ + if(unlikely(!get())) + throw type_error("Function cannot convert to Object"); } inline diff --git a/include/ircd/js/script.h b/include/ircd/js/script.h index ca2362646..c96df1d65 100644 --- a/include/ircd/js/script.h +++ b/include/ircd/js/script.h @@ -33,6 +33,7 @@ struct script script(const JS::CompileOptions &opts, const std::string &src); // new script script(JSScript *const &); + script(JSScript &); script(); script(script &&) noexcept; script(const script &) = delete; @@ -51,10 +52,18 @@ noexcept { } +inline +script::script(JSScript &val) +:JS::Rooted{*cx, &val} +{ +} + inline script::script(JSScript *const &val) :JS::Rooted{*cx, val} { + if(unlikely(!get())) + throw internal_error("NULL script"); } } // namespace js diff --git a/include/ircd/js/string.h b/include/ircd/js/string.h index dac0676e8..39d3901ab 100644 --- a/include/ircd/js/string.h +++ b/include/ircd/js/string.h @@ -46,8 +46,9 @@ struct string string(const char *const &, const size_t &len); explicit string(const std::string &); string(const char *const &); - string(JSString *const &); string(const value &); + string(JSString *const &); + string(JSString &); string(); string(string &&) noexcept; string(const string &) = delete; @@ -81,11 +82,10 @@ noexcept } inline -string::string(const value &val) +string::string(JSString &val) :JS::Rooted { - *cx, - JS::ToString(*cx, val)?: throw type_error("Failed to convert value to string") + *cx, &val } { } @@ -95,7 +95,16 @@ string::string(JSString *const &val) :JS::Rooted { *cx, - likely(val)? val : JS_GetEmptyString(*rt) + likely(val)? val : throw internal_error("NULL string") +} +{ +} + +string::string(const value &val) +:JS::Rooted +{ + *cx, + JS::ToString(*cx, val)?: throw type_error("Failed to convert value to string") } { } diff --git a/include/ircd/js/value.h b/include/ircd/js/value.h index 9db130a0c..f77fe3f45 100644 --- a/include/ircd/js/value.h +++ b/include/ircd/js/value.h @@ -54,10 +54,12 @@ struct value value(const jsid &); value(JSObject &); value(JSString *const &); + value(JSFunction *const &); value(JS::Symbol *const &); value(const JS::Value &); template value(const JS::Handle &h); + template value(const JS::MutableHandle &h); template value(const JS::Rooted &r); template value(const JS::PersistentRooted &p); @@ -102,6 +104,12 @@ value::value(const JS::Rooted &r) { } +template +value::value(const JS::MutableHandle &h) +:value(h.get()) +{ +} + template value::value(const JS::Handle &h) :value(h.get()) @@ -132,6 +140,17 @@ value::value(JSString *const &val) { } +inline +value::value(JSFunction *const &val) +:JS::Rooted{*cx} +{ + auto *const obj(JS_GetFunctionObject(val)); + if(unlikely(!obj)) + throw type_error("Function cannot convert to Object"); + + set(JS::ObjectValue(*obj)); +} + inline value::value(const jsid &val) :JS::Rooted{*cx}