1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-06-25 01:05:37 +00:00

[spidermonkey] Changes in setTimeout.

Spidermonkey is "hardcoded" in ecmascript, but ecmascript script engine
is rarely being changed.
This commit is contained in:
Witold Filipczyk 2020-11-22 16:42:23 +01:00
parent 085a93d544
commit a92df85c11
6 changed files with 98 additions and 10 deletions

View File

@ -736,7 +736,7 @@ if test "x$CONFIG_ECMASCRIPT_SMJS" = xyes ||
AC_SUBST(SPIDERMONKEY_LIBS)
AC_SUBST(SPIDERMONKEY_CFLAGS)
AC_SUBST(CONFIG_SPIDERMONKEY)
CFLAGS="$CFLAGS -fpermissive"
CFLAGS="$CFLAGS -fpermissive $SPIDERMONKEY_CFLAGS"
fi
# ===================================================================

View File

@ -138,6 +138,19 @@ ecmascript_eval(struct ecmascript_interpreter *interpreter,
interpreter->backend_nesting--;
}
static void
ecmascript_call_function(struct ecmascript_interpreter *interpreter,
JS::HandleValue fun, struct string *ret)
{
if (!get_ecmascript_enable())
return;
assert(interpreter);
interpreter->backend_nesting++;
spidermonkey_call_function(interpreter, fun, ret);
interpreter->backend_nesting--;
}
unsigned char *
ecmascript_eval_stringback(struct ecmascript_interpreter *interpreter,
struct string *code)
@ -313,6 +326,24 @@ ecmascript_timeout_handler(void *i)
ecmascript_eval(interpreter, &interpreter->code, NULL);
}
/* Timer callback for @interpreter->vs->doc_view->document->timeout.
* As explained in @install_timer, this function must erase the
* expired timer ID from all variables. */
static void
ecmascript_timeout_handler2(void *i)
{
struct ecmascript_interpreter *interpreter = i;
assertm(interpreter->vs->doc_view != NULL,
"setTimeout: vs with no document (e_f %d)",
interpreter->vs->ecmascript_fragile);
interpreter->vs->doc_view->document->timeout = TIMER_ID_UNDEF;
/* The expired timer ID has now been erased. */
ecmascript_call_function(interpreter, interpreter->fun, NULL);
}
void
ecmascript_set_timeout(struct ecmascript_interpreter *interpreter, unsigned char *code, int timeout)
{
@ -326,6 +357,19 @@ ecmascript_set_timeout(struct ecmascript_interpreter *interpreter, unsigned char
install_timer(&interpreter->vs->doc_view->document->timeout, timeout, ecmascript_timeout_handler, interpreter);
}
void
ecmascript_set_timeout2(struct ecmascript_interpreter *interpreter, JS::HandleValue f, int timeout)
{
assert(interpreter && interpreter->vs->doc_view->document);
done_string(&interpreter->code);
init_string(&interpreter->code);
kill_timer(&interpreter->vs->doc_view->document->timeout);
JS::RootedValue fun((JSContext *)interpreter->backend_data, f);
interpreter->fun = fun;
install_timer(&interpreter->vs->doc_view->document->timeout, timeout, ecmascript_timeout_handler2, interpreter);
}
static struct module *ecmascript_modules[] = {
#ifdef CONFIG_ECMASCRIPT_SMJS
&spidermonkey_module,

View File

@ -5,6 +5,8 @@
/* In the future you will get DOM, a complete ECMAScript interface and free
* plasm displays for everyone. */
#include <jsapi.h>
#include "main/module.h"
#include "util/time.h"
@ -56,6 +58,7 @@ struct ecmascript_interpreter {
void *ac;
void *ac2;
void *ar;
JS::RootedValue fun;
};
/* Why is the interpreter bound to {struct view_state} instead of {struct
@ -97,6 +100,8 @@ void ecmascript_set_action(unsigned char **action, unsigned char *string);
void ecmascript_set_timeout(struct ecmascript_interpreter *interpreter, unsigned char *code, int timeout);
void ecmascript_set_timeout2(struct ecmascript_interpreter *interpreter, JS::HandleValue f, int timeout);
extern struct module ecmascript_module;
#endif

View File

@ -400,6 +400,32 @@ spidermonkey_eval(struct ecmascript_interpreter *interpreter,
JS_EndRequest(ctx);
}
void
spidermonkey_call_function(struct ecmascript_interpreter *interpreter,
JS::HandleValue fun, struct string *ret)
{
JSContext *ctx;
JS::Value rval;
assert(interpreter);
if (!js_module_init_ok) {
return;
}
ctx = interpreter->backend_data;
JS_BeginRequest(ctx);
JSCompartment *comp = JS_EnterCompartment(ctx, interpreter->ac);
interpreter->heartbeat = add_heartbeat(interpreter);
interpreter->ret = ret;
JS::RootedValue r_val(ctx, rval);
JS::RootedObject cg(ctx, JS::CurrentGlobalOrNull(ctx));
JS_CallFunctionValue(ctx, cg, fun, JS::HandleValueArray::empty(), &r_val);
done_heartbeat(interpreter->heartbeat);
JS_LeaveCompartment(ctx, comp);
JS_EndRequest(ctx);
}
unsigned char *
spidermonkey_eval_stringback(struct ecmascript_interpreter *interpreter,

View File

@ -1,6 +1,8 @@
#ifndef EL__ECMASCRIPT_SPIDERMONKEY_H
#define EL__ECMASCRIPT_SPIDERMONKEY_H
#include <jsapi.h>
struct ecmascript_interpreter;
struct form_view;
struct form_state;
@ -17,5 +19,7 @@ void spidermonkey_eval(struct ecmascript_interpreter *interpreter, struct string
unsigned char *spidermonkey_eval_stringback(struct ecmascript_interpreter *interpreter, struct string *code);
int spidermonkey_eval_boolback(struct ecmascript_interpreter *interpreter, struct string *code);
void spidermonkey_call_function(struct ecmascript_interpreter *interpreter, JS::HandleValue fun, struct string *ret);
extern struct module spidermonkey_module;
#endif

View File

@ -367,20 +367,29 @@ window_setTimeout(JSContext *ctx, unsigned int argc, JS::Value *rval)
if (argc != 2)
return true;
code = jsval_to_string(ctx, args[0]);
if (!*code)
return true;
code = stracpy(code);
if (!code)
return true;
timeout = args[1].toInt32();
if (timeout <= 0) {
mem_free(code);
return true;
}
ecmascript_set_timeout(interpreter, code, timeout);
if (args[0].isString()) {
code = jsval_to_string(ctx, args[0]);
if (!*code) {
return true;
}
code = stracpy(code);
if (!code) {
return true;
}
ecmascript_set_timeout(interpreter, code, timeout);
return true;
}
ecmascript_set_timeout2(interpreter, args[0], timeout);
return true;
}