mirror of
https://github.com/matrix-construct/construct
synced 2024-12-25 23:14:13 +01:00
ircd::js: Add trap::property; Improve trap construction interface.
This commit is contained in:
parent
8d92c8a9c4
commit
01d814ea1a
6 changed files with 465 additions and 72 deletions
|
@ -36,8 +36,7 @@ inline object
|
|||
ctor(trap &trap,
|
||||
const vector<value>::handle &args = {})
|
||||
{
|
||||
object proto(trap());
|
||||
return JS_New(*cx, proto, args);
|
||||
return trap.construct(args);
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
|
|
|
@ -91,6 +91,7 @@ inline JSVersion version(const char *const &v) { return JS_StringToVersion(v);
|
|||
#include "args.h"
|
||||
#include "trap.h"
|
||||
#include "trap_function.h"
|
||||
#include "trap_property.h"
|
||||
#include "ctor.h"
|
||||
#include "generator.h"
|
||||
#include "global.h"
|
||||
|
|
|
@ -27,23 +27,26 @@ namespace js {
|
|||
|
||||
struct trap
|
||||
{
|
||||
struct property;
|
||||
struct function;
|
||||
|
||||
protected:
|
||||
const std::string parent;
|
||||
trap *parent;
|
||||
const std::string _name; // don't touch
|
||||
std::array<JSPropertySpec, 32> sps; // static property spec
|
||||
std::array<JSPropertySpec, 32> ps; // property spec
|
||||
std::array<JSFunctionSpec, 32> sfs; // static function spec
|
||||
std::array<JSFunctionSpec, 32> fs; // function spec
|
||||
std::unique_ptr<JSClass> _class;
|
||||
std::map<std::string, property *> member;
|
||||
std::map<std::string, function *> memfun;
|
||||
std::map<std::string, trap *> children;
|
||||
std::set<function *> memfun;
|
||||
trap *parent_prototype;
|
||||
trap *prototype;
|
||||
|
||||
std::array<JSConstIntegerSpec, 32> cis; // static const integer spec
|
||||
std::array<JSConstDoubleSpec, 32> cds; // static const double spec
|
||||
std::array<JSPropertySpec, 32> sps; // static property spec
|
||||
std::array<JSFunctionSpec, 32> sfs; // static function spec
|
||||
std::array<JSPropertySpec, 32> ps; // property spec
|
||||
std::array<JSFunctionSpec, 32> fs; // function spec
|
||||
std::unique_ptr<JSClass> _class; // class spec
|
||||
trap *prototrap; // pointer to __proto__ trap
|
||||
|
||||
static trap &from(const JSObject &);
|
||||
static trap &from(const JS::HandleObject &);
|
||||
static trap &from(const JSObject *const &);
|
||||
|
||||
protected:
|
||||
void debug(const void *const &that, const char *fmt, ...) const AFP(3, 4);
|
||||
|
@ -74,6 +77,8 @@ struct trap
|
|||
static bool handle_del(JSContext *, JS::HandleObject, JS::HandleId, JS::ObjectOpResult &) noexcept;
|
||||
static bool handle_has(JSContext *, JS::HandleObject, JS::HandleId, bool *resolved) noexcept;
|
||||
static bool handle_enu(JSContext *, JS::HandleObject) noexcept;
|
||||
static bool handle_setter(JSContext *, unsigned argc, JS::Value *argv) noexcept;
|
||||
static bool handle_getter(JSContext *, unsigned argc, JS::Value *argv) noexcept;
|
||||
static bool handle_call(JSContext *, unsigned argc, JS::Value *argv) noexcept;
|
||||
static bool handle_ctor(JSContext *, unsigned argc, JS::Value *argv) noexcept;
|
||||
static void handle_dtor(JSFreeOp *, JSObject *) noexcept;
|
||||
|
@ -81,6 +86,7 @@ struct trap
|
|||
public:
|
||||
auto &name() const { return _name; }
|
||||
auto &jsclass() const { return *_class; }
|
||||
auto &jsclass() { return *_class; }
|
||||
|
||||
// Get child by name (NOT PATH)
|
||||
const trap &child(const std::string &name) const;
|
||||
|
@ -93,10 +99,13 @@ struct trap
|
|||
operator const JSClass &() const { return jsclass(); }
|
||||
operator const JSClass *() const { return &jsclass(); }
|
||||
|
||||
// Produces prototype. Call ctor(trap) for full construction
|
||||
object operator()();
|
||||
object prototype(const object::handle &globals);
|
||||
object construct(const object::handle &globals, const vector<value>::handle &argv = {});
|
||||
object construct(const vector<value>::handle &argv = {});
|
||||
template<class... args> object operator()(args&&...);
|
||||
|
||||
trap(const std::string &path, const uint &flags = 0, const uint &prop_flags = 0);
|
||||
trap(trap &parent, const std::string &name, const uint &flags = 0, const uint &prop_flags = 0);
|
||||
trap(const std::string &name, const uint &flags = 0, const uint &prop_flags = 0);
|
||||
trap(trap &&) = delete;
|
||||
trap(const trap &) = delete;
|
||||
virtual ~trap() noexcept;
|
||||
|
@ -106,3 +115,11 @@ extern __thread trap *tree;
|
|||
|
||||
} // namespace js
|
||||
} // namespace ircd
|
||||
|
||||
template<class... args>
|
||||
ircd::js::object
|
||||
ircd::js::trap::operator()(args&&... a)
|
||||
{
|
||||
vector<value> argv{{std::forward<args>(a)...}};
|
||||
return construct(argv);
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ struct trap::function
|
|||
static bool handle_call(JSContext *, unsigned, JS::Value *) noexcept;
|
||||
|
||||
public:
|
||||
js::function operator()(const object::handle &);
|
||||
js::function operator()(const object::handle &) const;
|
||||
|
||||
function(trap &,
|
||||
std::string name,
|
||||
|
|
50
include/ircd/js/trap_property.h
Normal file
50
include/ircd/js/trap_property.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Charybdis Development Team
|
||||
* Copyright (C) 2016 Jason Volk <jason@zemos.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice is present in all copies.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#define HAVE_IRCD_JS_TRAP_PROPERTY
|
||||
|
||||
namespace ircd {
|
||||
namespace js {
|
||||
|
||||
struct trap::property
|
||||
{
|
||||
using function = js::function;
|
||||
|
||||
struct trap *trap;
|
||||
const std::string name;
|
||||
|
||||
virtual value on_set(function::handle, object::handle, value::handle);
|
||||
virtual value on_get(function::handle, object::handle);
|
||||
|
||||
private:
|
||||
static bool handle_set(JSContext *c, unsigned argc, JS::Value *argv) noexcept;
|
||||
static bool handle_get(JSContext *c, unsigned argc, JS::Value *argv) noexcept;
|
||||
|
||||
public:
|
||||
property(struct trap &, std::string name);
|
||||
property(property &&) = delete;
|
||||
property(const property &) = delete;
|
||||
virtual ~property() noexcept;
|
||||
};
|
||||
|
||||
} // namespace js
|
||||
} // namespace ircd
|
436
ircd/js.cc
436
ircd/js.cc
|
@ -436,7 +436,14 @@ ircd::js::global::global(trap &trap,
|
|||
if(!JS_InitStandardClasses(*cx, *this))
|
||||
throw error("Failed to init standard classes for global object");
|
||||
|
||||
for(auto it(begin(trap.memfun)); it != end(trap.memfun); ++it)
|
||||
{
|
||||
trap::function &deffun(*it->second);
|
||||
deffun(*this);
|
||||
}
|
||||
|
||||
JS_InitReflectParse(*cx, *this);
|
||||
|
||||
JS_FireOnNewGlobalObject(*cx, *this);
|
||||
}
|
||||
|
||||
|
@ -463,6 +470,169 @@ noexcept
|
|||
// ircd/js/generator.h
|
||||
//
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ircd/js/trap_property.h
|
||||
//
|
||||
|
||||
ircd::js::trap::property::property(struct trap &trap,
|
||||
std::string name)
|
||||
try
|
||||
:trap{&trap}
|
||||
,name{std::move(name)}
|
||||
{
|
||||
const auto it(std::find_if(begin(trap.ps), end(trap.ps), []
|
||||
(const JSPropertySpec &ps)
|
||||
{
|
||||
return !ps.name;
|
||||
}));
|
||||
|
||||
if(it == end(trap.ps))
|
||||
throw error("out of slots");
|
||||
|
||||
{
|
||||
const auto it(trap.member.emplace(this->name, this));
|
||||
if(!it.second)
|
||||
throw error("already exists");
|
||||
}
|
||||
|
||||
JSPropertySpec &spec(*it);
|
||||
spec.name = this->name.c_str();
|
||||
spec.flags = JSPROP_SHARED;
|
||||
spec.getter.native.op = handle_get;
|
||||
spec.setter.native.op = handle_set;
|
||||
|
||||
log.debug("Registered property '%s' on trap '%s'",
|
||||
this->name.c_str(),
|
||||
trap.name().c_str());
|
||||
}
|
||||
catch(const error &e)
|
||||
{
|
||||
throw error("Failed to register property '%s': out slots on trap '%s': %s",
|
||||
this->name.c_str(),
|
||||
trap.name().c_str(),
|
||||
e.what());
|
||||
}
|
||||
|
||||
ircd::js::trap::property::~property()
|
||||
noexcept
|
||||
{
|
||||
assert(trap);
|
||||
const auto it(std::find_if(begin(trap->ps), end(trap->ps), [this]
|
||||
(const JSPropertySpec &spec)
|
||||
{
|
||||
return name == spec.name;
|
||||
}));
|
||||
|
||||
if(it != end(trap->ps))
|
||||
{
|
||||
JSPropertySpec &spec(*it);
|
||||
memset(&spec, 0x0, sizeof(spec));
|
||||
}
|
||||
|
||||
const size_t erased(trap->member.erase(name));
|
||||
assert(erased);
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::js::trap::property::handle_get(JSContext *const c,
|
||||
const unsigned argc,
|
||||
JS::Value *const argv)
|
||||
noexcept try
|
||||
{
|
||||
using js::function;
|
||||
|
||||
const struct args args(argc, argv);
|
||||
object that(args.computeThis(c));
|
||||
function func(args.callee());
|
||||
const string name(js::name(func));
|
||||
|
||||
auto &trap(from(that));
|
||||
trap.debug(that.get(), "get '%s' (property)",
|
||||
name.c_str());
|
||||
|
||||
property &prop(*trap.member.at(name));
|
||||
args.rval().set(prop.on_get(func, that));
|
||||
return true;
|
||||
}
|
||||
catch(const jserror &e)
|
||||
{
|
||||
e.set_pending();
|
||||
return false;
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
auto ca(JS::CallArgsFromVp(argc, argv));
|
||||
object that(ca.computeThis(c));
|
||||
auto &trap(from(that));
|
||||
trap.host_exception(that.get(), "property get: %s", e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace ircd {
|
||||
namespace js {
|
||||
|
||||
struct foodata
|
||||
:priv_data
|
||||
{
|
||||
trap::property *ptr;
|
||||
|
||||
foodata(trap::property *const &ptr = nullptr): ptr{ptr} {}
|
||||
};
|
||||
|
||||
} // namespace js
|
||||
} // namespace ircd
|
||||
|
||||
bool
|
||||
ircd::js::trap::property::handle_set(JSContext *const c,
|
||||
const unsigned argc,
|
||||
JS::Value *const argv)
|
||||
noexcept try
|
||||
{
|
||||
using js::function;
|
||||
|
||||
const struct args args(argc, argv);
|
||||
object that(args.computeThis(c));
|
||||
function func(args.callee());
|
||||
const string name(js::name(func));
|
||||
|
||||
auto &trap(from(that));
|
||||
trap.debug(that.get(), "set '%s' (property)",
|
||||
name.c_str());
|
||||
|
||||
property &prop(*trap.member.at(name));
|
||||
args.rval().set(prop.on_get(func, that));
|
||||
return true;
|
||||
}
|
||||
catch(const jserror &e)
|
||||
{
|
||||
e.set_pending();
|
||||
return false;
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
auto ca(JS::CallArgsFromVp(argc, argv));
|
||||
object that(ca.computeThis(c));
|
||||
auto &trap(from(that));
|
||||
trap.host_exception(that.get(), "property set: %s", e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
ircd::js::value
|
||||
ircd::js::trap::property::on_get(function::handle,
|
||||
object::handle that)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
ircd::js::value
|
||||
ircd::js::trap::property::on_set(function::handle,
|
||||
object::handle that,
|
||||
value::handle val)
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ircd/js/trap_function.h
|
||||
|
@ -479,17 +649,18 @@ ircd::js::trap::function::function(trap &member,
|
|||
,flags{flags}
|
||||
,lambda{lambda}
|
||||
{
|
||||
member.memfun.emplace(this);
|
||||
member.memfun.emplace(this->name, this);
|
||||
}
|
||||
|
||||
ircd::js::trap::function::~function()
|
||||
noexcept
|
||||
{
|
||||
member->memfun.erase(this);
|
||||
member->memfun.erase(this->name);
|
||||
}
|
||||
|
||||
ircd::js::function
|
||||
ircd::js::trap::function::operator()(const object::handle &obj)
|
||||
const
|
||||
{
|
||||
const auto jsf(::js::DefineFunctionWithReserved(*cx,
|
||||
obj,
|
||||
|
@ -514,8 +685,8 @@ noexcept try
|
|||
assert(&our(c) == cx);
|
||||
|
||||
const struct args args(argc, argv);
|
||||
const value that(args.computeThis(c));
|
||||
const object func(args.callee());
|
||||
const value that(args.computeThis(c));
|
||||
auto &trap(from(func));
|
||||
log.debug("trap(%p) this(%p) %s() call argv[%u]",
|
||||
(const void *)&trap,
|
||||
|
@ -574,21 +745,24 @@ ircd::js::trap::function::on_call(object::handle obj,
|
|||
// ircd/js/trap.h
|
||||
//
|
||||
|
||||
ircd::js::trap::trap(const std::string &path,
|
||||
ircd::js::trap::trap(const std::string &name,
|
||||
const uint &flags,
|
||||
const uint &prop_flags)
|
||||
:parent{[&path]
|
||||
:trap{*tree, name, flags, prop_flags}
|
||||
{
|
||||
const auto ret(rsplit(path, ".").first);
|
||||
return ret == path? std::string{} : ret;
|
||||
}()}
|
||||
,_name
|
||||
{
|
||||
path.empty()? std::string{""} : token_last(path, ".")
|
||||
}
|
||||
|
||||
ircd::js::trap::trap(trap &parent,
|
||||
const std::string &name,
|
||||
const uint &flags,
|
||||
const uint &prop_flags)
|
||||
:parent{&parent != this? &parent : nullptr}
|
||||
,_name{name}
|
||||
,cis{0}
|
||||
,cds{0}
|
||||
,sps{0}
|
||||
,ps{0}
|
||||
,sfs{0}
|
||||
,ps{0}
|
||||
,fs{0}
|
||||
,_class{std::make_unique<JSClass>(JSClass
|
||||
{
|
||||
|
@ -608,13 +782,14 @@ ircd::js::trap::trap(const std::string &path,
|
|||
flags & JSCLASS_GLOBAL_FLAGS? JS_GlobalObjectTraceHook : handle_trace,
|
||||
{ this } // reserved[0] TODO: ?????????
|
||||
})}
|
||||
,parent_prototype{nullptr}
|
||||
,prototype{nullptr}
|
||||
,prototrap{nullptr}
|
||||
{
|
||||
std::fill(begin(sfs), end(sfs), (JSFunctionSpec)JS_FS_END);
|
||||
std::fill(begin(fs), end(fs), (JSFunctionSpec)JS_FS_END);
|
||||
|
||||
ps[0].flags |= prop_flags;
|
||||
//ps[0].name = "";
|
||||
//ps[0].flags |= prop_flags;
|
||||
//ps[0].flags |= JSPROP_ENUMERATE;
|
||||
add_this();
|
||||
}
|
||||
|
||||
|
@ -633,27 +808,51 @@ noexcept
|
|||
}
|
||||
|
||||
ircd::js::object
|
||||
ircd::js::trap::operator()()
|
||||
ircd::js::trap::construct(const vector<value>::handle &argv)
|
||||
{
|
||||
object p(prototype? ctor(*prototype) : object{});
|
||||
object pp(parent_prototype? ctor(*parent_prototype) : object{});
|
||||
object proto(JS_InitClass(*cx,
|
||||
p,
|
||||
pp,
|
||||
_class.get(),
|
||||
nullptr,
|
||||
0,
|
||||
ps.data(),
|
||||
fs.data(),
|
||||
sps.data(),
|
||||
sfs.data()));
|
||||
const object globals;
|
||||
return construct(globals, argv);
|
||||
}
|
||||
|
||||
ircd::js::object
|
||||
ircd::js::trap::construct(const object::handle &globals,
|
||||
const vector<value>::handle &argv)
|
||||
{
|
||||
const object prototype(this->prototype(globals));
|
||||
return JS_New(*cx, prototype, argv);
|
||||
}
|
||||
|
||||
ircd::js::object
|
||||
ircd::js::trap::prototype(const object::handle &globals)
|
||||
{
|
||||
const object super
|
||||
{
|
||||
prototrap? prototrap->construct() : object{object::uninitialized}
|
||||
};
|
||||
|
||||
const object proto
|
||||
{
|
||||
JS_InitClass(*cx,
|
||||
globals,
|
||||
super,
|
||||
_class.get(),
|
||||
nullptr,
|
||||
0,
|
||||
ps.data(),
|
||||
fs.data(),
|
||||
sps.data(),
|
||||
sfs.data())
|
||||
};
|
||||
|
||||
for(auto it(begin(memfun)); it != end(memfun); ++it)
|
||||
{
|
||||
trap::function &deffun(**it);
|
||||
deffun(proto);
|
||||
const function &deffun(*it->second);
|
||||
const js::function func(deffun(proto));
|
||||
}
|
||||
|
||||
JS_DefineConstIntegers(*cx, proto, cis.data());
|
||||
JS_DefineConstDoubles(*cx, proto, cds.data());
|
||||
|
||||
return proto;
|
||||
}
|
||||
|
||||
|
@ -661,25 +860,28 @@ void
|
|||
ircd::js::trap::del_this()
|
||||
try
|
||||
{
|
||||
if(name().empty())
|
||||
// It is a special condition when the parent is self (this) and the trap has no name.
|
||||
if(!parent && name().empty())
|
||||
{
|
||||
tree = nullptr;
|
||||
tree = nullptr; // thread_local
|
||||
return;
|
||||
}
|
||||
|
||||
auto &parent(find(this->parent));
|
||||
if(!parent.children.erase(name()))
|
||||
if(!parent)
|
||||
return;
|
||||
|
||||
if(!parent->children.erase(name()))
|
||||
throw std::out_of_range("child not in parent's map");
|
||||
|
||||
log.debug("Unregistered trap '%s' in `%s'",
|
||||
name().c_str(),
|
||||
this->parent.c_str());
|
||||
parent->name().c_str());
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
log.error("Failed to unregister object trap '%s' in `%s': %s",
|
||||
name().c_str(),
|
||||
parent.c_str(),
|
||||
parent->name().c_str(),
|
||||
e.what());
|
||||
return;
|
||||
}
|
||||
|
@ -688,36 +890,29 @@ void
|
|||
ircd::js::trap::add_this()
|
||||
try
|
||||
{
|
||||
if(name().empty())
|
||||
// It is a special condition when the parent is self (this) and the trap has no name.
|
||||
if(!parent && name().empty())
|
||||
{
|
||||
if(tree)
|
||||
throw error("ircd::js::tree is already active. Won't overwrite.");
|
||||
|
||||
tree = this;
|
||||
tree = this; // thread_local
|
||||
return;
|
||||
}
|
||||
|
||||
auto &parent(find(this->parent));
|
||||
const auto iit(parent.children.emplace(name(), this));
|
||||
if(!parent)
|
||||
return;
|
||||
|
||||
const auto iit(parent->children.emplace(name(), this));
|
||||
if(!iit.second)
|
||||
throw error("Failed to overwrite existing");
|
||||
|
||||
log.debug("Registered trap '%s' in `%s'",
|
||||
name().c_str(),
|
||||
this->parent.c_str());
|
||||
}
|
||||
catch(const std::out_of_range &e)
|
||||
{
|
||||
log.error("Failed to register object trap '%s' in `%s': missing parent.",
|
||||
name().c_str(),
|
||||
parent.c_str());
|
||||
throw;
|
||||
parent->name().c_str());
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
log.error("Failed to register object trap '%s' in `%s': %s",
|
||||
name().c_str(),
|
||||
parent.c_str(),
|
||||
parent->name().c_str(),
|
||||
e.what());
|
||||
throw;
|
||||
}
|
||||
|
@ -953,12 +1148,118 @@ catch(const jserror &e)
|
|||
catch(const std::exception &e)
|
||||
{
|
||||
auto &trap(from(obj));
|
||||
trap.host_exception("del '%s': %s",
|
||||
trap.host_exception(obj.get(), "del '%s': %s",
|
||||
string(id).c_str(),
|
||||
e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace ircd {
|
||||
namespace js {
|
||||
|
||||
std::map<std::string, heap_value> tempo;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::js::trap::handle_getter(JSContext *const c,
|
||||
unsigned argc,
|
||||
JS::Value *const argv)
|
||||
noexcept try
|
||||
{
|
||||
using js::function;
|
||||
|
||||
const struct args args(argc, argv);
|
||||
object that(args.computeThis(c));
|
||||
function func(args.callee());
|
||||
const string name(js::name(func));
|
||||
|
||||
auto &trap(from(that));
|
||||
trap.debug(that.get(), "get '%s' (getter)",
|
||||
name.c_str());
|
||||
|
||||
const auto it(tempo.find(name));
|
||||
if(it == end(tempo))
|
||||
{
|
||||
//throw reference_error("%s", name.c_str());
|
||||
args.rval().set(value{});
|
||||
return true;
|
||||
}
|
||||
|
||||
heap_value &val(it->second);
|
||||
args.rval().set(val);
|
||||
return true;
|
||||
}
|
||||
catch(const jserror &e)
|
||||
{
|
||||
e.set_pending();
|
||||
return false;
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
auto ca(JS::CallArgsFromVp(argc, argv));
|
||||
object that(ca.computeThis(c));
|
||||
auto &trap(from(that));
|
||||
trap.host_exception(that.get(), "getter: %s", e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::js::trap::handle_setter(JSContext *const c,
|
||||
unsigned argc,
|
||||
JS::Value *const argv)
|
||||
noexcept try
|
||||
{
|
||||
using js::function;
|
||||
|
||||
const struct args args(argc, argv);
|
||||
object that(args.computeThis(c));
|
||||
function func(args.callee());
|
||||
|
||||
value val(args[0]);
|
||||
const auto type(basic::type(val));
|
||||
const string name(js::name(func));
|
||||
|
||||
auto &trap(from(that));
|
||||
trap.debug(that.get(), "set '%s' (%s) (setter)",
|
||||
name.c_str(),
|
||||
reflect(type));
|
||||
|
||||
auto it(tempo.lower_bound(name));
|
||||
assert(it != end(tempo));
|
||||
heap_value &hval(it->second);
|
||||
switch(js::type(type))
|
||||
{
|
||||
case jstype::OBJECT:
|
||||
{
|
||||
//const auto flags(JSPROP_SHARED);
|
||||
//object ret(JS_DefineObject(*cx, object(val), "", &trap.jsclass(), flags));
|
||||
//tempo.emplace(name, heap_value(ret));
|
||||
//args.rval().set(ret);
|
||||
//return true;
|
||||
}
|
||||
|
||||
default:
|
||||
hval = val;
|
||||
args.rval().set(val);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch(const jserror &e)
|
||||
{
|
||||
e.set_pending();
|
||||
return false;
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
auto ca(JS::CallArgsFromVp(argc, argv));
|
||||
object that(ca.computeThis(c));
|
||||
auto &trap(from(that));
|
||||
trap.host_exception(that.get(), "setter: %s", e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::js::trap::handle_get(JSContext *const c,
|
||||
JS::HandleObject obj,
|
||||
|
@ -1108,9 +1409,9 @@ catch(const std::exception &e)
|
|||
}
|
||||
|
||||
ircd::js::trap &
|
||||
ircd::js::trap::from(const JS::HandleObject &o)
|
||||
ircd::js::trap::from(const JSObject *const &o)
|
||||
{
|
||||
return from(*o.get());
|
||||
return from(*o);
|
||||
}
|
||||
|
||||
ircd::js::trap &
|
||||
|
@ -1206,6 +1507,31 @@ bool
|
|||
ircd::js::trap::on_has(object::handle,
|
||||
id::handle id)
|
||||
{
|
||||
/*
|
||||
const string sid(id);
|
||||
if(children.count(sid))
|
||||
return false;
|
||||
|
||||
if(std::any_of(begin(memfun), end(memfun), [&sid]
|
||||
(const auto &it)
|
||||
{
|
||||
const auto &memfun(*it.second);
|
||||
return sid == memfun.name;
|
||||
}))
|
||||
return false;
|
||||
*/
|
||||
|
||||
/*
|
||||
value val;
|
||||
const auto flags(JSPROP_SHARED | JSPROP_ENUMERATE);
|
||||
if(!JS_DefinePropertyById(*cx, obj, id, val, flags, handle_getter, handle_setter))
|
||||
throw jserror("Failed to define property '%s'", sid.c_str());
|
||||
|
||||
*/
|
||||
// const auto flags(0);
|
||||
// if(!JS_DefineObject(*cx, obj, sid.c_str(), &jsclass(), flags))
|
||||
// throw jserror("Failed to define property '%s'", sid.c_str());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue