mirror of
https://github.com/rkd77/elinks.git
synced 2024-12-04 14:46:47 -05:00
[ecmascript] Handle more than 1 timeout at the same time.
This commit is contained in:
parent
6a7d8ba7bc
commit
bce7e87bb8
@ -142,6 +142,7 @@ init_document(struct cache_entry *cached, struct document_options *options)
|
|||||||
|
|
||||||
#ifdef CONFIG_ECMASCRIPT
|
#ifdef CONFIG_ECMASCRIPT
|
||||||
init_list(document->onload_snippets);
|
init_list(document->onload_snippets);
|
||||||
|
init_list(document->timeouts);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_COMBINE
|
#ifdef CONFIG_COMBINE
|
||||||
@ -351,7 +352,17 @@ done_document(struct document *document)
|
|||||||
#if defined(CONFIG_ECMASCRIPT_SMJS) || defined(CONFIG_QUICKJS) || defined(CONFIG_MUJS)
|
#if defined(CONFIG_ECMASCRIPT_SMJS) || defined(CONFIG_QUICKJS) || defined(CONFIG_MUJS)
|
||||||
free_string_list(&document->onload_snippets);
|
free_string_list(&document->onload_snippets);
|
||||||
free_uri_list(&document->ecmascript_imports);
|
free_uri_list(&document->ecmascript_imports);
|
||||||
kill_timer(&document->timeout);
|
|
||||||
|
{
|
||||||
|
struct ecmascript_timeout *t;
|
||||||
|
|
||||||
|
foreach(t, document->timeouts) {
|
||||||
|
kill_timer(&t->tid);
|
||||||
|
done_string(&t->code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free_list(document->timeouts);
|
||||||
|
|
||||||
mem_free_if(document->text);
|
mem_free_if(document->text);
|
||||||
free_document(document->dom);
|
free_document(document->dom);
|
||||||
#endif
|
#endif
|
||||||
@ -376,7 +387,15 @@ release_document(struct document *document)
|
|||||||
|
|
||||||
if (document->refresh) kill_document_refresh(document->refresh);
|
if (document->refresh) kill_document_refresh(document->refresh);
|
||||||
#ifdef CONFIG_ECMASCRIPT
|
#ifdef CONFIG_ECMASCRIPT
|
||||||
kill_timer(&document->timeout);
|
{
|
||||||
|
struct ecmascript_timeout *t;
|
||||||
|
|
||||||
|
foreach(t, document->timeouts) {
|
||||||
|
kill_timer(&t->tid);
|
||||||
|
done_string(&t->code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free_list(document->timeouts);
|
||||||
#endif
|
#endif
|
||||||
object_unlock(document);
|
object_unlock(document);
|
||||||
move_to_top_of_list(format_cache, document);
|
move_to_top_of_list(format_cache, document);
|
||||||
|
@ -16,6 +16,7 @@ extern "C" {
|
|||||||
|
|
||||||
struct cache_entry;
|
struct cache_entry;
|
||||||
struct document_refresh;
|
struct document_refresh;
|
||||||
|
struct ecmascript_timeout;
|
||||||
struct el_form_control;
|
struct el_form_control;
|
||||||
struct frame_desc;
|
struct frame_desc;
|
||||||
struct frameset_desc;
|
struct frameset_desc;
|
||||||
@ -67,7 +68,6 @@ struct tag {
|
|||||||
char name[1]; /* must be last of struct. --Zas */
|
char name[1]; /* must be last of struct. --Zas */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
enum link_type {
|
enum link_type {
|
||||||
LINK_HYPERTEXT,
|
LINK_HYPERTEXT,
|
||||||
LINK_MAP,
|
LINK_MAP,
|
||||||
@ -209,7 +209,7 @@ struct document {
|
|||||||
* unneeded. */
|
* unneeded. */
|
||||||
struct uri_list ecmascript_imports;
|
struct uri_list ecmascript_imports;
|
||||||
/** used by setTimeout */
|
/** used by setTimeout */
|
||||||
timer_id_T timeout;
|
LIST_OF(struct ecmascript_timeout) timeouts;
|
||||||
int ecmascript_counter;
|
int ecmascript_counter;
|
||||||
void *dom;
|
void *dom;
|
||||||
char *text;
|
char *text;
|
||||||
|
@ -275,8 +275,15 @@ ecmascript_put_interpreter(struct ecmascript_interpreter *interpreter)
|
|||||||
free_string_list(&interpreter->onload_snippets);
|
free_string_list(&interpreter->onload_snippets);
|
||||||
done_string(&interpreter->code);
|
done_string(&interpreter->code);
|
||||||
/* Is it superfluous? */
|
/* Is it superfluous? */
|
||||||
if (interpreter->vs->doc_view)
|
if (interpreter->vs->doc_view) {
|
||||||
kill_timer(&interpreter->vs->doc_view->document->timeout);
|
struct ecmascript_timeout *t;
|
||||||
|
|
||||||
|
foreach (t, interpreter->vs->doc_view->document->timeouts) {
|
||||||
|
kill_timer(&t->tid);
|
||||||
|
done_string(&t->code);
|
||||||
|
}
|
||||||
|
free_list(interpreter->vs->doc_view->document->timeouts);
|
||||||
|
}
|
||||||
interpreter->vs->ecmascript = NULL;
|
interpreter->vs->ecmascript = NULL;
|
||||||
interpreter->vs->ecmascript_fragile = 1;
|
interpreter->vs->ecmascript_fragile = 1;
|
||||||
mem_free(interpreter);
|
mem_free(interpreter);
|
||||||
@ -573,17 +580,22 @@ ecmascript_set_action(char **action, char *string)
|
|||||||
* As explained in @install_timer, this function must erase the
|
* As explained in @install_timer, this function must erase the
|
||||||
* expired timer ID from all variables. */
|
* expired timer ID from all variables. */
|
||||||
static void
|
static void
|
||||||
ecmascript_timeout_handler(void *i)
|
ecmascript_timeout_handler(void *val)
|
||||||
{
|
{
|
||||||
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)i;
|
struct ecmascript_timeout *t = (struct ecmascript_timeout *)val;
|
||||||
|
struct ecmascript_interpreter *interpreter = t->interpreter;
|
||||||
|
|
||||||
assertm(interpreter->vs->doc_view != NULL,
|
assertm(interpreter->vs->doc_view != NULL,
|
||||||
"setTimeout: vs with no document (e_f %d)",
|
"setTimeout: vs with no document (e_f %d)",
|
||||||
interpreter->vs->ecmascript_fragile);
|
interpreter->vs->ecmascript_fragile);
|
||||||
interpreter->vs->doc_view->document->timeout = TIMER_ID_UNDEF;
|
t->tid = TIMER_ID_UNDEF;
|
||||||
/* The expired timer ID has now been erased. */
|
/* The expired timer ID has now been erased. */
|
||||||
|
ecmascript_eval(interpreter, &t->code, NULL);
|
||||||
|
|
||||||
|
del_from_list(t);
|
||||||
|
done_string(&t->code);
|
||||||
|
mem_free(t);
|
||||||
|
|
||||||
ecmascript_eval(interpreter, &interpreter->code, NULL);
|
|
||||||
check_for_rerender(interpreter, "handler");
|
check_for_rerender(interpreter, "handler");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -592,16 +604,25 @@ ecmascript_timeout_handler(void *i)
|
|||||||
* As explained in @install_timer, this function must erase the
|
* As explained in @install_timer, this function must erase the
|
||||||
* expired timer ID from all variables. */
|
* expired timer ID from all variables. */
|
||||||
static void
|
static void
|
||||||
ecmascript_timeout_handler2(void *i)
|
ecmascript_timeout_handler2(void *val)
|
||||||
{
|
{
|
||||||
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)i;
|
struct ecmascript_timeout *t = (struct ecmascript_timeout *)val;
|
||||||
|
struct ecmascript_interpreter *interpreter = t->interpreter;
|
||||||
|
|
||||||
assertm(interpreter->vs->doc_view != NULL,
|
assertm(interpreter->vs->doc_view != NULL,
|
||||||
"setTimeout: vs with no document (e_f %d)",
|
"setTimeout: vs with no document (e_f %d)",
|
||||||
interpreter->vs->ecmascript_fragile);
|
interpreter->vs->ecmascript_fragile);
|
||||||
interpreter->vs->doc_view->document->timeout = TIMER_ID_UNDEF;
|
t->tid = TIMER_ID_UNDEF;
|
||||||
/* The expired timer ID has now been erased. */
|
/* The expired timer ID has now been erased. */
|
||||||
ecmascript_call_function(interpreter, interpreter->fun, NULL);
|
ecmascript_call_function(interpreter, t->fun, NULL);
|
||||||
|
|
||||||
|
del_from_list(t);
|
||||||
|
done_string(&t->code);
|
||||||
|
#ifdef CONFIG_MUJS
|
||||||
|
// js_unref(t->ctx, t->fun);
|
||||||
|
#endif
|
||||||
|
mem_free(t);
|
||||||
|
|
||||||
check_for_rerender(interpreter, "handler2");
|
check_for_rerender(interpreter, "handler2");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -611,21 +632,25 @@ ecmascript_set_timeout(struct ecmascript_interpreter *interpreter, char *code, i
|
|||||||
{
|
{
|
||||||
assert(interpreter && interpreter->vs->doc_view->document);
|
assert(interpreter && interpreter->vs->doc_view->document);
|
||||||
if (!code) return nullptr;
|
if (!code) return nullptr;
|
||||||
if (interpreter->code.source) {
|
struct ecmascript_timeout *t = (struct ecmascript_timeout *)calloc(1, sizeof(*t));
|
||||||
done_string(&interpreter->code);
|
|
||||||
}
|
if (!t) {
|
||||||
if (!init_string(&interpreter->code)) {
|
|
||||||
mem_free(code);
|
mem_free(code);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
add_to_string(&interpreter->code, code);
|
if (!init_string(&t->code)) {
|
||||||
mem_free(code);
|
mem_free(t);
|
||||||
if (found_in_map_timer(interpreter->vs->doc_view->document->timeout)) {
|
mem_free(code);
|
||||||
kill_timer(&interpreter->vs->doc_view->document->timeout);
|
return nullptr;
|
||||||
}
|
}
|
||||||
install_timer(&interpreter->vs->doc_view->document->timeout, timeout, ecmascript_timeout_handler, interpreter);
|
add_to_string(&t->code, code);
|
||||||
|
mem_free(code);
|
||||||
|
|
||||||
return interpreter->vs->doc_view->document->timeout;
|
t->interpreter = interpreter;
|
||||||
|
add_to_list(interpreter->vs->doc_view->document->timeouts, t);
|
||||||
|
install_timer(&t->tid, timeout, ecmascript_timeout_handler, t);
|
||||||
|
|
||||||
|
return t->tid;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_ECMASCRIPT_SMJS
|
#ifdef CONFIG_ECMASCRIPT_SMJS
|
||||||
@ -633,21 +658,23 @@ timer_id_T
|
|||||||
ecmascript_set_timeout2(struct ecmascript_interpreter *interpreter, JS::HandleValue f, int timeout)
|
ecmascript_set_timeout2(struct ecmascript_interpreter *interpreter, JS::HandleValue f, int timeout)
|
||||||
{
|
{
|
||||||
assert(interpreter && interpreter->vs->doc_view->document);
|
assert(interpreter && interpreter->vs->doc_view->document);
|
||||||
if (interpreter->code.source) {
|
|
||||||
done_string(&interpreter->code);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!init_string(&interpreter->code)) {
|
struct ecmascript_timeout *t = (struct ecmascript_timeout *)calloc(1, sizeof(*t));
|
||||||
return TIMER_ID_UNDEF;
|
|
||||||
|
if (!t) {
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (found_in_map_timer(interpreter->vs->doc_view->document->timeout)) {
|
if (!init_string(&t->code)) {
|
||||||
kill_timer(&interpreter->vs->doc_view->document->timeout);
|
mem_free(t);
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
t->interpreter = interpreter;
|
||||||
JS::RootedValue fun((JSContext *)interpreter->backend_data, f);
|
JS::RootedValue fun((JSContext *)interpreter->backend_data, f);
|
||||||
interpreter->fun = fun;
|
t->fun = fun;
|
||||||
install_timer(&interpreter->vs->doc_view->document->timeout, timeout, ecmascript_timeout_handler2, interpreter);
|
add_to_list(interpreter->vs->doc_view->document->timeouts, t);
|
||||||
|
install_timer(&t->tid, timeout, ecmascript_timeout_handler2, t);
|
||||||
|
|
||||||
return interpreter->vs->doc_view->document->timeout;
|
return t->tid;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -656,40 +683,48 @@ timer_id_T
|
|||||||
ecmascript_set_timeout2q(struct ecmascript_interpreter *interpreter, JSValueConst fun, int timeout)
|
ecmascript_set_timeout2q(struct ecmascript_interpreter *interpreter, JSValueConst fun, int timeout)
|
||||||
{
|
{
|
||||||
assert(interpreter && interpreter->vs->doc_view->document);
|
assert(interpreter && interpreter->vs->doc_view->document);
|
||||||
if (interpreter->code.source) {
|
struct ecmascript_timeout *t = (struct ecmascript_timeout *)calloc(1, sizeof(*t));
|
||||||
done_string(&interpreter->code);
|
|
||||||
}
|
|
||||||
if (!init_string(&interpreter->code)) {
|
|
||||||
return TIMER_ID_UNDEF;
|
|
||||||
}
|
|
||||||
if (found_in_map_timer(interpreter->vs->doc_view->document->timeout)) {
|
|
||||||
kill_timer(&interpreter->vs->doc_view->document->timeout);
|
|
||||||
}
|
|
||||||
interpreter->fun = fun;
|
|
||||||
install_timer(&interpreter->vs->doc_view->document->timeout, timeout, ecmascript_timeout_handler2, interpreter);
|
|
||||||
|
|
||||||
return interpreter->vs->doc_view->document->timeout;
|
if (!t) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (!init_string(&t->code)) {
|
||||||
|
mem_free(t);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
t->interpreter = interpreter;
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_MUJS
|
#ifdef CONFIG_MUJS
|
||||||
timer_id_T
|
timer_id_T
|
||||||
ecmascript_set_timeout2m(struct ecmascript_interpreter *interpreter, const char *handle, int timeout)
|
ecmascript_set_timeout2m(js_State *J, const char *handle, int timeout)
|
||||||
{
|
{
|
||||||
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)js_getcontext(J);
|
||||||
assert(interpreter && interpreter->vs->doc_view->document);
|
assert(interpreter && interpreter->vs->doc_view->document);
|
||||||
if (interpreter->code.source) {
|
|
||||||
done_string(&interpreter->code);
|
|
||||||
}
|
|
||||||
if (!init_string(&interpreter->code)) {
|
|
||||||
return TIMER_ID_UNDEF;
|
|
||||||
}
|
|
||||||
if (found_in_map_timer(interpreter->vs->doc_view->document->timeout)) {
|
|
||||||
kill_timer(&interpreter->vs->doc_view->document->timeout);
|
|
||||||
}
|
|
||||||
interpreter->fun = handle;
|
|
||||||
install_timer(&interpreter->vs->doc_view->document->timeout, timeout, ecmascript_timeout_handler2, interpreter);
|
|
||||||
|
|
||||||
return interpreter->vs->doc_view->document->timeout;
|
struct ecmascript_timeout *t = (struct ecmascript_timeout *)calloc(1, sizeof(*t));
|
||||||
|
|
||||||
|
if (!t) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (!init_string(&t->code)) {
|
||||||
|
mem_free(t);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
t->interpreter = interpreter;
|
||||||
|
t->ctx = J;
|
||||||
|
t->fun = handle;
|
||||||
|
|
||||||
|
add_to_list(interpreter->vs->doc_view->document->timeouts, t);
|
||||||
|
install_timer(&t->tid, timeout, ecmascript_timeout_handler2, t);
|
||||||
|
|
||||||
|
return t->tid;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -99,6 +99,24 @@ struct ecmascript_interpreter {
|
|||||||
bool changed;
|
bool changed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ecmascript_timeout {
|
||||||
|
LIST_HEAD(struct ecmascript_timeout);
|
||||||
|
struct string code;
|
||||||
|
#ifdef CONFIG_QUICKJS
|
||||||
|
JSValueConst fun;
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_ECMASCRIPT_SMJS
|
||||||
|
JS::RootedValue fun;
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_MUJS
|
||||||
|
js_State *ctx;
|
||||||
|
const char *fun;
|
||||||
|
#endif
|
||||||
|
struct ecmascript_interpreter *interpreter;
|
||||||
|
timer_id_T tid;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct delayed_goto {
|
struct delayed_goto {
|
||||||
/* It might look more convenient to pass doc_view around but it could
|
/* It might look more convenient to pass doc_view around but it could
|
||||||
* disappear during wild dances inside of frames or so. */
|
* disappear during wild dances inside of frames or so. */
|
||||||
@ -154,7 +172,7 @@ timer_id_T ecmascript_set_timeout2q(struct ecmascript_interpreter *interpreter,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_MUJS
|
#ifdef CONFIG_MUJS
|
||||||
timer_id_T ecmascript_set_timeout2m(struct ecmascript_interpreter *interpreter, const char *handle, int timeout);
|
timer_id_T ecmascript_set_timeout2m(js_State *J, const char *handle, int timeout);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int get_ecmascript_enable(struct ecmascript_interpreter *interpreter);
|
int get_ecmascript_enable(struct ecmascript_interpreter *interpreter);
|
||||||
|
@ -193,8 +193,18 @@ mjs_window_clearTimeout(js_State *J)
|
|||||||
int64_t number = atoll(text);
|
int64_t number = atoll(text);
|
||||||
timer_id_T id = reinterpret_cast<timer_id_T>(number);
|
timer_id_T id = reinterpret_cast<timer_id_T>(number);
|
||||||
|
|
||||||
if (found_in_map_timer(id) && (id == interpreter->vs->doc_view->document->timeout)) {
|
if (found_in_map_timer(id)) {
|
||||||
kill_timer(&interpreter->vs->doc_view->document->timeout);
|
struct ecmascript_timeout *t;
|
||||||
|
|
||||||
|
foreach (t, interpreter->vs->doc_view->document->timeouts) {
|
||||||
|
if (id == t->tid) {
|
||||||
|
kill_timer(&t->tid);
|
||||||
|
done_string(&t->code);
|
||||||
|
del_from_list(t);
|
||||||
|
mem_free(t);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
js_pushundefined(J);
|
js_pushundefined(J);
|
||||||
}
|
}
|
||||||
@ -330,8 +340,6 @@ end:
|
|||||||
js_pushboolean(J, ret);
|
js_pushboolean(J, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *handle = NULL;
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mjs_window_setTimeout(js_State *J)
|
mjs_window_setTimeout(js_State *J)
|
||||||
{
|
{
|
||||||
@ -363,12 +371,9 @@ mjs_window_setTimeout(js_State *J)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (handle) {
|
|
||||||
js_unref(J, handle);
|
|
||||||
}
|
|
||||||
js_copy(J, 1);
|
js_copy(J, 1);
|
||||||
handle = js_ref(J);
|
const char *handle = js_ref(J);
|
||||||
timer_id_T id = ecmascript_set_timeout2m(interpreter, handle, timeout);
|
timer_id_T id = ecmascript_set_timeout2m(J, handle, timeout);
|
||||||
char res[32];
|
char res[32];
|
||||||
snprintf(res, 31, "%ld", (int64_t)id);
|
snprintf(res, 31, "%ld", (int64_t)id);
|
||||||
js_pushstring(J, res);
|
js_pushstring(J, res);
|
||||||
|
@ -246,8 +246,18 @@ js_window_clearTimeout(JSContext *ctx, JSValueConst this_val, int argc, JSValueC
|
|||||||
|
|
||||||
timer_id_T id = reinterpret_cast<timer_id_T>(number);
|
timer_id_T id = reinterpret_cast<timer_id_T>(number);
|
||||||
|
|
||||||
if (found_in_map_timer(id) && (id == interpreter->vs->doc_view->document->timeout)) {
|
if (found_in_map_timer(id)) {
|
||||||
kill_timer(&interpreter->vs->doc_view->document->timeout);
|
struct ecmascript_timeout *t;
|
||||||
|
|
||||||
|
foreach (t, interpreter->vs->doc_view->document->timeouts) {
|
||||||
|
if (id == t->tid) {
|
||||||
|
kill_timer(&t->tid);
|
||||||
|
done_string(&t->code);
|
||||||
|
del_from_list(t);
|
||||||
|
mem_free(t);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return JS_UNDEFINED;
|
return JS_UNDEFINED;
|
||||||
|
@ -406,13 +406,22 @@ window_clearTimeout(JSContext *ctx, unsigned int argc, JS::Value *rval)
|
|||||||
int64_t number = JS::ToBigInt64(bi);
|
int64_t number = JS::ToBigInt64(bi);
|
||||||
timer_id_T id = reinterpret_cast<timer_id_T>(number);
|
timer_id_T id = reinterpret_cast<timer_id_T>(number);
|
||||||
|
|
||||||
if (found_in_map_timer(id) && (id == interpreter->vs->doc_view->document->timeout)) {
|
if (found_in_map_timer(id)) {
|
||||||
kill_timer(&id);
|
struct ecmascript_timeout *t;
|
||||||
|
|
||||||
|
foreach (t, interpreter->vs->doc_view->document->timeouts) {
|
||||||
|
if (id == t->tid) {
|
||||||
|
kill_timer(&t->tid);
|
||||||
|
done_string(&t->code);
|
||||||
|
del_from_list(t);
|
||||||
|
mem_free(t);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static bool
|
static bool
|
||||||
window_get_property_closed(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp)
|
window_get_property_closed(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp)
|
||||||
|
Loading…
Reference in New Issue
Block a user