2016-10-12 09:04:26 +02:00
|
|
|
/*
|
|
|
|
* 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_CONTEXT_H
|
|
|
|
|
|
|
|
namespace ircd {
|
|
|
|
namespace js {
|
|
|
|
|
|
|
|
struct context
|
2016-10-14 02:24:50 +02:00
|
|
|
:private custom_ptr<JSContext>
|
2016-10-12 09:04:26 +02:00
|
|
|
{
|
2016-10-16 01:53:44 +02:00
|
|
|
class lock
|
|
|
|
{
|
|
|
|
context *c;
|
|
|
|
|
|
|
|
public:
|
|
|
|
lock(context &c); // BeginRequest on cx of your choice
|
|
|
|
lock(); // BeginRequest on the thread_local cx
|
|
|
|
~lock() noexcept; // EndRequest
|
|
|
|
};
|
|
|
|
|
2016-10-14 02:24:50 +02:00
|
|
|
struct opts
|
2016-10-13 04:58:48 +02:00
|
|
|
{
|
2016-10-14 02:24:50 +02:00
|
|
|
size_t stack_chunk_size = 8_KiB;
|
|
|
|
bool dtor_gc = true;
|
2016-10-20 04:50:55 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct exstate
|
|
|
|
{
|
|
|
|
JSExceptionState *state; // exstate
|
|
|
|
JSErrorReport report; // note: ptrs within are not necessarily safe
|
|
|
|
};
|
|
|
|
|
|
|
|
struct opts opts; // We keep a copy of the given opts here.
|
|
|
|
std::stack<struct exstate> exstate;
|
2016-10-13 04:58:48 +02:00
|
|
|
|
|
|
|
operator JSContext *() const { return get(); }
|
|
|
|
operator JSContext &() const { return custom_ptr<JSContext>::operator*(); }
|
2016-10-14 02:24:50 +02:00
|
|
|
bool operator!() const { return !custom_ptr<JSContext>::operator bool(); }
|
|
|
|
auto &runtime() const { return our(JS_GetRuntime(get())); }
|
|
|
|
auto &runtime() { return our(JS_GetRuntime(get())); }
|
|
|
|
auto ptr() const { return get(); }
|
|
|
|
auto ptr() { return get(); }
|
2016-10-13 04:58:48 +02:00
|
|
|
|
2016-10-14 02:24:50 +02:00
|
|
|
context(JSRuntime *const &, const struct opts &);
|
2016-10-12 09:04:26 +02:00
|
|
|
context() = default;
|
2016-10-14 02:24:50 +02:00
|
|
|
context(context &&) noexcept;
|
|
|
|
context(const context &) = delete;
|
|
|
|
context &operator=(context &&) noexcept;
|
|
|
|
context &operator=(const context &) = delete;
|
2016-10-16 01:53:44 +02:00
|
|
|
~context() noexcept;
|
2016-10-12 09:04:26 +02:00
|
|
|
};
|
|
|
|
|
2016-10-16 01:53:44 +02:00
|
|
|
// Current thread_local context. Runtimes/Contexts (soon to be merged in future SpiderMonkey)
|
|
|
|
// are singled-threaded and this points to the context appropos your thread.
|
|
|
|
// Do not construct more than one context on the same thread- this is overwritten.
|
|
|
|
extern __thread context *cx;
|
|
|
|
|
2016-10-12 09:04:26 +02:00
|
|
|
// A default JSContext instance is provided residing near the main runtime as a convenience
|
2016-10-16 01:53:44 +02:00
|
|
|
// for misc/utility/system purposes if necessary. You should use *cx instead.
|
|
|
|
extern context main_cx;
|
2016-10-12 09:04:26 +02:00
|
|
|
|
2016-10-14 02:24:50 +02:00
|
|
|
// Get to our `struct context` from any upstream JSContext
|
|
|
|
const context &our(const JSContext *const &);
|
|
|
|
context &our(JSContext *const &);
|
|
|
|
|
2016-10-13 04:58:48 +02:00
|
|
|
// Get/Set your privdata managed by this object, casting to your expected type.
|
2016-10-14 02:24:50 +02:00
|
|
|
template<class T = privdata> const T *priv(const context &);
|
|
|
|
template<class T = privdata> T *priv(context &);
|
|
|
|
void priv(context &, privdata *const &);
|
2016-10-13 04:58:48 +02:00
|
|
|
|
2016-10-19 02:10:27 +02:00
|
|
|
inline auto version(const context &c) { return version(JS_GetVersion(c)); }
|
|
|
|
inline auto running(const context &c) { return JS_IsRunning(c); }
|
|
|
|
inline auto uncaught_exception(const context &c) { return JS_IsExceptionPending(c); }
|
|
|
|
inline auto interrupted(const context &c) { return JS_CheckForInterrupt(c); }
|
|
|
|
inline void out_of_memory(context &c) { JS_ReportOutOfMemory(c); }
|
|
|
|
inline void allocation_overflow(context &c) { JS_ReportAllocationOverflow(c); }
|
|
|
|
inline void run_gc(context &c) { JS_MaybeGC(c); }
|
2016-10-16 01:53:44 +02:00
|
|
|
JSObject *current_global(context &c);
|
2016-10-20 04:50:55 +02:00
|
|
|
bool rethrow_exception(context &c);
|
|
|
|
void push_exception(context &c, const JSErrorReport &);
|
|
|
|
JSErrorReport pop_exception(context &c);
|
|
|
|
|
|
|
|
// thread_local
|
|
|
|
JSObject *current_global();
|
2016-10-13 04:58:48 +02:00
|
|
|
|
2016-10-14 02:24:50 +02:00
|
|
|
|
2016-10-16 01:53:44 +02:00
|
|
|
inline JSObject *
|
|
|
|
current_global()
|
|
|
|
{
|
|
|
|
return current_global(*cx);
|
|
|
|
}
|
|
|
|
|
2016-10-20 04:50:55 +02:00
|
|
|
inline bool
|
|
|
|
rethrow_exception(context &c)
|
|
|
|
{
|
|
|
|
return JS_ReportPendingException(c);
|
|
|
|
}
|
|
|
|
|
2016-10-15 07:44:42 +02:00
|
|
|
inline JSObject *
|
2016-10-16 01:53:44 +02:00
|
|
|
current_global(context &c)
|
2016-10-15 07:44:42 +02:00
|
|
|
{
|
|
|
|
return JS::CurrentGlobalOrNull(c);
|
|
|
|
}
|
|
|
|
|
2016-10-14 02:24:50 +02:00
|
|
|
inline void
|
|
|
|
priv(context &c,
|
|
|
|
privdata *const &ptr)
|
2016-10-12 09:04:26 +02:00
|
|
|
{
|
2016-10-14 02:24:50 +02:00
|
|
|
delete priv(c); // Free any existing object to overwrite/null
|
|
|
|
JS_SetSecondContextPrivate(c, ptr);
|
2016-10-12 09:04:26 +02:00
|
|
|
}
|
2016-10-14 02:24:50 +02:00
|
|
|
|
|
|
|
template<class T>
|
|
|
|
T *
|
|
|
|
priv(context &c)
|
2016-10-12 09:04:26 +02:00
|
|
|
{
|
2016-10-14 02:24:50 +02:00
|
|
|
return dynamic_cast<T *>(static_cast<privdata *>(JS_GetSecondContextPrivate(c)));
|
2016-10-12 09:04:26 +02:00
|
|
|
}
|
|
|
|
|
2016-10-14 02:24:50 +02:00
|
|
|
template<class T>
|
|
|
|
const T *
|
|
|
|
priv(const context &c)
|
2016-10-13 04:58:48 +02:00
|
|
|
{
|
2016-10-14 02:24:50 +02:00
|
|
|
return dynamic_cast<const T *>(static_cast<const privdata *>(JS_GetSecondContextPrivate(c)));
|
2016-10-13 04:58:48 +02:00
|
|
|
}
|
|
|
|
|
2016-10-14 02:24:50 +02:00
|
|
|
inline context &
|
|
|
|
our(JSContext *const &c)
|
2016-10-13 04:58:48 +02:00
|
|
|
{
|
2016-10-14 02:24:50 +02:00
|
|
|
return *static_cast<context *>(JS_GetContextPrivate(c));
|
2016-10-13 04:58:48 +02:00
|
|
|
}
|
|
|
|
|
2016-10-14 02:24:50 +02:00
|
|
|
inline const context &
|
|
|
|
our(const JSContext *const &c)
|
2016-10-13 04:58:48 +02:00
|
|
|
{
|
2016-10-14 02:24:50 +02:00
|
|
|
return *static_cast<const context *>(JS_GetContextPrivate(const_cast<JSContext *>(c)));
|
2016-10-13 04:58:48 +02:00
|
|
|
}
|
|
|
|
|
2016-10-12 09:04:26 +02:00
|
|
|
} // namespace js
|
|
|
|
} // namespace ircd
|