1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-09-27 02:56:18 -04:00

[ecmascript] clearInterval and setInterval

Changed return type of ecmascript_set_timeout.
Now it is pointer to struct ecmascript_timeout.
This commit is contained in:
Witold Filipczyk 2024-01-19 21:36:28 +01:00
parent e77ff5aa8b
commit d34ae1371d
5 changed files with 293 additions and 42 deletions

View File

@ -454,13 +454,17 @@ ecmascript_timeout_handler(void *val)
assertm(interpreter->vs->doc_view != NULL,
"setTimeout: vs with no document (e_f %d)",
interpreter->vs->ecmascript_fragile);
t->tid = TIMER_ID_UNDEF;
/* The expired timer ID has now been erased. */
ecmascript_eval(interpreter, &t->code, NULL, 0);
del_from_list(t);
done_string(&t->code);
mem_free(t);
if (t->timeout_next > 0) {
install_timer(&t->tid, t->timeout_next, ecmascript_timeout_handler, t);
} else {
/* The expired timer ID has now been erased. */
t->tid = TIMER_ID_UNDEF;
del_from_list(t);
done_string(&t->code);
mem_free(t);
}
check_for_rerender(interpreter, "handler");
}
@ -478,23 +482,27 @@ ecmascript_timeout_handler2(void *val)
assertm(interpreter->vs->doc_view != NULL,
"setTimeout: vs with no document (e_f %d)",
interpreter->vs->ecmascript_fragile);
t->tid = TIMER_ID_UNDEF;
/* The expired timer ID has now been erased. */
ecmascript_call_function(interpreter, t->fun, NULL);
del_from_list(t);
done_string(&t->code);
if (t->timeout_next > 0) {
install_timer(&t->tid, t->timeout_next, ecmascript_timeout_handler2, t);
} else {
t->tid = TIMER_ID_UNDEF;
/* The expired timer ID has now been erased. */
del_from_list(t);
done_string(&t->code);
#ifdef CONFIG_MUJS
// js_unref(t->ctx, t->fun);
#endif
mem_free(t);
mem_free(t);
}
check_for_rerender(interpreter, "handler2");
}
#endif
timer_id_T
ecmascript_set_timeout(struct ecmascript_interpreter *interpreter, char *code, int timeout)
struct ecmascript_timeout *
ecmascript_set_timeout(struct ecmascript_interpreter *interpreter, char *code, int timeout, int timeout_next)
{
assert(interpreter && interpreter->vs->doc_view->document);
if (!code) return NULL;
@ -513,15 +521,16 @@ ecmascript_set_timeout(struct ecmascript_interpreter *interpreter, char *code, i
mem_free(code);
t->interpreter = interpreter;
t->timeout_next = timeout_next;
add_to_list(interpreter->vs->doc_view->document->timeouts, t);
install_timer(&t->tid, timeout, ecmascript_timeout_handler, t);
return t->tid;
return t;
}
#ifdef CONFIG_ECMASCRIPT_SMJS
timer_id_T
ecmascript_set_timeout2(struct ecmascript_interpreter *interpreter, JS::HandleValue f, int timeout)
struct ecmascript_timeout *
ecmascript_set_timeout2(struct ecmascript_interpreter *interpreter, JS::HandleValue f, int timeout, int timeout_next)
{
assert(interpreter && interpreter->vs->doc_view->document);
@ -535,18 +544,19 @@ ecmascript_set_timeout2(struct ecmascript_interpreter *interpreter, JS::HandleVa
return NULL;
}
t->interpreter = interpreter;
t->timeout_next = timeout_next;
JS::RootedValue fun((JSContext *)interpreter->backend_data, f);
t->fun = fun;
add_to_list(interpreter->vs->doc_view->document->timeouts, t);
install_timer(&t->tid, timeout, ecmascript_timeout_handler2, t);
return t->tid;
return t;
}
#endif
#ifdef CONFIG_QUICKJS
timer_id_T
ecmascript_set_timeout2q(struct ecmascript_interpreter *interpreter, JSValueConst fun, int timeout)
struct ecmascript_timeout *
ecmascript_set_timeout2q(struct ecmascript_interpreter *interpreter, JSValueConst fun, int timeout, int timeout_next)
{
assert(interpreter && interpreter->vs->doc_view->document);
struct ecmascript_timeout *t = (struct ecmascript_timeout *)mem_calloc(1, sizeof(*t));
@ -559,17 +569,18 @@ ecmascript_set_timeout2q(struct ecmascript_interpreter *interpreter, JSValueCons
return NULL;
}
t->interpreter = interpreter;
t->timeout_next = timeout_next;
t->fun = fun;
add_to_list(interpreter->vs->doc_view->document->timeouts, t);
install_timer(&t->tid, timeout, ecmascript_timeout_handler2, t);
return t->tid;
return t;
}
#endif
#ifdef CONFIG_MUJS
timer_id_T
ecmascript_set_timeout2m(js_State *J, const char *handle, int timeout)
struct ecmascript_timeout *
ecmascript_set_timeout2m(js_State *J, const char *handle, int timeout, int timeout_next)
{
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)js_getcontext(J);
assert(interpreter && interpreter->vs->doc_view->document);
@ -586,11 +597,12 @@ ecmascript_set_timeout2m(js_State *J, const char *handle, int timeout)
t->interpreter = interpreter;
t->ctx = J;
t->fun = handle;
t->timeout_next = timeout_next;
add_to_list(interpreter->vs->doc_view->document->timeouts, t);
install_timer(&t->tid, timeout, ecmascript_timeout_handler2, t);
return t->tid;
return t;
}
#endif

View File

@ -130,6 +130,7 @@ struct ecmascript_timeout {
#endif
struct ecmascript_interpreter *interpreter;
timer_id_T tid;
int timeout_next;
};
@ -165,18 +166,18 @@ void ecmascript_timeout_dialog(struct terminal *term, int max_exec_time);
void ecmascript_set_action(char **action, char *string);
timer_id_T ecmascript_set_timeout(struct ecmascript_interpreter *interpreter, char *code, int timeout);
struct ecmascript_timeout *ecmascript_set_timeout(struct ecmascript_interpreter *interpreter, char *code, int timeout, int timeout_next);
#ifdef CONFIG_ECMASCRIPT_SMJS
timer_id_T ecmascript_set_timeout2(struct ecmascript_interpreter *interpreter, JS::HandleValue f, int timeout);
struct ecmascript_timeout *ecmascript_set_timeout2(struct ecmascript_interpreter *interpreter, JS::HandleValue f, int timeout, int timeout_next);
#endif
#ifdef CONFIG_QUICKJS
timer_id_T ecmascript_set_timeout2q(struct ecmascript_interpreter *interpreter, JSValue f, int timeout);
struct ecmascript_timeout *ecmascript_set_timeout2q(struct ecmascript_interpreter *interpreter, JSValue f, int timeout, int timeout_next);
#endif
#ifdef CONFIG_MUJS
timer_id_T ecmascript_set_timeout2m(js_State *J, const char *handle, int timeout);
struct ecmascript_timeout *ecmascript_set_timeout2m(js_State *J, const char *handle, int timeout, int timeout_next);
#endif
int get_ecmascript_enable(struct ecmascript_interpreter *interpreter);

View File

@ -282,6 +282,25 @@ mjs_window_alert(js_State *J)
js_pushundefined(J);
}
static void
mjs_window_clearInterval(js_State *J)
{
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
const char *text = js_tostring(J, 1);
int64_t number = atoll(text);
struct ecmascript_timeout *t = (struct ecmasctript_timeout *)(number);
if (t && found_in_map_timer(t->tid)) {
kill_timer(&t->tid);
done_string(&t->code);
del_from_list(t);
mem_free(t);
}
js_pushundefined(J);
}
static void
mjs_window_clearTimeout(js_State *J)
{
@ -290,10 +309,9 @@ mjs_window_clearTimeout(js_State *J)
#endif
const char *text = js_tostring(J, 1);
int64_t number = atoll(text);
timer_id_T id = (timer_id_T)(number);
struct ecmascript_timeout *t = (struct ecmasctript_timeout *)(number);
if (found_in_map_timer(id)) {
struct ecmascript_timeout *t = (struct ecmascript_timeout *)(id->data);
if (t && found_in_map_timer(t->tid)) {
kill_timer(&t->tid);
done_string(&t->code);
del_from_list(t);
@ -443,6 +461,50 @@ end:
js_pushboolean(J, ret);
}
static void
mjs_window_setInterval(js_State *J)
{
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)js_getcontext(J);
int timeout = js_toint32(J, 2);
if (timeout <= 0) {
js_pushundefined(J);
return;
}
if (js_isstring(J, 1)) {
const char *code = js_tostring(J, 1);
if (!code) {
js_pushundefined(J);
return;
}
char *code2 = stracpy(code);
if (code2) {
struct ecmascript_timeout *id = ecmascript_set_timeout(interpreter, code2, timeout, timeout);
char res[32];
snprintf(res, 31, "%" PRId64, (int64_t)id);
js_pushstring(J, res);
return;
}
} else {
js_copy(J, 1);
const char *handle = js_ref(J);
struct ecmascript_timeout *id = ecmascript_set_timeout2m(J, handle, timeout, timeout);
char res[32];
snprintf(res, 31, "%" PRId64, (int64_t)id);
js_pushstring(J, res);
return;
}
js_pushundefined(J);
return;
}
static void
mjs_window_setTimeout(js_State *J)
{
@ -467,7 +529,7 @@ mjs_window_setTimeout(js_State *J)
char *code2 = stracpy(code);
if (code2) {
timer_id_T id = ecmascript_set_timeout(interpreter, code2, timeout);
struct ecmascript_timeout *id = ecmascript_set_timeout(interpreter, code2, timeout, -1);
char res[32];
snprintf(res, 31, "%" PRId64, (int64_t)id);
js_pushstring(J, res);
@ -476,7 +538,7 @@ mjs_window_setTimeout(js_State *J)
} else {
js_copy(J, 1);
const char *handle = js_ref(J);
timer_id_T id = ecmascript_set_timeout2m(J, handle, timeout);
struct ecmascript_timeout *id = ecmascript_set_timeout2m(J, handle, timeout, -1);
char res[32];
snprintf(res, 31, "%" PRId64, (int64_t)id);
js_pushstring(J, res);
@ -694,11 +756,13 @@ mjs_window_init(js_State *J)
{
addmethod(J, "window.addEventListener", mjs_window_addEventListener, 3);
addmethod(J, "window.alert", mjs_window_alert, 1);
addmethod(J, "window.clearInterval", mjs_window_clearInterval, 1);
addmethod(J, "window.clearTimeout", mjs_window_clearTimeout, 1);
addmethod(J, "window.getComputedStyle", mjs_window_getComputedStyle, 2);
addmethod(J, "window.open", mjs_window_open, 3);
addmethod(J, "window.postMessage", mjs_window_postMessage, 3);
addmethod(J, "window.removeEventListener", mjs_window_removeEventListener, 3);
addmethod(J, "window.setInterval", mjs_window_setInterval, 2);
addmethod(J, "window.setTimeout", mjs_window_setTimeout, 2);
addmethod(J, "window.toString", mjs_window_toString, 0);

View File

@ -248,6 +248,59 @@ end:
return ret;
}
/* @window_funcs{"setInterval"} */
JSValue
js_window_setInterval(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
REF_JS(this_val);
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx);
int64_t timeout = 0;
JSValueConst func;
if (argc != 2) {
return JS_UNDEFINED;
}
if (JS_ToInt64(ctx, &timeout, argv[1])) {
return JS_EXCEPTION;
}
if (timeout <= 0) {
return JS_UNDEFINED;
}
func = argv[0];
if (JS_IsFunction(ctx, func)) {
struct ecmascript_timeout *id = ecmascript_set_timeout2q(interpreter, JS_DupValue(ctx, func), timeout, timeout);
return JS_NewInt64(ctx, (int64_t)(id));
}
if (JS_IsString(func)) {
const char *code = JS_ToCString(ctx, func);
if (!code) {
return JS_EXCEPTION;
}
char *code2 = stracpy(code);
JS_FreeCString(ctx, code);
if (code2) {
struct ecmascript_timeout *id = ecmascript_set_timeout(interpreter, code2, timeout, timeout);
return JS_NewInt64(ctx, (int64_t)(id));
}
}
return JS_UNDEFINED;
}
/* @window_funcs{"setTimeout"} */
JSValue
js_window_setTimeout(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
@ -276,7 +329,7 @@ js_window_setTimeout(JSContext *ctx, JSValueConst this_val, int argc, JSValueCon
func = argv[0];
if (JS_IsFunction(ctx, func)) {
timer_id_T id = ecmascript_set_timeout2q(interpreter, JS_DupValue(ctx, func), timeout);
struct ecmascript_timeout *id = ecmascript_set_timeout2q(interpreter, JS_DupValue(ctx, func), timeout, -1);
return JS_NewInt64(ctx, (int64_t)(id));
}
@ -291,7 +344,7 @@ js_window_setTimeout(JSContext *ctx, JSValueConst this_val, int argc, JSValueCon
JS_FreeCString(ctx, code);
if (code2) {
timer_id_T id = ecmascript_set_timeout(interpreter, code2, timeout);
struct ecmascript_timeout *id = ecmascript_set_timeout(interpreter, code2, timeout, -1);
return JS_NewInt64(ctx, (int64_t)(id));
}
@ -300,6 +353,37 @@ js_window_setTimeout(JSContext *ctx, JSValueConst this_val, int argc, JSValueCon
return JS_UNDEFINED;
}
/* @window_funcs{"clearInterval"} */
JSValue
js_window_clearInterval(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
REF_JS(this_val);
if (argc != 1) {
return JS_UNDEFINED;
}
int64_t number;
if (JS_ToInt64(ctx, &number, argv[0])) {
return JS_UNDEFINED;
}
struct ecmascript_timeout *t = (struct ecmascript_timeout *)(number);
if (t && found_in_map_timer(t->tid)) {
kill_timer(&t->tid);
done_string(&t->code);
del_from_list(t);
mem_free(t);
}
return JS_UNDEFINED;
}
/* @window_funcs{"clearTimeout"} */
JSValue
js_window_clearTimeout(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
@ -317,11 +401,9 @@ js_window_clearTimeout(JSContext *ctx, JSValueConst this_val, int argc, JSValueC
if (JS_ToInt64(ctx, &number, argv[0])) {
return JS_UNDEFINED;
}
struct ecmascript_timeout *t = (struct ecmascript_timeout *)(number);
timer_id_T id = (timer_id_T)(number);
if (found_in_map_timer(id)) {
struct ecmascript_timeout *t = (struct ecmascript_timeout *)(id->data);
if (t && found_in_map_timer(t->tid)) {
kill_timer(&t->tid);
done_string(&t->code);
del_from_list(t);
@ -809,11 +891,13 @@ static const JSCFunctionListEntry js_window_proto_funcs[] = {
JS_CGETSET_DEF("window", js_window_get_property_self, NULL),
JS_CFUNC_DEF("addEventListener", 3, js_window_addEventListener),
JS_CFUNC_DEF("alert", 1, js_window_alert),
JS_CFUNC_DEF("clearInterval", 1, js_window_clearInterval),
JS_CFUNC_DEF("clearTimeout", 1, js_window_clearTimeout),
JS_CFUNC_DEF("getComputedStyle", 2, js_window_getComputedStyle),
JS_CFUNC_DEF("open", 3, js_window_open),
JS_CFUNC_DEF("postMessage", 3, js_window_postMessage),
JS_CFUNC_DEF("removeEventListener", 3, js_window_removeEventListener),
JS_CFUNC_DEF("setInterval", 2, js_window_setInterval),
JS_CFUNC_DEF("setTimeout", 2, js_window_setTimeout),
JS_CFUNC_DEF("toString", 0, js_window_toString)
};

View File

@ -171,21 +171,25 @@ void location_goto(struct document_view *doc_view, char *url);
static bool window_addEventListener(JSContext *ctx, unsigned int argc, JS::Value *rval);
static bool window_alert(JSContext *ctx, unsigned int argc, JS::Value *rval);
static bool window_clearInterval(JSContext *ctx, unsigned int argc, JS::Value *rval);
static bool window_clearTimeout(JSContext *ctx, unsigned int argc, JS::Value *rval);
static bool window_getComputedStyle(JSContext *ctx, unsigned int argc, JS::Value *rval);
static bool window_open(JSContext *ctx, unsigned int argc, JS::Value *rval);
static bool window_postMessage(JSContext *ctx, unsigned int argc, JS::Value *rval);
static bool window_removeEventListener(JSContext *ctx, unsigned int argc, JS::Value *rval);
static bool window_setInterval(JSContext *ctx, unsigned int argc, JS::Value *rval);
static bool window_setTimeout(JSContext *ctx, unsigned int argc, JS::Value *rval);
const spidermonkeyFunctionSpec window_funcs[] = {
{ "addEventListener", window_addEventListener, 3 },
{ "alert", window_alert, 1 },
{ "clearInterval", window_clearInterval, 1 },
{ "clearTimeout", window_clearTimeout, 1 },
{ "getComputedStyle", window_getComputedStyle, 2 },
{ "open", window_open, 3 },
{ "postMessage", window_postMessage, 3 },
{ "removeEventListener", window_removeEventListener, 3 },
{ "setInterval", window_setInterval, 2 },
{ "setTimeout", window_setTimeout, 2 },
{ NULL }
};
@ -565,6 +569,59 @@ end:
return true;
}
/* @window_funcs{"setInterval"} */
static bool
window_setInterval(JSContext *ctx, unsigned int argc, JS::Value *rval)
{
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
JS::Realm *comp = js::GetContextRealm(ctx);
if (!comp) {
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__);
#endif
return false;
}
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS::GetRealmPrivate(comp);
JS::CallArgs args = JS::CallArgsFromVp(argc, rval);
// struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx);
char *code;
int timeout;
if (argc != 2)
return true;
timeout = args[1].toInt32();
if (timeout <= 0) {
return true;
}
if (args[0].isString()) {
code = jsval_to_string(ctx, args[0]);
if (!code) {
return true;
}
struct ecmascript_timeout *id = ecmascript_set_timeout(interpreter, code, timeout, timeout);
JS::BigInt *bi = JS::NumberToBigInt(ctx, reinterpret_cast<int64_t>(id));
args.rval().setBigInt(bi);
return true;
}
struct ecmascript_timeout *id = ecmascript_set_timeout2(interpreter, args[0], timeout, timeout);
JS::BigInt *bi = JS::NumberToBigInt(ctx, reinterpret_cast<int64_t>(id));
args.rval().setBigInt(bi);
return true;
}
/* @window_funcs{"setTimeout"} */
static bool
window_setTimeout(JSContext *ctx, unsigned int argc, JS::Value *rval)
@ -604,18 +661,52 @@ window_setTimeout(JSContext *ctx, unsigned int argc, JS::Value *rval)
return true;
}
timer_id_T id = ecmascript_set_timeout(interpreter, code, timeout);
struct ecmascript_timeout *id = ecmascript_set_timeout(interpreter, code, timeout, -1);
JS::BigInt *bi = JS::NumberToBigInt(ctx, reinterpret_cast<int64_t>(id));
args.rval().setBigInt(bi);
return true;
}
timer_id_T id = ecmascript_set_timeout2(interpreter, args[0], timeout);
struct ecmascript_timeout *id = ecmascript_set_timeout2(interpreter, args[0], timeout, -1);
JS::BigInt *bi = JS::NumberToBigInt(ctx, reinterpret_cast<int64_t>(id));
args.rval().setBigInt(bi);
return true;
}
/* @window_funcs{"clearInterval"} */
static bool
window_clearInterval(JSContext *ctx, unsigned int argc, JS::Value *rval)
{
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
JS::Realm *comp = js::GetContextRealm(ctx);
if (!comp) {
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__);
#endif
return false;
}
JS::CallArgs args = JS::CallArgsFromVp(argc, rval);
if (argc != 1) {
return true;
}
JS::BigInt *bi = JS::ToBigInt(ctx, args[0]);
int64_t number = JS::ToBigInt64(bi);
struct ecmascript_timeout *t = reinterpret_cast<struct ecmascript_timeout *>(number);
if (t && found_in_map_timer(t->tid)) {
kill_timer(&t->tid);
done_string(&t->code);
del_from_list(t);
mem_free(t);
}
return true;
}
/* @window_funcs{"clearTimeout"} */
static bool
window_clearTimeout(JSContext *ctx, unsigned int argc, JS::Value *rval)
@ -638,10 +729,9 @@ window_clearTimeout(JSContext *ctx, unsigned int argc, JS::Value *rval)
}
JS::BigInt *bi = JS::ToBigInt(ctx, args[0]);
int64_t number = JS::ToBigInt64(bi);
timer_id_T id = reinterpret_cast<timer_id_T>(number);
struct ecmascript_timeout *t = reinterpret_cast<struct ecmascript_timeout *>(number);
if (found_in_map_timer(id)) {
struct ecmascript_timeout *t = (struct ecmascript_timeout *)(id->data);
if (t && found_in_map_timer(t->tid)) {
kill_timer(&t->tid);
done_string(&t->code);
del_from_list(t);