Skip to content

Commit

Permalink
Fix undefined return, rstan workaround
Browse files Browse the repository at this point in the history
  • Loading branch information
andrjohns committed May 30, 2024
1 parent cbcdd89 commit 3d1b079
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 7 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Authors@R: c(
comment = "Author of QuickJS sources and headers")
)
Description: An 'R' interface to the 'QuickJS' portable 'JavaScript'
engine. The engine and all 'R' to 'JavaScript' operability is bundled
engine. The engine and all 'R' to 'JavaScript' interopability is bundled
within the package, requiring no dependencies beyond a 'C' compiler.
License: MIT + file LICENSE
URL: https://github.com/andrjohns/QuickJSR, https://bellard.org/quickjs/
Expand Down
7 changes: 7 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# QuickJSR 1.2.0
- `Rcpp` dependency replaced with vendored `cpp11` headers
- `R6` dependency removed
- `R` and `JS` interopability added, removing `jsonlite` dependency
- Fixes for libatomic linking on 32-bit systems
- Added `to_json` and `from_json` functions for testing `R`/`JS` interop

# QuickJSR 1.1.0
- Fixed UBSAN error in `JS_Eval`
- Fixed compilation errors with older GCC & Clang (`stdatomic.h not found`)
Expand Down
13 changes: 10 additions & 3 deletions inst/include/quickjsr/JSCommonType.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,16 @@ enum JSCommonType {
Date,
NumberArray,
Object,
Undefined,
Unknown
};

JSCommonType JS_ArrayCommonType(JSContext* ctx, const JSValue& val);

JSCommonType JS_GetCommonType(JSContext* ctx, const JSValue& val) {
if (JS_IsUndefined(val)) {
return Undefined;
}
if (JS_IsBool(val)) {
return Logical;
}
Expand All @@ -32,6 +36,9 @@ JSCommonType JS_GetCommonType(JSContext* ctx, const JSValue& val) {
if (JS_IsString(val)) {
return Character;
}
if (JS_IsObject(val)) {
return Object;
}
if (JS_IsDate(ctx, val)) {
return Date;
}
Expand All @@ -41,9 +48,6 @@ JSCommonType JS_GetCommonType(JSContext* ctx, const JSValue& val) {
return NumberArray;
}
}
if (JS_IsObject(val)) {
return Object;
}
return Unknown;
}

Expand All @@ -56,6 +60,9 @@ JSCommonType JS_UpdateCommonType(JSCommonType current, JSContext* ctx, const JSV
if (current == new_type) {
return current;
}
if (new_type == Undefined) {
return current;
}
// If one, but not both, types are NumberArray or Date (checked above), return Object
if (new_type == NumberArray || current == NumberArray || new_type == Object
|| new_type == Date || current == Date) {
Expand Down
5 changes: 5 additions & 0 deletions inst/include/quickjsr/JSValue_Date.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <cpp11.hpp>
#include <quickjs-libc.h>
#include <cstring>
#include <iostream>

namespace quickjsr {

Expand All @@ -15,6 +16,10 @@ inline double get_tz_offset_seconds() {

inline bool JS_IsDate(JSContext* ctx, const JSValue& val) {
JSValue ctor = JS_GetPropertyStr(ctx, val, "constructor");
if (JS_IsException(ctor)) {
JS_FreeValue(ctx, ctor);
return false;
}
JSValue ctorName = JS_GetPropertyStr(ctx, ctor, "name");

const char* name = JS_ToCString(ctx, ctorName);
Expand Down
18 changes: 16 additions & 2 deletions inst/include/quickjsr/JSValue_to_SEXP.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ static void js_free_prop_enum(JSContext *ctx, JSPropertyEnum *tab, uint32_t len)
SEXP JSValue_to_SEXP(JSContext* ctx, const JSValue& val);

SEXP JSValue_to_SEXP_scalar(JSContext* ctx, const JSValue& val) {
if (JS_IsUndefined(val)) {
return R_NilValue;
}
if (JS_IsBool(val)) {
return cpp11::as_sexp(JSValue_to_Cpp<bool>(ctx, val));
}
Expand Down Expand Up @@ -54,6 +57,8 @@ SEXP JSValue_to_SEXP_vector(JSContext* ctx, const JSValue& val) {
return cpp11::as_sexp(JSValue_to_Cpp<std::vector<bool>>(ctx, val));
case Character:
return cpp11::as_sexp(JSValue_to_Cpp<std::vector<std::string>>(ctx, val));
case Undefined:
return R_NilValue;
case Date: {
cpp11::writable::doubles res = cpp11::as_sexp(JSValue_to_Cpp<std::vector<double>>(ctx, val));
res.attr("class") = "POSIXct";
Expand Down Expand Up @@ -95,8 +100,14 @@ SEXP JSValue_to_SEXP_vector(JSContext* ctx, const JSValue& val) {
}
return out;
}
default:
return cpp11::as_sexp("Unsupported type");
default: {
std::string type_str = "Unsupported type: ";
// Get result of typeof
JSValue typeof_val = JS_GetPropertyStr(ctx, val, "typeof");
type_str += JSValue_to_Cpp<std::string>(ctx, typeof_val);
JS_FreeValue(ctx, typeof_val);
return cpp11::as_sexp(type_str.c_str());
}
}
}

Expand All @@ -123,6 +134,9 @@ SEXP JSValue_to_SEXP_list(JSContext* ctx, const JSValue& val) {
}

SEXP JSValue_to_SEXP(JSContext* ctx, const JSValue& val) {
if (JS_IsUndefined(val)) {
return R_NilValue;
}
if (JS_IsArray(ctx, val)) {
return JSValue_to_SEXP_vector(ctx, val);
}
Expand Down
3 changes: 2 additions & 1 deletion src/quickjsr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ extern "C" SEXP qjs_context_(SEXP stack_size_) {
int stack_size = cpp11::as_cpp<int>(stack_size_);

RuntimeXPtr rt(JS_NewRuntime());
// Workaround for RStan stack overflow until they update
if (stack_size != -1) {
JS_SetMaxStackSize(rt.get(), stack_size);
JS_SetMaxStackSize(rt.get(), 0);
}
js_std_init_handlers(rt.get());
ContextXPtr ctx(JS_NewContext(rt.get()));
Expand Down

0 comments on commit 3d1b079

Please sign in to comment.