Search code examples
duktape

duktape js - have multiple contexts with own global and reference to one common 'singleton'


We are in the process of embedding JS in our application, and we will use a few dozen scripts each assigned to an event. Inside these scripts we provide a minimal callback api,

function onevent(value)
{ // user javascript code here
}

which is called whenever that event happens. The scripts have to have their own global, since this funtion has always the same name and we access it from cpp code with

duk_get_global_string(js_context_duk, "onevent");
duk_push_number(js_context_duk, val);
if (duk_pcall(js_context_duk, 1) != 0)
{
    printf("Duk error: %s\n", duk_safe_to_string(js_context_duk, -1));
}
duk_pop(js_context_duk);  /* ignore result */

Then again we want to allow minimal communication between scripts, e.g.

Script 1

var a = 1;
function onevent(val)
{
log(a);
}

Script 2

function onevent(val)
{
 a++;
}

Is there a way we achieve this? Maybe by introducing an own 'ueber-' global object, that is defined once and referencable everywhere? It should be possible to add properties to this 'ueber-global object' from any script like

Script 1

function onevent(val)
{
log(ueber.a);
}

Script 2

function onevent(val)
{
 ueber.a=1;
}

Solution

  • We have an approach that seems to work now. After creating the new context with

    duk_push_thread_new_globalenv(master_ctx);
    new_ctx = duk_require_context(master_ctx, -1);
    duk_copy_element_reference(master_ctx, new_ctx, "ueber");
    

    we issue this call sequence in for all properties/objects/functions created in the main context:

    void duk_copy_element_reference(duk_context* src, duk_context* dst, const char* element)
    {
        duk_get_global_string(src, element);
        duk_require_stack(dst, 1);
        duk_xcopy_top(dst, src, 1);
        duk_put_global_string(dst, element);
        duk_pop(src);
    }
    

    It seems to work (because everything is in the same heap and all is single threaded). Maybe someone with deeper insight into duktape can comment on this? Is this a feasible solution with no side effects?

    edit: mark this as answer. works as expected, no memory leaks or other issues.