static void settings_update(JSContext *cx, js_setting_t *jss, jsval v) { jsval cb, *argv, result; void *mark; JS_SetProperty(cx, JSVAL_TO_OBJECT(jss->jss_obj), "value", &v); JS_GetProperty(cx, JSVAL_TO_OBJECT(jss->jss_obj), "callback", &cb); argv = JS_PushArguments(cx, &mark, "v", v); JS_CallFunctionValue(cx, NULL, cb, 1, argv, &result); JS_PopArguments(cx, mark); }
/* JSCall function by name, cvalues will be converted * * deactivates controller if any script errors! * * format values: * case 'b': BOOLEAN_TO_JSVAL((JSBool) va_arg(ap, int)); * case 'c': INT_TO_JSVAL((uint16) va_arg(ap, unsigned int)); * case 'i': * case 'j': js_NewNumberValue(cx, (jsdouble) va_arg(ap, int32), sp) * case 'u': js_NewNumberValue(cx, (jsdouble) va_arg(ap, uint32), sp) * case 'd': * case 'I': js_NewDoubleValue(cx, va_arg(ap, jsdouble), sp) * case 's': JS_NewStringCopyZ(cx, va_arg(ap, char *)) * case 'W': JS_NewUCStringCopyZ(cx, va_arg(ap, jschar *)) * case 'S': va_arg(ap, JSString *) * case 'o': OBJECT_TO_JSVAL(va_arg(ap, JSObject *) * case 'f': * fun = va_arg(ap, JSFunction *); * fun ? OBJECT_TO_JSVAL(fun->object) : JSVAL_NULL; * case 'v': va_arg(ap, jsval); */ bool ControllerListener::call(const char *funcname, int argc, const char *format, ...) { va_list ap; jsval fval = JSVAL_VOID; jsval ret = JSVAL_VOID; func("%s try calling method %s.%s(argc:%i)", __func__, name, funcname, argc); JS_SetContextThread(jsContext); JS_BeginRequest(jsContext); int res = JS_GetProperty(jsContext, jsObject, funcname, &fval); if(JSVAL_IS_VOID(fval)) { warning("method unresolved by JS_GetProperty"); } else { jsval *argv; void *markp; va_start(ap, format); argv = JS_PushArgumentsVA(jsContext, &markp, format, ap); va_end(ap); res = JS_CallFunctionValue(jsContext, jsObject, fval, argc, argv, &ret); JS_PopArguments(jsContext, &markp); if (res) { if(!JSVAL_IS_VOID(ret)) { JSBool ok; JS_ValueToBoolean(jsContext, ret, &ok); if (ok) // JSfunc returned 'true', so event is done { JS_EndRequest(jsContext); JS_ClearContextThread(jsContext); return true; } } } } JS_EndRequest(jsContext); JS_ClearContextThread(jsContext); return false; // no callback, redo on next controller }
static void TestArgFormatter(JSContext* jscontext, JSObject* glob, nsIXPConnect* xpc) { jsval* argv; void* mark; const char* a_in = "some string"; nsCOMPtr<nsITestXPCFoo> b_in = new nsTestXPCFoo(); nsCOMPtr<nsIWritableVariant> c_in = do_CreateInstance("@mozilla.org/variant;1"); static NS_NAMED_LITERAL_STRING(d_in, "foo bar"); const char* e_in = "another meaningless chunck of text"; char* a_out; nsCOMPtr<nsISupports> b_out; nsCOMPtr<nsIVariant> c_out; nsAutoString d_out; char* e_out; nsCOMPtr<nsITestXPCFoo> specified; PRInt32 val; printf("ArgumentFormatter test: "); if(!b_in || !c_in || NS_FAILED(c_in->SetAsInt32(5))) { printf(" failed to construct test objects -- FAILED!\n"); return; } argv = JS_PushArguments(jscontext, &mark, "s %ip %iv %is s", a_in, &NS_GET_IID(nsITestXPCFoo2), b_in.get(), c_in.get(), static_cast<const nsAString*>(&d_in), e_in); if(!argv) { printf(" could not convert from native to JS -- FAILED!\n"); return; } if(!JS_ConvertArguments(jscontext, 5, argv, "s %ip %iv %is s", &a_out, static_cast<nsISupports**>(getter_AddRefs(b_out)), static_cast<nsIVariant**>(getter_AddRefs(c_out)), static_cast<nsAString*>(&d_out), &e_out)) { printf(" could not convert from JS to native -- FAILED!\n"); goto out; } if(!b_out) { printf(" JS to native for %%ip returned NULL -- FAILED!\n"); goto out; } specified = do_QueryInterface(b_out); if(!specified) { printf(" could not QI value JS to native returned -- FAILED!\n"); goto out; } if(specified.get() != b_in.get()) { printf(" JS to native returned wrong value -- FAILED!\n"); goto out; } if(!c_out) { printf(" JS to native for %%iv returned NULL -- FAILED!\n"); goto out; } if(NS_FAILED(c_out->GetAsInt32(&val)) || val != 5) { printf(" JS to native for %%iv holds wrong value -- FAILED!\n"); goto out; } if(!d_in.Equals(d_out)) { printf(" JS to native for %%is returned the wrong value -- FAILED!\n"); goto out; } if(!strcmp(a_in, a_out) && !strcmp(e_in, e_out)) printf("passed\n"); else printf(" conversion OK, but surrounding was mangled -- FAILED!\n"); out: JS_PopArguments(jscontext, mark); }