void test(duk_context *ctx) { duk_idx_t i, funcidx, argcount; duk_ret_t rc; /* test C function arg count variants */ duk_push_c_function(ctx, my_int_adder, 0); /* [0] = c func with 0 args */ duk_push_c_function(ctx, my_int_adder, 1); /* [1] = c func with 1 arg */ duk_push_c_function(ctx, my_int_adder, 2); /* [2] = c func with 2 args */ duk_push_c_function(ctx, my_int_adder, DUK_VARARGS); /* [3] = c func with varargs */ for (funcidx = 0; funcidx < 4; funcidx++) { for (argcount = 0; argcount < 5; argcount++) { duk_dup(ctx, funcidx); for (i = 0; i < argcount; i++) { duk_push_int(ctx, i + 1); /* 1, 2, 3, ... */ } /* [ ... func <args> ] */ duk_call(ctx, argcount); printf("funcidx=%ld, argcount=%ld -> result=%ld\n", (long) funcidx, (long) argcount, (long) duk_to_int(ctx, -1)); duk_pop(ctx); } } /* test C function return value 0 and negative */ duk_set_top(ctx, 0); duk_push_c_function(ctx, my_zero_ret, 0); duk_call(ctx, 0); printf("top after calling my_zero_ret: %ld, retval='%s'\n", (long) duk_get_top(ctx), duk_to_string(ctx, -1)); duk_pop(ctx); duk_set_top(ctx, 0); duk_push_c_function(ctx, my_neg_ret, 0); rc = duk_pcall(ctx, 0); printf("top after calling my_neg_ret: %ld, rc=%d, retval='%s'\n", (long) duk_get_top(ctx), (int) rc, duk_to_string(ctx, -1)); duk_pop(ctx); duk_set_top(ctx, 0); duk_push_c_function(ctx, my_type_error_ret, 0); rc = duk_pcall(ctx, 0); printf("top after calling my_type_error_ret: %ld, rc=%d, retval='%s'\n", (long) duk_get_top(ctx), (int) rc, duk_to_string(ctx, -1)); duk_pop(ctx); }
bool StyleContext::evalFilter(FunctionID _id) const { if (!duk_get_global_string(m_ctx, FUNC_ID)) { logMsg("Error: evalFilterFn - functions not initialized\n"); return false; } if (!duk_get_prop_index(m_ctx, -1, _id)) { logMsg("Error: evalFilterFn - function %d not set\n", _id); } if (duk_pcall(m_ctx, 0) != 0) { logMsg("Error: evalFilterFn: %s\n", duk_safe_to_string(m_ctx, -1)); } bool result = false; if (duk_is_boolean(m_ctx, -1)) { result = duk_get_boolean(m_ctx, -1); } // pop result duk_pop(m_ctx); // pop fns obj duk_pop(m_ctx); DUMP("evalFilterFn\n"); return result; }
int main(int argc, const char *argv[]) { duk_context *ctx = NULL; ctx = duk_create_heap_default(); if (!ctx) { printf("Failed to create a Duktape heap.\n"); exit(1); } duk_push_global_object(ctx); duk_push_c_function(ctx, native_prime_check, 2 /*nargs*/); duk_put_prop_string(ctx, -2, "primeCheckNative"); if (duk_peval_file(ctx, "prime.js") != 0) { printf("Error: %s\n", duk_safe_to_string(ctx, -1)); goto finished; } duk_pop(ctx); /* ignore result */ duk_get_prop_string(ctx, -1, "primeTest"); if (duk_pcall(ctx, 0) != 0) { printf("Error: %s\n", duk_safe_to_string(ctx, -1)); } duk_pop(ctx); /* ignore result */ finished: duk_destroy_heap(ctx); exit(0); }
/* * call-seq: * exec_string(string[, filename]) -> nil * * Evaluate JavaScript expression within context returning the value as a Ruby * object. * * ctx.exec_string("var foo = 42") * ctx.eval_string("foo") #=> 42 * */ static VALUE ctx_exec_string(int argc, VALUE *argv, VALUE self) { struct state *state; Data_Get_Struct(self, struct state, state); VALUE source; VALUE filename; rb_scan_args(argc, argv, "11", &source, &filename); if (NIL_P(filename)) { filename = sDefaultFilename; } StringValue(source); StringValue(filename); ctx_push_ruby_object(state, source); ctx_push_ruby_object(state, filename); if (duk_pcompile(state->ctx, 0) == DUK_EXEC_ERROR) { raise_ctx_error(state); } if (duk_pcall(state->ctx, 0) == DUK_EXEC_ERROR) { raise_ctx_error(state); } duk_set_top(state->ctx, 0); return Qnil; }
bool StyleContext::evalFunction(FunctionID id) { // Get all functions (array) in context if (!duk_get_global_string(m_ctx, FUNC_ID)) { LOGE("EvalFilterFn - functions array not initialized"); duk_pop(m_ctx); // pop [undefined] sitting at stack top return false; } // Get function at index `id` from functions array, put it at stack top if (!duk_get_prop_index(m_ctx, -1, id)) { LOGE("EvalFilterFn - function %d not set", id); duk_pop(m_ctx); // pop "undefined" sitting at stack top duk_pop(m_ctx); // pop functions (array) now sitting at stack top return false; } // pop fns array duk_remove(m_ctx, -2); // call popped function (sitting at stack top), evaluated value is put on stack top if (duk_pcall(m_ctx, 0) != 0) { LOGE("EvalFilterFn: %s", duk_safe_to_string(m_ctx, -1)); duk_pop(m_ctx); return false; } return true; }
static void es_fa_read(void *aux) { es_fa_handle_t *fah = aux; es_fap_t *ef = fah->fah_ef; es_context_t *ec = ef->super.er_ctx; duk_context *ctx = ec->ec_duk; es_context_begin(ec); duk_set_top(ctx, 0); duk_push_external_buffer(ctx); es_root_register(ctx, -1, fah->fah_readbuf); duk_config_buffer(ctx, 0, fah->fah_readbuf, fah->fah_readlen); es_push_root(ctx, ef); duk_get_prop_string(ctx, -1, "read"); es_push_native_obj(ctx, &es_native_fah, fah_retain(fah)); es_push_root(ctx, fah); duk_push_buffer_object(ctx, 0, 0, fah->fah_readlen, DUK_BUFOBJ_UINT8ARRAY); duk_push_int(ctx, fah->fah_readlen); duk_push_number(ctx, fah->fah_fpos); int rc = duk_pcall(ctx, 5); if(rc) { fah_exception(fah, ctx); es_dump_err(ctx); } es_context_end(ec, 0); fah_release(fah); }
static void es_fa_stat(void *aux) { es_fa_handle_t *fah = aux; es_fap_t *ef = fah->fah_ef; es_context_t *ec = ef->super.er_ctx; duk_context *ctx = ec->ec_duk; es_context_begin(ec); duk_set_top(ctx, 0); es_push_root(ctx, ef); duk_get_prop_string(ctx, -1, "stat"); es_push_native_obj(ctx, &es_native_fah, fah_retain(fah)); duk_push_string(ctx, fah->fah_url); int rc = duk_pcall(ctx, 2); if(rc) { fah_exception(fah, ctx); es_dump_err(ctx); } es_context_end(ec, 0); fah_release(fah); }
static void remapCallback(void* data, s32 x, s32 y, RemapResult* result) { RemapData* remap = (RemapData*)data; duk_context* duk = remap->duk; duk_push_heapptr(duk, remap->remap); duk_push_int(duk, result->index); duk_push_int(duk, x); duk_push_int(duk, y); duk_pcall(duk, 3); if(duk_is_array(duk, -1)) { duk_get_prop_index(duk, -1, 0); result->index = duk_to_int(duk, -1); duk_pop(duk); duk_get_prop_index(duk, -1, 1); result->flip = duk_to_int(duk, -1); duk_pop(duk); duk_get_prop_index(duk, -1, 2); result->rotate = duk_to_int(duk, -1); duk_pop(duk); } else { result->index = duk_to_int(duk, -1); } duk_pop(duk); }
Variant DuktapeScriptFunction::call(const std::vector<Variant> & args) { // Get function wrapper from stash duk_push_global_stash(m_context); duk_get_prop_index(m_context, -1, m_stashIndex); // Push arguments for (Variant var : args) { m_scriptBackend->pushToDukStack(var); } // Call function duk_int_t error = duk_pcall(m_context, args.size()); // Check for error if (error) { // Raise script exception m_scriptBackend->m_scriptContext->scriptException(std::string(duk_safe_to_string(m_context, -1))); duk_pop_2(m_context); return Variant(); } // Convert return value Variant value = m_scriptBackend->fromDukStack(-1); duk_pop_2(m_context); return value; }
void OnSignal(Entity * param0, Entity * param1, const float3 & param2, const float3 & param3, float param4, float param5, bool param6) { duk_context* ctx = ctx_; duk_push_global_object(ctx); duk_get_prop_string(ctx, -1, "_OnSignal"); duk_remove(ctx, -2); duk_push_number(ctx, (size_t)key_); duk_push_array(ctx); PushWeakObject(ctx, param0); duk_put_prop_index(ctx, -2, 0); PushWeakObject(ctx, param1); duk_put_prop_index(ctx, -2, 1); PushValueObjectCopy<float3>(ctx, param2, float3_ID, float3_Finalizer); duk_put_prop_index(ctx, -2, 2); PushValueObjectCopy<float3>(ctx, param3, float3_ID, float3_Finalizer); duk_put_prop_index(ctx, -2, 3); duk_push_number(ctx, param4); duk_put_prop_index(ctx, -2, 4); duk_push_number(ctx, param5); duk_put_prop_index(ctx, -2, 5); duk_push_boolean(ctx, param6); duk_put_prop_index(ctx, -2, 6); bool success = duk_pcall(ctx, 2) == 0; if (!success) LogError("[JavaScript] OnSignal: " + GetErrorString(ctx)); duk_pop(ctx); }
static void * timer_thread(void *aux) { int destroy = 0; es_timer_t *et; hts_mutex_lock(&timer_mutex); while(1) { et = LIST_FIRST(&timers); if(et == NULL) break; int64_t now = arch_get_ts(); int64_t delta = et->et_expire - now; if(delta > 0) { int ms = (delta + 999) / 1000; hts_cond_wait_timeout(&timer_cond, &timer_mutex, ms); continue; } LIST_REMOVE(et, et_link); if(et->et_interval) { et->et_expire = now + et->et_interval * 1000LL; LIST_INSERT_SORTED(&timers, et, et_link, estimercmp, es_timer_t); } else { et->et_expire = 0; destroy = 1; } es_resource_retain(&et->super); hts_mutex_unlock(&timer_mutex); es_context_t *ec = et->super.er_ctx; es_context_begin(ec); duk_context *ctx = ec->ec_duk; es_push_root(ctx, et); int rc = duk_pcall(ctx, 0); if(rc) es_dump_err(ctx); duk_pop(ctx); es_resource_release(&et->super); if(destroy) es_resource_destroy(&et->super); es_context_end(ec, 0); hts_mutex_lock(&timer_mutex); } thread_running = 0; hts_mutex_unlock(&timer_mutex); return NULL; }
int main(int argc, const char *argv[]) { duk_context *ctx = NULL; char line[4096]; size_t idx; int ch; (void) argc; (void) argv; ctx = duk_create_heap_default(); if (!ctx) { printf("Failed to create a Duktape heap.\n"); exit(1); } push_file_as_string(ctx, "process.js"); if (duk_peval(ctx) != 0) { printf("Error: %s\n", duk_safe_to_string(ctx, -1)); goto finished; } duk_pop(ctx); /* ignore result */ memset(line, 0, sizeof(line)); idx = 0; for (;;) { if (idx >= sizeof(line)) { printf("Line too long\n"); exit(1); } ch = fgetc(stdin); if (ch == 0x0a) { line[idx++] = '\0'; duk_push_global_object(ctx); duk_get_prop_string(ctx, -1 /*index*/, "processLine"); duk_push_string(ctx, line); if (duk_pcall(ctx, 1 /*nargs*/) != 0) { printf("Error: %s\n", duk_safe_to_string(ctx, -1)); } else { printf("%s\n", duk_safe_to_string(ctx, -1)); } duk_pop(ctx); /* pop result/error */ idx = 0; } else if (ch == EOF) { break; } else { line[idx++] = (char) ch; } } finished: duk_destroy_heap(ctx); exit(0); }
bool jsplugin_load(JSVM* vm, const String& pluginLibrary) { String errorMsg; atomic_plugin_validate_function validatefunc; duk_c_function initfunc; duk_context* ctx = vm->GetJSContext(); LOGINFOF("Loading Native Plugin: %s", pluginLibrary.CString()); if (!jsplugin_get_entry_points(pluginLibrary, &validatefunc, &initfunc, errorMsg)) { LOGERRORF("%s", errorMsg.CString()); return false; } int version = ATOMIC_JSPLUGIN_VERSION; if (!validatefunc(version, &gJSVMExports, sizeof(JSVMImports))) { LOGERRORF("Native Plugin: atomic_plugin_validate failed: %s", pluginLibrary.CString()); return false; } // just to verify that we're not doing anything funky with the stack int top = duk_get_top(ctx); // the import function is a standard duktape c function, neat duk_push_c_function(ctx, initfunc, 1); // requires exports to be at index 2 duk_dup(ctx, 2); bool success = true; if (duk_pcall(ctx, 1) != DUK_EXEC_SUCCESS) { success = false; LOGERRORF("Native Plugin: error calling atomic_plugin_init %s", pluginLibrary.CString()); } else { if (!duk_is_boolean(ctx, -1) || !duk_to_boolean(ctx, -1)) { success = false; LOGERRORF("Native Plugin: error calling atomic_plugin_init, didn't return true %s", pluginLibrary.CString()); } } duk_pop(ctx); assert(top == duk_get_top(ctx)); return success; }
void OnSignal() { duk_context* ctx = ctx_; duk_push_global_object(ctx); duk_get_prop_string(ctx, -1, "_OnSignal"); duk_remove(ctx, -2); duk_push_number(ctx, (size_t)key_); duk_push_array(ctx); bool success = duk_pcall(ctx, 2) == 0; if (!success) LogError("[JavaScript] OnSignal: " + GetErrorString(ctx)); duk_pop(ctx); }
void CallConnectSignal(duk_context* ctx, void* signal) { int numArgs = duk_get_top(ctx); duk_push_number(ctx, (size_t)signal); duk_insert(ctx, 0); duk_push_global_object(ctx); duk_get_prop_string(ctx, -1, "_ConnectSignal"); duk_remove(ctx, -2); // Global object duk_insert(ctx, 0); duk_pcall(ctx, numArgs + 1); duk_pop(ctx); }
bool StyleContext::evalStyleFn(const std::string& name, StyleParamKey _key, StyleParam::Value& _val) { if (!duk_get_global_string(m_ctx, name.c_str())) { logMsg("Error: evalFilter %s\n", name.c_str()); return false; } if (duk_pcall(m_ctx, 0) != 0) { logMsg("Error: evalStyleFn: %s\n", duk_safe_to_string(m_ctx, -1)); duk_pop(m_ctx); return false; } return parseStyleResult(_key, _val); }
void test(duk_context *ctx) { int rc; duk_eval_string(ctx, "this.testFunc = eval.bind(this, 'print(\\'hello from eval\\')');"); duk_pop(ctx); duk_push_global_object(ctx); duk_get_prop_string(ctx, -1, "testFunc"); rc = duk_pcall(ctx, 0); printf("rc=%d\n", rc); duk_pop_2(ctx); printf("final top: %d\n", duk_get_top(ctx)); }
static void callJavascriptOverline(tic_mem* memory, void* data) { tic_machine* machine = (tic_machine*)memory; duk_context* duk = machine->js; const char* OvrFunc = ApiKeywords[2]; if(duk_get_global_string(duk, OvrFunc)) { if(duk_pcall(duk, 0) != 0) machine->data->error(machine->data->data, duk_safe_to_string(duk, -1)); } duk_pop(duk); }
static void callJavascriptScanlineName(tic_mem* memory, s32 row, void* data, const char* name) { tic_machine* machine = (tic_machine*)memory; duk_context* duk = machine->js; if(duk_get_global_string(duk, name)) { duk_push_int(duk, row); if(duk_pcall(duk, 1) != 0) machine->data->error(machine->data->data, duk_safe_to_string(duk, -1)); } duk_pop(duk); }
static duk_ret_t test(duk_context *ctx) { duk_ret_t rc; /* basic success case */ duk_eval_string(ctx, "(function (x,y) { return x+y; })"); duk_push_int(ctx, 10); duk_push_int(ctx, 11); rc = duk_pcall(ctx, 2); printf("rc=%d, result='%s'\n", (int) rc, duk_safe_to_string(ctx, -1)); duk_pop(ctx); printf("top after pop: %ld\n", (long) duk_get_top(ctx)); /* basic error case */ duk_eval_string(ctx, "(function (x,y) { throw new Error('my error'); })"); duk_push_int(ctx, 10); duk_push_int(ctx, 11); rc = duk_pcall(ctx, 2); printf("rc=%d, result='%s'\n", (int) rc, duk_safe_to_string(ctx, -1)); duk_pop(ctx); printf("top after pop: %ld\n", (long) duk_get_top(ctx)); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
static duk_ret_t havefile2_helper(duk_context *ctx, duk_c_function target_func) { duk_int_t rc; target_func_hack = target_func; duk_push_c_function(ctx, havefile2_helper_2, 0); /* Duktape/C func with no .fileName */ duk_pcall(ctx, 0); (void) rc; duk_eval_string(ctx, "(function (e) { print(e.fileName, e.lineNumber); if (PRINT_STACK) { print(e.stack); } })"); duk_dup(ctx, -2); duk_call(ctx, 1); duk_pop(ctx); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
void OnSignal(IAssetTransfer * param0, String param1) { duk_context* ctx = ctx_; duk_push_global_object(ctx); duk_get_prop_string(ctx, -1, "_OnSignal"); duk_remove(ctx, -2); duk_push_number(ctx, (size_t)key_); duk_push_array(ctx); PushWeakObject(ctx, param0); duk_put_prop_index(ctx, -2, 0); duk_push_string(ctx, param1.CString()); duk_put_prop_index(ctx, -2, 1); bool success = duk_pcall(ctx, 2) == 0; if (!success) LogError("[JavaScript] OnSignal: " + GetErrorString(ctx)); duk_pop(ctx); }
void CallDisconnectSignal(duk_context* ctx, void* signal) { int numArgs = duk_get_top(ctx); duk_push_number(ctx, (size_t)signal); duk_insert(ctx, 0); duk_push_global_object(ctx); duk_get_prop_string(ctx, -1, "_DisconnectSignal"); duk_remove(ctx, -2); // Global object duk_insert(ctx, 0); duk_pcall(ctx, numArgs + 1); if (duk_get_boolean(ctx, -1)) // Last receiver disconnected { HashMap<void*, SharedPtr<SignalReceiver> >& signalReceivers = JavaScriptInstance::InstanceFromContext(ctx)->SignalReceivers(); signalReceivers.Erase(signal); } duk_pop(ctx); // Result }
static duk_ret_t test_ecma_pcall_error(duk_context *ctx) { duk_idx_t i; duk_int_t rc; duk_require_stack(ctx, STACK_REQUIRE + 1); duk_eval_string(ctx, "(function () { print('hello from ecma func'); throw Error('ecma thrown'); })"); rc = duk_pcall(ctx, 0 /*nargs*/); printf("duk_pcall: rc=%ld, value: %s\n", (long) rc, duk_safe_to_string(ctx, -1)); for (i = 0; i < STACK_REQUIRE; i++) { duk_push_int(ctx, 123); } printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
static duk_ret_t test_c_pcall_error2(duk_context *ctx) { duk_idx_t i; duk_int_t rc; duk_require_stack(ctx, STACK_REQUIRE + 1); duk_push_c_function(ctx, my_func_error2, 0); rc = duk_pcall(ctx, 0 /*nargs*/); printf("duk_pcall: rc=%ld, value: %s\n", (long) rc, duk_safe_to_string(ctx, -1)); for (i = 0; i < STACK_REQUIRE; i++) { duk_push_int(ctx, 123); } printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
void test(duk_context *ctx) { duk_ret_t rc; duk_eval_string(ctx, "this.testFunc = eval.bind(this, 'print(\\'hello from eval\\')');"); duk_pop(ctx); duk_push_global_object(ctx); duk_get_prop_string(ctx, -1, "testFunc"); rc = duk_pcall(ctx, 0); printf("rc=%d\n", (int) rc); if (rc != 0) { /* unexpected error */ printf("error=%s\n", duk_safe_to_string(ctx, -1)); } duk_pop_2(ctx); printf("final top: %ld\n", (long) duk_get_top(ctx)); }
static duk_int_t myload_code(duk_context *ctx, const char *code) { static int reqid = 0; char buf[1024]; uv_fs_t open_req1; sprintf(buf, "file%d.js", reqid++); unlink(buf); duk_push_thread_stash(ctx, ctx); duk_bool_t rc = duk_get_prop_string(ctx, -1, "__duk_loop"); assert(rc); uv_loop_t *dukLoop = (uv_loop_t *)duk_get_pointer(ctx, -1); duk_pop(ctx); duk_pop(ctx); int r; r = uv_fs_open(dukLoop, &open_req1, buf, O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR, NULL); assert(r >= 0); assert(open_req1.result >= 0); uv_fs_req_cleanup(&open_req1); uv_buf_t iov = uv_buf_init((char *)code, strlen(code)); uv_fs_t write_req; r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL); assert(r >= 0); assert(write_req.result >= 0); uv_fs_req_cleanup(&write_req); uv_fs_t close_req; uv_fs_close(dukLoop, &close_req, open_req1.result, NULL); duk_push_c_function(ctx, duv_main, 1); duk_push_string(ctx, buf); if (duk_pcall(ctx, 1)) { duv_dump_error(ctx, -1); //uv_loop_close(dukLoop); duk_destroy_heap(ctx); return 1; } return 0; }
AJ_Status AJS_HandleAcceptSession(duk_context* ctx, AJ_Message* msg, uint16_t port, uint32_t sessionId, const char* joiner) { uint32_t accept = TRUE; SessionInfo* sessionInfo; /* * Create an entry in the sessions table so we can track this peer */ AJS_GetGlobalStashObject(ctx, "sessions"); sessionInfo = AllocSessionObject(ctx, joiner); /* * If there is no handler automatically accept the connection */ AJS_GetAllJoynProperty(ctx, "onPeerConnected"); if (duk_is_callable(ctx, -1)) { /* Empty interface array */ duk_push_array(ctx); AddServiceObject(ctx, sessionInfo, "/", joiner); if (AJS_DebuggerIsAttached()) { msg = AJS_CloneAndCloseMessage(ctx, msg); } if (duk_pcall(ctx, 1) != DUK_EXEC_SUCCESS) { AJS_ConsoleSignalError(ctx); accept = FALSE; } else { accept = duk_get_boolean(ctx, -1); } } duk_pop_2(ctx); /* * It is possible that we already have an outbound session to this peer so if we are not * accepting the session we can only delete the entry if the refCount is zero. */ if (accept) { ++sessionInfo->refCount; sessionInfo->port = port; sessionInfo->sessionId = sessionId; } else if (sessionInfo->refCount == 0) { duk_del_prop_string(ctx, -1, joiner); } /* Pop sessions object */ duk_pop(ctx); return AJ_BusReplyAcceptSession(msg, accept); }
static duk_ret_t deep_helper(duk_context *ctx, duk_c_function target_func, int depth) { duk_int_t rc; target_func_hack = target_func; depth_hack = depth; duk_push_c_function(ctx, deep_helper_2, 0); /* Duktape/C func with .fileName */ duk_push_string(ctx, "fileName"); duk_push_string(ctx, "outer_limits.c"); duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_SET_WRITABLE | DUK_DEFPROP_SET_CONFIGURABLE); duk_pcall(ctx, 0); (void) rc; duk_eval_string(ctx, "(function (e) { print(e.fileName, e.lineNumber); if (PRINT_STACK) { print(e.stack); } })"); duk_dup(ctx, -2); duk_call(ctx, 1); duk_pop(ctx); printf("final top: %ld\n", (long) duk_get_top(ctx)); return 0; }
/* * Delete session info object pointed to by sessionId. If sessionId * is zero then delete all session info objects. */ static AJ_Status RemoveSessions(duk_context* ctx, uint32_t sessionId) { AJ_Status status = AJ_OK; AJS_GetGlobalStashObject(ctx, "sessions"); duk_enum(ctx, -1, DUK_ENUM_OWN_PROPERTIES_ONLY); while (duk_next(ctx, -1, 1)) { SessionInfo* sessionInfo; const char* peer = duk_get_string(ctx, -2); duk_get_prop_string(ctx, -1, "info"); sessionInfo = duk_get_buffer(ctx, -1, NULL); duk_pop_3(ctx); if (sessionId == 0) { AJ_InfoPrintf(("RemoveSessions(): Leaving session: %u\n", sessionInfo->sessionId)); status = AJ_BusLeaveSession(AJS_GetBusAttachment(), sessionInfo->sessionId); } else if (sessionInfo->sessionId == sessionId) { status = AJ_BusLeaveSession(AJS_GetBusAttachment(), sessionInfo->sessionId); duk_del_prop_string(ctx, -2, peer); break; } } duk_pop_2(ctx); /* * TODO - this is not all that useful because it only indicates that a peer has gone away * without being able to specify exactly which services are affected. The problem is we cannot * hold a reference to the service object because we a relying on the service object finalizer * to clean up sessions that are no longer in use. If we hold a reference the finalizer will * never get called. */ if (sessionId != 0) { AJS_GetAllJoynProperty(ctx, "onPeerDisconnected"); if (duk_is_callable(ctx, -1)) { if (duk_pcall(ctx, 0) != DUK_EXEC_SUCCESS) { AJS_ConsoleSignalError(ctx); } } duk_pop(ctx); } else { AJS_ClearGlobalStashObject(ctx, "sessions"); } return status; }