Initial support for javascript core plugins ##js

This commit is contained in:
pancake 2022-12-27 12:03:02 +01:00
parent 031da1be8f
commit dd8a58a07d
3 changed files with 108 additions and 2 deletions

View File

@ -9,6 +9,9 @@
#include "../js_require.c"
#include "../js_r2papi.c"
static R_TH_LOCAL JSContext *Gctx = NULL;
static R_TH_LOCAL JSValue Gfunc;
typedef struct {
JSContext *ctx;
JSRuntime *r;
@ -88,6 +91,85 @@ static JSValue b64(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst
free (ret);
return v;
}
static int r2plugin_core_call(void *_core, const char *input) {
// RCore *core = _core;
JSValueConst args[1] = {
JS_NewString (Gctx, input)
};
JSValue res = JS_Call (Gctx, Gfunc, JS_UNDEFINED, countof (args), args);
return JS_ToBool (Gctx, res) == 1;
}
static JSValue r2plugin_core(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) {
JSRuntime *rt = JS_GetRuntime (ctx);
QjsContext *k = JS_GetRuntimeOpaque (rt);
RCore *core = k->core;
if (argc != 2) {
return JS_ThrowRangeError(ctx, "r2plugin expects two arguments");
}
JSValueConst args[1] = {
JS_NewString (ctx, "POP"),
};
JSValue res = JS_Call (ctx, argv[1], JS_UNDEFINED, countof (args), args);
// check if res is an object
if (!JS_IsObject (res)) {
return JS_ThrowRangeError(ctx, "r2plugin function must return an object");
}
RCorePlugin *ap = R_NEW0 (RCorePlugin);
JSValue name = JS_GetPropertyStr (ctx, res, "name");
size_t namelen;
const char *nameptr = JS_ToCStringLen2 (ctx, &namelen, name, false);
if (nameptr) {
ap->name = strdup (nameptr);
}
JSValue desc = JS_GetPropertyStr (ctx, res, "desc");
const char *descptr = JS_ToCStringLen2 (ctx, &namelen, desc, false);
if (descptr) {
ap->desc = strdup (descptr);
}
JSValue license = JS_GetPropertyStr (ctx, res, "license");
const char *licenseptr = JS_ToCStringLen2 (ctx, &namelen, license, false);
if (licenseptr) {
ap->license = strdup (licenseptr);
}
JSValue func = JS_GetPropertyStr (ctx, res, "call");
Gctx = ctx; // XXX dont do globals
Gfunc = func;
ap->call = r2plugin_core_call;
RLibStruct *lib = R_NEW0 (RLibStruct);
lib->type = R_LIB_TYPE_CORE;
lib->data = ap;
lib->version = R2_VERSION;
r_lib_open_ptr (core->lib, "qjs", NULL, lib);
// ret = k->core->pluginAdd (k->core, n);
// r_core_plugin_add (core, ap);
return JS_NewBool (ctx, true);
}
static JSValue r2plugin(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) {
size_t plen;
const char *n = JS_ToCStringLen2 (ctx, &plen, argv[0], false);
if (R_STR_ISNOTEMPTY (n)) {
if (!strcmp (n, "core")) {
// { name: string, call: function, license: string, desc: string }
// JSValue val =
return r2plugin_core (ctx, this_val, argc, argv);
} else {
// invalid throw exception here
return JS_ThrowRangeError(ctx, "invalid r2plugin type");
}
}
return JS_NewBool (ctx, false);
}
static JSValue r2cmd(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) {
JSRuntime *rt = JS_GetRuntime (ctx);
QjsContext *k = JS_GetRuntimeOpaque (rt);
@ -218,6 +300,8 @@ static void register_helpers(JSContext *ctx) {
JS_NewCFunction (ctx, b64, "b64", 1));
JS_SetPropertyStr (ctx, global_obj, "r2cmd",
JS_NewCFunction (ctx, r2cmd, "r2cmd", 1));
JS_SetPropertyStr (ctx, global_obj, "r2plugin",
JS_NewCFunction (ctx, r2plugin, "r2plugin", 1));
JS_SetPropertyStr (ctx, global_obj, "r2log",
JS_NewCFunction (ctx, r2log, "r2log", 1));
JS_SetPropertyStr (ctx, global_obj, "write",

24
libr/lang/t/coreplug.qjs Normal file
View File

@ -0,0 +1,24 @@
const { log } = console;
function examplePlugin() {
function coreCall(input) {
if (input.startsWith("test")) {
log("This is a QJS test");
return true;
}
return false;
}
return {
name: "qjs-example",
desc: "Example QJS plugin (type 'test') in the r2 shell",
call: coreCall,
};
}
log("Installing the `qjs-example` core plugin");
log("Type 'test' to confirm it works");
r2plugin("core", examplePlugin);
log(r2cmd("Lc"));

View File

@ -1569,11 +1569,9 @@ R_API const char *r_file_extension(const char *str) {
R_API bool r_file_is_newer(const char *f1, const char *f2) {
struct stat a1, a2;
if (stat (f1, &a1) == -1) {
eprintf ("no\n");
return false;
}
if (stat (f2, &a2) == -1) {
eprintf ("no 2\n");
return false;
}
long a = a1.st_mtime;