0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2025-01-01 18:34:18 +01:00

ircd::js: Add trap to define JSObject functionality in C.

This commit is contained in:
Jason Volk 2016-10-14 22:44:42 -07:00
parent e6c6137fcb
commit 6db6b2a975
5 changed files with 338 additions and 0 deletions

View file

@ -72,8 +72,22 @@ auto interrupted(const context &c) { return JS_CheckForInterrupt(c
void out_of_memory(context &c) { JS_ReportOutOfMemory(c); }
void allocation_overflow(context &c) { JS_ReportAllocationOverflow(c); }
void run_gc(context &c) { JS_MaybeGC(c); }
JSObject *current_global_p(context &c);
JS::RootedObject current_global(context &c);
inline JS::RootedObject
current_global(context &c)
{
return { c, current_global_p(c) };
}
inline JSObject *
current_global_p(context &c)
{
return JS::CurrentGlobalOrNull(c);
}
inline void
priv(context &c,
privdata *const &ptr)

View file

@ -68,3 +68,4 @@ JSVersion version(const char *const &v) { return JS_StringToVersion(v);
#include "for_each.h"
#include "script.h"
#include "debug.h"
#include "trap.h"

View file

@ -73,6 +73,10 @@ extern runtime main;
const runtime &our(const JSRuntime *const &);
runtime &our(JSRuntime *const &);
// Get to our runtime from any JSObject
const runtime &object_runtime(const JSObject &);
runtime &object_runtime(JSObject &);
void interrupt(runtime &r);
void run_gc(runtime &r);
@ -90,6 +94,18 @@ interrupt(runtime &r)
JS_RequestInterruptCallback(r);
}
inline runtime &
object_runtime(JSObject &o)
{
return our(JS_GetObjectRuntime(&o));
}
inline const runtime &
object_runtime(const JSObject &o)
{
return our(JS_GetObjectRuntime(const_cast<JSObject *>(&o)));
}
inline runtime &
our(JSRuntime *const &c)
{

74
include/ircd/js/trap.h Normal file
View file

@ -0,0 +1,74 @@
/*
* 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_H
namespace ircd {
namespace js {
class trap
{
const std::string _name; // don't touch
const JSClass _class;
// Override these to define JS objects in C
virtual bool on_add(context &, const JSObject &, const jsid &, const JS::Value &);
virtual bool on_set(context &, const JSObject &, const jsid &, JS::MutableHandleValue);
virtual bool on_get(context &, const JSObject &, const jsid &, JS::MutableHandleValue);
virtual bool on_del(context &, const JSObject &, const jsid &);
virtual bool on_res(context &, const JSObject &, const jsid &, bool &resolved);
virtual bool on_enu(context &, const JSObject &);
virtual bool on_call(context &, const unsigned &argc, JS::Value &argv);
virtual bool on_ctor(context &, const unsigned &argc, JS::Value &argv);
private:
static trap &from(const JSObject &);
static trap &from(const JS::HandleObject &);
// Internal callback interface
static void handle_trace(JSTracer *, JSObject *);
static bool handle_inst(JSContext *, JS::HandleObject, JS::MutableHandleValue, bool *yesno);
static bool handle_add(JSContext *, JS::HandleObject, JS::HandleId, JS::HandleValue);
static bool handle_set(JSContext *, JS::HandleObject, JS::HandleId, JS::MutableHandleValue, JS::ObjectOpResult &);
static bool handle_get(JSContext *, JS::HandleObject, JS::HandleId, JS::MutableHandleValue);
static bool handle_del(JSContext *, JS::HandleObject, JS::HandleId, JS::ObjectOpResult &);
static bool handle_res(JSContext *, JS::HandleObject, JS::HandleId, bool *resolved);
static bool handle_enu(JSContext *, JS::HandleObject);
static bool handle_call(JSContext *, unsigned argc, JS::Value *argv);
static bool handle_ctor(JSContext *, unsigned argc, JS::Value *argv);
static void handle_dtor(JSFreeOp *, JSObject *);
public:
auto &name() const { return _name; }
auto &jsclass() const { return _class; }
JSObject *operator()(context &, JS::HandleObject proto);
JSObject *operator()(context &);
trap(std::string name, const uint32_t &flags = 0);
trap(trap &&) = delete;
trap(const trap &) = delete;
virtual ~trap() noexcept;
};
} // namespace js
} // namespace ircd

View file

@ -100,6 +100,239 @@ ircd::js::version(const ver &type)
// ircd/js/js.h - With 3rd party (JSAPI) symbols
//
///////////////////////////////////////////////////////////////////////////////
//
// ircd/js/trap.h
//
ircd::js::trap::trap(std::string name,
const uint32_t &flags)
:_name{std::move(name)}
,_class
{
this->_name.c_str(),
flags,
handle_add,
handle_del,
handle_get,
handle_set,
handle_enu,
handle_res,
nullptr, // JSConvertOp - Obsolete since SpiderMonkey 44 // 45 = mayResolve?
handle_dtor,
handle_call,
handle_inst,
handle_ctor,
handle_trace,
{ this } // reserved[0] TODO: ?????????
}
{
}
ircd::js::trap::~trap()
noexcept
{
}
JSObject *
ircd::js::trap::operator()(context &c)
{
return JS_NewObject(c, &_class);
}
JSObject *
ircd::js::trap::operator()(context &c,
JS::HandleObject proto)
{
return JS_NewObjectWithGivenProto(c, &_class, proto);
}
void
ircd::js::trap::handle_dtor(JSFreeOp *const op,
JSObject *const obj)
{
}
bool
ircd::js::trap::handle_ctor(JSContext *const c,
unsigned argc,
JS::Value *const argv)
{
return false;
}
bool
ircd::js::trap::handle_call(JSContext *const c,
unsigned argc,
JS::Value *const argv)
{
return false;
}
bool
ircd::js::trap::handle_enu(JSContext *const c,
JS::HandleObject obj)
{
auto &trap(from(obj));
return trap.on_enu(our(c), *obj.get());
}
bool
ircd::js::trap::handle_res(JSContext *const c,
JS::HandleObject obj,
JS::HandleId id,
bool *const resolved)
{
auto &trap(from(obj));
return trap.on_res(our(c), *obj.get(), id.get(), *resolved);
}
bool
ircd::js::trap::handle_del(JSContext *const c,
JS::HandleObject obj,
JS::HandleId id,
JS::ObjectOpResult &res)
{
auto &trap(from(obj));
if(!trap.on_del(our(c), *obj.get(), id.get()))
return false;
res.succeed();
return true;
}
bool
ircd::js::trap::handle_get(JSContext *const c,
JS::HandleObject obj,
JS::HandleId id,
JS::MutableHandleValue val)
{
auto &trap(from(obj));
return trap.on_get(our(c), *obj.get(), id.get(), val);
}
bool
ircd::js::trap::handle_set(JSContext *const c,
JS::HandleObject obj,
JS::HandleId id,
JS::MutableHandleValue val,
JS::ObjectOpResult &res)
{
auto &trap(from(obj));
return trap.on_get(our(c), *obj.get(), id.get(), val);
}
bool
ircd::js::trap::handle_add(JSContext *const c,
JS::HandleObject obj,
JS::HandleId id,
JS::HandleValue val)
{
auto &trap(from(obj));
return trap.on_add(our(c), *obj.get(), id.get(), val.get());
}
bool
ircd::js::trap::handle_inst(JSContext *const c,
JS::HandleObject obj,
JS::MutableHandleValue val,
bool *const has_instance)
{
return false;
}
void
ircd::js::trap::handle_trace(JSTracer *const tracer,
JSObject *const obj)
{
}
ircd::js::trap &
ircd::js::trap::from(const JS::HandleObject &o)
{
return from(*o.get());
}
ircd::js::trap &
ircd::js::trap::from(const JSObject &o)
{
auto *const c(JS_GetClass(const_cast<JSObject *>(&o)));
if(!c)
std::terminate(); //TODO: exception
if(!c->reserved[0])
std::terminate(); //TODO: exception
return *static_cast<trap *>(c->reserved[0]); //TODO: ???
}
bool
ircd::js::trap::on_ctor(context &c,
const unsigned &argc,
JS::Value &argv)
{
return false;
}
bool
ircd::js::trap::on_call(context &c,
const unsigned &argc,
JS::Value &argv)
{
return false;
}
bool
ircd::js::trap::on_enu(context &c,
const JSObject &obj)
{
return false;
}
bool
ircd::js::trap::on_res(context &c,
const JSObject &obj,
const jsid &id,
bool &resolved)
{
return false;
}
bool
ircd::js::trap::on_del(context &c,
const JSObject &obj,
const jsid &id)
{
return false;
}
bool
ircd::js::trap::on_get(context &c,
const JSObject &obj,
const jsid &id,
JS::MutableHandleValue val)
{
return false;
}
bool
ircd::js::trap::on_set(context &c,
const JSObject &obj,
const jsid &id,
JS::MutableHandleValue val)
{
return false;
}
bool
ircd::js::trap::on_add(context &c,
const JSObject &obj,
const jsid &id,
const JS::Value &val)
{
return false;
}
///////////////////////////////////////////////////////////////////////////////
//
// ircd/js/debug.h