Skip to content

Commit

Permalink
Testing JSValue wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
andrjohns committed May 15, 2024
1 parent 6050efd commit 145769a
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 27 deletions.
37 changes: 27 additions & 10 deletions inst/include/quickjsr/wrapper_classes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,44 @@

namespace quickjsr {

JSRuntime* InitRuntime(int stack_size) {
JSRuntime* rt = JS_NewRuntime();
if (stack_size != -1) {
JS_SetMaxStackSize(rt, stack_size);
}
js_std_init_handlers(rt);
return rt;
}

struct JSRuntimeContextWrapper {
JSRuntime* rt;
JSContext* ctx;

JSRuntimeContextWrapper() : rt(JS_NewRuntime()), ctx(JS_NewContext(rt)) {
js_std_init_handlers(rt);
}

JSRuntimeContextWrapper(int stack_size) : rt(JS_NewRuntime()), ctx(JS_NewContext(rt)) {
if (stack_size != -1) {
JS_SetMaxStackSize(rt, stack_size);
}
js_std_init_handlers(rt);
}
JSRuntimeContextWrapper(int stack_size = -1) :
rt(InitRuntime(stack_size)), ctx(JS_NewContext(rt)) { }

~JSRuntimeContextWrapper() {
JS_FreeContext(ctx);
js_std_free_handlers(rt);
JS_FreeRuntime(rt);
}
};

JSContext* current_context = nullptr;

struct ExecutionScope {
ExecutionScope(JSContext* ctx) { current_context = ctx; }
~ExecutionScope() { current_context = nullptr; }
};

struct JSValueWrapper {
JSValue val;

JSValueWrapper(JSValue val) : val(val) { }
operator JSValue() const { return val; }
JSValue* operator&() { return &val; }
~JSValueWrapper() { JS_FreeValue(current_context, val); }
};
} // namespace quickjsr

#endif
29 changes: 12 additions & 17 deletions src/quickjsr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <quickjsr.hpp>

using quickjsr::JSRuntimeContextWrapper;
using quickjsr::JSValueWrapper;

// The wrapper class has a destructor that frees the context and runtime
// so we don't need to provide a finaliser function for the external pointer.
Expand Down Expand Up @@ -46,7 +47,9 @@ extern "C" SEXP qjs_validate_(SEXP ctx_ptr_, SEXP code_string_) {

extern "C" SEXP qjs_call_(SEXP ctx_ptr_, SEXP function_name_, SEXP args_json_) {
BEGIN_CPP11
JSContext* ctx = RtCtxPtr(ctx_ptr_)->ctx;
quickjsr::ExecutionScope scope(RtCtxPtr(ctx_ptr_)->ctx);
JSContext* ctx = quickjsr::current_context;

std::string function_name = cpp11::as_cpp<std::string>(function_name_);
std::string args_json = cpp11::as_cpp<std::string>(args_json_);
// Arguments are passed from R as a JSON object string, so we use a wrapper function
Expand All @@ -56,21 +59,18 @@ extern "C" SEXP qjs_call_(SEXP ctx_ptr_, SEXP function_name_, SEXP args_json_) {
"function " + wrapped_name + "(args_object) { return " + function_name +
"(...Object.values(JSON.parse(args_object))); }";

JSValue tmp = JS_Eval(ctx, call_wrapper.c_str(), call_wrapper.size(), "", 0);
JSValueWrapper tmp = JS_Eval(ctx, call_wrapper.c_str(), call_wrapper.size(), "", 0);
bool failed = JS_IsException(tmp);
JS_FreeValue(ctx, tmp);
if (failed) {
js_std_dump_error(ctx);
return cpp11::as_sexp("Error!");
}

JSValue global = JS_GetGlobalObject(ctx);
JSValue function_wrapper = JS_GetPropertyStr(ctx, global, wrapped_name.c_str());
JSValue args[] = {
JS_NewString(ctx, args_json.c_str())
};
JSValueWrapper global = JS_GetGlobalObject(ctx);
JSValueWrapper function_wrapper = JS_GetPropertyStr(ctx, global, wrapped_name.c_str());
JSValueWrapper args = JS_NewString(ctx, args_json.c_str());

JSValue result_js = JS_Call(ctx, function_wrapper, global, 1, args);
JSValueWrapper result_js = JS_Call(ctx, function_wrapper, global, 1, &args);
std::string result;
if (JS_IsException(result_js)) {
js_std_dump_error(ctx);
Expand All @@ -79,18 +79,13 @@ extern "C" SEXP qjs_call_(SEXP ctx_ptr_, SEXP function_name_, SEXP args_json_) {
result = quickjsr::JSValue_to_JSON(ctx, &result_js);
}

JS_FreeValue(ctx, result_js);
JS_FreeValue(ctx, args[0]);
JS_FreeValue(ctx, function_wrapper);
JS_FreeValue(ctx, global);

return cpp11::as_sexp(result);
END_CPP11
}

extern "C" SEXP qjs_eval_(SEXP eval_string_) {
BEGIN_CPP11
JSRuntimeContextWrapper rt = JSRuntimeContextWrapper();
JSRuntimeContextWrapper rt;
std::string eval_string = cpp11::as_cpp<std::string>(eval_string_);

JSValue val = JS_Eval(rt.ctx, eval_string.c_str(), eval_string.size(), "", 0);
Expand All @@ -110,7 +105,7 @@ extern "C" SEXP qjs_eval_(SEXP eval_string_) {

extern "C" SEXP to_json_(SEXP arg_) {
BEGIN_CPP11
JSRuntimeContextWrapper rt = JSRuntimeContextWrapper();
JSRuntimeContextWrapper rt;

JSValue arg = quickjsr::SEXP_to_JSValue(rt.ctx, arg_);
std::string result = quickjsr::JSValue_to_JSON(rt.ctx, &arg);
Expand All @@ -124,7 +119,7 @@ extern "C" SEXP to_json_(SEXP arg_) {

extern "C" SEXP from_json_(SEXP json_) {
BEGIN_CPP11
JSRuntimeContextWrapper rt = JSRuntimeContextWrapper();
JSRuntimeContextWrapper rt;

std::string json = cpp11::as_cpp<std::string>(json_);
JSValue result = quickjsr::JSON_to_JSValue(rt.ctx, json);
Expand Down

0 comments on commit 145769a

Please sign in to comment.