diff --git a/src/sbbs3/js_internal.c b/src/sbbs3/js_internal.c index 3c4b1720ca8f6ac12e69e65cb29b8075db594438..cc52ef6dd3078f241abb77d998d91c1a3a3fd30b 100644 --- a/src/sbbs3/js_internal.c +++ b/src/sbbs3/js_internal.c @@ -879,6 +879,52 @@ js_setInterval(JSContext *cx, uintN argc, jsval *arglist) return JS_TRUE; } +static JSBool +js_setImmediate(JSContext *cx, uintN argc, jsval *arglist) +{ + jsval *argv=JS_ARGV(cx, arglist); + JSFunction *cbf; + JSObject *obj=JS_THIS_OBJECT(cx, arglist); + js_callback_t *cb; + struct js_runq_entry *rqe; + + if((cb=(js_callback_t*)JS_GetPrivate(cx,obj))==NULL) + return(JS_FALSE); + + if (argc < 1) { + JS_ReportError(cx, "js.setImmediate() requires a callback"); + return JS_FALSE; + } + + cbf = JS_ValueToFunction(cx, argv[0]); + if (cbf == NULL) { + return JS_FALSE; + } + + if (argc > 1) { + if (!JS_ValueToObject(cx, argv[1], &obj)) + return JS_FALSE; + } + + rqe = malloc(sizeof(*rqe)); + if (rqe == NULL) { + JS_ReportError(cx, "error allocating %ul bytes", sizeof(*rqe)); + return JS_FALSE; + } + rqe->func = cbf; + rqe->cx = obj; + JS_AddObjectRoot(cx, &rqe->cx); + rqe->next = NULL; + if (cb->rq_tail != NULL) + cb->rq_tail->next = rqe; + cb->rq_tail = rqe; + if (cb->rq_head == NULL) + cb->rq_head = rqe; + + JS_SET_RVAL(cx, arglist, JSVAL_VOID); + return JS_TRUE; +} + static JSBool js_addEventListener(JSContext *cx, uintN argc, jsval *arglist) { @@ -1438,6 +1484,10 @@ static jsSyncMethodSpec js_functions[] = { ,JSDOCSTR("Add all listeners of eventName to the runqueue. If obj is passed, specifies this in the callback (the js object is used otherwise).") ,31802 }, + {"setImmediate", js_setImmediate, 1, JSTYPE_VOID, JSDOCSTR("callback[, thisObj]") + ,JSDOCSTR("adds the callback to the end of the run queue, where it will be called after all pending events are processed") + ,31900 + }, {0} };