I am interested in using QuickJS to modify preferences in a C++ app. So, there is a preference variable called
int myPref = 0
I want to expose this as a JS variable called
jsPref
Then the user can modify this directly via JS using
jsPref = 1
This can be extended to a struct - where one can define
struct myPref { int a, int b}; which is exposed as a global in JS as jsPref
Inside the JS script, I wish to call
jsPref.a = 1;
jsPref.b = 2;
and the assignments should be reflected in the C struct myPref
Sadly, I do not even have sample code on exposing a struct. After searching, I only came up with examples of C/C++ functions exposed as JS methods.
Take a look at e.g.
JS_AddIntrinsicAtomicsin the QuickJS source code. It usesJS_SetPropertyFunctionListto create an object whose properties are defined by a simple array of structures, with the help of some convenience macros.Instead of
JS_CFUNC_MAGIC_DEF, you can useJS_CGETSET_DEForJS_CGETSET_MAGIC_DEFto define custom properties with getters and setters. Since the contents of theJSContextstructure are not exposed in the public API, you will have to useJS_GetGlobalObjectto access the global object. Otherwise though, what you need to do is substantially the same.This should look something like this:
The above defines the struct variation. For a single preference, you can put a
JS_CGETSET_DEFdefinition directly in theprefs_obj, to define an accessor-based property of the global object.Note that properties defined using
JS_CGETSET_DEFare configurable, which means user code can perform e.g.delete jsPrefs.a;and lose access to the exposed property. If you want to prevent that, you will have to write your own helper macro so that you can set property flags yourself. You may also want to have a look atJS_PreventExtensions, to catch user code attempting to write to a preference that doesn’t exist. If you want to use that, you may need to create the preferences object withJS_NewObject, define its properties withJS_SetPropertyFunctionList, seal it and add it to the global object manually, withJS_DefinePropertyValue, instead of doing everything at once with just oneJS_SetPropertyFunctionListcall: