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

270 Views Asked by At

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;
}
2

There are 2 best solutions below

0
Heiner On BEST ANSWER

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.

1
Mike Lischke On

Instead of simple JS files you could use modules. duktape comes with a code example to implement a module system (including its code isolation) like in Node.js. Having that in place you can export variables that should be sharable.