mirror of
https://github.com/DoneJS-Runtime/quickjs-done-nextgen.git
synced 2025-01-09 17:43:15 +00:00
parent
54afb19745
commit
5bf35450cd
1 changed files with 41 additions and 67 deletions
106
quickjs-libc.c
106
quickjs-libc.c
|
@ -94,6 +94,8 @@ extern char **environ;
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "quickjs-libc.h"
|
#include "quickjs-libc.h"
|
||||||
|
|
||||||
|
#define MAX_SAFE_INTEGER (((int64_t) 1 << 53) - 1)
|
||||||
|
|
||||||
/* TODO:
|
/* TODO:
|
||||||
- add socket calls
|
- add socket calls
|
||||||
*/
|
*/
|
||||||
|
@ -112,7 +114,7 @@ typedef struct {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct list_head link;
|
struct list_head link;
|
||||||
uint8_t has_object:1;
|
int64_t timer_id;
|
||||||
uint8_t repeats:1;
|
uint8_t repeats:1;
|
||||||
int64_t timeout;
|
int64_t timeout;
|
||||||
int64_t delay;
|
int64_t delay;
|
||||||
|
@ -150,6 +152,7 @@ typedef struct JSThreadState {
|
||||||
struct list_head os_timers; /* list of JSOSTimer.link */
|
struct list_head os_timers; /* list of JSOSTimer.link */
|
||||||
struct list_head port_list; /* list of JSWorkerMessageHandler.link */
|
struct list_head port_list; /* list of JSWorkerMessageHandler.link */
|
||||||
int eval_script_recurse; /* only used in the main thread */
|
int eval_script_recurse; /* only used in the main thread */
|
||||||
|
int64_t next_timer_id; /* for setTimeout / setInterval */
|
||||||
/* not used in the main thread */
|
/* not used in the main thread */
|
||||||
JSWorkerMessagePipe *recv_pipe, *send_pipe;
|
JSWorkerMessagePipe *recv_pipe, *send_pipe;
|
||||||
} JSThreadState;
|
} JSThreadState;
|
||||||
|
@ -2029,41 +2032,13 @@ static uint64_t js__hrtime_ms(void)
|
||||||
return js__hrtime_ns() / (1000 * 1000);
|
return js__hrtime_ns() / (1000 * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unlink_timer(JSRuntime *rt, JSOSTimer *th)
|
|
||||||
{
|
|
||||||
if (th->link.prev) {
|
|
||||||
list_del(&th->link);
|
|
||||||
th->link.prev = th->link.next = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_timer(JSRuntime *rt, JSOSTimer *th)
|
static void free_timer(JSRuntime *rt, JSOSTimer *th)
|
||||||
{
|
{
|
||||||
|
list_del(&th->link);
|
||||||
JS_FreeValueRT(rt, th->func);
|
JS_FreeValueRT(rt, th->func);
|
||||||
js_free_rt(rt, th);
|
js_free_rt(rt, th);
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSClassID js_os_timer_class_id;
|
|
||||||
|
|
||||||
static void js_os_timer_finalizer(JSRuntime *rt, JSValue val)
|
|
||||||
{
|
|
||||||
JSOSTimer *th = JS_GetOpaque(val, js_os_timer_class_id);
|
|
||||||
if (th) {
|
|
||||||
th->has_object = FALSE;
|
|
||||||
if (!th->link.prev)
|
|
||||||
free_timer(rt, th);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void js_os_timer_mark(JSRuntime *rt, JSValue val,
|
|
||||||
JS_MarkFunc *mark_func)
|
|
||||||
{
|
|
||||||
JSOSTimer *th = JS_GetOpaque(val, js_os_timer_class_id);
|
|
||||||
if (th) {
|
|
||||||
JS_MarkValue(rt, th->func, mark_func);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(bnoordhuis) accept string as first arg and eval at timer expiry
|
// TODO(bnoordhuis) accept string as first arg and eval at timer expiry
|
||||||
// TODO(bnoordhuis) retain argv[2..] as args for callback if argc > 2
|
// TODO(bnoordhuis) retain argv[2..] as args for callback if argc > 2
|
||||||
static JSValue js_os_setTimeout(JSContext *ctx, JSValue this_val,
|
static JSValue js_os_setTimeout(JSContext *ctx, JSValue this_val,
|
||||||
|
@ -2074,7 +2049,6 @@ static JSValue js_os_setTimeout(JSContext *ctx, JSValue this_val,
|
||||||
int64_t delay;
|
int64_t delay;
|
||||||
JSValue func;
|
JSValue func;
|
||||||
JSOSTimer *th;
|
JSOSTimer *th;
|
||||||
JSValue obj;
|
|
||||||
|
|
||||||
func = argv[0];
|
func = argv[0];
|
||||||
if (!JS_IsFunction(ctx, func))
|
if (!JS_IsFunction(ctx, func))
|
||||||
|
@ -2083,42 +2057,50 @@ static JSValue js_os_setTimeout(JSContext *ctx, JSValue this_val,
|
||||||
return JS_EXCEPTION;
|
return JS_EXCEPTION;
|
||||||
if (delay < 1)
|
if (delay < 1)
|
||||||
delay = 1;
|
delay = 1;
|
||||||
obj = JS_NewObjectClass(ctx, js_os_timer_class_id);
|
|
||||||
if (JS_IsException(obj))
|
|
||||||
return obj;
|
|
||||||
th = js_mallocz(ctx, sizeof(*th));
|
th = js_mallocz(ctx, sizeof(*th));
|
||||||
if (!th) {
|
if (!th)
|
||||||
JS_FreeValue(ctx, obj);
|
|
||||||
return JS_EXCEPTION;
|
return JS_EXCEPTION;
|
||||||
}
|
th->timer_id = ts->next_timer_id++;
|
||||||
th->has_object = TRUE;
|
if (ts->next_timer_id > MAX_SAFE_INTEGER)
|
||||||
|
ts->next_timer_id = 1;
|
||||||
th->repeats = (magic > 0);
|
th->repeats = (magic > 0);
|
||||||
th->timeout = js__hrtime_ms() + delay;
|
th->timeout = js__hrtime_ms() + delay;
|
||||||
th->delay = delay;
|
th->delay = delay;
|
||||||
th->func = JS_DupValue(ctx, func);
|
th->func = JS_DupValue(ctx, func);
|
||||||
list_add_tail(&th->link, &ts->os_timers);
|
list_add_tail(&th->link, &ts->os_timers);
|
||||||
JS_SetOpaque(obj, th);
|
return JS_NewInt64(ctx, th->timer_id);
|
||||||
return obj;
|
}
|
||||||
|
|
||||||
|
static JSOSTimer *find_timer_by_id(JSThreadState *ts, int timer_id)
|
||||||
|
{
|
||||||
|
struct list_head *el;
|
||||||
|
if (timer_id <= 0)
|
||||||
|
return NULL;
|
||||||
|
list_for_each(el, &ts->os_timers) {
|
||||||
|
JSOSTimer *th = list_entry(el, JSOSTimer, link);
|
||||||
|
if (th->timer_id == timer_id)
|
||||||
|
return th;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSValue js_os_clearTimeout(JSContext *ctx, JSValue this_val,
|
static JSValue js_os_clearTimeout(JSContext *ctx, JSValue this_val,
|
||||||
int argc, JSValue *argv)
|
int argc, JSValue *argv)
|
||||||
{
|
{
|
||||||
JSOSTimer *th = JS_GetOpaque2(ctx, argv[0], js_os_timer_class_id);
|
JSRuntime *rt = JS_GetRuntime(ctx);
|
||||||
if (!th)
|
JSThreadState *ts = JS_GetRuntimeOpaque(rt);
|
||||||
|
JSOSTimer *th;
|
||||||
|
int64_t timer_id;
|
||||||
|
|
||||||
|
if (JS_ToInt64(ctx, &timer_id, argv[0]))
|
||||||
return JS_EXCEPTION;
|
return JS_EXCEPTION;
|
||||||
unlink_timer(JS_GetRuntime(ctx), th);
|
th = find_timer_by_id(ts, timer_id);
|
||||||
JS_FreeValue(ctx, th->func);
|
if (!th)
|
||||||
th->func = JS_UNDEFINED;
|
return JS_UNDEFINED;
|
||||||
|
free_timer(rt, th);
|
||||||
return JS_UNDEFINED;
|
return JS_UNDEFINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSClassDef js_os_timer_class = {
|
|
||||||
"OSTimer",
|
|
||||||
.finalizer = js_os_timer_finalizer,
|
|
||||||
.gc_mark = js_os_timer_mark,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* return a promise */
|
/* return a promise */
|
||||||
static JSValue js_os_sleepAsync(JSContext *ctx, JSValueConst this_val,
|
static JSValue js_os_sleepAsync(JSContext *ctx, JSValueConst this_val,
|
||||||
int argc, JSValueConst *argv)
|
int argc, JSValueConst *argv)
|
||||||
|
@ -2142,7 +2124,7 @@ static JSValue js_os_sleepAsync(JSContext *ctx, JSValueConst this_val,
|
||||||
JS_FreeValue(ctx, resolving_funcs[1]);
|
JS_FreeValue(ctx, resolving_funcs[1]);
|
||||||
return JS_EXCEPTION;
|
return JS_EXCEPTION;
|
||||||
}
|
}
|
||||||
th->has_object = FALSE;
|
th->timer_id = -1;
|
||||||
th->timeout = js__hrtime_ms() + delay;
|
th->timeout = js__hrtime_ms() + delay;
|
||||||
th->func = JS_DupValue(ctx, resolving_funcs[0]);
|
th->func = JS_DupValue(ctx, resolving_funcs[0]);
|
||||||
list_add_tail(&th->link, &ts->os_timers);
|
list_add_tail(&th->link, &ts->os_timers);
|
||||||
|
@ -2185,13 +2167,10 @@ static int js_os_run_timers(JSRuntime *rt, JSContext *ctx, JSThreadState *ts)
|
||||||
min_delay = min_int(min_delay, delay);
|
min_delay = min_int(min_delay, delay);
|
||||||
} else {
|
} else {
|
||||||
func = JS_DupValueRT(rt, th->func);
|
func = JS_DupValueRT(rt, th->func);
|
||||||
unlink_timer(rt, th);
|
if (th->repeats)
|
||||||
if (th->repeats) {
|
|
||||||
th->timeout = cur_time + th->delay;
|
th->timeout = cur_time + th->delay;
|
||||||
list_add_tail(&th->link, &ts->os_timers);
|
else
|
||||||
} else if (!th->has_object) {
|
|
||||||
free_timer(rt, th);
|
free_timer(rt, th);
|
||||||
}
|
|
||||||
call_handler(ctx, func);
|
call_handler(ctx, func);
|
||||||
JS_FreeValueRT(rt, func);
|
JS_FreeValueRT(rt, func);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -3785,15 +3764,11 @@ static const JSCFunctionListEntry js_os_funcs[] = {
|
||||||
|
|
||||||
static int js_os_init(JSContext *ctx, JSModuleDef *m)
|
static int js_os_init(JSContext *ctx, JSModuleDef *m)
|
||||||
{
|
{
|
||||||
JSRuntime *rt = JS_GetRuntime(ctx);
|
|
||||||
os_poll_func = js_os_poll;
|
os_poll_func = js_os_poll;
|
||||||
|
|
||||||
/* OSTimer class */
|
|
||||||
JS_NewClassID(rt, &js_os_timer_class_id);
|
|
||||||
JS_NewClass(rt, js_os_timer_class_id, &js_os_timer_class);
|
|
||||||
|
|
||||||
#ifdef USE_WORKER
|
#ifdef USE_WORKER
|
||||||
{
|
{
|
||||||
|
JSRuntime *rt = JS_GetRuntime(ctx);
|
||||||
JSThreadState *ts = JS_GetRuntimeOpaque(rt);
|
JSThreadState *ts = JS_GetRuntimeOpaque(rt);
|
||||||
JSValue proto, obj;
|
JSValue proto, obj;
|
||||||
/* Worker class */
|
/* Worker class */
|
||||||
|
@ -3819,8 +3794,7 @@ static int js_os_init(JSContext *ctx, JSModuleDef *m)
|
||||||
}
|
}
|
||||||
#endif /* USE_WORKER */
|
#endif /* USE_WORKER */
|
||||||
|
|
||||||
return JS_SetModuleExportList(ctx, m, js_os_funcs,
|
return JS_SetModuleExportList(ctx, m, js_os_funcs, countof(js_os_funcs));
|
||||||
countof(js_os_funcs));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name)
|
JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name)
|
||||||
|
@ -3904,6 +3878,8 @@ void js_std_init_handlers(JSRuntime *rt)
|
||||||
init_list_head(&ts->os_timers);
|
init_list_head(&ts->os_timers);
|
||||||
init_list_head(&ts->port_list);
|
init_list_head(&ts->port_list);
|
||||||
|
|
||||||
|
ts->next_timer_id = 1;
|
||||||
|
|
||||||
JS_SetRuntimeOpaque(rt, ts);
|
JS_SetRuntimeOpaque(rt, ts);
|
||||||
|
|
||||||
#ifdef USE_WORKER
|
#ifdef USE_WORKER
|
||||||
|
@ -3936,8 +3912,6 @@ void js_std_free_handlers(JSRuntime *rt)
|
||||||
|
|
||||||
list_for_each_safe(el, el1, &ts->os_timers) {
|
list_for_each_safe(el, el1, &ts->os_timers) {
|
||||||
JSOSTimer *th = list_entry(el, JSOSTimer, link);
|
JSOSTimer *th = list_entry(el, JSOSTimer, link);
|
||||||
unlink_timer(rt, th);
|
|
||||||
if (!th->has_object)
|
|
||||||
free_timer(rt, th);
|
free_timer(rt, th);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue