-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Tidy functionality and add tests for R to JS conversions
- Loading branch information
Showing
13 changed files
with
219 additions
and
65 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,3 +9,4 @@ | |
^src/quickjs/\.github$ | ||
^src/quickjs/\.git$ | ||
semicolon_delimited_script | ||
Makefile |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
clean: | ||
$(MAKE) -C src -f Makevars clean |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#ifndef QUICKJSR_HPP | ||
#define QUICKJSR_HPP | ||
|
||
#include <quickjsr/SEXP_to_JSValue.hpp> | ||
#include <quickjsr/JSValue_to_SEXP.hpp> | ||
#include <quickjsr/JSValue_to_JSON.hpp> | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
#ifndef QUICKJSR_JSVALUE_TO_JSON_HPP | ||
#define QUICKJSR_JSVALUE_TO_JSON_HPP | ||
|
||
#include <cpp11.hpp> | ||
#include <quickjs-libc.h> | ||
|
||
namespace quickjsr { | ||
|
||
std::string JS_ValToJSON(JSContext* ctx, JSValue* val) { | ||
JSValue global = JS_GetGlobalObject(ctx); | ||
JSValue json = JS_GetPropertyStr(ctx, global, "JSON"); | ||
JSValue stringify = JS_GetPropertyStr(ctx, json, "stringify"); | ||
|
||
JSValue result_js = JS_Call(ctx, stringify, global, 1, val); | ||
std::string result; | ||
if (JS_IsException(result_js)) { | ||
js_std_dump_error(ctx); | ||
result = "Error!"; | ||
} else { | ||
result = JS_ToCString(ctx, result_js); | ||
} | ||
|
||
JS_FreeValue(ctx, result_js); | ||
JS_FreeValue(ctx, stringify); | ||
JS_FreeValue(ctx, json); | ||
JS_FreeValue(ctx, global); | ||
|
||
return result; | ||
} | ||
|
||
} // namespace quickjsr | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
#ifndef QUICKJSR_JSVALUE_TO_SEXP_HPP | ||
#define QUICKJSR_JSVALUE_TO_SEXP_HPP | ||
|
||
#include <cpp11.hpp> | ||
#include <quickjs-libc.h> | ||
|
||
namespace quickjsr { | ||
|
||
SEXP JSValue_to_SEXP_scalar(JSContext* ctx, JSValue val) { | ||
if (JS_IsBool(val)) { | ||
return cpp11::as_sexp(static_cast<bool>(JS_ToBool(ctx, val))); | ||
} | ||
if (JS_IsNumber(val)) { | ||
double res; | ||
JS_ToFloat64(ctx, &res, val); | ||
return cpp11::as_sexp(res); | ||
} | ||
if (JS_IsString(val)) { | ||
return cpp11::as_sexp(JS_ToCString(ctx, val)); | ||
} | ||
return cpp11::as_sexp("Unsupported type"); | ||
} | ||
|
||
SEXP JSValue_to_SEXP(JSContext* ctx, JSValue val) { | ||
// TODO: Implement array and object conversion | ||
return JSValue_to_SEXP_scalar(ctx, val); | ||
} | ||
|
||
} // namespace quickjsr | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
#ifndef QUICKJSR_SEXP_TO_JSVALUE_HPP | ||
#define QUICKJSR_SEXP_TO_JSVALUE_HPP | ||
|
||
#include <cpp11.hpp> | ||
#include <quickjs-libc.h> | ||
#include <iostream> | ||
|
||
namespace quickjsr { | ||
|
||
JSValue SEXP_to_JSValue_scalar(JSContext* ctx, SEXP x, int i = 0) { | ||
switch(TYPEOF(x)) { | ||
case REALSXP: | ||
return JS_NewFloat64(ctx, REAL(x)[i]); | ||
case INTSXP: | ||
return JS_NewInt32(ctx, INTEGER(x)[i]); | ||
case LGLSXP: | ||
return JS_NewBool(ctx, LOGICAL(x)[i]); | ||
case STRSXP: | ||
return JS_NewString(ctx, CHAR(STRING_ELT(x, i))); | ||
default: | ||
return JS_UNDEFINED; | ||
} | ||
} | ||
|
||
JSValue SEXP_to_JSValue_vector(JSContext* ctx, SEXP x) { | ||
JSValue arr = JS_NewArray(ctx); | ||
for (int i = 0; i < Rf_length(x); i++) { | ||
JSValue val = SEXP_to_JSValue_scalar(ctx, x, i); | ||
JS_SetPropertyUint32(ctx, arr, i, val); | ||
} | ||
return arr; | ||
} | ||
|
||
JSValue SEXP_to_JSValue(JSContext* ctx, SEXP x, bool auto_unbox = false) { | ||
if (TYPEOF(x) == VECSXP) { | ||
cpp11::list x_list(x); | ||
if (x_list.named()) { | ||
JSValue obj = JS_NewObject(ctx); | ||
for (int i = 0; i < Rf_length(x); i++) { | ||
SEXP name = STRING_ELT(Rf_getAttrib(x, R_NamesSymbol), i); | ||
JSValue val = SEXP_to_JSValue(ctx, VECTOR_ELT(x, i)); | ||
JS_SetPropertyStr(ctx, obj, CHAR(name), val); | ||
} | ||
return obj; | ||
} else { | ||
JSValue arr = JS_NewArray(ctx); | ||
for (int i = 0; i < Rf_length(x); i++) { | ||
JSValue val = SEXP_to_JSValue(ctx, VECTOR_ELT(x, i)); | ||
JS_SetPropertyUint32(ctx, arr, i, val); | ||
} | ||
return arr; | ||
} | ||
} | ||
if (Rf_length(x) == 1 && auto_unbox) { | ||
return SEXP_to_JSValue_scalar(ctx, x); | ||
} else { | ||
return SEXP_to_JSValue_vector(ctx, x); | ||
} | ||
} | ||
|
||
} // namespace quickjsr | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Check conversions from R types to JS types are consistent with jsonlite. | ||
# - The inputs are directly converted from R to JS types using the QuickJS API. | ||
# - The outputs are returned as JSON strings and parsed back to R using jsonlite. | ||
# - If the conversion is consistent, the output should be the same as the input. | ||
expect_eq_jsonlite <- function(x) { | ||
expect_equal(qjs_passthrough(x), jsonlite::fromJSON(jsonlite::toJSON(x))) | ||
} | ||
expect_eq_jsonlite(1) | ||
expect_eq_jsonlite(1:3) | ||
expect_eq_jsonlite(c(1.5, 2.5)) | ||
|
||
expect_eq_jsonlite("a") | ||
expect_eq_jsonlite(c("a", "b", "c")) | ||
|
||
expect_eq_jsonlite(TRUE) | ||
expect_eq_jsonlite(FALSE) | ||
expect_eq_jsonlite(c(TRUE, FALSE)) | ||
|
||
expect_eq_jsonlite(list(1, 2, 3)) | ||
expect_eq_jsonlite(list(a = 1, b = 2, c = 3)) | ||
expect_eq_jsonlite(list(a = "d", b = "e", c = "f")) | ||
|
||
expect_eq_jsonlite(list(c(1, 2), c(3, 4))) | ||
expect_eq_jsonlite(list(list(1, 2), list(3, 4))) | ||
expect_eq_jsonlite(list(list(a = 1, b = 2), list(c = 3, d = 4))) | ||
|
||
expect_eq_jsonlite(list(c("e", "f"), c("g", "h"))) | ||
expect_eq_jsonlite(list(list("e", "f"), list("g", "h"))) | ||
expect_eq_jsonlite(list(list(a = "e", b = "f"), list(c = "g", d = "h"))) |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters